Anarchy Golf 945. Merge Digits

,

今回はまったくだめ

ruby 2系

55byte

http://golf.shinh.org/reveal.rb?Merge+Digits/kimiyuki_1460757307

$<.map{|l|a=l.split;$><<$&while a.max.sub! /./,'';puts}

Histocratさん 36byte

http://golf.shinh.org/reveal.rb?Merge+Digits/Histocrat_1460689180

#!ruby -pa
gsub(/./){$F.max.slice!0}
  • splitの代わりに、-a option1
  • 先頭からの破壊的なpopに、String#slice!2
  • ちょうど必要回数のloopと出力をするのに、Kernel.#gsub3

perl

76byte

http://golf.shinh.org/reveal.rb?Merge+Digits/kimiyuki_1461031695

for(<>){@s=split;while($s[1].0){@[email protected];$s[1]=~s/.//;print$&;}[email protected],$/;}

不要な;が複数個ある

teebeeさん 42byte

http://golf.shinh.org/reveal.rb?Merge+Digits/teebee_1460744837

#!perl -pa
s/./$&x${\(@F=sor[email protected])}=~s;;;/ge

llhuiiさん 42byte

http://golf.shinh.org/reveal.rb?Merge+Digits/llhuii_1460767529

#!perl -pa
s!.!$&x$F[$F[1]gt"@F"]=~s///!ge

解読

  • The empty pattern //
    • If the PATTERN evaluates to the empty string, the last successfully matched regular expression is used instead.

であるので、 =~s/// はpop4

両者の相違であるmaxを取る部分であるが、llhuiiさんのものは分かりやすい。 一方でteebeeさんのそれは、まず直接sortをする。しかし([email protected])[1]などとするとlvalue的なものにならないので、\によって@Fのreferenceと${...}によるdereferenceを挟んだ上で置換を行っている5

c

126byte

char*p,*q,*r,s[99];main(){for(;~scanf("%s%s",p=s,q=s+50);putchar('\n'))for(;*p+*q;putchar(*q++))strcmp(p,q)>0&&(r=p,p=q,q=r);}

変数宣言が多すぎて見苦しいが、どうにもならなかった。

nuさん 90byte

http://golf.shinh.org/reveal.rb?Merge+Digits/tails_1461832311

char*a[];main(){while(*a&&putchar(*a[bcmp(*a,a[1])<0]++?:10)-10||~scanf("%ms%ms",a,a+1));}

単一のwhile (...);で綺麗。 同氏のもうひとつの提出は手元で動かなかった。

解読

整形

char *a[];
main(){
    while (*a
        && putchar(* (a[bcmp(*a, a[1]) < 0] ++) ? : 10) != 10
        || scanf("%ms%ms", a, a+1) != -1
        );
}

char *a[]char *への(実質的に0要素の6)arrayで、その先頭はbss領域の先頭。 なので(他にglobal変数を使っていなければ)十分長い領域として扱える。

*a(char *)NULLでないとき、putcharが実行される。 bcmp7memcmpと考えてよい。第3引数にはゴミが渡される。 a ? : cはGNU拡張の省略記法で、a ? a : cと副作用を除いて等価。 putcharは引数をそのまま返す。

*a(char *)NULLあるいはputcharが改行を出力したとき、scanfが実行される。 %msはGNU拡張8で、いい感じにmallocしてくれるようだ。

tailsさん 91byte

http://golf.shinh.org/reveal.rb?Merge+Digits/tails_1461832311

o;main(p,q){for(;o||~scanf("%s%s",p=q+32,q);putchar(o?:10))o=*(0?"":~strcmp(p,q)?p++:q++);}

0?"":がすごい。

手元ではsegvで動かなかった。

解読

整形

int o;
main(int p, int q){
    for(; o || scanf("%s%s", p=q+32, q) != -1
            ; putchar(o ? : 10))
        o = *(0 ? "" : strcmp(p,q) != -1 ? p++ : q++);
}

qchar **argvなので、これを領域として使っている。

        o = *(0 ? "" : strcmp(p,q) != -1 ? p++ : q++);

の左の条件演算は実行時には意味をなさない。しかしこれがないと型がintのままであり、

        o = *(char *)(strcmp(p,q) != -1 ? p++ : q++);

と書くことになる90?"":の5byteと(char*)の7byteでは2byteの有利である。

tailsさん (+ nuさん) 87byte

http://golf.shinh.org/reveal.rb?Merge+Digits/tails+%28nu%29_1461906785

o;main(p,q){for(;o||~scanf("%ms%s",&p,q);putchar(o?:10))o=*(0?"":bcmp(p,q)>0?p++:q++);}

解読

tailsさん本人のものを基本に、%msを使用し、strcmpbcmpに変更したもの。

比較:

<   o;main(p,q){for(;o||~scanf("%s%s",p=q+32,q);putchar(o?:10))o=*(0?"":~strcmp(p,q)?p++:q++);}
>   o;main(p,q){for(;o||~scanf("%ms%s",&p   ,q);putchar(o?:10))o=*(0?"": 0<bcmp(p,q)?p++:q++);}

sed

まともな長さで書ける気がしなかったので見送り。 早くsedが書けるようになりたい。

tailsさん 108byte

http://golf.shinh.org/reveal.rb?Merge+Digits/tails_1460734343

s/.*/ &z=9876543210z/
:
/\( .*\)\(.\).*\1\(.\).*=.*\2.*\3/!s/ \(.* \)\(\w\)/ \2\1/
s/ \(.\)/\1 /
s/  z.*//
t

この手の正規表現見るたびに、正則性とはなんだったのかという気持ちになる。

解読

s/.*/ &z=9876543210z/

は前処理。RESULT FOO BARz=9876543210zという形に。

/\( .*\)\(.\).*\1\(.\).*=.*\2.*\3/    ! s/ \(.* \)\(\w\)/ \2\1/

条件節の\1にはふたつの列の共通接頭辞が入る。それぞれの共通接頭辞の次の文字\2,\3\2 $\gt$ \3かどうかを見ている。\3にはzが入りうる。 matchしなかったとき、ふたつめの文字列の先頭をひとつめの文字列の先頭に移動。これは次で結果の文字列の末尾に移される。 \w.でもよい。

s/ \(.\)/\1 /

は、ひとつめの文字列の先頭を結果の文字列の末尾に移動。

s/  z.*//

は後処理。

%20さん 115byte

s/.*/\n&@@@0123456789/
:
/\n\(.*\)\(.\).* \1\(.\).*@.*\3.*\2/s/\n\(.\)/\1\n/
t
s/\(\n.* \)\(\w\)/\2\1/
/\n @/!b
P
d

Pdがあって珍しいしloopの形も複雑で技巧的だなあという印象。

解読

s/.*/\n&@@@0123456789/

RESULT\nFOO [email protected]@@0123456789の形。 @@@;=;などとしてもよい。

/\n\(.*\)\(.\).* \1\(.\).*@.*\3.*\2/    s/\n\(.\)/\1\n/

共通接頭辞を取ってその次の文字で比較。\3には@が入りうる。 \3 $\lt \2なら、ひとつめの文字列の先頭を結果の文字列に移動。 matchし続ける間繰り返す。

s/\(\n.* \)\(\w\)/\2\1/

ふたつめの文字列の先頭を結果の文字列に移動。

/\n @/!b

空になったら終了。

P
d

Pは最初の\nまでを出力10dでpatter spaceを削除し次の行へ。

mitchsさん (+ tailsさん) 105byte

s/.*/ &z=9876543210z/
:
/\( .*\)\(.\).*\1\(.\).*=.*\2.*\3/!s/  z.*\| \(.* \)\(.\)/ \2\1/
s/ ./& /
s/ //
t

tailsさんのを基本として改良。

解読

/\( .*\)\(.\).*\1\(.\).*=.*\2.*\3/    ! s/  z.*\| \(.* \)\(.\)/ \2\1/
/\( .*\)\(.\).*\1\(.\).*=.*\2.*\3/    ! s/     \| \(.* \)\(.\)/ \2\1/

条件部はそのまま。 置換の\w.になっているのと、z.*を空白ひとつで置換するようになっている。

s/ ./& /
s/ //

は、元々は

s/ \(.\)/\1 /

だったもの。ひとつめの文字列から結果の文字列へ移す処理に、z.*が置き換わってできた空白を消す役割を追加した。

brainfuck

mitchsさん 185byte

http://golf.shinh.org/reveal.rb?Merge+Digits/mitchs_1461888378

->,+[->-[>>>,[>+>+<<-]++++[>>--------<<-]>>]+[-<+]+[,>>>>>]<,[<[<+[-[+[<+<+>>-]>]>>[>->+<<-]>[>]>]<<[<+[<<<<]>[>+<<<<<]>>+>>-]>[-<]<<[<<<<<]->>>>>.[-]+[[<<<<<+>>>>>-]>>>>>]]+[-<+]->],+]

I was going to try to write it if he writes this (because I have no confidence to write a short code). But his submittion is too near to the deadline for me to write a code.

description

I’ll read later.