From d80ee90178d48e530a2df3966fee3b5e06ec3ecc Mon Sep 17 00:00:00 2001 From: Khushi Shukla Date: Sun, 29 Oct 2023 02:43:14 +0530 Subject: [PATCH] Create crossword_puzzle_solver.py (#11011) * Create crossword_puzzle_solver.py * Update crossword_puzzle_solver.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update crossword_puzzle_solver.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update crossword_puzzle_solver.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update crossword_puzzle_solver.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update crossword_puzzle_solver.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update crossword_puzzle_solver.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update crossword_puzzle_solver.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update crossword_puzzle_solver.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update crossword_puzzle_solver.py * Update backtracking/crossword_puzzle_solver.py * Update crossword_puzzle_solver.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update crossword_puzzle_solver.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update crossword_puzzle_solver.py * Apply suggestions from code review * Update crossword_puzzle_solver.py * Update crossword_puzzle_solver.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- backtracking/crossword_puzzle_solver.py | 132 ++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 backtracking/crossword_puzzle_solver.py diff --git a/backtracking/crossword_puzzle_solver.py b/backtracking/crossword_puzzle_solver.py new file mode 100644 index 000000000..b9c01c4ef --- /dev/null +++ b/backtracking/crossword_puzzle_solver.py @@ -0,0 +1,132 @@ +# https://www.geeksforgeeks.org/solve-crossword-puzzle/ + + +def is_valid( + puzzle: list[list[str]], word: str, row: int, col: int, vertical: bool +) -> bool: + """ + Check if a word can be placed at the given position. + + >>> puzzle = [ + ... ['', '', '', ''], + ... ['', '', '', ''], + ... ['', '', '', ''], + ... ['', '', '', ''] + ... ] + >>> is_valid(puzzle, 'word', 0, 0, True) + True + >>> puzzle = [ + ... ['', '', '', ''], + ... ['', '', '', ''], + ... ['', '', '', ''], + ... ['', '', '', ''] + ... ] + >>> is_valid(puzzle, 'word', 0, 0, False) + True + """ + for i in range(len(word)): + if vertical: + if row + i >= len(puzzle) or puzzle[row + i][col] != "": + return False + else: + if col + i >= len(puzzle[0]) or puzzle[row][col + i] != "": + return False + return True + + +def place_word( + puzzle: list[list[str]], word: str, row: int, col: int, vertical: bool +) -> None: + """ + Place a word at the given position. + + >>> puzzle = [ + ... ['', '', '', ''], + ... ['', '', '', ''], + ... ['', '', '', ''], + ... ['', '', '', ''] + ... ] + >>> place_word(puzzle, 'word', 0, 0, True) + >>> puzzle + [['w', '', '', ''], ['o', '', '', ''], ['r', '', '', ''], ['d', '', '', '']] + """ + for i, char in enumerate(word): + if vertical: + puzzle[row + i][col] = char + else: + puzzle[row][col + i] = char + + +def remove_word( + puzzle: list[list[str]], word: str, row: int, col: int, vertical: bool +) -> None: + """ + Remove a word from the given position. + + >>> puzzle = [ + ... ['w', '', '', ''], + ... ['o', '', '', ''], + ... ['r', '', '', ''], + ... ['d', '', '', ''] + ... ] + >>> remove_word(puzzle, 'word', 0, 0, True) + >>> puzzle + [['', '', '', ''], ['', '', '', ''], ['', '', '', ''], ['', '', '', '']] + """ + for i in range(len(word)): + if vertical: + puzzle[row + i][col] = "" + else: + puzzle[row][col + i] = "" + + +def solve_crossword(puzzle: list[list[str]], words: list[str]) -> bool: + """ + Solve the crossword puzzle using backtracking. + + >>> puzzle = [ + ... ['', '', '', ''], + ... ['', '', '', ''], + ... ['', '', '', ''], + ... ['', '', '', ''] + ... ] + + >>> words = ['word', 'four', 'more', 'last'] + >>> solve_crossword(puzzle, words) + True + >>> puzzle = [ + ... ['', '', '', ''], + ... ['', '', '', ''], + ... ['', '', '', ''], + ... ['', '', '', ''] + ... ] + >>> words = ['word', 'four', 'more', 'paragraphs'] + >>> solve_crossword(puzzle, words) + False + """ + for row in range(len(puzzle)): + for col in range(len(puzzle[0])): + if puzzle[row][col] == "": + for word in words: + for vertical in [True, False]: + if is_valid(puzzle, word, row, col, vertical): + place_word(puzzle, word, row, col, vertical) + words.remove(word) + if solve_crossword(puzzle, words): + return True + words.append(word) + remove_word(puzzle, word, row, col, vertical) + return False + return True + + +if __name__ == "__main__": + PUZZLE = [[""] * 3 for _ in range(3)] + WORDS = ["cat", "dog", "car"] + + if solve_crossword(PUZZLE, WORDS): + print("Solution found:") + for row in PUZZLE: + print(" ".join(row)) + else: + print("No solution found:")