せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Ruby】【アルゴリズム】10パズルを解く。全ての数式を逆ポーランドで作る編

4桁の数字から全ての数式のパターンを列挙する。
数式は逆ポーランド記法で記述する。
(例)"12+3+4+"


 
すごい!30分で書けた!
もう再帰は見切ったぞ。

 

dupでコピーをとりながら再帰を回す(必要に応じて深いコピー)
・終了条件を満たしたものをresult配列に詰め込む

のポイントだけ押さえれば、後は応用が効く。
 
吐きながら勉強した甲斐があった><

 

コード

class Calc
  def self.make_expression(str)
    @@data = str.split("")
    @@operatars = ["+","-","*","/"]
    _make_rpn([], [], [0,0,0,0], 0, 0)
  end
  def self._make_rpn(result, candidate, is_uesd, num_count, ope_count)
    return result << candidate.join('') if num_count+ope_count == 7
    return if  num_count+ope_count > 7
    if num_count - ope_count >=2
      @@operatars.each do |ope|
        tmp = candidate.dup
        tmp << ope
        self._make_rpn(result, tmp, is_uesd, num_count, ope_count + 1)
      end
    end
    if num_count < 4
      is_uesd.each_with_index do |isused, idx|
        if isused == 0
          tmp = is_uesd.dup
          tmp2 = candidate.dup
          tmp[idx] = 1
          tmp2 << @@data[idx]
          self._make_rpn(result, tmp2, tmp, num_count + 1, ope_count)
        end
      end
    end
    result
  end
end

p Calc.make_expression("1234")


 

ポイント

・与えられた数字を、最初は定数化しようと思ったけれどもRubyはメソッド内では定数が定義できない。
 ⇒クラスを作ってクラス定数に。


 
■実行結果

["12+3+4+", "12+3+4-", "12+3+4*",
 "132+/4-", "132+/4*", "132+/4/",
 "143*2**", "143*2*/", "143*2/+",
 "23*4-1/", "23*4*1+", "23*4*1-",
 "2413/-+", "2413/--", "2413/-*",
 "32-1+4-", "32-1+4*", "32-1+4/", 
などなど。