Combinações de pinyin

13

Crie uma função que use uma sequência de sílabas pinyin como argumento e retorne true da combinação existente, caso contrário, false.

Use "v" para "ü".

Aqui está uma lista completa de combinações. http://www.pinyin.info/rules/initials_finals.html

Exemplos

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

Por favor, não faça coisas como raspar páginas da Web ou ler arquivos de métodos de entrada para reduzir a contagem de caracteres. (Se o fizer, o comprimento dos dados será contado na contagem de caracteres) Um dos objetivos desse código de golfe é ver como as regras podem ser simplificadas. O menor código vence.

Ming-Tang
fonte
Que tal algo assim nar? : P
JiminP 21/06
1
Apenas como uma observação, apesar do que dizem os exemplos, não acredito que nviseja uma combinação válida.
rintaun
Se a página vinculada já diz »  er foi omitida desta tabela«, não deveria ser incluída também? (Afinal de contas, era um número, se bem me lembro ;-))
Joey

Respostas:

4

JavaScript 1.6, 503 496 477 caracteres

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)}

Fomatizado um pouco mais facilmente (exceto erros ao quebrar o código em algumas linhas):

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)))
}

Os casos com zero inicial e alguns pontuais são testados com uma expressão regular. Depois disso, a tabela é codificada como uma série (concatenada) de números de base 36 de 6 dígitos, um por som inicial. A pesquisa usa um par de indexOfchamadas e um turno para selecionar o bit certo.

Testado em todas as células da tabela de combinações (células preenchidas testadas como verdadeiras, células vazias testadas como falsas).

Edit: Substituiu alguns dos 36 caracteres da pesquisa base-36 por comparações desde g -, k -, h -, j -, q - e z - têm blocos densos de verdadeiro / falso.

Edit: Reorganizou o teste de bits para evitar um desnecessário !!e compactou mais o regex.

DocMax
fonte
Por que você precisa de um !!? Eu não estou certo que eu entendo por que você iria precisar de um duplo não ...
Peter Olson
Com isso, o retorno é 0 ou 1; sem ele "true" é retornado como diferente de zero, mas não necessariamente 1. Meu script de teste está validando com o if (g(s) == (validList.indexOf(s) >= 0)qual retorna false 16 == true; Eu debati-lo de um "o que faz 'true' realmente significa" perspectiva e deixou a coisa. Em ambos os casos, eu tenho uma mudança planejada para mais tarde hoje que vai acabar com o !!substituindo 1<<r&*parseIntcom (mais ou menos) (parseInt>>r)&1para que o o retorno é 1 e eu raspo dois caracteres.
DocMax
1

PHP, 548 caracteres

Concedido, provavelmente não é o ideal, mas escrevi um regex para combinar combinações válidas de pinyin. Caracteres reduzidos substituindo substrings repetidos por variáveis.

Código

<?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";

Uso

> php pinyin.php bu
> true
> php pinyin.php cei
> false
rintaun
fonte
1

F #, 681 caracteres

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

Não consegue as sílabas sem a consoante inicial correta (Y, W, etc.).

Mark H
fonte
1

APL (Dyalog Extended) , 475 bytes

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'}

Experimente online!

Golfe em andamento.

Ungolfed

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}

Experimente online!

A função auxiliar sdescompacta uma sequência delimitada por espaço:

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

Primeiro guardo as possíveis sequências iniciais e finais na sílaba e, em seguida, faço uma tabela tabcontendo a concatenação de cada sequência da primeira lista com cada sequência da segunda lista.

Em seguida, armazeno dados binários como uma lista de números inteiros. Alguns dos números inteiros são repetidos e, portanto, podem ser armazenados em variáveis, o que também permite a elisão de alguns espaços.

Cada número inteiro é decodificado em binário e representa uma linha da tabela. Cada bit no número representa se uma determinada sílaba nessa linha é uma sílaba válida, com o MSB representando a primeira coluna. Todas as sílabas inválidas são removidas da tabela.

Achatamos a tabela em uma lista, adicionamos os formulários sem consoante inicial como um caso especial e, finalmente, verificamos se nossa entrada está na lista.

Possível potencial de golfe adicional:

  • Escreva codificação base64 ou base255
  • Reordene as colunas e linhas para diminuir os números.

Script útil em Python e gerador de casos de teste: Experimente online!

lirtosiast
fonte