Urutan alfabet Hongaria

19

Bagi mereka yang menginginkan lebih banyak tantangan daripada urutan abjad Spanyol yang lama , mari kita lihat bagaimana alfabet Hungaria dipesan.

a, á, b, c, cs, d, dz, dzs, e, é, f, g, gy, h, i, í, j, k, l, ly, m, n, ny, o, ó, ö, ő, p, q, r, s, sz, t, ty, u, ú, ü, ű, v, w, x, y, z, zs

sebenarnya, q, w, xdan ytidak digunakan dalam kata-kata Hungaria, tetapi mereka termasuk untuk kata-kata pinjaman dan nama asing. Karakter beraksen asing yang bukan bagian dari alfabet Hongaria (seperti ñ), memiliki prioritas yang sama dengan yang tidak beraksen, tetapi kami mengabaikannya untuk tantangan ini.

Aturannya, diringkas:

  • Digraphs ( cs,, szdll.) Dan trigraph ( dzs) dianggap sebagai huruf tersendiri.
cudar
cukor
cuppant
csalit
csata
  • Jika digraf atau trigraph yang sama muncul dua kali secara langsung setelah satu sama lain dalam sebuah kata, mereka ditulis dengan cara yang disederhanakan: sszalih- alih szsz, ddzsalih-alih dzsdzstetapi untuk urutan alfabet, urutan yang tidak disederhanakan digunakan. Misalnya kasza< kaszinó< kassza, karena kasszadigunakan sebagai k+ a+ sz+ sz+ ademi pemesanan. Kadang-kadang Anda dapat menemukan versi yang tidak dikontrak dalam sebuah kata, seandainya ada kata majemuk.
kasza
kaszinó
kassza
kaszt
nagy
naggyá
nagygyakorlat
naggyal
nagyít
  • kapitalisasi tidak masalah, dengan pengecualian ketika dua kata akan persis sama tanpa kapitalisasi, dalam hal huruf kecil memiliki prioritas
jácint
Jácint
Zoltán
zongora
  • Versi pendek dan panjang vokal beraksen memiliki prioritas yang sama ( a - á, e -é, i - í, o - ó, ö - ő, u - ú ü - ű), dengan satu pengecualian: jika dua kata lain akan persis sama, vokal pendek memiliki prioritas di atas vokal panjang. Perhatikan, bahwa vokal dengan umlaut ( ödan ü) adalah karakter yang sepenuhnya berbeda dari odan u.
Eger
egér
író
iroda
irónia
kerek
kerék
kérek
szúr
szül
  • Tanda hubung atau spasi (misalnya, dalam kata majemuk, nama, dll.) Sepenuhnya diabaikan
márvány
márványkő
márvány sírkő
Márvány-tenger
márványtömb

Tugas

Program / fungsi Anda menerima string, terdiri dari karakter dari alfabet Hongaria (huruf kecil dan huruf besar), tetapi string mungkin berisi spasi atau tanda hubung. Demi kesederhanaan, tanda minus (ASCII 45) dapat digunakan sebagai tanda hubung. Perhatikan bahwa beberapa karakter (seperti itu ő) bukan bagian dari ASCII. Anda dapat menggunakan penyandian yang Anda inginkan, jika mendukung semua karakter yang diperlukan.

Anda harus memesan garis dengan benar dan menampilkan / mengembalikan hasilnya.

Anda dapat menggunakan subhimpunan acak dari contoh di atas untuk pengujian.

EDIT:

Tolong jangan gunakan built-in atau cara lain yang sudah tahu urutan abjad Hongaria dengan sendirinya. Itu akan membuat kompetisi tidak ada gunanya, dan mengambil semua tantangan dari menemukan ekspresi reguler terbaik atau trik kode golf terbaik.

EDIT2:

Untuk menghapus klarifikasi yang ditanyakan oleh isaacg: "dua string yang hanya berbeda dengan huruf kapital dan vokal panjang vs pendek, tetapi berbeda dalam kedua cara": Meskipun tidak ada aturan dalam dokumen resmi yang secara eksplisit membahas pertanyaan ini, sebuah contoh ditemukan dalam beberapa poin panjangnya. dari vokal yang lebih penting daripada kapitalisasi.

