0% found this document useful (0 votes)
8 views100 pages

Week 6 Leacture

NPTEL

Uploaded by

viloje7980
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF or read online on Scribd
0% found this document useful (0 votes)
8 views100 pages

Week 6 Leacture

NPTEL

Uploaded by

viloje7980
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF or read online on Scribd
You are on page 1/ 100
Backtracking * Systematically search for a solution * Build the solution one step at a time * If we hit a dead-end * Undo the last step * Try the next option Eight queens * Place 8 queens on a chess board so that none of them attack each other * In chess, a queen can move any number of squares along a row column or diagonal N queens e Place N queens on an N x N chess board so that none attack each other ° N= 2, 3 impossible * N= 4is possible ° And all bigger N as well Q Q Q 8 queens * Clearly, exactly one queen in each row, column « Place queens row by row * In each row, place a queen in the first available column ° Can't place a queen in the 8th row! Backtracking * Keep trying to extend the next solution * If we cannot, undo previous move and try again * Exhaustively search through all possibilities « ... but systematically! Coding the solution * How do we represent the board? * nxn grid, number rows and columns from @ to n-1 * board[i][}] = 1 indicates queen at (i,j) * board[i][j] == @ indicates no queen * We know there is only one queen per row * Single list board of length n with entries @ to n-1 * board[i] == j : queen in row 1, column j, i.e. (i, }) Overall structure def placequeen(i,board): # Trying row i for each c such that Ci,c) ts available: place queen at (1,c) and update board if i == n-1: return(True) # Last queen has been placed else: extendsoln = placequeen(i+1, board) if extendsoln: return(True) # This solution extends fully else: undo this move and update board else: return(False) # Row i failed Backtracking * Systematically search for a solution * Build the solution one step at a time « If we hit a dead-end * Undo the last step * Try the next option Coding the solution * How do we represent the board? * nx ngnd, number rows and columns from @ to n-1 * board[i][}] = 1 indicates queen at (i,j) * board[i][j] — @ indicates no queen * We know there is only one queen per row * Single list board of length n with entnes 0 to n-1 * board[i] == j : queen in row 1, column j, ie. (i,j) Overall structure def placequeen(i,board): # Trying row i for each c such that Ci,c) ts available: place queen at (1,c) and update board if i == n-1: return(True) # Last queen has been placed else: extendsoln = placequeen(i+1, board) if extendsoln: return(True) # This solution extends fully else: undo this move and update board else: return(False) # Row i failed Updating the board * Our 1-D and 2-D representations keep track of the queens * Need an efficient way to compute which squares are free to place the next queen * nxnattack grid * attack(iJ[)] == lif (i,)}) is attacked by a queen * attack{.J[j] == @if (1,)) is currently available * How do we undo the effect of placing a queen? Updating the board * Our 1-D and 2-D representations keep track of the queens * Need an efficient way to compute which squares are free to place the next queen * nxnattack grid * attack(t][j] == Lif (i,}) is attacked by a queen * attack[.][}] == Oif (1,3) ts currently available * How do we undo the effect of placing a queen? * Which attack[i1][j}] should be reset to 0? Updating the board * Queens are added row by row * Number the queens 0 to n-1 * Record earliest queen that attacks each square * attack[1)[j] == kif (.,)) was first attacked by queen k * attack[i}[j] == -1if (i,j) is free * Remove queen k — reset attack(iJ][{j] == kto-1 * All other squares still attacked by earlier queens Updating the board * Queens are added row by row * Number the queens 0 to n-1 « Record earliest queen that attacks each square * attack[ij[j] == kif (1, )) was first attacked by queen k * attack[iJ[j] = -1if (i,j) is free * Remove queen k — reset attack({i][j] == kto-1 * All other squares still attacked by earlier queens A better representation * How many queens attack row i? * How many queens attack row j? * An individual square (i,j) is attacked by upto 4 queens | * Queen on row i and on column j * One queen on each diagonal through (i,j) Numbering diagonals Decreasing diagonal: column - row is invariant Increasing diagonal: column + row is invariant (ij) is attacked if * row iis attacked * column j is attacked * diagonal j-i is attacked * diagonal j+i is attacked NOWhe Wn =o 01234567 c+er=12 Numbering diagonals Decreasing diagonal: column - row is invariant Increasing diagonal: column + row is invanant (i,j) is attacked if * row jis attacked * column | is attacked * diagonal j-i is attacked * diagonal j+i is attacked NOOewn—o t-0 01234567 c+r=12 O(n) representation * row{i] «= 1 if row’ is attacked, @. .N-1 * col{i] == 1 if column iis attacked, 0. .N-1 * NWtoSE[i] == 1 if NW to SE diagonal i is \ attacked, -(N-1) to (N-1) y Updating the board * Ci,)) is free if row[t J==col[j]==NitoSE[j-i]==SWtoNE[j+i]=-0 * Add queen at (i,j) board[i} = 3 Crow[t),collj] ,NWtoSE[j-1],SWtoNE[j+i]) = (1,1,1,1) * Remove queen at (i,j) board[i] = -1 Crow[i],col[j] ,NWtoSE[}-1],SWtoNE[j+i]) = (8,0,0,0) Overall structure def placequeen(i,board: # Trying row i for each ¢ such that Ci,c) is available: place queen ot (i,¢) and update board if i == n-1: return(True) # Last queen has been placed else: extendsoln = placequeen(i+1,board) if extendsoln: return(True) # This solution extends fully else: undo this move and update board else: return(False) # Row i failed Implementation details * Maintain board as nested dictionary board[ ‘queen’ ][i] = ) : Queen located at (i,j) board["row'){i] = 1: Row i attacked board[‘col'][i} = 1: Column: attacked board['nwtose'}[i] = 1: NWtoSW diagonal 1 attacked board['swtone'J[i] = 1: SWtoNE diagonal i attacked Updating the board * Ci, )) Is free if row[i ]==col [j] ==NitoSE[j-i]--SWtoNE[j+i]--0 * Add queen at (i, )) board[i} = j CrowLi],col[j] ,NWtoSE[}-1],SWtoNE[}j+i]) = d1,2,1,1) + Remove queen at (i, 3) board[i] = -1 Crow[i],col(j] ,NWtoSE(j-i],SWtoNE(j+1]) = (@,0,0,0) ag return ee) ane - PeL eo a Ea [rem Pe a a) [osmY All solutions? def placequeen(i,board): # Try row i for each c such that (i,c) is available: place queen at (i,c) and update board if i s= n-1; record solution # Last queen placed else: extendsoln = placequeen(i+1,board) undo this move and update board placequeen( 0, box tatoo) ee eee pier TE | Recall 8 queens def placequeen(i,board: # Trying row i for each ¢ such that (i,c) is available: place queen at (i,c) and update board if i == n-1: return(True) # Last queen has been placed else: extendsoln = placequeen(1+1,board) if extendsoln: return(True) # This solution extends fully else: undo this move and update board else: return(False) # Row i failed Global variables * Can we avoid passing board explicitly to each function? * Can we have a single global copy of board that all functions can update? Scope of name * Scope of name is the portion of code where it is available to read and update * By default, in Python, scope is local to functions * But actually, only if we update the name inside the function Two examples def FQ: y = (x) vnt(y) we. ? Oo Global variables * Actually, this applies only to immutable values Global variables * Actually, this applies def f(): only to immutable y « x{@] values print(y) x[{@] = 22 x = [7] FO Recall 8 queens def placequeen(i , board} # Trying row i for each c such that (i,c) is availeble: place queen at (i,c) and update board if i == n-1: return(True) # Last queen has been placed else: extendsoln = placequeen(1+1,board) if extendsoln: return(True) # This solution extends fully else: undo this move and update board else: return(False) # Row i failed Global variables + Can we avoid passing board explicitly to each function? * Can we have a single global copy of board that all functions can update? Two examples def FO: y = &) oo Xa? FO roe eo hot mez) | Two examples def fC): def F(): y=x vee print(y) print(y) x = 22 x=7 se) x=? Fine! FO Two examples def f(): def f(): yer y=x print(y) print(y) x = 22 x= 7 fO x=7 Fine! fC) Error! * If x is not found in f(), Python looks at enclosing function for global x Two examples def f(): def f(): ye y=x print(y) print(y) x = 22 xa 7 FQ) x= 7 FO Error! * If x is not found in f(), Python looks at enclosing function for global x * If x is updated in fC), it becomes a local name!

You might also like