-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathis_boggleable.py
More file actions
64 lines (50 loc) · 2.02 KB
/
is_boggleable.py
File metadata and controls
64 lines (50 loc) · 2.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/python
"""
Check if a word can be formed using the letters on a Boggle board.
"""
import click
from helpers import normalize_qu, boggle_dice
# Convert each die into a set of faces (lowercased).
# String dice become single-char sets; the tuple die preserves "qu" as one face.
dice_faces = [{face.lower() for face in die} for die in boggle_dice]
def can_form_word(word):
"""Return True if the word can be spelled using the 16 Boggle dice.
Each die may only be used once. This is a constraint-satisfaction problem:
assign one die to each letter such that no die is reused. A backtracking
search tries each available die for the current letter, recurses on the
rest of the word, and undoes the choice if it leads to a dead end.
"""
try:
chars = list(normalize_qu(word.lower()))
except ValueError:
return False
def backtrack(index, used):
"""Recursively assign dice to letters starting at index.
Backtracking works by making a tentative choice (marking a die as
used), then exploring whether the remaining letters can be satisfied.
If they can't, the choice is undone (the die is removed from 'used')
and the next candidate die is tried. This exhaustive search guarantees
a solution is found if one exists.
"""
if index == len(chars):
return True
char = chars[index]
# Iterate over each die face
for i, face in enumerate(dice_faces):
if i not in used and char in face:
# Use this die face
used.add(i)
if backtrack(index + 1, used):
return True
# Backtrack
used.remove(i)
return False
# Start backtracking from the first character of the word
return backtrack(0, set())
@click.command()
@click.argument("word")
def cli(word):
"""Check if a word can be formed using the 16 Boggle dice."""
click.echo(can_form_word(word))
if __name__ == "__main__":
cli()