In the Lights Out Puzzle class, write a method copy(self) that returns a new LightsOutPuzzle object initialized with a deep copy of the current board. Changes made to the original puzzle should not be reflected in the copy, and vice versa. >>> p = create_puzzle(3, 3) >>> p2 = p.copy() >>> p.get_board() == p2.get_board() True >>> p = create_puzzle(3, 3) >>> p2 = p.copy() >>> p.perform_move(1, 1) >>> p.get_board() == p2.get_board() False In the LightsOutPuzzle class, write a method successors(self) that yields all successors of the puzzle as (move, new-puzzle) tuples, where moves themselves are (row, column) tuples. The second element of each successor should be a new LightsOutPuzzle object whose board is the result of applying the corresponding move to the current board. The successors may be generated in whichever order is most convenient. >>> p = create_puzzle(2, 2) >>> for move, new_p in p.successors(): ... print(move, new_p.get_board()) ... (0, 0) [[True, True], [True, False]] (0, 1) [[True, True], [False, True]] (1, 0) [[True, False], [True, True]] (1, 1) [[False, True], [True, True]] >>> for i in range(2, 6): ... p = create_puzzle(i, i + 1) ... print(len(list(p.successors()))) ... 6 12 20 30 In the LightsOutPuzzle class, write a method find_solution(self) that returns an optimal solution to the current board as a list of moves, represented as (row, column) tuples. If more than one optimal solution exists, any of them may be returned. Your solver should be implemented using a breadth-first graph search, which means that puzzle states should not be added to the frontier if they have already been visited, or are currently in the frontier. If the current board is not solvable, the value None should be returned instead. You are highly encouraged to reuse the methods defined in the previous exercises while developing your solution. >>> p = create_puzzle(2, 3) >>> for row in range(2): ... for col in range(3): ... p.perform_move(row, col) ... >>> p.find_solution() [(0, 0), (0, 2)] >>> b = [[False, False, False], ... [False, False, False]] >>> b[0][0] = True >>> p = LightsOutPuzzle(b) >>> p.find_solution() is None True my code: import random class LightsOutPuzzle: def __init__(self, board): self.board = board self.rows = len(board) self.cols = len(board[0]) def get_board(self): return self.board def perform_move(self, row, col): self.toggle(row, col) self.toggle(row-1, col) self.toggle(row+1, col) self.toggle(row, col-1) self.toggle(row, col+1) def toggle(self, row, col): if 0 <= row < self.rows and 0 <= col < self.cols: self.board[row][col] = not self.board[row][col] def scramble(self): for row in range(self.rows): for col in range(self.cols): if random.random() < 0.5: self.perform_move(row, col) def is_solved(self): for row in range(self.rows): for col in range(self.cols): if self.board[row][col]: return False return True def create_puzzle(rows, cols): return LightsOutPuzzle([[False] * cols for _ in range(rows)]) # Test cases def run_tests(): # Test case 1 b = [[True, False], [False, True]] p = LightsOutPuzzle(b) assert p.get_board() == [[True, False], [False, True]] b = [[True, True], [True, True]] p = LightsOutPuzzle(b) assert p.get_board() == [[True, True], [True, True]]
In the Lights Out Puzzle class, write a method copy(self) that returns a new LightsOutPuzzle object initialized with a deep copy of the current board. Changes made to the original puzzle should not be reflected in the copy, and vice versa.
>>> p = create_puzzle(3, 3)
>>> p2 = p.copy()
>>> p.get_board() == p2.get_board()
True
>>> p = create_puzzle(3, 3)
>>> p2 = p.copy()
>>> p.perform_move(1, 1)
>>> p.get_board() == p2.get_board()
False
In the LightsOutPuzzle class, write a method successors(self) that yields all successors of the puzzle as (move, new-puzzle) tuples, where moves themselves are (row, column) tuples. The second element of each successor should be a new LightsOutPuzzle object whose board is the result of applying the corresponding move to the current board. The successors may be generated in whichever order is most convenient.
>>> p = create_puzzle(2, 2)
>>> for move, new_p in p.successors():
... print(move, new_p.get_board())
...
(0, 0) [[True, True], [True, False]]
(0, 1) [[True, True], [False, True]]
(1, 0) [[True, False], [True, True]]
(1, 1) [[False, True], [True, True]]
>>> for i in range(2, 6):
... p = create_puzzle(i, i + 1)
... print(len(list(p.successors())))
...
6
12
20
30
In the LightsOutPuzzle class, write a method find_solution(self) that returns an optimal solution to the current board as a list of moves, represented as (row, column) tuples. If more than one optimal solution exists, any of them may be returned. Your solver should be implemented using a breadth-first graph search, which means that puzzle states should not be added to the frontier if they have already been visited, or are currently in the frontier. If the current board is not solvable, the value None should be returned instead. You are highly encouraged to reuse the methods defined in the previous exercises while developing your solution.
>>> p = create_puzzle(2, 3)
>>> for row in range(2):
... for col in range(3):
... p.perform_move(row, col)
...
>>> p.find_solution()
[(0, 0), (0, 2)]
>>> b = [[False, False, False],
... [False, False, False]]
>>> b[0][0] = True
>>> p = LightsOutPuzzle(b)
>>> p.find_solution() is None
True
my code:
import random
class LightsOutPuzzle:
def __init__(self, board):
self.board = board
self.rows = len(board)
self.cols = len(board[0])
def get_board(self):
return self.board
def perform_move(self, row, col):
self.toggle(row, col)
self.toggle(row-1, col)
self.toggle(row+1, col)
self.toggle(row, col-1)
self.toggle(row, col+1)
def toggle(self, row, col):
if 0 <= row < self.rows and 0 <= col < self.cols:
self.board[row][col] = not self.board[row][col]
def scramble(self):
for row in range(self.rows):
for col in range(self.cols):
if random.random() < 0.5:
self.perform_move(row, col)
def is_solved(self):
for row in range(self.rows):
for col in range(self.cols):
if self.board[row][col]:
return False
return True
def create_puzzle(rows, cols):
return LightsOutPuzzle([[False] * cols for _ in range(rows)])
# Test cases
def run_tests():
# Test case 1
b = [[True, False], [False, True]]
p = LightsOutPuzzle(b)
assert p.get_board() == [[True, False], [False, True]]
b = [[True, True], [True, True]]
p = LightsOutPuzzle(b)
assert p.get_board() == [[True, True], [True, True]]
Step by step
Solved in 4 steps with 3 images