Code Golf

16,688 views

Published on

For talk about code golf in program symposium.

Published in: Technology
0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
16,688
On SlideShare
0
From Embeds
0
Number of Embeds
2,374
Actions
Shares
0
Downloads
105
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide

Code Golf

  1. 1. Code Golfについて Shinichiro Hamaji <shinichiro.hamaji _at_ gmail.com> 2007 年 8 月 9 日 夏のプログラムシンポジウム
  2. 2. 概要 <ul><li>Code Golfとは </li></ul><ul><li>歴史や派閥など </li></ul><ul><li>意義と面白さ </li></ul><ul><li>アルゴリズム選択の重要性 </li></ul><ul><li>なんでもアリの最小化 </li></ul><ul><li>各言語のゴルフ </li></ul>
  3. 3. 概要 <ul><li>Code Golf とは </li></ul><ul><li>歴史や派閥など </li></ul><ul><li>意義と面白さ </li></ul><ul><li>アルゴリズム選択の重要性 </li></ul><ul><li>なんでもアリの最小化 </li></ul><ul><li>各言語のゴルフ </li></ul>
  4. 4. Code Golfとは <ul><li>ゴルフ: 少ないストローク数でホールインすることを競う </li></ul><ul><li>Code Golf: 少ないストローク(打鍵)数で仕様を満たすプログラムを書くことを競う </li></ul><ul><ul><li>ショートコーディングなどとも </li></ul></ul>
  5. 5. 具体例(仕様) <ul><li>空行削除: 標準入力から受け取った文章から改行だけの行を除去しろ。 </li></ul><ul><ul><li>http://golf.shinh.org/p.rb?delete+blank+lines </li></ul></ul>
  6. 6. 具体例(投稿) <ul><li>コードを書いて </li></ul><ul><li>Webフォームから投稿すると </li></ul><ul><li>サーバが自動的に実行して動作確認して </li></ul><ul><li>OKなら記録が残る </li></ul>
  7. 7. 具体例(圧縮) <ul><li>適当に縮めて37B </li></ul><ul><li>短さだけが正義 </li></ul><ul><ul><li>#includeしてない </li></ul></ul><ul><ul><li>intの省略、mainの引数が一つだけ </li></ul></ul><ul><ul><li>int*をgetsに渡してputsに至っては引数省略 </li></ul></ul><ul><ul><li>リトルエンディアンを仮定 </li></ul></ul><ul><ul><li>@ (ASCIIで64)で始まる文字列が来ないと仮定 </li></ul></ul>
  8. 8. 具体例(制約条件) <ul><li>基本的にはなんでもアリではあるものの </li></ul><ul><li>外部プロセス呼び出し禁止 </li></ul><ul><ul><li>main(){system(&quot;perl ...&quot;);} </li></ul></ul><ul><li>モジュール禁止 </li></ul><ul><li>ファイル入出力禁止 </li></ul><ul><li>制限時間 </li></ul><ul><li>バイナリ文字列の使用制限 </li></ul><ul><ul><li>eval Zlib.decode(&quot;*BINARY*&quot;) </li></ul></ul><ul><li>などの制限がつくことも </li></ul>
  9. 9. 概要 <ul><li>Code Golfとは </li></ul><ul><li>歴史や派閥など </li></ul><ul><li>意義と面白さ </li></ul><ul><li>アルゴリズム選択の重要性 </li></ul><ul><li>なんでもアリの最小化 </li></ul><ul><li>各言語のゴルフ </li></ul>
  10. 10. 歴史 <ul><li>おそらくオリジナルはPerl Golf </li></ul><ul><ul><li>プログラムで変なことさせたらPerlは天下一品 </li></ul></ul><ul><ul><li>2001年にはNewsGroupでコンペティションが </li></ul></ul><ul><ul><li>520ページにも及ぶPerlgolf History Book </li></ul></ul><ul><ul><li>http://perlgolf.sf.net/ </li></ul></ul><ul><li>もちろんそれ以前にもコードサイズを縮める文化は多数存在していた </li></ul><ul><ul><li>「ハッカーズ」によるとMITの学生はコードサイズを縮めることに魂を注ぎ込んでいた </li></ul></ul><ul><ul><li>IOCCCにも短いコードは何度も登場 </li></ul></ul>
  11. 11. 歴史2 <ul><li>Code Golf (2006/5~) </li></ul><ul><ul><li>http://codegolf.com/ </li></ul></ul><ul><ul><li>Perl だけでなく、Ruby, Python, PHPも使用可 </li></ul></ul><ul><ul><li>運営者が出題して真剣に競う </li></ul></ul><ul><ul><li>休止気味? </li></ul></ul><ul><li>Anarchy Golf (2007/01~) </li></ul><ul><ul><li>http://golf.shinh.org/ </li></ul></ul><ul><ul><li>約50言語をサポート </li></ul></ul><ul><ul><li>ユーザーが出題して適当に競う </li></ul></ul>
  12. 12. 参加者 <ul><li>Code Golfサイトのtop10中6(7?)人が日本人 </li></ul><ul><li>http://golf.shinh.org/ </li></ul><ul><ul><li>全部で: 400000 access/month </li></ul></ul><ul><ul><li>トップ: 30000 access/month </li></ul></ul><ul><ul><li>~1000 unique users </li></ul></ul><ul><li>ちょっとしたブーム? </li></ul>
  13. 13. Short Coders <ul><li>C言語では北京大学がICPCなどの練習用として公開しているオンラインジャッジシステムを用いてゴルフをする文化がある </li></ul><ul><li>他のゴルフよりややアルゴリズム重視 </li></ul><ul><li>Short Coding 職人達の技法 </li></ul>
  14. 14. ゴルフで人気の言語
  15. 15. ゴルフに強い言語
  16. 16. 概要 <ul><li>Code Golfとは </li></ul><ul><li>歴史や派閥など </li></ul><ul><li>意義と面白さ </li></ul><ul><li>アルゴリズム選択の重要性 </li></ul><ul><li>なんでもアリの最小化 </li></ul><ul><li>各言語のゴルフ </li></ul>
  17. 17. 意義 <ul><li>昔はコードサイズ=実行速度だった </li></ul><ul><ul><li>今でもハードウェア屋だと命令数は重要 </li></ul></ul><ul><li>とはいえ現在では基本的にゴルフによって作られたコードは実用性は皆無 </li></ul><ul><ul><li>メンテ不能 </li></ul></ul><ul><ul><li>最速・省メモリとも限らない </li></ul></ul><ul><li>というわけで 基本的には Just for Fun </li></ul><ul><ul><li>だと、私は考えています </li></ul></ul>
  18. 18. 何がおもしろいのか? <ul><li>一般化はできないのですが、個人的には </li></ul><ul><li>パズルゲームとして </li></ul><ul><ul><li>コードを眺めつつチマチマ削るのは数独などのパズルに通じるものがあるかも </li></ul></ul><ul><li>元々ヘンなコードが好き </li></ul><ul><ul><li>Quine, Polyglot, esoteric languages </li></ul></ul><ul><li>プログラム言語の可能性 </li></ul><ul><ul><li>1000ケタの円周率をbzip2で圧縮して524B </li></ul></ul><ul><ul><li>Rubyだと54B </li></ul></ul>
  19. 19. 副産物としての意義 <ul><li>プログラマのための頭の体操 </li></ul><ul><li>新しい言語を学ぶ時にとりあえずゴルフの問題を解いてみるという学習法 </li></ul><ul><ul><li>ゴルフのためにRubyを覚えたゴルファー、優秀な成績を残すがclassの書き方すら知らない事件 </li></ul></ul><ul><li>短いイディオムや言語機能は身につく </li></ul><ul><ul><li>ひとつやり方を覚えると使い続けてしまう現象 </li></ul></ul><ul><ul><li>勝ちたければ新しい表現を模索する必要がある </li></ul></ul><ul><li>実は短いコードはたいてい速い </li></ul><ul><ul><li>最初は時間制限にひっかかったけど縮めていたら通ったり </li></ul></ul>
  20. 20. 概要 <ul><li>Code Golfとは </li></ul><ul><li>歴史や派閥など </li></ul><ul><li>意義と面白さ </li></ul><ul><li>アルゴリズム選択の重要性 </li></ul><ul><li>なんでもアリの最小化 </li></ul><ul><li>各言語のゴルフ </li></ul>
  21. 21. 基本はアルゴリズム <ul><li>意外にも、最も差がつく部分 </li></ul><ul><ul><li>例えば自分が100Bで解いた問題を他の人が70Bで解いてたら間違いなくアルゴリズムが違う </li></ul></ul><ul><li>とにかく色んな方法で問題をとらえてみる </li></ul><ul><li>多くの場合、速いアルゴリズムは短い </li></ul><ul><ul><li>特に長い/難しい問題では </li></ul></ul>
  22. 22. 空行削除問題アゲイン <ul><li>空行削除をCの感覚でRubyで解いてみると </li></ul>適当に縮める 22B 21B
  23. 23. 発想の転換 <ul><li>「一行ずつ読んで空行じゃなきゃ表示する」->「全部読んで空行だけの行を捨てる」 </li></ul><ul><li>良いアルゴリズム>細かい小細工 </li></ul>18B! 暗号化 ゴルフイディオム適用 14B!
  24. 24. 中置記法->後置記法問題 <ul><li>普通に考えると再帰下降のパーサとか書く </li></ul><ul><ul><li>Shunting yard algorithm とかいうのがあるらしい </li></ul></ul><ul><li>間違いなく暗号(104B) </li></ul>
  25. 25. 処理系におまかせ <ul><li>Rubyはもともと中置記法->eval </li></ul><ul><li>a,b,c,dは未定義な変数->method_missing </li></ul><ul><li>逆にpが定義済みなので邪魔->undef 短くなったのに暗号度大幅にダウン </li></ul><ul><ul><ul><li>http://www.kmonos.net/wlog/71.html#_2014070301 </li></ul></ul></ul>61B!
  26. 26. 概要 <ul><li>Code Golfとは </li></ul><ul><li>歴史や派閥など </li></ul><ul><li>意義と面白さ </li></ul><ul><li>アルゴリズム選択の重要性 </li></ul><ul><li>なんでもアリの最小化 </li></ul><ul><li>各言語のゴルフ </li></ul>
  27. 27. 暗号記述言語Perl <ul><li>Hello, world! </li></ul><ul><ul><ul><li>by ppencode (http://www.namazu.org/~takesako/ppencode/demo.html) </li></ul></ul></ul>
  28. 28. 暗号記述言語Perl <ul><li>rev(1) </li></ul><ul><li>明らかに括弧の対応がおかしい </li></ul>
  29. 29. 暗号記述言語Perl <ul><li>実は-pオプションは前後にプログラムコードを追加しているだけというすごい実装 </li></ul>
  30. 30. マインスイーパ <ul><li>まわりにある爆弾の数を数える </li></ul><ul><ul><ul><li>Perl Golf history book p.268 http://terje2.frox25.no-ip.org/perlgolf_history_070109.pdf </li></ul></ul></ul>
  31. 31. Insane Perl Golfers <ul><li>36B </li></ul><ul><ul><li>(ただしPerl Golfでは#!perlはカウントしない) </li></ul></ul><ul><li>正規表現1個で終了 </li></ul><ul><li>しかもほぼ同一の解に4人が到達 </li></ul>
  32. 32. 正規表現の構文でループ <ul><li>shebangは入力を全て$_に入れるという意味 </li></ul><ul><ul><li>$_=&quot; ........ ........ ....***.  …&quot;; </li></ul></ul><ul><li>s!.!!eg は、全ての.を、右辺を実行した結果に置き換える、という意味 </li></ul><ul><li>s///egはループの代用としてよく使われる </li></ul>
  33. 33. 悪魔の数字 <ul><li>$`はマッチした部分の 左側文字列 </li></ul><ul><li>666e6=666000000 </li></ul><ul><li>666e6x3= 666000000666000000666000000 </li></ul><ul><li>まさにマジックナンバー </li></ul>ここがマッチ したとする
  34. 34. 悪魔の数字 <ul><li>$`はマッチした部分の 左側文字列 </li></ul><ul><li>666e6=666000000 </li></ul><ul><li>666e6x3= 666000000666000000666000000 </li></ul><ul><li>つまり右図のような文字列…? </li></ul>
  35. 35. 謎の特殊変数 <ul><li>$^は&quot;STDOUT_TOP&quot;という文字列 </li></ul><ul><ul><li>10Byte(8+1+1)の文字列なら なんでも良かった </li></ul></ul><ul><li>$_ は最初に全部読み込んだ </li></ul>一行と一列 だけずれた
  36. 36. 文字列& <ul><li>全ての文字に対して論理和 </li></ul>& =
  37. 37. mapで数を数える言語 <ul><li>後は &quot; の数を数えるだけ </li></ul><ul><li>神秘的な理由により、 Perl では関数型言語でおなじみの map 関数を使って文字列中に出現した部分文字列の数を数えることができる </li></ul>
  38. 38. C <ul><li>機械語をはじめとして、低レベル技術と仲良しであることが必要 </li></ul><ul><ul><li>スタックやらポインタやら </li></ul></ul><ul><ul><li>ビット演算 </li></ul></ul><ul><li>~演算子 </li></ul><ul><ul><li>x*(x+1) vs. x*-~x </li></ul></ul><ul><ul><li>-10 vs. ~9 </li></ul></ul><ul><ul><li>for(;~scanf(&quot;%d&quot;);) </li></ul></ul>
  39. 39. qsort
  40. 40. qsort (正しい実装) <ul><li>intをソートしたい </li></ul><ul><li>完全に問題の無い実装 </li></ul><ul><ul><li>ゴルフとしては0点 </li></ul></ul>
  41. 41. qsort (入力依存) <ul><li>intをソートしたい </li></ul><ul><li>型宣言を消して引き算でかえり値を計算 </li></ul><ul><ul><li>オーバーフローの危険 </li></ul></ul><ul><ul><li>ゴルフとしては50点 </li></ul></ul>
  42. 42. qsort (引数減らし) <ul><li>intをソートしたい </li></ul><ul><li>メモリ空間の知識がないと理解できない </li></ul><ul><li>C言語の知識がないと理解できない </li></ul>
  43. 43. qsort (return消し) <ul><li>intをソートしたい </li></ul><ul><li>アセンブリの知識がないと理解できない </li></ul><ul><ul><li>代入しとけばEAXに残ったままの場合がある </li></ul></ul>
  44. 44. qsort (x86) <ul><li>intをソートしたい </li></ul><ul><li>Cは匿名関数をサポートした言語 </li></ul><ul><ul><li>これで短くなるのはCISCの神秘 </li></ul></ul><ul><ul><li>11Byteで9命令 </li></ul></ul><ul><ul><ul><li>pop, pop, pop, push, push, push, mov, sub, ret </li></ul></ul></ul><ul><ul><ul><li>処理系依存でさらに短くなったりも </li></ul></ul></ul>
  45. 45. まとめ <ul><li>Code Golf について概要および実際のコードを紹介しました </li></ul><ul><li>言語自身や処理系の癖などについて、広い知識が必要なパズル </li></ul><ul><li>たぶん時間がないと思って割愛しましたが、OCaml, Haskell, LISP, PHP, PostScript, sed, Bash, Brainf*ck, Befungeでのゴルフや、サーバの構成について補足としてつけました </li></ul>
  46. 46. 概要 <ul><li>Code Golfとは </li></ul><ul><li>歴史や派閥など </li></ul><ul><li>意義と面白さ </li></ul><ul><li>アルゴリズム選択の重要性 </li></ul><ul><li>なんでもアリの最小化 </li></ul><ul><li>各言語のゴルフ </li></ul>
  47. 47. OCaml <ul><li>関数名が長い(print_string) </li></ul><ul><li>型システムをいかに騙すか </li></ul><ul><ul><li>Trueより1>0 </li></ul></ul><ul><ul><li>if c then print_stirng&quot;hoge&quot; より c&()=print_string&quot;hoge&quot; </li></ul></ul><ul><li>切り札Obj.magic </li></ul><ul><ul><li>自然対数の底の小数点以下を100ケタ表示せよ </li></ul></ul><ul><ul><ul><li>http://d.hatena.ne.jp/KeisukeNakano/20070319/1174307629 </li></ul></ul></ul>
  48. 48. Haskell <ul><li>割と強い </li></ul><ul><ul><li>Cより強くてスクリプト言語に負けるくらい </li></ul></ul><ul><li>気の効いた標準関数群 </li></ul><ul><ul><li>interact :: (String -> String) -> IO() </li></ul></ul><ul><li>細かいシンタクスシュガー </li></ul><ul><ul><li>$で括弧を除去 </li></ul></ul><ul><ul><li>main再帰 </li></ul></ul>
  49. 49. CLISP / Scheme <ul><li>あまり強くない? </li></ul><ul><li>マクロがあるとは言うけれど </li></ul><ul><ul><li>そもそもマクロが生きるほど長い問題は少なめ </li></ul></ul><ul><ul><li>可読性無視のゴルフでは、LISPのマクロが使える局面では、スクリプト言語のevalも使える </li></ul></ul>
  50. 50. PHP <ul><li>Hello, world!最強言語 </li></ul><ul><li>基本的には長い標準関数名が不利でスクリプト言語としてはイマイチ </li></ul><ul><ul><li>ereg_replace </li></ul></ul>
  51. 51. PostScript <ul><li>割と強い </li></ul><ul><li>その上バイナリ表現ができる </li></ul>
  52. 52. sed <ul><li>実は四則演算やソートくらいはできる </li></ul><ul><li>単純な問題で無類の強さ </li></ul><ul><ul><li>空行除去5B </li></ul></ul><ul><li>ただし、難しい問題はそもそも制限時間内に解けないことが多い </li></ul>
  53. 53. Bash <ul><li>FizzBuzz最強 </li></ul><ul><ul><li>1から100まで数え上げていって、3の倍数ならFizzを、5の倍数ならBuzzを、15の倍数ならFizzBuzzを出力し、それらでなければその数値を出力する。 </li></ul></ul>
  54. 54. Brainf*ck <ul><li>ただ解くだけでも大変 </li></ul><ul><li>データの用意のしかたが重要 </li></ul><ul><ul><li>16を用意したいのなら… </li></ul></ul><ul><li>メモリ領域を喰いつぶしていく </li></ul><ul><ul><li>0クリアしたい場合、[-]とかするより>で新しいメモリアドレスに </li></ul></ul><ul><ul><li>空行除去 </li></ul></ul>
  55. 55. Befunge <ul><li>2D言語ゴルフ </li></ul><ul><li>演算能力は結構ある </li></ul><ul><ul><li>calを253Bで </li></ul></ul><ul><li>非常に独特のパズルに </li></ul><ul><ul><li>なるべく左寄せ </li></ul></ul><ul><ul><li>行数は少なく </li></ul></ul>
  56. 56. x86 <ul><li>ELFヘッダとプログラムヘッダと機械語をがんばって重ねる </li></ul><ul><ul><li>http://shinh.skr.jp/binary/fsij061115/ </li></ul></ul><ul><li>CISCマジック </li></ul><ul><ul><li>1Bでも強力な子たち: push, pop, inc, dec, ... </li></ul></ul><ul><ul><li>decでZFが立つとか </li></ul></ul><ul><ul><ul><li>for (int i = 0; i < 10; i++) { ... } </li></ul></ul></ul><ul><ul><ul><li>for (int i = 10; --i; ) { ... } </li></ul></ul></ul><ul><ul><li>未だに残る8bitレジスタ群 </li></ul></ul><ul><ul><ul><li>2Bで計算実行 </li></ul></ul></ul>
  57. 57. サーバ構成 <ul><li>Celeron 1.7GHz, 384MB, Ubuntu linux </li></ul><ul><ul><li>負荷記録: 20000access/6hours </li></ul></ul><ul><li>Webサーバ(lighttpd & mod_fastcgi) </li></ul><ul><ul><li>実行以外の全てを担当 </li></ul></ul><ul><li>実行サーバ(Xen) </li></ul><ul><ul><li>基本的にノーガード </li></ul></ul><ul><ul><ul><li>fork連打やファイル書き込みで破壊可能 </li></ul></ul></ul><ul><ul><li>ネットワークはホストとしかつながっていない </li></ul></ul><ul><ul><ul><li>人様には迷惑をかけない </li></ul></ul></ul><ul><ul><li>exec(2)対策にstrace(1)を利用 </li></ul></ul>

×