From: Daniel Finnie Date: 2006-12-19T12:27:42+09:00 Subject: Re: [QUIZ] Chess960 (#106) --Boundary_(ID_6svXY46JdpCkN+cKGpBBYA) Content-type: text/plain; charset=ISO-8859-1; format=flowed Content-transfer-encoding: 7BIT This is my solution. It makes use of my ArrayValue class which was discussed on the list previously. It calculate the placement of pieces for a certain number without first calculating the placement of the pieces for all numbers lower than it by using the following algorithm (found at http://frcec.tripod.com/fischerrandomchessstartingpositions/): 1. id % 4 * 2 = light square bishop (counting left to right 2. (id / 4) % 4 * 2 + 1 = dark square bishop ^ starting at 0) 3. (id / 4 / 6) % 6 = queen, number of vacant squares from the left 4. (id / 4 / 6) = KeRN code of the other pieces (see the website for more. The KeRN codes do have a pattern but I hard coded it). First, an explaination of the ArrayValue class. The code is below: daniel@daniel-desktop:~$ cat arrayvalue.rb class ArrayValue instance_methods.each do |m| undef_method(m) unless m =~ /^_*(method_missing|send|id)_*$/ end def initialize(origArray, origIndex) @origArray, @origIndex = origArray, origIndex end def set(newObj) @origArray[@origIndex] = newObj end def get @origArray[@origIndex] end def method_missing(method, *args) get.send(method, *args) rescue super end define_method(:'= ') {|other| set(other)} end class Array def to_av() ret = [] each_index {|x| ret << ArrayValue.new(self, x) } ret end end So, an ArrayValue stores the array and index it originally came from and it can edit/get those values. Otherwise, an ArrayValue inherits all of the methods of the value it represents because of the method_missing definition. One thing missing from the ArrayValue class is what to do if CRD (CRUD minus the U) operations are performed on the original array. Because of this, I recommend never actually storing an ArrayValue but creating them again every time you need one. Also, the array class is edited to provide a to_av method, which returns an array of ArrayValues. This is the only recommended way of creating ArrayValues. Note that Logan Capaldo wrote something with the same concept but that uses some tricks with arrays and overriding []= so that calling ArrayValue#Set is not necessary, you just go ArrayOfArrayValues[0]=Something and it changes the original array. Some uses of ArrayValue: daniel@daniel-desktop:~$ irb -r arrayvalue.rb irb(main):001:0> ary = [1, 2, 3, "a", :b] => [1, 2, 3, "a", :b] irb(main):002:0> ary.to_av[4].set("c") => "c" irb(main):003:0> ary => [1, 2, 3, "a", "c"] irb(main):005:0> ary.to_av.select{|x| x.kind_of?(Numeric)}.each{|x| x.set(42)} => [42, 42, 42] irb(main):006:0> ary => [42, 42, 42, "a", "c"] irb(main):013:0> ary = ["Skip me!", nil, nil, nil, 43] => ["Skip me!", nil, nil, nil, 43] irb(main):014:0> ary.to_av.select{|x| x.nil?}[1].set("The 2nd nil") => "The 2nd nil" irb(main):015:0> ary => ["Skip me!", nil, "The 2nd nil", nil, 43] Now to the real code: daniel@daniel-desktop:~$ cat chess960short.rb #! /usr/bin/ruby require 'arrayvalue.rb' KeRN = <<-END.split("\n").collect{|x| x.split(" ")} N N R K R N R N K R N R K N R N R K R N R N N K R R N K N R R N K R N R K N N R R K N R N R K R N N END id = ARGV[0].to_i % 960 out = Array.new(8) 1.downto(0) {|x| out[id % 4 *2 + x] = "B"; id /= 4 } out.to_av.select{|x| x.nil?}[id % 6].set("Q"); id /= 6 KeRN[id].each{ |currentPiece| out.to_av.select{|x| x.nil?}.first.set(currentPiece) } Another, commented and not written for brevity version will be posted shortly. Ruby Quiz wrote: > The three rules of Ruby Quiz: > > 1. Please do not post any solutions or spoiler discussion for this quiz until > 48 hours have passed from the time on this message. > > 2. Support Ruby Quiz by submitting ideas as often as you can: > > http://www.rubyquiz.com/ > > 3. Enjoy! > > Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone > on Ruby Talk follow the discussion. Please reply to the original quiz message, > if you can. > > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= > > by Kieran Wild > > Chess960, is a chess variant produced by Grandmaster Bobby Fischer by > formalizing the rules of Shuffle Chess. Its goal was to create a chess variant > in which chess creativity and talent would be more important than memorization > and analysis of opening moves. His approach was to create a randomized initial > chess position, which would thus make memorizing chess opening move sequences > far less helpful. The initial position is set up in a special way and there are > 960 such positions, thus the name Chess960. > > The starting position for Chess960 must meet certain rules. White pawns are > placed on the second rank as in chess. All remaining white pieces are placed > randomly on the first rank, but with the following restrictions: > > * The king is placed somewhere between the two rooks. > * The bishops are placed on opposite-colored squares. > > The black pieces are placed equal-and-opposite to the white pieces. For example, > if the white king is placed on b1, then the black king is placed on b8. Note > that the king never starts on file a or h, because there would be no room for a > rook > > Can I suggest a nice little ruby program to generates all 960 possible starting > positions and outputs a random one on request. > > Output could be as follows. > > Starting Position 432: > > White > > a1 b1 c1 d1 e1 f1 g1 h1 > N B B R K R Q N > > Black > > a8 b8 c8 d8 e8 f8 g8 h8 > N B B R K R Q N > > Or some better output. > > --Boundary_(ID_6svXY46JdpCkN+cKGpBBYA) Content-type: application/x-ruby; name=arrayvalue.rb Content-transfer-encoding: base64 Content-disposition: inline; filename=arrayvalue.rb Y2xhc3MgQXJyYXlWYWx1ZQoJaW5zdGFuY2VfbWV0aG9kcy5lYWNoIGRvIHxtfAoJCXVuZGVm X21ldGhvZChtKSB1bmxlc3MgbSA9fiAvXl8qKG1ldGhvZF9taXNzaW5nfHNlbmR8aWQpXyok LwoJZW5kCgkKCWRlZiBpbml0aWFsaXplKG9yaWdBcnJheSwgb3JpZ0luZGV4KQoJCUBvcmln QXJyYXksIEBvcmlnSW5kZXggPSBvcmlnQXJyYXksIG9yaWdJbmRleAoJZW5kCgkKCWRlZiBz ZXQobmV3T2JqKQoJCUBvcmlnQXJyYXlbQG9yaWdJbmRleF0gPSBuZXdPYmoKCWVuZAoJCglk ZWYgZ2V0CgkJQG9yaWdBcnJheVtAb3JpZ0luZGV4XQoJZW5kCgkKCWRlZiBtZXRob2RfbWlz c2luZyhtZXRob2QsICphcmdzKQoJCQlnZXQuc2VuZChtZXRob2QsICphcmdzKQoJCXJlc2N1 ZQoJCQlzdXBlcgoJZW5kCgkKCWRlZmluZV9tZXRob2QoOic9ICcpIHt8b3RoZXJ8IHNldChv dGhlcil9CmVuZAoKY2xhc3MgQXJyYXkKCWRlZiB0b19hdigpCgkJcmV0ID0gW10KCQllYWNo X2luZGV4IHt8eHwgcmV0IDw8IEFycmF5VmFsdWUubmV3KHNlbGYsIHgpIH0KCQlyZXQKCWVu ZAplbmQKCl9fRU5EX18KJSBjYXQgdmlldy5yYgpjbGFzcyBBcnJheVZpZXcKICBjbGFzcyBB cnJheUluZGV4UmVmCiAgICBkZWYgaW5pdGlhbGl6ZSggYXJyYXksIGluZGV4ICkKICAgICAg QGFycmF5ID0gYXJyYXkKICAgICAgQGluZGV4ID0gaW5kZXgKICAgIGVuZAoKICAgIGRlZiB2 YWx1ZQogICAgICBAYXJyYXlbQGluZGV4XQogICAgZW5kCgogICAgZGVmIHZhbHVlPShuZXdf dmFsdWUpCiAgICAgIEBhcnJheVtAaW5kZXhdID0gbmV3X3ZhbHVlCiAgICBlbmQKICBlbmQK CiAgZGVmIGluaXRpYWxpemUoIGFycmF5ICkKICAgIEBhcnJheSA9IGFycmF5CiAgICBAcmVm ZXJlbmNlcyA9IFtdCiAgZW5kCgogIGRlZiBbXSgqYXJncykKICAgIGlmIGFyZ3MubGVuZ3Ro ID09IDEgYW5kIGFyZ3Mua2luZF9vZj8gUmFuZ2Ugb3IgYXJncy5sZW5ndGggPiAxCiAgICAg IEByZWZlcmVuY2VzWyphcmdzXS5tYXAgeyB8eHwgeC52YWx1ZSB9CiAgICBlbHNlCiAgICAg IEByZWZlcmVuY2VzWyphcmdzXS52YWx1ZQogICAgZW5kCiAgZW5kCgogIGRlZiBbXT0oaW5k ZXgsIHZhbHVlKQogICAgQHJlZmVyZW5jZXNbaW5kZXhdLnZhbHVlID0gdmFsdWUKICBlbmQK CiAgZGVmIGVhY2gKICAgIEByZWZlcmVuY2VzLmVhY2ggZG8gfHh8CiAgICAgIHlpZWxkIHgu dmFsdWUKICAgIGVuZAogIGVuZAoKCiAgZGVmIGFkZF9yZWYoIGluZGV4ICkKICAgIEByZWZl cmVuY2VzIDw8IEFycmF5SW5kZXhSZWYubmV3KCBAYXJyYXksIGluZGV4ICkKICBlbmQKZW5k CgoKY2xhc3MgQXJyYXkKICBkZWYgc2VsZWN0X3ZpZXcKICAgIHIgPSBBcnJheVZpZXcubmV3 KCBzZWxmICkKICAgIGVhY2hfd2l0aF9pbmRleCBkbyB8aXRlbSwgaW5kZXh8CiAgICAgIHIu YWRkX3JlZiggaW5kZXggKSBpZiB5aWVsZCggaXRlbSApICAgICBlbmQKICAgIHIKICBlbmQK ZW5kCgphID0gKDEuLjEwKS50b19hCgpwIGEKYiA9IGEuc2VsZWN0X3ZpZXcgeyB8eHwgKHgg JSAyKS56ZXJvPyB9CmJbMF0gPSA0MgpwIGEKCiUgcnVieSB2aWV3LnJiClsxLCAyLCAzLCA0 LCA1LCA2LCA3LCA4LCA5LCAxMF0KWzEsIDQyLCAzLCA0LCA1LCA2LCA3LCA4LCA5LCAxMF0g --Boundary_(ID_6svXY46JdpCkN+cKGpBBYA) Content-type: application/x-ruby; name=chess960short.rb Content-transfer-encoding: base64 Content-disposition: inline; filename=chess960short.rb IyEgL3Vzci9iaW4vcnVieQpyZXF1aXJlICdhcnJheXZhbHVlLnJiJwoKS2VSTiA9IDw8LUVO RC5zcGxpdCgiXG4iKS5jb2xsZWN0e3x4fCB4LnNwbGl0KCIgIil9CglOIE4gUiBLIFIKCU4g UiBOIEsgUgoJTiBSIEsgTiBSCglOIFIgSyBSIE4KCVIgTiBOIEsgUgoJUiBOIEsgTiBSCglS IE4gSyBSIE4KCVIgSyBOIE4gUgoJUiBLIE4gUiBOCglSIEsgUiBOIE4KCUVORAoKaWQgPSBB UkdWWzBdLnRvX2kgJSA5NjAKb3V0ID0gQXJyYXkubmV3KDgpCjEuZG93bnRvKDApIHt8eHwg b3V0W2lkICUgNCAqMiArIHhdID0gIkIiOyBpZCAvPSA0IH0Kb3V0LnRvX2F2LnNlbGVjdHt8 eHwgeC5uaWw/fVtpZCAlIDZdLnNldCgiUSIpOyBpZCAvPSA2CktlUk5baWRdLmVhY2h7IHxj dXJyZW50UGllY2V8IG91dC50b19hdi5zZWxlY3R7fHh8IHgubmlsP30uZmlyc3Quc2V0KGN1 cnJlbnRQaWVjZSkgfQpwdXRzIG91dC5qb2lu --Boundary_(ID_6svXY46JdpCkN+cKGpBBYA)--