From: Pedro Date: 2005-05-25T06:33:24+09:00 Subject: Re: [QUIZ] Tiling Turmoil (#33) Here's my solution, and without googling!. I'm new in Ruby, and I have a little doubt in my solution. The to_s method is too slow in the way I implemented it, Is there any better approach?. class Board def initialize(n) @w = 2**n; @tiles = Array.new(4**n, '0') end # Solve a board indicating row and column of the missing tile def solve(xm, ym) @count = 0 @tiles[getPos(xm, ym)] = 'X' solve_r(0, 0, xm, ym, @w) end # n: position of the tromino (upper left corner) # miss: tile shouldn't be marked # code: character writed in each position, but in miss. def setTromino(n, miss, code) [0, 1, @w, @w+1].each { |i| @tiles[n+i] = code if miss!=n+i } end # # Transform coordinates # def getPos(i, j) return i*@w+j end # Warning: this is too slow (Why?) # Avoid this method in benchmarks def to_s cad = '' @tiles.each_index { |i| cad += @tiles[i] + ' ' cad += "\n" if i%@w==@w-1 } return cad end private =begin This is a Divide and Conquer solution. Base case: 2x2 board. Solution is trivial in this case 0 X 0 0 General case: NxN board. We solve the 4 subboards following this scheme: p.e: 4x4 0 0 0 X 0 S 0 0 0 S S 0 0 0 0 0 We solve 4 2x2 boards. If the selected tile X is in the subboard, we solve it normally. If not, we solve supossing selected tiles are the marked as S. Finally, in the place of S, we put another tromino, and the board is solved. =end def solve_r(x0, y0, xm, ym, n) if(n==2) setTromino(getPos(x0, y0), getPos(xm, ym), @count.to_s) @count += 1 return end n/=2 s = [] # Position for missing tile in the S tromino [[0, 0], [0, n], [n, 0], [n, n]].each { |d| # (x1, y1): upper left corner of the subboard # (dx, dy): position of S in the subboard x1, y1, dx, dy = x0+d[0], y0+d[1], x0+(d[0]==0 ? n-1:n), y0+(d[1]==0 ? n-1:n) if((x1...x1+n).include?(xm) && (y1...y1+n).include?(ym)) s = [dx, dy] solve_r(x1, y1, xm, ym, n) else solve_r(x1, y1, dx, dy, n) end } setTromino(getPos(x0+n-1, y0+n-1), getPos(s[0], s[1]), @count.to_s) @count += 1 end end if ARGV.length == 2 b = Board.new(3) b.solve(ARGV[0].to_i, ARGV[1].to_i) puts b.to_s end