Combinaciones de pinyin

13

Cree una función que tome una cadena de una sílaba pinyin como argumento, y devuelva verdadero de la combinación existente, falso de lo contrario.

Use "v" para "ü".

Aquí hay una lista completa de combinaciones. http://www.pinyin.info/rules/initials_finals.html

Ejemplos

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, no haga cosas como raspar páginas web o leer archivos de métodos de entrada para reducir el recuento de caracteres. (Si lo hace, la longitud de los datos se contará para el recuento de caracteres). Uno de los propósitos de este código de golf es ver cómo se pueden simplificar las reglas. El código más corto gana.

Ming-Tang
fuente
¿Qué tal algo así nar? : P
JiminP
1
Solo como una nota, a pesar de lo que dicen los ejemplos, no creo que nvisea ​​una combinación válida.
Rintaun
Si la página vinculada ya dice »  er ha sido omitido de esta tabla« ¿no debería incluirse también? (Después de todo, era un número, si no recuerdo mal ;-))
Joey

Respuestas:

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 un poco más legible (salvo cualquier error al dividir el código en unas pocas líneas):

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

Los casos iniciales cero más algunos únicos se prueban con una expresión regular. Después de eso, la tabla se codifica como una serie (concatenada) de 6 dígitos, números base 36, uno por sonido inicial. La búsqueda luego utiliza un par de indexOfllamadas y un cambio para seleccionar el bit correcto.

Probado contra todas las celdas en la tabla de combinaciones (celdas llenas probadas para verdaderas, celdas vacías probadas para falsas).

Editar: Reemplazó algunos de los 36 caracteres de la búsqueda de base 36 con comparaciones ya que g–, k–, h–, j–, q– y z– tienen bloques densos de verdadero / falso.

Editar: reorganizó la prueba de bits para evitar una innecesaria !!y compactó más la expresión regular.

DocMax
fuente
¿Por qué necesitas un !!? No estoy seguro de entender por qué necesitarías un doble no ...
Peter Olson
Con él, el retorno es 0 o 1; sin él, "verdadero" se devuelve como distinto de cero, pero no necesariamente 1. Mi script de prueba se valida con el if (g(s) == (validList.indexOf(s) >= 0)cual devuelve falso en 16 == true; Lo debatí desde una perspectiva de "lo que realmente significa 'verdadero'" y dejé la cosa adentro. En cualquier caso, tengo un cambio planeado para hoy más tarde que eliminará el !!reemplazo 1<<r&*parseIntcon (más o menos) (parseInt>>r)&1para que el return es 1 y me afeito dos caracteres.
DocMax
1

PHP, 548 caracteres

De acuerdo, es probable que no sea óptimo, pero escribí una expresión regular para que coincida con combinaciones válidas de pinyin. Caracteres reducidos mediante la sustitución de subcadenas repetidas con variables.

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
fuente
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

No obtiene las sílabas sin la consonante inicial correcta (Y, W, etc.).

Mark H
fuente
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'}

Pruébalo en línea!

Golf en progreso.

Sin golf

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}

Pruébalo en línea!

La función auxiliar sdesempaqueta una cadena delimitada por espacios:

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

Primero almaceno las posibles cadenas iniciales y finales en la sílaba, luego hago una tabla que tabcontiene la concatenación de cada cadena de la primera lista con cada cadena de la segunda lista.

A continuación, almaceno datos binarios como una lista de enteros. Algunos de los enteros se repiten y, por lo tanto, se pueden almacenar en variables, lo que también permite la elisión de algunos espacios.

Cada número entero se decodifica en binario y representa una fila de la tabla. Cada bit en el número representa si cierta sílaba en esa fila es una sílaba válida, con el MSB representando la primera columna. Todas las sílabas no válidas se eliminan de la tabla.

Aplanamos la tabla en una lista, agregamos las formas sin consonante inicial como un caso especial y finalmente verificamos si nuestra entrada está en la lista.

Posible potencial de golf adicional:

  • Escribir codificación base64 o base255
  • Reordenar las columnas y filas para hacer los números más pequeños.

Script útil de Python y generador de casos de prueba: ¡ Pruébelo en línea!

lirtosiast
fuente