2007年5月23日星期三

A Newbie's Scripts for Cygwin 3

用 ruby 写的一个计算 24 点的练习,不知道有没有出错的地方。用法:

$ 24points.rb 7 4 3 9
(3*9)-(7-4)
(4-7)+(3*9)
(9-7)*(4*3)
((7+4)*3)-9
((7-4)*9)-3
((9-7)*4)*3
((9-7)*3)*4
((3*9)-7)+4
4-(7-(3*9))
((3*9)+4)-7


源文件:

#!/usr/bin/env ruby
# 24points.rb developed by Shi Zhan
# Michael.Fantasia@Gmail.Com

class Combination
  def initialize(a, b, c, d)
    @num = [ a, b, c, d ]
    @box = {}
  end

  def each_two
    0.upto(2) do |i|
      (i+1).upto(3) do |j|
        yield @num[i], @num[j]
      end
    end
  end

  def two_group
    1.upto(3) do |i|
      tmp = @num.dup
      tmp.delete_at(i)
      tmp.delete_at(0)
      yield [@num[0], @num[i]], tmp
    end
  end

  def two_one_one
    0.upto(2) do |i|
      (i+1).upto(3) do |j|
        tmp = @num.dup
        tmp.delete_at(j)
        tmp.delete_at(i)
        yield [@num[i], @num[j]], tmp
      end
    end
  end

  def make_box
    each_two do |m, n|
      tmp = []
      ["+", "*"].each do |op|
        tmp.push("(" + m.to_f.to_s + op + n.to_f.to_s + ")")
      end
      ["-", "/"].each do |op|
        tmp.push("(" + m.to_f.to_s + op + n.to_f.to_s + ")")
        tmp.push("(" + n.to_f.to_s + op + m.to_f.to_s + ")")
      end
      @box[[m,n]] = tmp
    end
    two_one_one do |m, n|
      n.each do |i|
        tmp = []
        @box[m].each do |exp|
          ["+", "*"].each do |op|
            tmp.push("(" + exp + op + i.to_f.to_s + ")")
          end
          ["-", "/"].each do |op|
            tmp.push("(" + exp + op + i.to_f.to_s + ")")
            tmp.push("(" + i.to_f.to_s + op + exp + ")")
          end
        end
        @box[[m,i]] = tmp
      end
    end
  end

  def test(exp1, exp2)
    ["+", "*"].each do |op|
      result = exp1 + op + exp2
      yield result if eval(result) == 24
    end
    ["-", "/"].each do |op|
      result = exp1 + op + exp2
      yield result if eval(result) == 24
      result = exp2 + op + exp1
      yield result if eval(result) == 24
    end
  end

  def find_answer
    @solution = []
    two_group do |a, b|
      @box[a].each do |exp1|
        @box[b].each do |exp2|
          test(exp1, exp2) do |answer|
            @solution.push(answer)
          end
        end
      end
    end
    two_one_one do |a, b|
      @box[[a, b[0]]].each do |exp1|
        exp2 = b[1].to_f.to_s
        test(exp1, exp2) do |answer|
          @solution.push(answer)
        end
      end
      @box[[a, b[1]]].each do |exp1|
        exp2 = b[0].to_f.to_s
        test(exp1, exp2) do |answer|
          @solution.push(answer)
        end
      end
    end
    @solution.uniq!
  end

  def output
    puts "No answer found." if @solution.empty?
    @solution.each { |exp| puts exp.gsub(/\.0/, '') }
  end
end

a, b, c, d = ARGV
comb = Combination.new(a.to_i, b.to_i, c.to_i, d.to_i)
comb.make_box
comb.find_answer
comb.output

没有评论: