素数のマトリックス(Ruby)

アルゴリズム・パズルです。

問題:

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回です。
 

 

追記

もう少しエレガントにやってみようと思ったのですが…。

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)