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}
perl
76byte
http://golf.shinh.org/reveal.rb?Merge+Digits/kimiyuki_1461031695
for(<>){@s=split;while($s[1].0){@s=sort@s;$s[1]=~s/.//;print$&;}print@s,$/;}
不要な;が複数個ある
teebeeさん 42byte
http://golf.shinh.org/reveal.rb?Merge+Digits/teebee_1460744837
#!perl -pa
s/./$&x${\(@F=sort@F)}=~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をする。しかし(sort@F)[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が実行される。
bcmp7はmemcmpと考えてよい。第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++);
}
qはchar **argvなので、これを領域として使っている。
o = *(0 ? "" : strcmp(p,q) != -1 ? p++ : q++);
の左の条件演算は実行時には意味をなさない。しかしこれがないと型がintのままであり、
o = *(char *)(strcmp(p,q) != -1 ? p++ : q++);
と書くことになる9。0?"":の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を使用し、strcmpをbcmpに変更したもの。
比較:
< 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
Pやdがあって珍しいしloopの形も複雑で技巧的だなあという印象。
解読
s/.*/\n&@@@0123456789/
RESULT\nFOO BAR@@@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までを出力10、dで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.
-
http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2frubycmd.html ↩
-
http://docs.ruby-lang.org/ja/2.3.0/method/String/i/slice=21.html ↩
-
http://docs.ruby-lang.org/ja/2.3.0/method/Kernel/m/gsub.html ↩
-
sizeofしようとするとinvalid application of ‘sizeof’ to incomplete type ‘char *[]’↩ -
http://stackoverflow.com/questions/11926883/scanf-dynamic-allocation/16044055 ↩
-
はず。 実際には試せていない。 ↩