Węgierski porządek alfabetyczny

19

Dla tych, którzy chcą o wiele więcej wyzwań niż stara hiszpańska kolejność alfabetyczna , rzućmy okiem na kolejność alfabetu węgierskiego.

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

Właściwie q, w, xi ynie są wykorzystywane w węgierskich słów, ale są one włączone do zapożyczeń i nazw obcych. Obce znaki akcentowane, które nie są częścią alfabetu węgierskiego (podobnego ñ), mają taki sam priorytet jak znaki nieakcentowane, ale pomijamy je w tym wyzwaniu.

Zasady podsumowane:

  • Digraphy ( cs, szitp.) I trigraf ( dzs) są uważane za same w sobie litery.
cudar
cukor
cuppant
csalit
csata
  • Jeśli ten sam digraf lub kaligraf występuje dwa razy bezpośrednio po sobie w słowie, są one zapisywane w sposób uproszczony: sszzamiast szsz, ddzszamiast w dzsdzskolejności alfabetycznej stosuje się kolejność nie uproszczoną. Na przykład kasza< kaszinó< kassza, ponieważ kasszasłuży jako k+ a+ sz+ sz+ adla dobra zamawiania. Czasami można znaleźć wersję bez umowy w jednym słowie, w przypadku słów złożonych.
kasza
kaszinó
kassza
kaszt
nagy
naggyá
nagygyakorlat
naggyal
nagyít
  • wielkie litery nie mają znaczenia, z wyjątkiem tego, że dwa słowa byłyby dokładnie takie same bez wielkich liter, w którym to przypadku mała litera ma priorytet
jácint
Jácint
Zoltán
zongora
  • Krótkie i długie wersje akcentowanych samogłosek mają ten sam priorytet ( a - á, e -é, i - í, o - ó, ö - ő, u - ú ü - ű), z jednym wyjątkiem: jeśli te dwa słowa w przeciwnym razie być dokładnie taka sama, krótka samogłoska ma pierwszeństwo przed długą samogłoską. Zauważ, że samogłoski z umlaut ( öi ü) są całkowicie różnymi znakami od oi u.
Eger
egér
író
iroda
irónia
kerek
kerék
kérek
szúr
szül
  • Łączniki lub spacje (na przykład złożone słowa, nazwy itp.) Są całkowicie ignorowane
márvány
márványkő
márvány sírkő
Márvány-tenger
márványtömb

Zadanie

Twój program / funkcja odbiera ciągi złożone ze znaków z węgierskiego alfabetu (zarówno małe, jak i wielkie litery), ale ciąg może zawierać spacje lub łączniki. Dla uproszczenia znak minus (ASCII 45) może być używany jako łącznik. Zauważ, że niektóre znaki (takie jak ő) nie są częścią ASCII. Możesz użyć dowolnego kodowania, jeśli obsługuje ono wszystkie wymagane znaki.

Musisz poprawnie zamówić wiersze i wyświetlić / zwrócić wynik.

Do testowania możesz użyć dowolnego losowo uporządkowanego podzestawu powyższych przykładów.

EDYTOWAĆ:

Proszę nie używać żadnego wbudowanego lub innego sposobu, który już zna węgierską kolejność alfabetyczną. Sprawiłoby to, że zawody stałyby się bezcelowe, i podjęłyby wszelkie wyzwanie ze znalezienia najlepszego wyrażenia regularnego lub najlepszych sztuczek golfowych.

EDYCJA 2:

Aby wyjaśnić wyjaśnienie zadane przez isaacga: „dwa ciągi, które różnią się jedynie wielkimi literami i długimi a krótkimi samogłoskami, ale różnią się w obu kierunkach”: Chociaż żadna reguła w oficjalnym dokumencie nie odnosi się wyraźnie do tego pytania, przykład znajduje się w obrębie długości samogłoska ma większe znaczenie niż wielkie litery.

vsz
źródło
@FryAmTheEggman Gdzie to widzisz?
Morgan Thrapp,
9
Człowieku, nie mogę nawet zapamiętać naszej właściwej kolejności alfabetycznej. Jak mam to zaprogramować? ;)
Andras Deak,
1
Próbowałem wymyślić przeciwprzykładowy przykład, w którym pozornym wykresem są tak naprawdę dwie litery, takie jak malacsültlub nyílászáró. Zastanawiam się, czy są jakieś (ale potrzebujesz słownictwa, aby to sprawdzić, co prawdopodobnie nie jest częścią tego wyzwania)
Andras Deak
1
Nie ma żadnego przykładu zawierającego dzs
TheConstructor 11.11.16

Odpowiedzi:

4

Perl, 250

Obejmuje +11 za -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}<>

