From: Robert Dober Date: 2006-12-20T05:44:38+09:00 Subject: Re: [QUIZ] Chess960 (#106) ------=_Part_8865_23745272.1166559611016 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline As they say in France, there is no Two without Three, though it is much easier to prove the inverse theorem ;) The last one, promised. #!/usr/bin/ruby # This solution still uses Jim Weirich's Amb class # but this time it is inlined into the Chess960 class # and adapted for the exact problem. # As a matter of fact we do not use assert as # the constraints for the positions can be expressed # declaratively, all work Amb has to do is the callcc trick # to back up to the next solution # class Chess960 ExhaustedError = Class.new RuntimeError # We use objects which respond to #each already # optimize the calls so that we do not have to splat def choose(choices) choices.each { |choice| # avoid any duplicate positions if @free.delete( choice ) then callcc { |fk| @back << fk return choice } @free.unshift choice end } failure end def failure @back.pop.call end N = 8 Queen = ?Q King = ?K Rook = ?R Bishop = ?B attr_accessor :b1, :b2, :r1, :r2, :k, :q attr_reader :solutions # prepare the constraints LeftBishop = proc { @b1 = choose 1..N-1 } RightBishop = proc { @b2 = choose( (@b1.succ..N).select{ |b| b & 1 != @b1 & 1 } ) } LeftRook = proc { @r1 = choose 1..N-2 } SoleKing = proc { @k = choose @r1.succ..N-1 } RightRook = proc { @r2 = choose @k.succ..N } SoleQueen = proc { @q = choose 1..N save_solution } def initialize @free = [*1..8] @back = [ lambda { fail ExhaustedError } ] @solutions = [] init generate raise RuntimeError, "Illegal Number of solutions #{@solutions.length}" unless @solutions.length == 960 end def [] sol_nb @solutions[ sol_nb ] end private def init @sol="N " * N end # So all boils down to place the pieces ;) def generate instance_eval( &LeftBishop ) instance_eval( &RightBishop ) instance_eval( &LeftRook ) instance_eval( &SoleKing ) instance_eval( &RightRook ) instance_eval( &SoleQueen ) rescue ExhaustedError end def save_solution @sol[2*(b1-1)]= Bishop @sol[2*(b2-1)]= Bishop @sol[2*(r1-1)]= Rook @sol[2*(r2-1)]= Rook @sol[2*(q-1)]= Queen @sol[2*(k-1)]= King @solutions << @sol init # force another solution if there is one failure end end c = Chess960.new puts % until (n = gets.strip) =~ /^q/i if n =~ /^a/i then c.solutions.each_with_index do |sol, i| puts "%3d: %s" % [i, sol] end next end i = n.to_i i = rand(960) if n =~ /^r/i puts "%3d: %s" % [i, c [i]] end -- "The real romance is out ahead and yet to come. The computer revolution hasn't started yet. Don't be misled by the enormous flow of money into bad defacto standards for unsophisticated buyers using poor adaptations of incomplete ideas." - Alan Kay ------=_Part_8865_23745272.1166559611016--