Skip to content

Add word ladder algorithm in backtracking #11590

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* [Rat In Maze](backtracking/rat_in_maze.py)
* [Sudoku](backtracking/sudoku.py)
* [Sum Of Subsets](backtracking/sum_of_subsets.py)
* [Word Ladder](backtracking/word_ladder.py)
* [Word Search](backtracking/word_search.py)

## Bit Manipulation
Expand Down
76 changes: 76 additions & 0 deletions backtracking/word_ladder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""
Word Ladder is a classic problem in computer science.
The problem is to transform a start word into an end word
by changing one letter at a time.
Each intermediate word must be a valid word from a given list of words.
The goal is to find a transformation sequence
from the start word to the end word.

Wikipedia: https://en.wikipedia.org/wiki/Word_ladder
"""


def word_ladder_backtrack(
begin_word: str, end_word: str, word_list: list[str]
) -> list[str]:
"""
Solve the Word Ladder problem using Backtracking and return
the list of transformations from begin_word to end_word.

Parameters:
begin_word (str): The word from which the transformation starts.
end_word (str): The target word for transformation.
word_list (list[str]): The list of valid words for transformation.

Returns:
list[str]: The list of transformations from begin_word to end_word.
Returns an empty list if there is no valid transformation.

Example:
>>> word_ladder_backtrack("hit", "cog", ["hot", "dot", "dog", "lot", "log", "cog"])
['hit', 'hot', 'dot', 'lot', 'log', 'cog']

>>> word_ladder_backtrack("hit", "cog", ["hot", "dot", "dog", "lot", "log"])
[]

>>> word_ladder_backtrack("lead", "gold", ["load", "goad", "gold", "lead", "lord"])
['lead', 'lead', 'load', 'goad', 'gold']

>>> word_ladder_backtrack("game", "code", ["came", "cage", "code", "cade", "gave"])
['game', 'came', 'cade', 'code']
"""

# Step 1: Convert the word_list to a set for faster lookup
word_set = set(word_list)

# Step 2: If end_word is not in the word_list, return an empty list
if end_word not in word_set:
return []

# Step 3: Backtracking function to find the word ladder
def backtrack(current_word, path):
# Base case: If the current word is the end word, return the path
if current_word == end_word:
return path

# Try all possible single-letter transformations
for i in range(len(current_word)):
for c in "abcdefghijklmnopqrstuvwxyz": # Try changing each letter
transformed_word = current_word[:i] + c + current_word[i + 1 :]

# If the transformed word is valid and has not been visited
if transformed_word in word_set:
# Remove it from the set to avoid revisiting
word_set.remove(transformed_word)
# Recur with the new word added to the path
result = backtrack(transformed_word, [*path, transformed_word])
if result: # If we found a valid result, return it
return result
# Add it back to the set after exploring this path (backtrack)
word_set.add(transformed_word)

# If no valid path is found, return an empty list
return []

# Step 4: Start backtracking from the begin_word
return backtrack(begin_word, [begin_word])