vsz
sumber
@FryAmTheEggman Di mana Anda melihat itu?
Morgan Thrapp
9
Sobat, aku bahkan tidak bisa mengingat urutan abjad kami yang benar. Bagaimana saya akan memprogram ini? ;)
Andras Deak
1
Saya telah mencoba untuk membuat dengan counterexample terikat-ke-gagal, di mana digraf sebenarnya adalah dua huruf, seperti malacsültatau nyílászáró. Saya ingin tahu apakah ada (tetapi Anda perlu kosakata untuk memeriksanya, yang mungkin bukan bagian dari tantangan ini)
Andras Deak
1
Tidak ada contoh yang mengandung dzs
TheConstructor

Jawaban:

4

Perl, 250

Termasuk +11 untuk -Mutf8 -CS.

use Unicode::Normalize;$r="(?=cs|zs|dz|sz|[glnt]y)";print map/\PC*
/g,sort map{$d=$_;s/d\Kd(zs)|(.)\K$r\2(.)/\L$+\E$&/gi;s/d\Kzs/~$&/gi;s/$r.\K./~$&/gi;s/(\p{Ll}*)(\w?)\s*-*/\U$1\L$2/g;$c=$_;$b=$_=NFD lc;y/̈̋/~~/d;join$;,$_,$b,$c,$d}<>

Menggunakan idiom menghias-sort-undecorate (AKA Schwartzian Transform ), dan sortasi bertingkat , di mana levelnya adalah:

  • L1: bandingkan huruf dasar, abaikan diakritik, kasing, dan beberapa tanda baca.
  • L2: bandingkan huruf dasar dan diakritik, abaikan case dan beberapa tanda baca.
  • L3: bandingkan huruf dasar, diakritik dan kasing, abaikan tanda baca.
  • Ln: perbandingan byte-level tie-breaking.

Secara internal, (ASCII 0x1C Field Separator - yang nilainya kurang dari karakter apa pun dalam alfabet untuk tantangan ini) digunakan sebagai pemisah level.

Implementasi ini memiliki banyak keterbatasan, di antaranya:

  • Tidak ada dukungan untuk karakter asing.
  • Tidak dapat menyatukan dua digraphs / trigraphs yang dikontrak (panjang) yang dikontrak, dan konsonan + digraph / trigraph, misalnya: könnyű harus disusun sebagai <k><ö><ny> <ny> <ű> , sementara tizennyolc harus disusun sebagai <t> < i> <z> <e> <n> <ny> <o> <l> <c> ; házszám 'address = nomor rumah (ház) (szám)' harus disusun sebagai <h><á><z><sz><á> <m> dan bukan sebagai * <h><á><zs> <z> <á> <m> .
  • Susunan untuk digraf panjang yang dikontrak tidak begitu konsisten (tetapi stabil): kami disambiguasi pada tingkat yang sama ( ssz < n szsz, ..., zszs < n zzs ); glibc menyusun formulir pendek sebelum bentuk penuh ( ssz <szsz, ..., zzs <zszs ), ICU menyusun formulir panjang sebelum formulir pendek mulai dari L3 Case dan Varian ( szsz < 3 ssz, ..., zszs < 3 zzs )

Versi yang diperluas:

use Unicode::Normalize;

$r="(?=cs|zs|dz|sz|[glnt]y)";   # look-ahead for digraphs

print map/\PC*\n/g,             # undecorate
  sort                          # sort
  map{                          # decorate

          $d=$_;                # Ln: identical level

          # expand contracted digraphs and trigraphs
          s/d\Kd(zs)|(.)\K$r\2(.)/\L$+\E$&/gi;

          # transform digraphs and trigraphs so they 
          #  sort correctly
          s/d\Kzs/~$&/gi;s/$r.\K./~$&/gi;

          # swap case, so lower sorts before upper
          # also, get rid of space, hyphen, and newline
          s/(\p{Ll}*)(\w?)\s*-*/\U$1\L$2/g;

          $c=$_;                # L3: Case

          $b=$_=NFD lc;         # L2: Diacritics

          # transform öő|üű so they sort correctly
          # ignore diacritics (acute) at this level
          y/\x{308}\x{30b}\x{301}/~~/d;

                                # L1: Base characters
          join$;,$_,$b,$c,$d
  }<>

