どう書く: 参考問題1「ポーカー」
来月はひさしぶりにどう書くに参加するので、リハビリに参考問題1を解きました。Rubyで。
#!/usr/bin/ruby def is_fourcards (cs) return cs.has_value?(4) end def is_threecards (cs) return cs.has_value?(3) end def cnt_pairs (cs) return cs.select {|k,v| v == 2}.length end input = ARGV[0] ws = input.gsub(/10/,"T").split("") cs = [] ws.each { |w| cs.push(w) unless /S|H|D|C/ =~ w } nums = { } (2..9).each { |n| nums[n.to_s] = 0 } nums.update({"T" => 0, "J" => 0, "Q" => 0, "K" => 0, "A" => 0}) cs.each { |c| nums[c] = nums[c] + 1 } result = "--" if is_fourcards(nums) then rsult = "4K" elsif is_threecards(nums) && cnt_pairs(nums) == 1 then result = "FH" elsif is_threecards(nums) then result = "3K" elsif cnt_pairs(nums) == 2 then result = "2P" elsif cnt_pairs(nums) == 1 then result = "1P" end print result
最初、配列のeachメソッドを呼んでブロックを引数に渡し、ブロック外で定義したhashをブロック内で更新しようとしたら、毎回hashがリセットされてしまって悩みました。スコープ周りを理解してないかも。というか何も理解してないかも。
それはそうと、nidoさんの解答が3行だったので、ひっくり返りました。(ATNDのコメント欄で読めます)
以下、勉強になった点。
- hashのキーに配列を使うという発想はなかった
- トランプのsuitを区切り文字としてsplitするという発想はなかった
- arrayオブジェクトのインデックスをrangeにするのはイディオム?
- [1..-1]にしているのは、区切り文字が先頭にある場合に先頭要素が空白になるから? これって仕様?
- group_byは便利