Ordre alphabétique hongrois

19

Pour ceux qui souhaitent beaucoup plus de défis que l' ancien ordre alphabétique espagnol , examinons comment l'ordre alphabétique hongrois est ordonné.

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

en fait, q, w, xet yne sont pas utilisés dans les mots hongrois, mais ils sont inclus pour étrangers et des noms loanwords. Les caractères accentués étrangers qui ne font pas partie de l'alphabet hongrois (comme ñ) ont la même priorité que les caractères non accentués, mais nous les ignorons pour ce défi.

Les règles, résumées:

  • Digraphs ( cs, sz, etc.) et le trigramme ( dzs) sont considérés comme des lettres qu'ils étaient eux - mêmes.
cudar
cukor
cuppant
csalit
csata
  • Si le même digraphe ou trigraphe apparaît deux fois directement l'un après l'autre dans un mot, ils sont écrits de manière simplifiée: sszau lieu de szsz, ddzsau lieu de dzsdzsmais pour l'ordre alphabétique, l'ordre non simplifié est utilisé. Par exemple kasza< kaszinó< kassza, parce que l' kasszaon utilise comme k+ a+ sz+ sz+ apour le bien de la commande. Parfois, vous pouvez trouver la version non contractuelle dans un mot, en cas de mots composés.
kasza
kaszinó
kassza
kaszt
nagy
naggyá
nagygyakorlat
naggyal
nagyít
  • la majuscule n'a pas d'importance, à l'exception où les deux mots seraient exactement les mêmes sans majuscule, auquel cas la lettre minuscule a priorité
jácint
Jácint
Zoltán
zongora
  • Les versions courtes et longues voyelles accentuées ont la même priorité ( a - á, e -é, i - í, o - ó, ö - ő, u - ú ü - ű), avec une seule exception: si les deux mots seraient autrement exactement la même chose, la voyelle courte a la priorité sur la voyelle longue. Notez que les voyelles avec tréma ( öet ü) sont des caractères complètement différents de oet u.
Eger
egér
író
iroda
irónia
kerek
kerék
kérek
szúr
szül
  • Les tirets ou les espaces (par exemple, dans les mots composés, les noms, etc.) sont complètement ignorés
márvány
márványkő
márvány sírkő
Márvány-tenger
márványtömb

La tâche

Votre programme / fonction reçoit des chaînes, composées de caractères de l'alphabet hongrois (majuscules et minuscules), mais une chaîne peut contenir des espaces ou des tirets. Par souci de simplicité, le signe moins (ASCII 45) peut être utilisé comme trait d'union. Notez que certains caractères (comme le ő) ne font pas partie de l'ASCII. Vous pouvez utiliser n'importe quel encodage que vous souhaitez, s'il prend en charge tous les caractères requis.

Vous devez ordonner les lignes correctement et afficher / retourner le résultat.

Vous pouvez utiliser n'importe quel sous-ensemble aléatoire des exemples ci-dessus pour les tests.

ÉDITER:

Veuillez ne pas utiliser de méthode intégrée ou autre qui connaît déjà l'ordre alphabétique hongrois par lui-même. Cela rendrait la compétition inutile et releverait tout le défi de trouver la meilleure expression régulière ou les meilleures astuces de golf de code.

EDIT2:

Pour clarifier une clarification demandée par isaacg: "deux chaînes qui ne diffèrent que par la majuscule et les voyelles longues par rapport aux voyelles courtes, mais qui diffèrent dans les deux sens": Bien qu'aucune règle dans le document officiel ne traite explicitement de cette question, un exemple trouvé à quelques points près de la longueur de la voyelle ayant plus d'importance que la capitalisation.

vsz
la source
@FryAmTheEggman Où voyez-vous cela?
Morgan Thrapp
9
Mec, je ne peux même pas mémoriser notre ordre alphabétique. Comment vais-je programmer cela? ;)
Andras Deak
1
J'ai essayé de trouver un contre-exemple lié à l'échec, où un digraphe apparent est en fait deux lettres, comme malacsültou nyílászáró. Je me demande s'il y en a (mais vous auriez besoin d'un vocabulaire pour vérifier cela, ce qui ne fait probablement pas partie de ce défi)
Andras Deak
1
Il n'y a pas d'exemple contenant dzs
TheConstructor

Réponses:

4

Perl, 250

Comprend +11 pour -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}<>

