バカがいますよ
終端に到達する前に枝刈りすればいいなら,これでどうか.
1000回実行で,総当り61.891sec,早期枝刈りあり2.359sec (ちなみに条件チェックを省略した総当りバージョンは23.782sec)だった.
def pseud_amb(*ar, &block) result = [] amb_impl = lambda {|a, work| if a[0]==nil # 終端に到達 result.push( work.dup) else a[0].each {|d| tmp = work.dup.push(d) amb_impl[a[1..-1], tmp] if !block_given? || block[tmp] } end } amb_impl[ar, []] result end Baker = 0 Cooper = 1 Fletcher = 2 Miller = 3 Smith = 4 old = Process.times.utime p pseud_amb(1..5, 1..5, 1..5, 1..5, 1..5) {|a| ret = false if (a.uniq.size == a.size) case a.size when 1; ret = (a[Baker] != 5) when 2; ret = (a[Cooper] != 1) when 3; ret = (a[Fletcher] != 1 and a[Fletcher] != 5 and (a[Fletcher] - a[Cooper]).abs != 1) when 4; ret = (a[Miller] > a[Cooper]) when 5; ret = ((a[Smith] - a[Fletcher]).abs != 1) end end ret } p Process.times.utime - old