Kombinacje pinyin

13

Utwórz funkcję, która pobiera ciąg sylaby pinyin jako argument i zwraca wartość true dla kombinacji, w przeciwnym razie wartość false.

Użyj „v” dla „ü”.

Oto pełna lista kombinacji. http://www.pinyin.info/rules/initials_finals.html

Przykłady

f("bu") == true
f("zheng") == true
f("nv") == true
f("ri") == true
f("cei") == false
f("ia") == false
f("kian") == false
f("qa") == false

Nie rób takich rzeczy, jak skrobanie stron internetowych lub czytanie plików metod wprowadzania, aby zmniejszyć liczbę znaków. (Jeśli to zrobisz, długość danych będzie liczona do liczby znaków) Jednym z celów tego kodu golfa jest sprawdzenie, w jaki sposób można uprościć reguły. Najkrótszy kod wygrywa.

Ming-Tang
źródło
Co powiesz na coś takiego nar? : P
JiminP
1
Dla przypomnienia, pomimo tego, co mówią przykłady, nie sądzę, aby nvikiedykolwiek była to poprawna kombinacja.
rintaun
Jeśli na linkowanej stronie jest już napisane: „  er został pominięty w tej tabeli”, czy nie należy go również uwzględnić? (W końcu był to numer, jeśli dobrze pamiętam ;-))
Joey,

Odpowiedzi:

4

JavaScript 1.6, 503 496 477 znaków

function g(s){return/^([bfmpw]?o|[yjqx]ua?n|[ln]ve?|ei?|y[aio]ng|w?[ae]ng?|w?ai?|wei|y?ao|y?ou|y[ai]n?|yu?e|[^aeiou]+u)$/.test(s)|(((k=6*("ccsszzdflmnprtbghkjqx".indexOf(s[0])+(f=s[1]=='h')))|(r="a.e.ai.ei.ao.ou.an.ang.en.eng.ong.ua.uo.uai.ui.uan.uang.un.i.ia.ie.iao.iu.ian.iang.in.ing.iong.u.ue".split('.').indexOf(s.slice(f+1))))<0?0:k>84?r>17^k<108:parseInt("009m2f00b8jb009m2f00b7r3009m2n00b8jj1dwcfz0000rtfjba4f1xgbnjfj01rz1uyfb1009nn61b37cv1uyfa5".slice(k,k+6),36)>>r&1)}

Sformatowano trochę bardziej czytelnie (wykluczając wszelkie błędy przy dzieleniu kodu na kilka wierszy):

function _g(s)
{
  f = s[1] == 'h'
  k = "ccsszzdfghjklmnpqrtxb".indexOf(s[0]) * 6
  k += 6 * f
  return /^(weng|[bfmp]?o|[yjqx]ua?n|[ln]ve?|[ae]i?|y[aeiu]|y[aio]ng|[ae]ng?|wang?|wai?|we[in]|w[ou]|y?ao|y?ou?|y[ai]n|yue)$/.test(s) | 
         !!(k >= 0 && (1 << "a.e.ai.ei.ao.ou.an.ang.en.eng.ong.u.ua.uo.uai.ui.uan.uang.un.i.ia.ie.iao.iu.ian.iang.in.ing.iong.u.ue".split('.').indexOf(s.slice(f + 1)) & parseInt("00j85300mh2v00j85300mgan00j85b00mh332rsovz0002cp00b8jj00b8jjqmlts000b8jjv2mkfz3uwo3jv203jz3pwvelqmlts000jbaq2m6ewvqmlts03pwvdp".slice(k, k + 6), 36)))
}

Przypadki początkowe od zera oraz kilka zdarzeń jednorazowych są testowane przy użyciu wyrażenia regularnego. Następnie tabela jest kodowana jako (połączona) seria 6 cyfr, liczba podstawowa 36, ​​po jednej na dźwięk początkowy. Wyszukiwanie następnie używa pary indexOfpołączeń i Shift, aby wybrać odpowiedni bit.

