もっと金くれや問題

send more money - krystal: プログラミング超初心者(文系) - Rubyist

send + more = money を満たすそれぞれ異なる 0 以上 9以下の数 s, e, n, d, m, o, r, y を求めよ。(ただし s, m は 0 でない)

いかにも中学入試に出そうな問題。

Ruby 1.8.7以降ではArray#permutationが導入されたのでそれを使う。

(0..9).to_a.permutation(8) do |s, e, n, d, m, o, r, y|
  next if s == 0 or m == 0
  send = s*1000 + e*100 + n*10 + d
  more = m*1000 + o*100 + r*10 + e
  money = m*10000 + o*1000 + n*100 + e*10 + y
  print "#{send} + #{more} = #{money}" if send+more == money
end

手で解くには、すぐにわかるものからあてはめていく。そして、繰り上がりがあるのかないのかで場合分けをする。これが大変そうなのだが、「0〜9までの整数」である条件と「それぞれが異なる数字」である条件のおかげでそんなに大変ではない。一見解くのが不可能に思える問題であっても、特定の条件を課せば一意的に解が決定するのがおもしろい。算数の妙だ。この問題を考えた人天才すぎww

ちなみに、これはほとんどの時間でRubyに制御があるため、Ruby 1.9で大幅に高速化される。10.5秒vs3.2秒。

$ time ruby18 send-more-money.rb > /dev/null
ruby18 send-more-money.rb > /dev/null  10.21s user 0.00s system 96% cpu 10.529 total
$ time ruby19 send-more-money.rb > /dev/null
ruby19 send-more-money.rb > /dev/null  3.18s user 0.05s system 99% cpu 3.255 total