Utilise l' idiome décorer-trier-décorer (AKA Schwartzian Transform ) et le tri à plusieurs niveaux , où les niveaux sont:

  • L1: comparer les lettres de base, ignorer les signes diacritiques, la casse et certains signes de ponctuation.
  • L2: comparer les lettres de base et les signes diacritiques, ignorer la casse et certains signes de ponctuation.
  • L3: comparer les lettres de base, les signes diacritiques et la casse, ignorer certaines ponctuations.
  • Ln: comparaison au niveau des octets de départage.

En interne, (séparateur de champ ASCII 0x1C - dont la valeur est inférieure à n'importe quel caractère de l'alphabet pour ce défi) est utilisé comme séparateur de niveau.

Cette implémentation a de nombreuses limites, parmi lesquelles:

  • Aucun support pour les caractères étrangers.
  • Impossible de lever l'ambiguïté entre les digraphes / trigraphes géminés (longs) contractés et les consonnes + digraph / trigraph, par exemple: könnyű doit être assemblé comme <k><ö><ny> <ny> <ű> , tandis que tizennyolc doit être assemblé comme <t> < i> <z> <e> <n> <ny> <o> <l> <c> ; házszám 'adresse = numéro de maison (ház) (szám)' doit être regroupé en <h><á><z><sz><á> <m> et non en * <h><á><zs> <z> <á> <m> .
  • Le classement des digraphes longs contractés n'est pas aussi cohérent (mais il est stable): nous désambiguïsons au même niveau ( ssz < n szsz, ..., zszs < n zzs ); glibc rassemble les formulaires courts avant les formulaires complets ( ssz <szsz, ..., zzs <zszs ), ICU rassemble les formulaires longs avant les formulaires courts à partir de L3 Case and Variants ( szsz < 3 ssz, ..., zszs < 3 zzs )

Version étendue:

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

†. Certains algorithmes de classement à plusieurs niveaux bien connus sont l'algorithme de classement Unicode (UCA, Unicode UTS # 10) , ISO 14651 (disponible sur le site ISO ITTF ), les parties LC_COLLATE à ISO TR 30112 (projet disponible à ISO / IEC JTC1 / SC35 / WG5 home ) qui rend obsolète ISO / IEC TR 14652 (disponible à la maison ISO / IEC JTC1 / SC22 / WG20 ) et LC_COLLATE chez POSIX.

‡. Faire cela correctement nécessiterait un dictionnaire. L'ICU traite les groupes étrangement capitalisés comme des non-contractions / non-digraphes / non-trigraphs, par exemple: 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
la source
Vous devriez pouvoir enregistrer quelques octets en utilisant mon extension RegExp.
TheConstructor
6

Java 8, 742 octets

Pourrait réduire de 3 octets supplémentaires en nommant la fonction sau lieu de sortou 16 octets supplémentaires si la définition de classe n'est pas comptée.

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

Peut être utilisé comme ceci:

new H().sort(list);

Suite de tests:

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

céder

[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

Non golfé:

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

J'utilise le Listtype de Java et order()sa fonction, mais le comparateur est tout à moi.

TheConstructor
la source
Impressionnant! J'imagine que vous devriez pouvoir supprimer le spécificateur de type de liste <String>et enregistrer quelques caractères au prix de quelques avertissements?
Josh
@Josh nah, cela produirait deux transtypages comme Java en déduirait Objectalors le type de a et b. Je pourrais probablement m'éloigner de la définition d'une extension de paramètre générique de classe String. De plus, je ne m'attends pas à avoir le code le plus court. ;-)
TheConstructor
3

Python 3, 70

8 octets enregistrés grâce à shooqie.

J'adore Python. :RÉ

Attend une liste de chaînes.

from locale import*;setlocale(0,'hu')
f=lambda x:sorted(x,key=strxfrm)
Morgan Thrapp
la source
3
N'est-ce pas une échappatoire standard?
vsz
1
@vsz Pas autant que je sache. L'utilisation de modules intégrés fait partie de nombreux défis.
Morgan Thrapp
1
@vsz Le taux de vote sur les failles standard est trop faible pour être comptabilisé comme standard, vous devez l'interdire explicitement.
FryAmTheEggman
1
Ok, c'est fait. J'ai envisagé de l'interdire explicitement, mais je pense qu'il devrait être évident que cela ferait de l'ensemble du défi un point discutable. Je suis désolé du dérangement.
vsz
1
from locale import*économise beaucoup d'octets
shooqie