1

Having watched the Computerphile video on backtracking, I've decided to attempt to implement this algorithm for a different problem. My code seems to work up until depth ~48 when it starts to endlessly iterate through depth 46-53. It is not a problem of memory, as for a 6x6 table it gets stuck similarly around depth 20.

table = np.zeros((8, 8)) - 1
table[0, 0] = 0
knightDOWN = [1, 2, 2, 1, -1, -2, -2, -1]
knightRIGHT = [2, 1, -1, -2, -2, -1, 1, 2]
depth = 0
def correctmove(move, startROW, startCOL):
    newROW = startROW + knightDOWN[move]
    newCOL = startCOL + knightRIGHT[move]
    if newROW < 0 or newROW > 7:
        return False
    if newCOL < 0 or newCOL > 7:
        return False
    if table[newROW, newCOL] != -1:
        return False
    return True

def goBoard(startROW, startCOL, nummove):
    if depth == 64:
        print(table)
        exit()
    for x in range(0, 8):
        if correctmove(x, startROW, startCOL):
            print(table[startROW, startCOL])
            startROW += knightDOWN[x]
            startCOL += knightRIGHT[x]
            table[startROW, startCOL] = nummove
            nummove += 1
            goBoard(startROW, startCOL, nummove)
            table[startROW, startCOL] = -1
            startROW -= knightDOWN[x]
            startCOL -= knightRIGHT[x]
            nummove -= 1
    return
goBoard(0, 0, 0)

The code is basically supposed to check whether it can go with the knight to some new position, do it until it cannot move forward anymore and at this point the part of code after recursion call resets it back again. After seeing sample tables it seems to correctly create those first 50 or so tries but gets stuck on those and iterates over and over.

false
  • 10,264
  • 13
  • 101
  • 209

1 Answers1

0

This should take a long time, and backtrack a lot, as you're using a brute force algorithm that needs to exhaust a lot of possibilities.

In your code I don't see where depth is incremented though it's redundant with nummove which should start at 1, not 0, as you've already made move 0. I reworked your code to return a result, rather than print and exit, removed numpy, rewriting it in straight Python instead, and simplified it a bit -- undoing fewer steps:

KNIGHT_MOVES = [(1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1), (-2, 1), (-1, 2)]

table = [[-1] * 8 for _ in range(8)]

table[0][0] = 0

def correctmove(row, col):
    return 0 <= row <= 7 and 0 <= col <= 7 and table[row][col] == -1

def goBoard(startROW, startCOL, nummove):
    if nummove == 64:
        return table

    for down, right in KNIGHT_MOVES:
        row = startROW + down
        col = startCOL + right

        if correctmove(row, col):
            print(nummove)

            table[row][col] = nummove
            result = goBoard(row, col, nummove + 1)

            if result:
                return result

            table[row][col] = -1

    return None

print(*goBoard(0, 0, 1), sep='\n')

After about 2 1/3 minutes, it produces the following (slightly hand reformatted):

[ 0, 37, 58, 35, 42, 47, 56, 51]
[59, 34,  1, 48, 57, 50, 43, 46]
[38, 31, 36, 41,  2, 45, 52, 55]
[33, 60, 39, 26, 49, 54,  3, 44]
[30,  9, 32, 61, 40, 25, 22, 53]
[17, 62, 27, 10, 23, 20, 13,  4]
[ 8, 29, 18, 15,  6, 11, 24, 21]
[63, 16,  7, 28, 19, 14,  5, 12]
cdlane
  • 40,441
  • 5
  • 32
  • 81
  • Not sure why it didn't show up in my inbox, but this is a great answer. I worked with my code for a while the next day and realised that what you said was true - it was correct (or maybe I did some fixes, not sure) but ultimately I just didn't give it time to get the solution. Your code still taught me a damn lot, especially how you one-lined the correct move function and simplified the hell of the main function. Thank you and sorry for late answer! – Hubert Janczak Oct 20 '20 at 17:08