eight queens problem in Python

后端 未结 4 1378
自闭症患者
自闭症患者 2021-02-03 16:34

8-queens problem in Python.

Hi! I only start teaching Python, so could someone explain the code written below (found in the Internet)? Some pieces of the code are compli

相关标签:
4条回答
  • 2021-02-03 16:55

    Here is my solution. It is much more easier to understand and straighforward:

    def under_attack(row, column, existing_queens):
        if not len(existing_queens): return False
        for queen in existing_queens:
            if not len(queen):
                continue
            r,c = queen
            if r == row: return True # Check row
            if c == column: return True # Check column
            if (column-c) == (row-r): return True # Check left diagonal
            if (column-c) == -(row-r): return True # Check right diagonal
        return False
    
    def iter_solve(n):
        solutions = None
        for row in range(1, n+1):
            # for each row, check all valid column
            solutions = check(solutions, row, n)
        return solutions
    
    def check(solutions, row, n):
        new_solutions = []
        for column in range(1, n+1):
            if not solutions or not len(solutions):
                new_solutions.append([] + [(row, column)])
            else:
                for solution in solutions:
                    if not under_attack(row, column, solution):
                        new_solutions.append(solution + [(row, column)])
        return new_solutions
    
    0 讨论(0)
  • 2021-02-03 16:57

    This is the source program where the output of this code will be generated in the separate file name as "queen.txt"

    import json
    import sys
    
    BOARD_SIZE = 8
    
    def under_attack(col, queens):
        x = y = col
    
        for r, c in reversed(queens):
            x , y = x - 1, y + 1 #check for the prev queen location 
    
            if c in (x , col, y):
                return True
        return False
    
    def solve(n): # n is the number of queens to be placed
        if n == 0:
            return [[]]
    
        smaller_solutions = solve(n - 1)
    
        return [solution+[(n,i+1)]
            for i in xrange(BOARD_SIZE)
                for solution in smaller_solutions
                    if not under_attack(i+1, solution)] #call the function 
    
    former, sys.stdout = sys.stdout, open('queen.txt','w')
    
    for answer in solve(BOARD_SIZE):
        print answer
    
    results, sys.stdout = sys.stdout, former #former is used for ip & op
    print json.dumps(answer) #dumps is used to write in json file
    

    output file will like this [(1, 4), (2, 2), (3, 7), (4, 3), (5, 6), (6, 8), (7, 5), (8, 1)] [(1, 5), (2, 2), (3, 4), (4, 7), (5, 3), (6, 8), (7, 6), (8, 1)] [(1, 3), (2, 5), (3, 2), (4, 8), (5, 6), (6, 4), (7, 7), (8, 1)] . . . . [(1, 4), (2, 7), (3, 5), (4, 2), (5, 6), (6, 1), (7, 3), (8, 8)] [(1, 5), (2, 7), (3, 2), (4, 6), (5, 3), (6, 1), (7, 4), (8, 8)]

    0 讨论(0)
  • 2021-02-03 17:00

    Your code is wrong (cut and paste error?), but here's the gist:

    You want a list of possible solutions. Each solution is a list of queens. Every queen is a tuple - a row (integer) and column (integer). For example, the solution for BOARD_SIZE=1 is [[(1,1)]] - a single solution - [(1,1)] containing a single queen - (1,1) placed on row 1 and column 1.

    There are 8 smaller_solutions for BOARD_SIZE=8, and n=1 - [[(1,1)],[(1,2)],[(1,3)],[(1,4)],[(1,5)],[(1,6)],[(1,7)],[(1,8)]] - a single queen placed in every column in the first row.

    You understand recursion? If not, google it NOW.

    Basically, you start by adding 0 queens to a size 0 board - this has one trivial solution - no queens. Then you find the solutions that place one queen the first row of the board. Then you look for solutions which add a second queen to the 2nd row - somewhere that it's not under attack. And so on.

    def solve(n):
        if n == 0: return [[]] # No RECURSION if n=0. 
        smaller_solutions = solve(n-1) # RECURSION!!!!!!!!!!!!!!
        solutions = []
        for solution in smaller_solutions:# I moved this around, so it makes more sense
            for column in range(1,BOARD_SIZE+1): # I changed this, so it makes more sense
                # try adding a new queen to row = n, column = column 
                if not under_attack(column , solution): 
                    solutions.append(solution + [(n,column)])
        return solutions
    

    That explains the general strategy, but not under_attack.

    under_attack could be re-written, to make it easier to understand (for me, you, and your students):

    def under_attack(column, existing_queens):
        # ASSUMES that row = len(existing_queens) + 1
        row = len(existing_queens)+1
        for queen in existing_queens:
            r,c = queen
            if r == row: return True # Check row
            if c == column: return True # Check column
            if (column-c) == (row-r): return True # Check left diagonal
            if (column-c) == -(row-r): return True # Check right diagonal
        return False
    

    My method is a little slower, but not much.

    The old under_attack is basically the same, but it speeds thing up a bit. It looks through existing_queens in reverse order (because it knows that the row position of the existing queens will keep counting down), keeping track of the left and right diagonal.

    0 讨论(0)
  • 2021-02-03 17:12
    BOARD_SIZE = 8
    
    def under_attack(col, queens): # You do not need to fill in these fields. This is a helper function for the solve function.
        left = right = col
        for r, c in reversed(queens): # Reversing queens causes them to be iterated over in reverse order.
            left, right = left-1, right+1
            if c in (left, col, right):
                return True
        return False
    
    def solve(n):
        if n == 0: return [[]]
        smaller_solutions = solve(n-1) # It appears that in solving this board, it solves all boards smaller than it in a recursive manner.
        return [solution+[(n,i+1)] # This line appears to be in error. Have you run this code and verified that it runs correctly?
            for i in range(BOARD_SIZE)
                for solution in smaller_solutions
                    if not under_attack(i+1, solution)]
    for answer in solve(BOARD_SIZE): print answer
    
    0 讨论(0)
提交回复
热议问题