†. Beberapa algoritma collation multi-level yang terkenal adalah Unicode Collation Algorithm (UCA, Unicode UTS # 10) , ISO 14651 (tersedia di situs ISO ITTF ) bagian LC_COLLATE di ISO TR 30112 (draft tersedia di ISO / IEC JTC1 / Rumah SC35 / WG5 ) yang usang ISO / IEC TR 14652 (tersedia di rumah ISO / IEC JTC1 / SC22 / WG20 ) dan LC_COLLATE di POSIX.

‡. Melakukan ini dengan benar akan membutuhkan kamus. ICU memperlakukan kelompok bermodal aneh sebagai non-kontraksi / non-digraf / non-trigraph, misalnya: ccS < 3 CcS < 3 c Cs < 3 c CS < 3 C CS < 3 cS < 3 cs < 3 Cs < 3 CS < 3 ccs < 3 Ccs < 3 CCS

ninjalj
sumber
Anda harus dapat menyimpan beberapa byte menggunakan RegExp ekspansi saya.
TheConstructor
6

Java 8, 742 byte

Bisa mengurangi 3 byte lain penamaan fungsi, sbukan sortatau 16 byte lain jika tidak menghitung definisi kelas.

public class H{String d="cs|dzs?|gy|ly|sz|ty|zs";void sort(java.util.List<String>l){l.sort((a,b)->{String o="-a-á-b-cs-dzs-e-é-f-gy-h-i-í-j-k-ly-m-ny-o-ó-ö-ő-p-q-r-sz-ty-u-ú-ü-ű-v-w-x-y-zs-";int i=c(r(a),r(b),r(o));return i!=0?i:(i=c(a,b,o))!=0?i:b.charAt(0)-a.charAt(0);});}String r(String a){for(int i=0;i<8;i++)a=a.toLowerCase().replace("ááéíóőúű".charAt(i),"aaeioöuü".charAt(i));return a;}int c(String a,String b,String o){a=n(a);b=n(b);while(!"".equals(a+b)){int i=p(a,o),j=p(b,o);if(i!=j)return i-j;a=a.substring(i%4);b=b.substring(j%4);}return 0;}int p(String a,String o){a=(a+1).replaceAll("("+d+"|.).*","-$1");return o.indexOf(a)*4+a.length()-1;}String n(String a){return a.toLowerCase().replaceAll("(.)(?=\\1)("+d+")| |-","$2$2");}}

Dapat digunakan seperti ini:

new H().sort(list);

Test-suite:

public static void main(String[] args) {
    test(Arrays.asList("cudar", "cukor", "cuppant", "csalit", "csata"));
    test(Arrays.asList("kasza", "kaszinó", "kassza", "kaszt", "nagy", "naggyá", "nagygyakorlat", "naggyal",
            "nagyít"));
    test(Arrays.asList("jácint", "Jácint", "Zoltán", "zongora"));
    test(Arrays.asList("Eger", "egér", "író", "iroda", "irónia", "kerek", "kerék", "kérek", "szúr", "szül"));
    test(Arrays.asList("márvány", "márványkő", "márvány sírkő", "Márvány-tenger", "márványtömb"));
}

private static void test(final List<String> input) {
    final ArrayList<String> random = randomize(input);
    System.out.print(input + " -> " + random);
    new H().sort(random);
    System.out.println(" -> " + random + " -> " + input.equals(random));
}

private static ArrayList<String> randomize(final List<String> input) {
    final ArrayList<String> temp = new ArrayList<>(input);
    final ArrayList<String> randomOrder = new ArrayList<>(input.size());
    final Random r = new Random();
    for (int i = 0; i < input.size(); i++) {
        randomOrder.add(temp.remove(r.nextInt(temp.size())));
    }
    return randomOrder;
}

menghasilkan

[cudar, cukor, cuppant, csalit, csata] -> [csata, cudar, cuppant, csalit, cukor] -> [cudar, cukor, cuppant, csalit, csata] -> true
[kasza, kaszinó, kassza, kaszt, nagy, naggyá, nagygyakorlat, naggyal, nagyít] -> [naggyá, kassza, kaszinó, nagygyakorlat, nagyít, nagy, kaszt, kasza, naggyal] -> [kasza, kaszinó, kassza, kaszt, nagy, naggyá, nagygyakorlat, naggyal, nagyít] -> true
[jácint, Jácint, Zoltán, zongora] -> [Zoltán, jácint, zongora, Jácint] -> [jácint, Jácint, Zoltán, zongora] -> true
[Eger, egér, író, iroda, irónia, kerek, kerék, kérek, szúr, szül] -> [egér, Eger, kerék, iroda, író, kerek, kérek, szúr, irónia, szül] -> [Eger, egér, író, iroda, irónia, kerek, kerék, kérek, szúr, szül] -> true
[márvány, márványkő, márvány sírkő, Márvány-tenger, márványtömb] -> [márványtömb, márványkő, Márvány-tenger, márvány sírkő, márvány] -> [márvány, márványkő, márvány sírkő, Márvány-tenger, márványtömb] -> true

Tidak Disatukan:

public class HungarianOrder {

    String d = "cs|dzs?|gy|ly|sz|ty|zs";

    void sort(java.util.List<String> l) {
        l.sort((a, b) -> {
            String o = "-a-á-b-cs-dzs-e-é-f-gy-h-i-í-j-k-ly-m-ny-o-ó-ö-ő-p-q-r-sz-ty-u-ú-ü-ű-v-w-x-y-zs-";
            int i = c(r(a), r(b), r(o));
            return i != 0 ? i
                    : (i = c(a, b, o)) != 0 ? i
                            : b.charAt(0) - a.charAt(0);
        });
    }

    // toLower + remove long accent
    String r(String a) {
        for (int i = 0; i < 8; i++)
            a = a.toLowerCase().replace("ááéíóőúű".charAt(i), "aaeioöuü".charAt(i));
        return a;
    }

    // iterate over a and b comparing positions of chars in o
    int c(String a, String b, String o) {
        a = n(a);
        b = n(b);
        while (!"".equals(a + b)) {
            int i = p(a, o), j = p(b, o);
            if (i != j)
                return i - j;
            a = a.substring(i % 4);
            b = b.substring(j % 4);
        }
        return 0;
    }

    // find index in o, then looking if following characters match
    // return is index * 4 + length of match; if String is empty or first character is unknown -1 is returned
    int p(String a, String o) {
        a = (a+1).replaceAll("("+d+"|.).*", "-$1");
        return o.indexOf(a) * 4 + a.length() - 1;
    }

    // expand ddz -> dzdz and such
    String n(String a) {
        return a.toLowerCase().replaceAll("(.)(?=\\1)("+ d +")| |-", "$2$2");
    }
}

Saya menggunakan Listtipe -Java dan order()-fungsi itu, tetapi komparator semua milik saya.

Korektor
sumber
Impresif! Saya membayangkan Anda harus dapat menjatuhkan specifier tipe daftar <String>dan menyimpan beberapa karakter dengan mengorbankan beberapa peringatan?
Josh
@ Astaga, itu akan menghasilkan dua gips karena Java akan menyimpulkan Objectsebagai tipe a dan b kalau begitu. Saya mungkin bisa pergi mendefinisikan ekstensi kelas-generik String, meskipun. Saya juga tidak berharap memiliki kode terpendek. ;-)
TheConstructor
3

Python 3, 70

Disimpan 8 byte berkat shooqie.

Saya suka Python. : D

Mengharapkan daftar string.

from locale import*;setlocale(0,'hu')
f=lambda x:sorted(x,key=strxfrm)
Morgan Thrapp
sumber
3
Bukankah ini celah standar?
vsz
1
@ vsz Tidak sejauh yang saya tahu. Menggunakan bawaan adalah bagian dari banyak tantangan.
Morgan Thrapp
1
@vsz Ini memiliki rasio suara naik ke bawah yang terlalu rendah pada pos standar untuk dihitung sebagai standar, Anda harus melarangnya secara eksplisit.
FryAmTheEggman
1
Ok, lakukan itu. Saya mempertimbangkan untuk melarangnya secara eksplisit tetapi saya pikir itu harus jelas bahwa itu akan membuat seluruh tantangan menjadi poin yang diperdebatkan. Saya minta maaf atas ketidaknyamanannya.
vsz
1
from locale import*menghemat banyak byte
shooqie