Угорський алфавітний порядок


19

Для тих, хто бажає набагато більше викликів, ніж старий іспанський алфавітний порядок , давайте подивимось, як упорядкований угорський алфавіт.

a, á, b, c, cs, d, dz, dss, 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

на самому ділі, q, w, xі yне використовуються в угорських слів, але вони включені в запозичених і іноземних імен. Іноземні наголошені символи, які не входять до угорського алфавіту (подібні ñ), мають той же пріоритет, що й символи, які не мають акценту, але ми нехтуємо ними для цього завдання.

Правила, узагальнені:

  • Диграфи ( cs, szі т. Д.) Та триграф ( dzs) вважаються такими, якими вони були самі букви.
cudar
cukor
cuppant
csalit
csata
  • Якщо один і той же диграф або триграф відбувається двічі безпосередньо один за одним словом, вони записуються спрощеним способом: sszзамість szsz, ddzsа не dzsdzsза алфавітним порядком, використовується не спрощений порядок. Наприклад kasza< kaszinó< kassza, так як kasszaвикористовується як k+ a+ sz+ sz+ aзадля впорядкування. Іноді можна зустріти позаконтрактну версію словом, у випадку складних слів.
kasza
kaszinó
kassza
kaszt
nagy
naggyá
nagygyakorlat
naggyal
nagyít
  • написання великої літери не має значення, за винятком випадків, коли два слова були б абсолютно однакові без написання великих літер, і в цьому випадку нижня літера має пріоритет
jácint
Jácint
Zoltán
zongora
  • Короткі і довгі версії акцентованих голосними мають однаковий пріоритет ( a - á, e -é, i - í, o - ó, ö - ő, u - ú ü - ű), з одним винятком: якщо два слова , інакше було б точно так же, короткий голосний має пріоритет над довгими голосними. Зауважте, що голосні звуки з umlaut ( öі ü) є абсолютно різними символами від oта u.
Eger
egér
író
iroda
irónia
kerek
kerék
kérek
szúr
szül
  • Дефіси або пробіли (наприклад, у складених словах, іменах тощо) повністю ігноруються
márvány
márványkő
márvány sírkő
Márvány-tenger
márványtömb

Завдання

Ваша програма / функція отримує рядки, складені з символів угорського алфавіту (як малі, так і великі регістри), але рядок може містити пробіли чи дефіси. Для простоти знак мінус (ASCII 45) може бути використаний як дефіс. Зауважте, що деякі символи (як-от ő) не є частиною ASCII. Ви можете використовувати будь-яке бажане кодування, якщо воно підтримує всі необхідні символи.

Ви повинні правильно впорядкувати лінії та відобразити / повернути результат.

Для тестування можна використовувати будь-яку випадкову впорядковану підмножину з наведених вище прикладів.

Редагувати:

Будь ласка, не використовуйте будь-який вбудований чи інший спосіб, який уже знає угорський алфавітний порядок. Це зробило б змагання безглуздим і взяло б на себе все завдання, щоб знайти найкращий регулярний вираз чи найкращий трюк з гольф-кодом.

EDIT2:

Щоб очистити уточнення, яке запитує isaacg: "два рядки, які відрізняються лише за великої літери та довгих порівняно з короткими голосними, але різняться обома способами": Хоча жодне правило в офіційному документі прямо не вирішує це запитання, приклад, знайдений у межах точок до довжини голосного, що має більше значення, ніж велика література.


@FryAmTheEggman Де ви це бачите?
Морган Трапп

9
Людина, я навіть не можу запам'ятати наш належний алфавітний порядок. Як я буду це програмувати? ;)
Андрас Дік

1
Я намагався створити примірник невдалого контрприкладу, де очевидним диграфом є ​​насправді дві літери, наприклад, malacsültабо nyílászáró. Цікаво, чи є такі (але для цього вам потрібен словник, який, мабуть, не є частиною цього виклику)
Andras Deak

1
Немає прикладу, що містить dzs
TheConstructor

Відповіді:


4

Perl, 250

Включає +11 для -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}<>

