masalibの日記

システム開発、運用と猫の写真ブログです

Codegolf(コードゴルフ)を解析して勉強する

社内の勉強会でプログラムパズルみたいなものをやっているのですが、なかなかいいクイズがなかった・Codegolf(コードゴルフ)をおこないたかったのですが1時間程度では無理ゲーなので答えを解析することにした

Codegolf(コードゴルフ)とは

プログラムのソースを短くするゲームの事を
Codegolf(コードゴルフ)といいます
代表的なコードにFizzBuzzというものがあります

FizzBuzzとは

最初のプレイヤーは「1」と数字を発言する。次のプレイヤーは直前のプレイヤーの次の数字を発言していく。ただし、3で割り切れる場合は「Fizz」(Bizz Buzzの場合は「Bizz」)、5で割り切れる場合は「Buzz」、両者で割り切れる場合(すなわち15で割り切れる場合)は「Fizz Buzz」(Bizz Buzzの場合は「Bizz Buzz」)を数の代わりに発言しなければならない。発言を間違えた者や、ためらった者は脱落となる。
という英語圏の遊びですね

FizzBuzzのソース

実際のjavasciprtのソースは以下のとおりです

(function() {
  fizzBuzz(1, 100);
  
  function fizzBuzz(start, times) {
    for(var i = start; i <= times; i++) {
      console.log(
          (i % 3 == 0? "Fizz": "") +
          (i % 5 == 0? "Buzz": "") +
          (i % 3 != 0 && i % 5 != 0? i: "")
      );
    }
  }
})();
FizzBuzzのCodegolfした内容

このソースをCodegolf(コードゴルフ)すると

for(i=0;++i<101;)console.log((i%3?'':'fizz')+(i%5?'':'buzz')||i)  

になります
あれだけながかったソースが1行になります。このように短くすることを楽しむゲームです

Codegolf(コードゴルフ)を解析する

短くするゲームなのですが、普通に難しいです
なので社内の勉強会では解析する事に特化しました

問題は下記です
https://codegolf.stackexchange.com/questions/166623/generate-a-deck-of-cards

問題

トランプを表示する

2つのジョーカーを含むカードの標準デッキを表す配列です。
[
"AS", "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S", "10S", "JS", "QS", "KS",
"AD", "2D", "3D", "4D", "5D", "6D", "7D", "8D", "9D", "10D", "JD", "QD", "KD",
"AH", "2H", "3H", "4H", "5H", "6H", "7H", "8H", "9H", "10H", "JH", "QH", "KH",
"AC", "2C", "3C", "4C", "5C", "6C", "7C", "8C", "9C", "10C", "JC", "QC", "KC",
"J", "J"
]

これは次のように構成されています:
4つのスーツがあります。ハート、スペード、ダイヤモンド、クラブ(H、S、D、C)
各スーツには、2〜10の数字のカードと4枚の写真カード、Ace、Jack、Queen、King(A、J、Q、K)のカードが1枚ずつあります。
スーツと値の組み合わせごとに、配列内に文字列であるアイテムが1つあり、スーツが後に続く値で構成されていなければなりません(これらの間の空白が許されます)。
その上に、2つのジョーカーカード( 'J')があります。

答えの例

javascript

`J,J,${[..."A23456789JQK",10].map(c=>[..."SDHC"].map(s=>c+s))}`.split`,`

php

<?php $r=[J,J];foreach([A,J,Q,K,2,3,4,5,6,7,8,9,10]as$t)
$r=array_merge($r,[H.$t,S.$t,D.$t,C.$t]);

ruby

->{[*0..52,52].map{|x|['JAKQ'[w=x%13]||w-2,'SDHC'[x/13]]*''}}

bash

d=({A,J,Q,K,{2..10}}{H,S,D,C} J J)

java

v->("AJQK2345678910".replaceAll("1?.","$0H,$0S,$0D,$0C,")+"J,J").split(",")

java解説の解説

v->
"AJQK2345678910"
.replaceAll("1?.", // リプレイスする
"$0H,$0S,$0D,$0C,") // ハート(H)やダイヤ(D)などの文字列をくっつける
+"J,J") // "J,J"はハードコード
.split(",") // 結果And split everything by commas

一番感動したコード

bash

echo -e \\U1F0{{A..D}{{1..9},{A..E}},{CF,DF}}
# 以下、出力結果
🂡 🂢 🂣 🂤 🂥 🂦 🂧 🂨 🂩 🂪 🂫 🂬 🂭 🂮 🂱 🂲 🂳 🂴 🂵 🂶 🂷 🂸 🂹 🂺 🂻 🂼 🂽 🂾 🃁 🃂 🃃 🃄 🃅 🃆 🃇 🃈 🃉 🃊 🃋 🃌 🃍 🃎 🃑 🃒 🃓 🃔 🃕 🃖 🃗 🃘 🃙 🃚 🃛 🃜 🃝 🃞 🃏 🃟

トランプの絵文字が書いてあるぱねーーーー
Safariだと文字化けするみたいなので画像も貼り付けますf:id:masalib:20180718112804p:plain

総括

言語によって、省略の仕方が微妙違います
正規表現や配列の持ち方など普通の業務でも使える所があります

Codegolf(コードゴルフ)はできなくてもCodegolf(コードゴルフ)した結果なら解析する事ができると思います(解説があったりします)
得意な分野の言語のソースを解析してみてはどうでしょうか

おまけ

難読プログラムで有名な「brainfuck」のソース

++++++++++[>+++>+++++>+++++++<<<-]>++>->[>+>+>+>+<<<<-]>----->++++.<<<<.>>>>.<<<<.>>>>>--->+++++++++++++<<<<<.-.+>>>>.<<<<<.>.-.+>>>>+.<<<<<.>.-.+>>>>++++.-----<<<<<.>.-.+>>>>>.<<<<<<.>>++++++++[-<+.>>>>.<<<<<.>.>>>>+.<<<<<.>.>>>>++++.-----<<<<<.>.>>>>>.<<<<<<.>>]>.>>.<<<<<.>>>>.>.<<<<<.>>>>+.>.<<<<<.>>>>++++++.>.<<<<<.>>>.>>+.<<<<<.>>>>.>.<<<<<.>>>>------.>.<<<<<.>>>>-.>.<<<<<.>>>.>>++++.<<<<<.>>>>.>.<<<<<.>>>>+.>.<<<<<.>>>>++++++.>.<<<<<.>>>.>>>.<<<<<<.>>>>.>>.<<<<<<.>>>>------.>>.<<<<<<.>>>>-.>>.

何が何だか・・・でも後輩にbrainfuckのソースのみかたを教えてもらった
時間があるときにbrainfuckのHelloWorldをやってみたい