『第7回デスマコロシアム』答案
CodeIQの『第7回デスマコロシアム』(※)に参戦しました。
※以下を特徴とするコードゴルフ大会です。
- ideoneで使用可能な言語なら何でもOK。
- 有利な言語に偏りすぎないよう、参戦人数の多い言語にはハンディあり。
- バイト数でなく、文字数で競う。
- import文は文字数カウント対象外、ideoneの自動生成部分もカウント対象外。(本稿のコードも、自動生成部分は略記しています)
第7回出題テーマは、「"deathma colosseum"を出力するbrainf**kのコード」を標準出力に出力する問題。brainf**kのコード自体は問題文で指定されているので、あまり深く考える必要は無く、要は「>("deathma colosseum"の各文字のasciiコード).」という文字列を出力するだけです。問題もシンプルなので、以下を以下に短く書けるかが短縮化のポイントとなったのかなと思います。
- 文字列から各文字をiterateする
- 文字をasciiコード(数値)に変換する
- "+"を指定した回数繰り返す
- 上記の結果を標準出力に出力する
いつもCOBOLでばかり参加していたので、今回は勉強がてら色々な言語で書いてみました。
Clojure(70)
(doseq[%"deathma colosseum"](printf">%s."(apply str(repeat(int%)'+))))
- 普通にmap関数とかを使って書くと遅延シーケンスに苦しめられるので、doseqで書くのが良さそうです。
C#(74)
foreach(int c in"efbuinb!dpmpttfvn")Console.Write(">"+".".PadLeft(c,'+'));
- 「"+"を指定した回数繰り返す」&「その後に"."を出力する」処理を「"."を指定桁になるよう"+"で桁揃えして出力」として一遍に行うことで、多少文字が稼げます。そのために"deathma colosseum"の文字そのものでなく、各文字をrot-1した"efbuinb!dpmpttfvn"をiterateしてやる必要があります。
F#(73)
"efbuinb!dpmpttfvn"|>Seq.iter(fun c->printf">%s"(".".PadLeft(int c,'+')))
- 同上。文字列とかのiterateがC#よりも1文字だけ楽なのかな。
Go(72)
import . "strings" for _,c:=range"deathma colosseum"{fmt.Printf(">%s.",Repeat("+",int(c)))}
- 冒頭に挙げたポイントのどれもが少しずつ書き辛く、もどかしい言語です。
Groovy(48)
'deathma colosseum'.any{print">${'+'*(int)it}."}
- 今回書いた言語では唯一、無名関数の引数を宣言しなくても"it"として参照できる点が有利そうでした。(一応Scalaもできるけど、癖が有って今回の短縮には使えなそうでした)
- ".each"でなく".any"を使って1文字短縮するあたりがちょっとしたコツでしょうか。
Haskell(64)
import Data.Char mapM putStr$[">"++([1..ord c]>>"+")++"."|c<-"deathma colosseum"]
- 文字列の結合に"++"と2文字必要となるのが辛い。
Java/Java7(95)
import static java.lang.System.out; import static java.lang.String.format; for(int i:"efbuinb!dpmpttfvn".toCharArray())out.print(format(">%"+i+"s",'.').replace(' ','+'));
Java/Java7(91)※機種依存でCodeIQ投稿不可、ideoneでは稼働
for(int i:"𐮑n".toCharArray())out.print(format(">%"+i%200+"s",'.').replace(' ','+'));
Nemerle(69)
using System.Console; using System.Convert; foreach(c in"deathma colosseum")Write($">$(String('+',ToInt32(c))).")
- これもどうも、今回は活躍し辛い言語。
PHP(74)
for($s="efbuinb!dpmpttfvn";$i<17;)echo str_pad(">",ord($s[$i++]),"+").".";
Python(59)
print"".join('>'+'+'*ord(c)+'.'for c in"deathma colosseum")
- 末尾の改行/空白無しでのprintが結構面倒なので、printは一度に抑える形の方が楽そうです。
- foreach的なことをするために、リスト内包表記([f(n) for n in ほげほげ])とするよりも、ジェネレータ式(f(n) for n in ほげほげ)とすることで括弧がちょっと減らせます。
Python 3(54)
for b in b"deathma colosseum":print('>'+'+'*b,end=".")