Posts Tagged ‘Ruby’

麻雀問題解いてみた

4月 4th, 2010

Mahjong set [04/04]
Creative Commons License photo credit: drdaeman

makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (1/2) – ITmedia エンタープライズを解いてみました。ソースはtune’s itmedia_makeplex at master – GitHubに上げてありますのでリビジョンも見れるようになってます。最初のコミットを上げるまでに、面子の表示順の違いを抑えるところで詰まってチンイツの待ちを出力するプログラム – 107143955443560を参考にしました。参考にしましたというよりもC++のソースをRubyに移植しましたと言う方が近いほど同じ処理です。基本的なアルゴリズムは最後まで踏襲しています。

最初のコミットまでが3時間ぐらい、リファクタリングに1時間ぐらいです。ちょっと時間がかかりすぎですが、日常的に書いてないRubyで、日常的にプログラムしてない家のMacパソコン、プラグインが古いのか5分に1回落ちてしまうMacVimで時間がとられたと言い訳しておきます。ただの実力不足です、ごめんなさい。

成立する可能性がある面子を減らしながら、総当たりで探索しています。面子の順序違いによる重複表示を避けるのが結構面倒ですね。刻子を優先して探さなければならず、色々試行錯誤してみたのですが、参考にさせていただいたid:staebchenさんよりも良さそうな方法に達しませんでした。もっといいやり方があると思いますが、参考まで。

#!/usr/bin/ruby

class Array
  def sum
    s = 0
    self.each do |v|
      s += v
    end
    return s
  end
end

class Fixnum
  # 刻子
  def anko
    num = self+1
    "(#{num},#{num},#{num})"
  end

  # 順子
  def shuntsu
    num = self+1
    "(#{num},#{num+1},#{num+2})"
  end

  # アタマ
  def atama
    num = self+1
    "(#{num},#{num})"
  end

  # 単騎
  def tanki
    num = self+1
    "[#{num}]"
  end

  # リャンメン(ペンチャンも兼ねる)
  def ryanmen
    num = self+1
    "[#{num},#{num+1}]"
  end

  # カンチャン
  def kanchan
    num = self+1
    "[#{num},#{num+2}]"
  end

  # シャボ
  def shabo
    num = self+1
    "[#{num},#{num}]"
  end
end