Використовується ідіома прикрасити-сортувати-нерозбірливо (AKA Schwartzian Transform ) та багаторівневе сортування , де рівні:

  • L1: порівняйте основні літери, ігноруйте діакритику, регістр та деякі розділові знаки.
  • L2: порівняйте основні літери та діакритику, ігноруйте регістр та деякі пунктуації.
  • L3: порівнюйте основні літери, діакритику та регістр, ігноруйте деякі розділові знаки.
  • Ln: порівняння рівня байтового рівня, що розбиває краватку

Внутрішньо (ASCII 0x1C Field Separator - значення якого менше, ніж будь-який символ алфавіту для цього виклику) використовується як роздільник рівнів.

Ця реалізація має багато обмежень, серед них:

  • Немає підтримки для іноземних персонажів.
  • Неможливо розмежовувати між договірними гемінованими (довгими) диграфами / триграфами і приголосним + диграфом / триграфом, наприклад: könnyű має порівнюватися як <k><ö><ny> <ny> <ű> , тоді як тизенньолк повинен порівнювати як <t> < i> <z> <e> <n> <ny> <o> <l> <c> ; házszám 'address = номер будинку (ház) (szám)' повинен порівнюватися як <h><á><z><sz><á> <m>, а не як * <h><á><zs> <z> <á> <m> .
  • Збірка довгих диграфів за контрактом не така вже й послідовна (але вона стабільна): ми роз'єднуємось на однаковому рівні ( ssz < n szsz, ..., zszs < n zzs ); glibc поєднує короткі форми перед повними формами ( ssz <szsz, ..., zzs <zszs ), ICU зводить довгі форми до коротких форм, починаючи з випадку L3 та варіантів ( szsz < 3 ssz, ..., zszs < 3 zzs )

Розширена версія:

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

†. Деякі відомі багаторівневі алгоритми зіставлення - це алгоритм зібрання Unicode (UCA, Unicode UTS № 10) , ISO 14651 (доступний на сайті ISO ITTF ), частини LC_COLLATE в ISO TR 30112 (проект доступний на ISO / IEC JTC1 / SC35 / WG5 home ), який застаріває ISO / IEC TR 14652 (доступний в домашніх умовах ISO / IEC JTC1 / SC22 / WG20 ) та LC_COLLATE на POSIX.

‡ Для цього правильно знадобиться словник. ICU розглядає дивновеликі групи з великою літери, як не скорочення / недиграфи / нетриграфи , наприклад: 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


Ви повинні мати можливість зберегти кілька байт за допомогою мого RegExp розширення.
Конструктор

6

Java 8, 742 байти

Можна зменшити ще на 3 байти, називаючи функцію sзамість sortабо ще 16 байт, якщо не рахувати визначення класу.

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

Можна використовувати так:

new H().sort(list);

Набір тестів:

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

врожайний

[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

Безголівки:

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

Я використовую Listтип Java і функцію order()його, але компаратор все мій.


Вражає! Я думаю, ви повинні мати можливість скинути специфікатор типу списку <String>і зберегти кілька символів ціною кількох попереджень?
Джош

@Josh nah, це призведе до двох ролях, як Java може зробити висновок Objectяк типів a і b тоді. Я, мабуть, міг би піти, визначаючи клас-загальний параметр, що розширюється String, хоча. Також я не сподіваюся мати найкоротший код. ;-)
TheConstructor

3

Пітон 3, 70

Збережено 8 байт завдяки shooqie.

Я люблю Python. : D

Очікує список рядків.

from locale import*;setlocale(0,'hu')
f=lambda x:sorted(x,key=strxfrm)

3
Це не стандартна лазівка?
vsz

1
@vsz Не наскільки я знаю. Використання вбудованих програм є частиною багатьох проблем.
Морган Трапп

1
@vsz У нього занадто низький коефіцієнт збільшення кількості голосів на стандартній посаді лазівки, щоб рахуватися як стандарт, вам доведеться прямо заборонити це.
FryAmTheEggman

1
Гаразд, зробив це. Я вважав, що це прямо забороняє, але, хоча, мабуть, очевидно, що це зробить весь виклик суперечливим. Вибачте за незручності.
vsz

1
from locale import*економить багато байтів
shooqie
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.