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
が実行される。
bcmp
7は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 ↩
-
はず。 実際には試せていない。 ↩