Kombinasi Pinyin

13

Buat fungsi yang mengambil string suku kata pinyin sebagai argumen, dan mengembalikan true dari kombinasi yang ada, salah jika tidak.

Gunakan "v" untuk "ü".

Berikut adalah daftar lengkap kombinasi. http://www.pinyin.info/rules/initials_finals.html

Contohnya

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

Tolong, jangan lakukan hal-hal seperti mengikis halaman web atau membaca file metode input untuk mengurangi jumlah karakter. (Jika Anda melakukannya, panjang data akan dihitung terhadap jumlah karakter). Salah satu tujuan golf kode ini adalah untuk melihat bagaimana aturan dapat disederhanakan. Kode terpendek menang.

Ming-Tang
sumber
Bagaimana dengan sesuatu seperti itu nar? : P
JiminP
1
Sama seperti catatan, terlepas dari apa yang dikatakan contoh, saya tidak percaya nvipernah kombinasi yang valid.
rintaun
Jika halaman tertaut sudah mengatakan »  er telah dihilangkan dari tabel ini« tidakkah seharusnya dimasukkan juga? (Lagi pula, itu nomor, jika saya ingat dengan benar ;-))
Joey

Jawaban:

4

JavaScript 1.6, 503 496 477 karakter

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

Fomatt sedikit lebih mudah dibaca (kecuali ada kesalahan dalam memecah kode menjadi beberapa baris):

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

Kasus nol-inisial ditambah beberapa kali diuji dengan ekspresi reguler. Setelah itu, tabel dikodekan sebagai seri (digabungkan) dari 6 digit, angka dasar-36, satu per suara awal. Pencarian kemudian menggunakan sepasang indexOfpanggilan dan pergeseran untuk memilih bit yang tepat.

Diuji terhadap semua sel dalam tabel kombinasi (sel terisi diuji benar, sel kosong diuji false).

Sunting: Mengganti beberapa dari 36 karakter dari base-36 lookup dengan perbandingan sejak g–, k–, h–, j–, q–, dan z– memiliki blok padat benar / salah.

Sunting: Mengatur ulang uji bit untuk menghindari yang tidak perlu !!dan memadatkan regex lebih lanjut.

DocMax
sumber
Mengapa Anda membutuhkannya !!? Saya tidak yakin saya mengerti mengapa Anda akan membutuhkan ganda bukan ...
Peter Olson
Dengan itu, pengembaliannya adalah 0 atau 1; tanpanya "true" dikembalikan sebagai bukan nol tetapi tidak harus 1. Skrip pengujian saya memvalidasi if (g(s) == (validList.indexOf(s) >= 0)yang mengembalikan false on 16 == true; Saya memperdebatkannya dari sudut pandang "apa yang benar-benar 'benar-benar berarti" dan meninggalkannya. Dalam kedua kasus tersebut, saya memiliki perubahan terencana untuk hari ini yang akan menghapus dengan !!mengganti 1<<r&*parseIntdengan (lebih atau kurang) (parseInt>>r)&1sehingga return adalah 1 dan saya mencukur dua karakter.
DocMax
1

PHP, 548 karakter

Memang, sepertinya tidak optimal, tetapi saya menulis regex agar cocok dengan kombinasi pinyin yang valid. Mengurangi karakter dengan mengganti substring berulang dengan variabel.

Kode

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

Pemakaian

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

F #, 681 karakter

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

Tidak cukup mendapatkan suku kata tanpa konsonan awal yang benar (Y, W dll).

Markus H
sumber
1

APL (Dyalog Extended) , 475 byte

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

Cobalah online!

Golf sedang berlangsung.

Tidak disatukan

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}

Cobalah online!

Fungsi helper smembongkar string yang dibatasi ruang:

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

Saya pertama-tama menyimpan string awal dan terakhir yang mungkin dalam suku kata, kemudian membuat tabel yang tabberisi rangkaian setiap string dari daftar pertama dengan setiap string dari daftar kedua.

Selanjutnya, saya menyimpan data biner sebagai daftar bilangan bulat. Beberapa bilangan bulat diulang dan karena itu dapat disimpan dalam variabel, yang juga memungkinkan penghilangan beberapa ruang.

Setiap integer diterjemahkan ke dalam biner, dan mewakili satu baris tabel. Setiap bit dalam jumlah mewakili apakah suku kata tertentu di baris itu adalah suku kata yang valid, dengan MSB mewakili kolom pertama. Semua suku kata yang tidak valid dihapus dari tabel.

Kami meratakan tabel ke dalam daftar, menambahkan formulir tanpa konsonan awal sebagai kasus khusus, dan akhirnya memeriksa apakah input kami ada dalam daftar.

Kemungkinan potensi bermain golf lebih lanjut:

  • Tulis pengkodean base64 atau base255
  • Susun ulang kolom dan baris untuk membuat angka lebih kecil.

Skrip bermanfaat Python dan generator kasus uji: Coba online!

lirtosiast
sumber