匈牙利字母顺序


19

对于那些希望比旧的西班牙字母顺序更具挑战性的人,让我们看一下匈牙利字母的顺序。

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

实际上,qwxy不是在匈牙利词连用,但它们包含了外来语和外国名字。不属于匈牙利字母(如ñ)的外来带重音符号的字符与不带重音的字符具有相同的优先级,但是我们对此挑战视而不见。

规则总结如下:

  • 有向图(cssz,等)和三字符(dzs)被认为是因为他们对自己的信件。
cudar
cukor
cuppant
csalit
csata
  • 如果同一图或三部曲在一个单词中彼此直接出现两次,则它们将以简化方式书写:ssz代替szszddzs而不是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 - ú ü - ű),有一个例外:如果两个词本来是完全一样的,短元音比长元音具有优先权。请注意,与元音(元音öü)是由完全不同的人物ou
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的一部分。如果支持所有必需的字符,则可以使用任何所需的编码。

您必须正确排列行并显示/返回结果。

您可以使用上述示例的任何随机排序的子集进行测试。

编辑:

请不要使用任何本身已经知道匈牙利字母顺序的内置方式或其他方式。这将使比赛毫无意义,并从寻找最佳正则表达式或最佳代码高尔夫技巧中接受所有挑战。

编辑2:

为了澄清isaacg提出的澄清要求:“两个字符串仅在大小写和长元音与短元音上有所不同,但在两种方式上都不同”:尽管官方文档中没有任何规则明确地解决此问题,但在长度上有一个例子元音的重要性比大写更重要。


@FryAmTheEggman您在哪里看到的?
Morgan Thrapp '16

9
伙计,什至不记得我们正确的字母顺序。我该如何编程?;)
Andras Deak

1
我一直在尝试提出一个注定失败的反例,其中一个明显的有向图实际上是两个字母,例如malacsültnyílászáró。我想知道是否有(但是您需要掌握词汇表才能证明这一点,这大概不是挑战的一部分)
Andras Deak

1
有没有含DZS例子
TheConstructor

Answers:


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

使用decorate-sort-unecorate成语(AKA Schwartzian Transform)和多层排序,其中级别为:

  • L1:比较基本字母,忽略变音符号,大小写和标点符号。
  • L2:比较基本字母和变音符号,忽略大小写和标点符号。
  • L3:比较基本字母,变音符号和大小写,忽略一些标点符号。
  • Ln:抢七式字节级比较。

在内部,(ASCII 0x1C字段分隔符-该值小于此挑战中字母的任何字符)用作级别分隔符。

此实现有很多限制,其中包括:

  • 不支持外来字符。
  • 无法区分缩略的加长的有向图/有向图和辅音+有向图/有向图,例如:könnyű应该归类为<k> <ö> <ny> <ny> <ű>,而tizennyolc应该归类为<t> < i> <z> <e> <n> <ny> <o> <l> <c> ; házszám '地址=房屋(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 Case和Variantsszsz < 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站点上可用),ISO TR 30112的LC_COLLATE部分(在ISO / IEC JTC1 /上可用的草稿)。SC35 / WG5 home),已过时(ISO / IEC JTC1 / SC22 / WG20 home可用)和LC_COLLATE 已过时。

‡。正确执行此操作将需要字典。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保存一些字节。
TheConstructor

6

Java 8,742字节

如果不计算类定义,则可以再减少3个字节来命名函数,s而不是减少sort16个字节。

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

我正在使用Java的List-type和order()-function,但是比较器都是我的。


令人印象深刻!我想您应该能够删除列表类型说明符<String>并以警告的代价保存一些字符?
乔什

@Josh不,它将产生两个强制Object类型转换,就像Java会推断为a和b的类型一样。不过,我可能可以逃避定义一个class-generic-parameter扩展String。另外,我不希望代码最短。;-)
TheConstructor

3

Python 3、70

由于shooqie,节省了8个字节。

我喜欢Python。:D

需要一个字符串列表。

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

3
这不是标准漏洞吗?
vsz 2016年

1
@vsz据我所知。使用内置功能是许多挑战的一部分。
Morgan Thrapp '16

1
@vsz它在标准漏洞发布上的上下投票比率太低,无法算作标准,您必须明确禁止它。
FryAmTheEggman '16

1
好的,完成了。我考虑过明确禁止它,但是我很显然这将使整个挑战成为一个争论点。对不起给您带来不便。
vsz 2016年

1
from locale import*节省很多字节
shooqie
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.