Używa idiomu dekorowanie-sortowanie-i dekorowanie (AKA Schwartzian Transform ) oraz sortowanie wielopoziomowe , gdzie poziomy są następujące:

  • L1: porównuj podstawowe litery, ignoruj ​​znaki diakrytyczne, wielkość liter i niektóre znaki interpunkcyjne.
  • L2: porównaj podstawowe litery i znaki diakrytyczne, zignoruj ​​wielkość liter i niektóre znaki interpunkcyjne.
  • L3: porównaj podstawowe litery, znaki diakrytyczne i wielkość liter, zignoruj ​​niektóre znaki interpunkcyjne.
  • Ln: rozstrzygające porównanie bajtów na poziomie.

Wewnętrznie (separator pól ASCII 0x1C - którego wartość jest mniejsza niż dowolny znak w alfabecie dla tego wyzwania) jest używany jako separator poziomu.

Ta implementacja ma wiele ograniczeń, między innymi:

  • Brak obsługi obcych znaków.
  • Może nie disambiguate między umownej geminated (długi) digrafach / trójznaków i spółgłoski + digraph / trigraph, np könnyű należy zestawiać jako <k> <o> <ny> <ny> <u> , natomiast tizennyolc należy zestawiać jako <t> < i> <z> <e> <n> <ny> <o> <l> <c> ; házszám „adres = numer domu (ház) (szám)” powinien być zestawiony jako <h><á><z><sz><á> <m>, a nie jako * <h><á><zs> <z> <á> <m> .
  • Układanie w przypadku zakontraktowanych długich digrafów nie jest tak spójne (ale jest stabilne): ujednoznaczniamy na tym samym poziomie ( ssz < n szsz, ..., zszs < n zzs ); glibc zestawia krótkie formularze przed pełnymi formularzami ( ssz <szsz, ..., zzs <zszs ), ICU zestawia długie formularze przed krótkimi formularzami, zaczynając od L3 Case and Variants ( szsz < 3 ssz , ..., zszs < 3 zzs )

Wersja rozszerzona:

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

†. Niektóre dobrze znane wielopoziomowe algorytmy zestawiania to Algorytm sortowania Unicode (UCA, Unicode UTS # 10) , ISO 14651 (dostępny w witrynie ISO ITTF ) części LC_COLLATE w ISO TR 30112 (szkic dostępny w ISO / IEC JTC1 / SC35 / WG5 home ), która unieważnia ISO / IEC TR 14652 (dostępny w domu ISO / IEC JTC1 / SC22 / WG20 home ) i LC_COLLATE w POSIX.

‡. Wykonanie tego poprawnie wymagałoby słownika. OIOM traktuje dziwnie skapitalizowane grupy jako niekontrakty / non-digraphs / non-trigrafs, np .: 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
źródło
Powinieneś być w stanie zapisać niektóre bajty za pomocą mojego rozszerzenia RegExp.
TheConstructor
6

Java 8, 742 bajtów

Można zmniejszyć o kolejne 3 bajty nazywając funkcję szamiast sortlub o kolejne 16 bajtów, jeśli nie licząc definicji klasy.

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

Można użyć w następujący sposób:

new H().sort(list);

Zestaw testowy:

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

wydajność

[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

Nie golfowany:

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

Korzystam z Listtypu Java i jego order()funkcji, ale cały komparator jest mój.

TheConstructor
źródło
Imponujący! Wyobrażam sobie, że powinieneś być w stanie upuścić specyfikator typu listy <String>i zapisać kilka znaków kosztem kilku ostrzeżeń?
Josh
@Josh nie, produkowałby dwa odlewy, tak jak Java wnioskuje Objectjako typ a i b. Prawdopodobnie mógłbym jednak uciec od zdefiniowania rozszerzenia parametru generic-parametric String. Nie oczekuję też, że będę mieć najkrótszy kod. ;-)
TheConstructor
3

Python 3, 70

Zaoszczędź 8 bajtów dzięki shooqie.

Uwielbiam Python. :RE

Oczekuje listy ciągów.

from locale import*;setlocale(0,'hu')
f=lambda x:sorted(x,key=strxfrm)
Morgan Thrapp
źródło
3
Czy to nie jest standardowa luka?
vsz
1
@vsz Nie, o ile wiem. Korzystanie z wbudowanych elementów jest częścią wielu wyzwań.
Morgan Thrapp,
1
@vsz Ma zbyt niski współczynnik up-to-down głosowania w standardowych postach z lukami, aby można go było uznać za standard, musisz go wyraźnie zakazać.
FryAmTheEggman
1
Ok, zrób to. Zastanawiałem się nad wyraźnym zakazem, ale uważam, że powinno być oczywiste, że sprawi, że całe wyzwanie stanie się spornym punktem. Przepraszam za utrudnienia.
vsz
1
from locale import*oszczędza dużo bajtów
shooqie