Reputation: 2396
I'm trying to the knights tour problem as an exercise in recursion since I have not used it in awhile, but my script does not seem to find a solution and only goes as high as 56 moves. Any tips to point me in the right direction would be appreciated.
class KnightsTour
def initialize
board = [nil, nil, nil, nil, nil, nil, nil, nil]
8.times do |i|
board[i] = [0, 0, 0, 0, 0, 0, 0, 0]
end
tour(0,0,board)
end
def tour(x,y,board,current_move=0)
puts board if current_move == 64
return if board[x] == nil ||
board[x][y] == nil ||
board[x][y] != 0 ||
x < 0 ||
y < 0 ||
current_move == 64
current_move +=1
board[x][y] = current_move
tour(x+2, y+1, board.dup, current_move)
tour(x+2, y-1, board.dup, current_move)
tour(x+1, y-2, board.dup, current_move)
tour(x-1, y-2, board.dup, current_move)
tour(x-1, y+2, board.dup, current_move)
tour(x+1, y+2, board.dup, current_move)
tour(x-2, y+1, board.dup, current_move)
tour(x-2, y-1, board.dup, current_move)
end
end
KnightsTour.new
Upvotes: 1
Views: 201
Reputation: 1
def is_safe?(solution, x, y)
x >= 0 && x < solution.length && y>= 0 && y < solution.length && solution[x][y] == -1
end
def solve_nt_helper(size, solution, curr_x, curr_y, num, xmoves, ymoves)
return true if num == size * size
size.times.each do |i|
# p "i:#{i}"
next_x = curr_x + xmoves[i]
next_y = curr_y + ymoves[i]
if is_safe?(solution, next_x, next_y)
solution[next_x][next_y] = num
return true if solve_nt_helper(size, solution, next_x, next_y, num + 1, xmoves, ymoves)
solution[next_x][next_y] = -1
end
end
# p "failed at num #{num}"
false
end
def solve_nt(n)
xmoves = [2, 1, -1, -2, -2, -1, 1, 2]
ymoves = [1, 2, 2, 1, -1, -2, -2, -1]
solution = Array.new(n) { Array.new(n) { -1 } }
solution[0][0] = 0
solution.each do |row|
p row
end
return 'invalid' unless solve_nt_helper(n, solution, 0, 0, 1, xmoves, ymoves)
solution.each do |row|
p row
end
solution
end
n = 8
require 'memory_profiler'
report = MemoryProfiler.report do
solve_nt(n)
end
report.pretty_print
here is a ruby version that works. The trick of this solution is
trick 1 also seems to applicalbe to java and python.did not try item2 for java and python. The algorithm is borrowed from geekstogeeks
Upvotes: 0
Reputation: 54223
The main problem is that you only use one board
object for all the recursions. You should use a copy of board
anytime you try a move. dup
produces a shallow copy, and isn't enough to duplicate the board.
Another problem might be that the bruteforce approach is too slow because of exponential growth (8 moves at every iteration, even if you stop early for some).
The usual approach is to pick the cell having the fewest possibilities as the next move.
Upvotes: 1