Ungarische alphabetische Reihenfolge

19

Für diejenigen, die eine viel größere Herausforderung als die alte spanische alphabetische Reihenfolge wünschen , werfen wir einen Blick auf die Reihenfolge des ungarischen Alphabets.

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

tatsächlich, q, w, xund ysind nicht in der ungarischen Worte verwendet, aber sie sind für Lehnwörter und ausländische Namen enthalten. Ausländische Zeichen mit Akzent, die nicht Teil des ungarischen Alphabets sind (wie ñ), haben die gleiche Priorität wie die nicht akzentuierten, aber wir ignorieren sie für diese Herausforderung.

Die Regeln, zusammengefasst:

  • Digraphen ( cs, szusw.) und Trigraphen ( dzs) werden als eigenständige Buchstaben betrachtet.
cudar
cukor
cuppant
csalit
csata
  • Wenn die gleiche digraph oder trigraph hintereinander in einem Wort zweimal direkt auftritt, werden sie in einer vereinfachten Art und Weise geschrieben: sszstatt szsz, ddzsstatt dzsdzsaber für die alphabetische Reihenfolge wird die nicht vereinfachte verwendet. Zum Beispiel kasza< kaszinó< kassza, da kasszawird verwendet als k+ a+ sz+ sz+ azum Zweck der Bestellung. Manchmal finden Sie die nicht vertraglich vereinbarte Version in einem Wort, wenn es sich um zusammengesetzte Wörter handelt.
kasza
kaszinó
kassza
kaszt
nagy
naggyá
nagygyakorlat
naggyal
nagyít
  • Die Groß- und Kleinschreibung spielt keine Rolle, mit der Ausnahme, dass die beiden Wörter ohne die Groß- und Kleinschreibung genau gleich wären. In diesem Fall hat der Kleinbuchstabe Vorrang
jácint
Jácint
Zoltán
zongora
  • Die kurzen und langen Versionen von akzentuierten Vokale haben die gleiche Priorität ( a - á, e -é, i - í, o - ó, ö - ő, u - ú ü - ű), mit einer einzigen Ausnahme: Wenn die beiden Wörter sonst genau das gleiche sein würde, hat der kurze Vokal Vorrang vor dem langen Vokal. Beachten Sie, dass die Vokale mit Umlaut ( öund ü) völlig andere Zeichen als ound sind u.
Eger
egér
író
iroda
irónia
kerek
kerék
kérek
szúr
szül
  • Bindestriche oder Leerzeichen (z. B. in zusammengesetzten Wörtern, Namen usw.) werden vollständig ignoriert
márvány
márványkő
márvány sírkő
Márvány-tenger
márványtömb

Die Aufgabe

Ihr Programm / Ihre Funktion empfängt Zeichenfolgen, die aus Zeichen des ungarischen Alphabets bestehen (sowohl in Klein- als auch in Großbuchstaben). Eine Zeichenfolge kann jedoch Leerzeichen oder Bindestriche enthalten. Das Minuszeichen (ASCII 45) kann der Einfachheit halber als Bindestrich verwendet werden. Beachten Sie, dass einige Zeichen (wie das ő) nicht Teil von ASCII sind. Sie können eine beliebige Codierung verwenden, wenn alle erforderlichen Zeichen unterstützt werden.

Sie müssen die Zeilen richtig bestellen und das Ergebnis anzeigen / zurückgeben.

Sie können jede zufällig angeordnete Teilmenge der obigen Beispiele zum Testen verwenden.

BEARBEITEN:

Bitte verwenden Sie keine eingebaute oder andere Methode, die die ungarische alphabetische Reihenfolge bereits kennt. Dies würde den Wettbewerb unnötig machen und die Herausforderung darin bestehen, den besten regulären Ausdruck oder die besten Code-Golf-Tricks zu finden.

EDIT2:

Um eine Klärung klar gestellt von isaacg: „zwei Strings , die nur durch Aktivierung abweichen und lange gegen kurze Vokale, unterscheidet sich aber in beide Richtungen“: Obwohl keine Regel in dem amtlichen Dokument ausdrücklich diese Frage befasst, ein Beispiel innerhalb Punkte der Länge gefunden des Vokals hat mehr Bedeutung als die Großschreibung.

vsz
quelle
@FryAmTheEggman Wo siehst du das?
Morgan Thrapp
9
Mann, ich kann mir nicht einmal unsere richtige alphabetische Reihenfolge merken. Wie programmiere ich das? ;)
Andras Deak
1
Ich habe versucht, ein unwiderrufliches Gegenbeispiel zu finden, bei dem ein scheinbarer Digraph eigentlich aus zwei Buchstaben wie malacsültoder besteht nyílászáró. Ich frage mich, ob es welche gibt (aber du brauchst ein Vokabular, um das zu überprüfen, was vermutlich nicht Teil dieser Herausforderung ist)
Andras Deak
1
Es gibt kein Beispiel mit dzs
TheConstructor

Antworten:

4

Perl, 250

Beinhaltet +11 für -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}<>

