function call expression #anagol
anarchy golf - Function call expression
問題初投稿。JavaScript風の関数呼び出し式をS式へ変換しろというお題。
例.
in: f(f(f(f))(f)) out: (f ((f (f f)) f))
普通に文字列置換で解ける事に気付いてなかったので、トップは関数がファーストクラスオブジェクトな言語で80〜100byteくらいになるんじゃないかなーと考えてた所、1日経たない内にPerlの43Bが来たのでビビった。いやしかしこの置換は普通じゃない…
比較的普通なsedの解
: s/\(\w*\)(\(\w*\))/o\1_\2c/ t y/o_c/( )/
\Wか\Dが使えればスペースを置き替えなくても済むのだけど残念ながらsedにはないみたいだ。
JSでの想定解は
function g (s) { return function (a) { return a ? g("("+s+" "+a()+")") : s; } } var f = g("f"); for (;;) print(eval(readline())());
こんな感じ。これを1位のnnさんと同点の88byteまで縮めたのだけど、nnさんの解は全く内容が違っていて吹いた。C的なコードだけどこんなに短かくなるのか。
JS想定解と同じ内容でpythonも書いてみたのだけど、1位のSvenさんの解はずっと賢かった。
ruby1.9で書くとこんな感じか。
#!ruby -n class String def call(s) "(#{self} #{s})" end end f="f" puts eval $_.gsub(/\(/,".(")
Pythonは.callとか.(へ変換しなくて良いから短かくなるみたい。
Lisp系は式全体を( )で囲って読んでevalできるよう関数fを定義するか、ParensのScheme実装のような変換をするか。
Arc
(def f r(if r(reduce list `(f,@r))'f))(while:prn:eval:readall:readline)
CommonLisp
(defun f(&rest r)(reduce'list`("f",@r)))(loop(#0=format t"~A "(eval(read-from-string(#0#/"(~A)"(read-line))))))
(while(print((rec'l(fold(^(b a)`(,a,'b))`f(cdr l)))(read-from-string #`"(,(read-line))"))))
(while 1(prn((fn r[l](reduce #(list%(r%2))l))(read-string(str\((or(read-line)\;)\))))))
ArcとCLは関数fを定義してeval、evalしようとすると大変なSchemeとevalするとtimeoutになるclojureはリスト変形。
Arcは全体でも1位取れるんじゃ、と思ったけど甘過ぎだった。
あと参加してない所でHaskellとCが読めない。(毎度の事だけど) 解説欲しいなー。
追記
Haskell解説書いてもらえた!
Function call expression 参戦記 - Life Goes On
携帯でHakell書いて一発通過とか何このBPS
Cの解説も
Function call expression & SQR - nn_xの日記
CとHaskellが一緒の方法だったんだなー。面白い。