#
# 雀牌を表す数字列を解析し、0〜8の配列に与えられた個数を入れて返す
#
def parsePai(str)
  pai = Array.new(9, 0)
  str.split(//).each do |p|
    pai[p.to_i-1] += 1
  end

  # 入力の妥当性チェック
  if pai.sum != 13 then
    # 与えられる牌は13枚
    raise RuntimeError
  else
    pai.each do |val|
      if val > 4 then
        # 1種類の牌が4枚より多いことはない
        raise RuntimeError
      end
    end
  end

  return pai
end

#
# 手牌を再帰的に解析し待ちを表示する
#
# 順子を刻子に優先して探索する。
# 順子はfromが9〜18の時に探索される
#
def analyzeTehai(pai, from=0, mentsu=[])
  shuntsu_phase = 9
  skip_anko_check = false

  if from >= 9 then
    skip_anko_check = true
    from -= shuntsu_phase
  end

  if pai.sum > 4 then
    # 面子を揃える

    # 刻子
    unless skip_anko_check then
      from.upto(8).each do |i|
        if pai[i] >= 3 then
          tmp = pai.dup
          tmp[i] -= 3
          analyzeTehai(tmp, i+1, mentsu+[i.anko])
        end
      end
    end

    # 順子
    from.upto(6).each do |i|
      if pai[i]>=1 && pai[i+1]>=1 && pai[i+2]>=1 then
        tmp = pai.dup
        tmp[i] -= 1
        tmp[i+1] -= 1
        tmp[i+2] -= 1
        analyzeTehai(tmp, i+shuntsu_phase, mentsu+[i.shuntsu])
      end
    end

  else
    # 残った4枚から待ちを絞る

    # アタマを探す
    0.upto(8).each do |i|
      if pai[i] >= 2 then
        tmp = pai.dup
        tmp[i] -= 2
        analyzeMachi(tmp, mentsu+[i.atama])
      end
    end

    # 面子(刻子 or 順子)があれば単騎待ち
    # 刻子
    unless skip_anko_check then
      from.upto(8).each do |i|
        if pai[i] >= 3 then
          tmp = pai.dup
          tmp[i] -= 3
          analyzeTanki(tmp, mentsu+[i.anko])
        end
      end
    end

    # 順子
    from.upto(6).each do |i|
      if pai[i]>=1 && pai[i+1]>=1 && pai[i+2]>=1 then
        tmp = pai.dup
        tmp[i] -= 1
        tmp[i+1] -= 1
        tmp[i+2] -= 1
        analyzeTanki(tmp, mentsu + [i.shuntsu])
      end
    end
  end
end

#
# 4枚から待ちを絞る
#
def analyzeMachi(pai, mentsu)
  0.upto(8).each do |i|
    # リャンメン(ペンチャン)
    if pai[i]==1 && pai[i+1]==1 then
      puts mentsu.sort.to_s + i.ryanmen
    end

    # カンチャン
    if pai[i]==1 && pai[i+2]==1 then
      puts mentsu.sort.to_s + i.kanchan
    end

    # シャボ
    if pai[i]==2 then
      puts mentsu.sort.to_s + i.shabo
    end
  end
end

#
# 単騎待ちの数字を調べて待ちを表示する
#
def analyzeTanki(pai, mentsu)
  # 単騎待ち
  0.upto(8).each do |i|
    if pai[i] == 1 then
      puts mentsu.sort.to_s + i.tanki
    end
  end
end

# 以下実際の処理
pai = parsePai ARGV[0] unless ARGV[0] == nil
analyzeTehai(pai)

gruff

11月 30th, 2008
http://geoffreygrosenbach.com/projects/show/5#map_yxdijbqs" />

gullery photo gallery via kwout

Rubyできれいなグラフが書けるライブラリ、仕事で数値を扱うのに使いました。使うにはImageMagickとRMagickが必要です。

リンク先のグラフはどれも洗練されていて美しいのですが、データがちょっと多かったりすると見た目が悪くなって困り者です。なんだかんだ言って細かな調整ができるExcelの方がまだ使い勝手がいいです。
細かい所に手が届かないのも問題ですが、使い方のサンプルが少なくてちょっと分かりにくいかな。

Railsでも使えるみたいなんで、もうちょっと情報が出てくるといいですね。

Gruff Graphs for Ruby | Ruby on Rails for Newbies

追記、Railsならhtml5jp_graphsなんてのもあるらしい。こっちの方が細かい所まで手が届く感じ。

今日買った本 – Google本とRuby本

6月 8th, 2008

”Googleを支える技術 ”まるごと

最近読書量が明らかに減っているので積読を増やして自らにプレッシャーをかけるよう本を買ってきました。

評判がよく、売れてるらしいGoogleを支える技術 ‾巨大システムの内側の世界とディープな話題が盛りだくさんのまるごと Ruby! Vol.1にしてみました。

実はかれこれ2ヶ月ぐらいアジャイルプラクティス達人プログラマに学ぶ現場開発者の習慣で詰まっています。早く読んでどんどん知識を吸収しよう > 自分

Rubular

1月 21st, 2008

http://www.rubular.com#kwout_b376t94x" height="442" width="516" />

Rubular: a Ruby regular expression editor via kwout

Rubyの正規表現の動きをチェックできるWebサイト、いつもirbでやってたのでこういうのがあるとやっぱり便利かも。

redMine

7月 31st, 2007



Railsで作られたBTS+Wiki+バージョン管理ソフト、Tracの対抗馬になりそうです。Tracよりもデフォルトで優れているのはバージョン管理ソフトがSubversion意外にMercurialやCVSにも対応していること、複数プロジェクトの生成が楽なこと、管理がWeb上でほぼ完結することです。

使っている人はTracの方が多いようですが、redMineも徐々に注目を集めているようです。使ってみて日本語の情報がまだまだ少ないなと感じました。職場のPCに入れてみたので使っていって分かったことがあればこの日記にも書いていきたいですね。

RubyInline

3月 13th, 2007

netswitch! | netswitch!さんで知った RubyInlineが気になります.Rubyのソースでネックとなる箇所をインラインのC言語記述で置き換えることで高速化できるようです.

RubyにはC言語で作ったライブラリを組み込む機能が元々あって,大学時代の研究用プログラムで一部使っていましたがやっぱりインラインで書ける方が便利でいいですね.機会があったら使ってみたいと思います.

VisualStudioで○○言語の開発をする

1月 5th, 2007

VisualStudioのカスタマイズを調べていたら本来VisualStudioがサポートしていない言語での開発をサポートするソフトをいくつか見つけたのでまとめておきます.

* PHP – VS.Php


まずは有名どころのPHPから.デバッガ,インテリセンスも使えてPEAR,Smartyなんかも対応しているらしいです.日本では アシアル株式会社 事業紹介 VS.Phpから購入できます.30日の無料体験版がダウンロードできて製品版は39800円です.
- Php IDE – VS.Php Standalone Edition | Jcx.Software Corp.

* Ruby – Ruby In Steel


お次はRuby,PHPと同じくデバッガ,インテリセンスが使えて,Ruby on Railsも対応しているようです.無料版もあって,有料版だと$249,いまなら期間限定で$199で購入できるみたいです.
- Ruby IDE :: Ruby In Steel :: Ruby Programming with Visual Studio 2005

* Haskell – Visual Haskell


最後は関数型言語のHaskellです.無料で使えるのでHaskellの勉強にも使えそうです.
- Visual Haskell

PerlやPythonは以前VisualPerlやVisualPythonといったソフトがあったようなのですが開発は終了してしまったようです.探せば他の言語のもありそうですね.あとは何の言語があったかな・・・

バグつぶし

2月 26th, 2004

今日はアルバイトのプログラムのバグをつぶしていて終わってしまった・・・( ̄□||||!!

このバグが困り者で、月曜日に見つけたバグ・・・月曜の日記にも書いたがこのせいで由美子とちょっとした喧嘩になってしまったし、自分も時間がとられたり、バグの原因が一向にわからなかったりで相当に振り回された。自分の中で歴史に残りそうだ・・・でもそこまででも無いか・・・冷静に考えれば。

原因はrubyプログラムでの画像の縮小処理。ImageMagickをRMagickを使って呼び出して利用していたが、アニメーションGIFの扱いに問題があった。
-問題1:ImageMagickだと圧縮GIFが作れないことを忘れていた。
-問題2:JPEGやPNGに変換したときに、複数のファイルに分かれてしまうことを忘れていた。
-問題3:非圧縮のGIFを携帯サイズに圧縮しようとして画像がすごく小さくなってしまっていた。
-問題4:20枚とか複数の絵からなるGIFの場合、1枚のサイズがどれだけがんばっても1kぐらいにしかならず、目標の10kまで届かなかった。
-問題5:それでも縮小処理を続けようとするので画像の解像度が0ピクセルになってしまい、RMagickでエラーが発生していた。
わかってしまうとなんてこと無いが、全てのバグってそんなもの。