Verwendet das Dekorieren-Sortieren-Undekorieren- Idiom (AKA Schwartzian Transform ) und die mehrstufige Sortierung , wobei die Ebenen wie folgt lauten:

  • L1: Vergleichen Sie die Grundbuchstaben, ignorieren Sie diakritische Zeichen, Groß- und Kleinschreibung und einige Satzzeichen.
  • L2: Vergleichen Sie die Grundbuchstaben und diakritischen Zeichen, ignorieren Sie die Groß- und Kleinschreibung und setzen Sie Satzzeichen.
  • L3: Grundbuchstaben, diakritische Zeichen und Groß- / Kleinschreibung vergleichen, Satzzeichen ignorieren.
  • Ln: Unentschiedener Vergleich auf Byte-Ebene.

Intern wird als Ebenentrennzeichen (ASCII 0x1C-Feldtrennzeichen - dessen Wert kleiner als ein beliebiges Zeichen im Alphabet für diese Abfrage ist) verwendet.

Diese Implementierung hat viele Einschränkungen, darunter:

  • Keine Unterstützung für fremde Zeichen.
  • Kann nicht Disambiguieren zwischen kontrahierten geminated (long) Digraphe / trigraphs und Konsonant + digraph / trigraph, zB: könnyű sollte als collate <k> <o> <ny> <ny> <u> , während tizennyolc als collate sollte <t> < i> <z> <e> <n> <ny> <o> <l> <c> ; házszám 'address = house (ház) number (szám)' sollte als <h> <á> <z> <sz> <á> <m> und nicht als * <h> <á> <zs> <z> sortiert werden <a> <m> .
  • Die Kollation für kontrahierte lange Digraphen ist nicht so konsistent (aber stabil): Wir disambigieren auf der gleichen Ebene ( ssz < n szsz, ..., zszs < n zzs ); glibc sortiert die Kurzformen vor den Vollformen ( ssz <szsz, ..., zzs <zszs ), ICU sortiert die Langformen vor den Kurzformen ab L3 Case und Variants ( szsz < 3 ssz, ..., zszs < 3 zzs )

Erweiterte Version:

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

†. Einige bekannte mehrstufige Kollatierungsalgorithmen sind der Unicode-Kollatierungsalgorithmus (UCA, Unicode UTS # 10) , ISO 14651 (erhältlich auf der ISO ITTF-Website ) und die LC_COLLATE-Teile bei ISO TR 30112 (Entwurf erhältlich bei ISO / IEC JTC1 / SC35 / WG5 home ), das ISO / IEC TR 14652 (verfügbar bei ISO / IEC JTC1 / SC22 / WG20 home ) und LC_COLLATE bei POSIX ersetzt.

‡. Für eine korrekte Ausführung ist ein Wörterbuch erforderlich. ICU behandelt weirdly aktivierten Gruppen als nicht-Kontraktionen / non-Digraphen / non-trigraphs, zB: 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
quelle
Sie sollten in der Lage sein, einige Bytes mit meiner Erweiterung RegExp zu speichern.
TheConstructor
6

Java 8, 742 Bytes

Könnte die Benennung der Funktion sstattdessen um weitere 3 Bytes reduzieren sortoder um weitere 16 Bytes, wenn Klassendefinition nicht gezählt wird.

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

Kann so verwendet werden:

new H().sort(list);

Testsuite:

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

nachgebend

[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

Ungolfed:

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

Ich benutze Javas List-Typ und die Funktion order()davon, aber der Komparator gehört mir.

DerKonstruktor
quelle
Beeindruckend! Ich stelle mir vor, Sie sollten den Listentyp-Bezeichner löschen <String>und ein paar Zeichen auf Kosten einiger Warnungen speichern können.
Josh
@Josh nah, es würde zwei Casts erzeugen, da Java dann Objectals Typ von a und b schließen würde . Ich könnte wahrscheinlich davonkommen, einen klassengenerischen Parameter zu definieren, der erweitert Stringwird. Auch erwarte ich nicht, den kürzesten Code zu haben. ;-)
TheConstructor
3

Python 3, 70

8 Bytes gespart dank shooqie.

Ich liebe Python. : D

Erwartet eine Liste von Zeichenfolgen.

from locale import*;setlocale(0,'hu')
f=lambda x:sorted(x,key=strxfrm)
Morgan Thrapp
quelle
3
Ist das nicht eine Standardlücke?
vsz
1
@vsz Soweit ich weiß nicht. Die Verwendung von integrierten Funktionen ist Teil vieler Herausforderungen.
Morgan Thrapp
1
@vsz Es gibt zu wenig Up-Down-Voting für den Standard-Lücken-Post, um als Standard gezählt zu werden. Sie müssten ihn explizit verbieten.
FryAmTheEggman
1
Ok, fertig. Ich dachte darüber nach, es explizit zu verbieten, aber ich denke, es sollte offensichtlich sein, dass es die ganze Herausforderung zu einem strittigen Punkt machen würde. Ich entschuldige mich für die Unannehmlichkeiten.
vsz
1
from locale import*spart eine Menge Bytes
Shooqie