How to solve problems with backtracking
Problem:
In the last round of dungeons and dragons the DM told us a riddle:
The goal ist to fill it out in a way, that in every row and in every column and in every diagonal line no two letters appear twice.
As the nerd I am, I solved the problem with a backtracking algorithm:
Backtracking is a general algorithm for finding all (or some) solutions to some computational problems, notably constraint satisfaction problems, that incrementally builds candidates to the solutions, and abandons a candidate („backtracks“) as soon as it determines that the candidate cannot possibly be completed to a valid solution.
Wikipedia, 13.04.2021
Code:
problem = [ ["A" ,"B" ,"C" ,"D" ,"E" ,"F" ], [None,None,None,None,None,None], [None,None,False,False,None,None], [None,None,False,False,None,None], [None,None,None,None,None,None], [None,None,None,None,None,None] ] def isRow(p,r,v) : # Checks, if the value v is in p at row r for i in p[r] : if i == v : return True return False def isColumn(p,c,v) : # Checks, if the value v is in p at column c for i in range(6) : if p[i][c] == v : return True return False def isDiagonal(p,r,c,v) : # Checks, if the value v is in p in the diagonals from position r and c pos = [r-1,c-1] # Check the top left values while pos[0] >= 0 and pos[1] >= 0 : if p[pos[0]][pos[1]] == v : return True pos = [pos[0]-1,pos[1]-1] pos = [r-1,c+1] # Check the top right values while pos[0] >= 0 and pos[1] <= 5 : if p[pos[0]][pos[1]] == v : return True pos = [pos[0]-1,pos[1]+1] pos = [r+1,c+1] # Check the bottom right values while pos[0] <= 5 and pos[1] <= 5 : if p[pos[0]][pos[1]] == v : return True pos = [pos[0]+1,pos[1]+1] pos = [r+1,c-1] # Check the right left values while pos[0] <= 5 and pos[1] >= 0 : if p[pos[0]][pos[1]] == v : return True pos = [pos[0]+1,pos[1]-1] return False def res(p,r=0,c=0) : values = ["A","B","C","D","E","F"] if r == 5 and c == 5 : # If last Value if p[r][c] == None : # And it is empty for v in values : # Check for every value if not (isRow(p,r,v) + isColumn(p,c,v) + isDiagonal(p,r,c,v)) : # Checks, if v can be placed at (r,c) p[r][c] = v # Insert value for j in p : # Does the printing and formatting str = " " for k in j : if k == False : str += " " else : str += k + " " print(str) print() p[r][c] = None # Resets the position for cleaning elif p[r][c] == None : for v in values : if not (isRow(p,r,v) + isColumn(p,c,v) + isDiagonal(p,r,c,v)) : p[r][c] = v if c == 5 : res(p,r+1,0) # If last value in row jump one down else : res(p,r,c+1) # else next value p[r][c] = None else : if c == 5 : res(p,r+1,0) else : res(p,r,c+1) res(problem)
Result:
A B C D E F C F E B A D E A F B B D C E F C B E D A D E A F B C A B C D E F C F E B A D E A F B B D C E F C B E D A D E F A B C A B C D E F D E A F B C B C D A F D C E C A E B F D E F D C A B A B C D E F D E A F B C B C D E F D C A C A E B F D E F D C A B A B C D E F D E A F B C F C D A B D C E C A B E F D E F D C A B A B C D E F D E A F B C F C D A B D C E C A E B F D E F D C A B A B C D E F D E A F B C F C D E B D C A C A E B F D E F D C A B A B C D E F D E F A B C F C D A B D C E C A B E F D E F D C A B A B C D E F D E F A B C F C D A B D C E C A E B F D E F D C A B A B C D E F D E F B A C F C D B B A C E C D B E F A E F A C B D A B C D E F D E F B C A F C D B B D A E C A B E F D E F D A B C A B C D E F D F E A B C E C D A B D F E F A B E C D C E D F A B A B C D E F D F E B A C E A D B B C F E F D B E C A C E A F B D A B C D E F D F E B A C E A F B B C D E F D B E C A C E A F B D A B C D E F D F E B A C E A F B B C D E F D B E C A C E F A B D A B C D E F D F E B A C E C D B B A F E F D B E C A C E A F B D A B C D E F D F E B A C E C D B B D F A F E B A C D C A D F B E A B C D E F D F E B A C E C D B F A C E C D F E B A B E A C F D A B C D E F D F E B A C E C D B F D C A C E F A B D B A D C F E A B C D E F D F E B A C E C F B B A D E F D B E C A C E A F B D A B C D E F D F E B C A E C D B F D A E C A F E B D B E D A F C A B C D E F F D E A B C E C D A B F C E C A B E F D D E F C A B A B C D E F F D E B A C E C D B B F C A C E B A F D D A F C B E A B C D E F F D E B C A E C D B B F A E C A B E F D D E F A B C