Testowane względem wszystkich komórek w tabeli kombinacji (wypełnione komórki testowane na prawdziwość, puste komórki testowane na fałsz).

Edycja: Zastąpiłem niektóre z 36 znaków wyszukiwania podstawowego 36 porównaniami, ponieważ g–, k–, h–, j–, q– i z– mają gęste bloki wartości prawda / fałsz.

Edycja: Zmieniono ułożenie testu bitów, aby uniknąć niepotrzebnych !!i bardziej zagęściło wyrażenie regularne.

DocMax
źródło
Dlaczego potrzebujemy !!? Nie jestem pewien, czy rozumiem, dlaczego miałbyś kiedykolwiek potrzebować podwójnej nie ...
Peter Olson
Przy tym zwrot wynosi 0 lub 1; bez tego „prawda” jest zwracana jako niezerowa, ale niekoniecznie 1. Mój skrypt testowy sprawdza, z if (g(s) == (validList.indexOf(s) >= 0)którą zwraca false 16 == true; Dyskutowałem o tym z perspektywy „co to prawda” naprawdę znaczy „i zostawiłem to w sobie. W obu przypadkach mam dziś planowaną zmianę na później, która zakończy się !!zastąpieniem 1<<r&*parseInt(mniej więcej) (parseInt>>r)&1tak, aby return wynosi 1 i golę dwa znaki.
DocMax
1

PHP, 548 znaków

To prawda, że ​​prawdopodobnie nie jest to optymalne, ale napisałem wyrażenie regularne w celu dopasowania prawidłowych kombinacji pinyin. Zredukowane znaki poprzez zastąpienie powtarzających się podciągów zmiennymi.

Kod

<?php $a='?|e(i|ng?)';$b='|o(u|ng)|u';$c='|a?n)?|i(a[on]';$d='(a(ng?|o|i)';$e='|ng?)';$f='(i|ng)?';echo(preg_match("/^([bpm](a(i|o$e$a|u|o|i(e|a[on]$e?)|[pm]ou|m(e|iu)|f(a(ng?)?|ou$a|u)|d$d$a?$b(o|i$c?|e|u)?)|[dtnl]$d?|e$f$b(o$c|e)?)|[jqxy](i(a(o$e?|e|u|o?ng|n)|u(e|a?n))|([zcs]h?|r)i|[nl](ve?|i(n|ang?|u))|[dl]ia|[dt](ing|ui)|[dn]en|diu|([gkh]|[zcs]h?)(e(ng?)|a(o|ng?|i)?|ou|u(o|i|a?n)?)|r(e(ng?)?|a(o$e$b(a?n?|o|i)?)|[gkh](ei|ong|u(a$f))|[zcs]hua$f|([zcs]|[zc]h)ong|(z|[zs]h)ei|a(i|o$e?|ou$a?|w(u|a(i$e?|o|e(i$e))$/",$argv[1]))?"true":"false";

Stosowanie

> php pinyin.php bu
> true
> php pinyin.php cei
> false
rintaun
źródło
1

F #, 681 znaków

type l=Y|J|Q|X|W|F|B|P|M|N|L|T|D|Z|K|H|Zh|G|Sh|Ch|C|S|R|Iong|Vn|Van|Ia|Iu|In|Iang|Ve|V|Ian|Iao|Ie|Ing|I|Ei|A|Ai|An|Ang|Eng|U|Ao|E|Ou|Uo|Uan|Un|Ui|En|Ong|Ua|Uang|Uai|Ueng|O
let v x=x.GetHashCode()
let n x=J.GetType().GetNestedType("Tags").GetFields().GetValue(v x).ToString().Substring(6).ToLower();
let(^)a b=List.collect(fun x->List.map(fun z-> n x+ n z)b)a
let(-)a b=[v a..v b]
let(&)a b=a@b
let(!)a=[v a]
[<EntryPoint>]
let main a=
 printf"%b"(List.exists(fun x->x=a.[0])(Y-X^Iong-I& !W^Ei-Ui@Ua-O& !F^Ei-A@An-U@ !Ou&(F-N@D-Sh)^ !En&F-M^ !O&B-M^ !In&N-L^Iu-Un& !D^Ia-Iu&B-D^Ian-Ao& !M^E-Ou&Ch-S^A-Ong&T-Sh^Ei-Ui&N-G^ !Ong&K-Ch^Ua-Uai& !R^An-Ua&(Sh-R@ !Z@ !Zh)^ !I&["lia";"pou";"mui"]))
 0

Nie do końca rozumie sylaby bez poprawnej początkowej spółgłoski (Y, W itp.).

Mark H.
źródło
1

APL (Dyalog Extended) , 475 bajtów

s←⊢⊆⍨' '≠⊢
a b c2097144 131064 1957895
f←{(⊂⍵)∊(12v),(s'yi ya ye yao you yan yang yin ying yong yu yue yuan yun wu wa wo wai wei wan wang wen weng nv lv nve lve'),(,⊤(a-8)1966080 393208 1966064 2096720 1966072 1048568a a 2056184a 131048a 7288b 7280 106488b 7280b 0 1958911 73735c c 352263c 24583 1859591c,57)/,('bpmfdtnlgkhzcs',s'zh ch sh r j q x')∘.,v'aoe',s'ai ei ao ou an ang en eng ong u ua uo uai ui uan uang un ueng i ia ie iao iu ian iang in ing iong u ue uan un'}

Wypróbuj online!

Gra w golfa w toku.

Nie golfił

s←{⍵⊆⍨' '≠⍵}
cons'b p m f d t n l g k h z c s zh ch sh r j q x'
vwls'a o e ai ei ao ou an ang en eng ong u ua uo uai ui uan uang un ueng i ia ie iao iu ian iang in ing iong u ue uan un'
tabcon∘.,vwl
bin←,⊤2097136 1966080 393208 1966064 2096720 1966072 1048568 2097144 2097144 2056184 2097144 131048 2097144 7288 131064 7280 106488 131064 7280 131064 0 1958911 73735 1957895 1957895 352263 1957895 24583 1859591 1957895 7 7 7 7 7
all'aoe',(12vwl),(s'yi ya ye yao you yan yang yin ying yong yu yue yuan yun wu wa wo wai wei wan wang wen weng nv lv nve lve'),bin/,tab
f←{(⊂⍵)∊all}

Wypróbuj online!

Funkcja pomocnika srozpakowuje łańcuch rozdzielany spacjami:

{⍵⊆⍨' '≠⍵}    monadic function taking a string
    ' '≠⍵       0s at spaces, 1s elsewhere
 ⍵⊆⍨            Partition (split at 0s)

Najpierw przechowuję ewentualne ciągi początkowe i końcowe w sylabie, a następnie tworzę tabelę tabzawierającą konkatenację każdego ciągu z pierwszej listy z każdym ciągiem z drugiej listy.

Następnie przechowuję dane binarne jako listę liczb całkowitych. Niektóre liczby całkowite są powtarzane i dlatego mogą być przechowywane w zmiennych, co pozwala również na elucję niektórych spacji.

Każda liczba całkowita jest dekodowana na binarną i reprezentuje jeden wiersz tabeli. Każdy bit liczby wskazuje, czy dana sylaba w tym wierszu jest prawidłową sylabą, przy czym MSB reprezentuje pierwszą kolumnę. Wszystkie nieprawidłowe sylaby są usuwane z tabeli.

Spłaszczamy tabelę do listy, dodajemy formularze bez początkowej spółgłoski jako specjalny przypadek i na koniec sprawdzamy, czy nasze dane wejściowe znajdują się na liście.

Możliwy dalszy potencjał golfowy:

  • Napisz kodowanie base64 lub base255
  • Zmień kolejność kolumn i wierszy, aby zmniejszyć liczby.

Pomocny generator skryptów i przypadków testowych w Pythonie: Wypróbuj online!

lirtosiast
źródło