アルゴリズム・パズルです。
問題:
1 1 3 2 3 3 7 9 7 3桁の異なる素数3つを選びます。これら(例えば 113, 233, 797)を上のように横に行列で並べたとき(行を入れ替えたものは別の行列とみなします)、行列を縦に見て得られる3つの数(ここでは 127, 139, 337)がすべて 3桁の素数であるような選び方は何とおりあるでしょうか? ただし、最初に選んだ素数と縦に見て得られた素数あわせて6つは、すべて異ならなくてはなりません。
Ruby で解いてみました。
q45.rb
require 'prime' co = 0 prs = Prime.each(999).select {|i| i >= 100} prs.permutation(3) do |x| x1 = x.map(&:to_s) catch(:jump) do memo = [] 3.times do |i| n = (x1[0][i] + x1[1][i] + x1[2][i]).to_i throw(:jump) if x.include?(n) or memo.include?(n) or !prs.include?(n) memo << n end co += 1 end end puts co #=>29490
答えは 29490とおりです。時間は結構かかって、自分の環境だと 7秒くらいでした。特に工夫していないですからね。ちなみに、ループを回している回数は 3412145回です。
プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問
- 作者: 増井敏克
- 出版社/メーカー: 翔泳社
- 発売日: 2015/10/16
- メディア: Kindle版
- この商品を含むブログ (9件) を見る
追記
もう少しエレガントにやってみようと思ったのですが…。
require 'prime' table = (0..999).map {|i| Prime.prime?(i)} co = (100..999).select {|i| table[i]}.permutation(3).map do |rows| rs = rows.map(&:to_s) cols = 3.times.map {|i| rs.map {|s| s[i]}.join.to_i} next if (rows + cols).uniq.size != 6 cols.all? {|n| n >= 100 and table[n]} end.compact.count(true) puts co
これだと 14.5秒くらいかかりますね。最初の単純にやった方がだいぶ速いという結果でした。(2019/4/9)