sugiです。
配列の順列を求めるのに良い方法がないかと考えていたのですが、
「Rubyプログラミング入門」に良いサンプルがありました。
そこで、ちょっと拡張。
任意の異なる数値の配列が与えられたとき、その中からN個の数値を取り
出して、四則演算(+、−、×、÷)で指定値になる組み合わせを探す。
--^ ticket3.rb
#! ruby
num= %w(2 3 6 8)
op = %w(+ - * /)
n = 3
ans= 10
# 順列
def perm(n,m=n)
if n<m
elsif m<=0
yield([])
else
perm(n-1,m-1) do |x|
(0...m).each do |i|
yield(x[0...i]+[n-1]+x[i..-1])
end
end
perm(n-1,m) do |x|
yield(x)
end
end
end
# 重複順列
def perm2(n,m=n)
if n<m
elsif m<=0
yield([])
else
perm(n,m-1) do |x|
(0...n).each do |i|
yield(x+[i])
end
end
end
end
if num.size<n
puts "配列の要素数が足りません"
exit0
end
count=1
num.collect!{|e| e.to_f.to_s}
num_a,op_a=[],[]
perm(num.size,n){|x|
num_a<<x.collect{|e| num[e]}}
perm2(4,n-1){|x|
op_a<<x.collect{|e| op[e]}}
num_a.sort!
op_a.sort!
num_a.each do |num|
op_a.each do |op|
ex=""
for i in 0...n
ex +=(op[i]) ? num[i]+op[i] : num[i]
end
if eval(ex)==ans
print %Q|#{count} #{ex.gsub(/\.0/,"")}|
puts %Q|=#{eval(ex.gsub(/\.0/,""))}|
count+=1
end
end
end
--$
実行結果
% ruby ticket3.rb
1 2*8-6=10
2 3*6-8=10
3 6*3-8=10
4 6/3+8=10
5 6+8/2=10
6 8*2-6=10
7 8/2+6=10
8 8+6/3=10
ようやく yield の使い方がちょっと分かってきました。
この言語の比較シリーズのお題って、いろいろ勉強になります。:-)
--
sugi