-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathmain.py
98 lines (72 loc) · 2.03 KB
/
main.py
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
from sys import stdin
from collections import deque
ALPHABET = "abcdefghijklmnopqrstuvwxyz"
def readdict():
d = set()
while True:
word = stdin.readline().strip()
if len(word) == 0:
break
d.add(word)
return d
def readwords():
cases = []
while True:
case = tuple(stdin.readline().split())
if not case:
break
cases.append(case)
return cases
def word_mods(w, dictionary):
"""Return list of all valid step modifications from a given word"""
mods = []
for pos in range(len(w)):
for c in ALPHABET:
word = w[:pos]+c+w[(pos+1):]
if word in dictionary and word!=w:
mods.append(word)
return mods
def find_solution(start, end, dictionary):
"""Use BFS to find shortest path from start to end words"""
if start == end:
return [start, end]
# Add endword to dictionary
add_end = end not in dictionary
if add_end:
dictionary.add(end)
# BFS Search
parent = {}
q = deque([start])
while q:
word = q.popleft()
if word == end:
break
# Enqueue word mods that haven't been reached yet.
for w in word_mods(word, dictionary):
if w not in parent:
parent[w] = word
q.append(w)
# Restore dictionary to original state
if add_end:
dictionary.remove(end)
if word != end:
return []
# Reconstruct modification path
path = [word]
while parent[word]!= start:
path.append(parent[word])
word = parent[word]
path.append(start)
return list(reversed(path))
if __name__ == '__main__':
dictionary = readdict()
words = list(reversed(readwords()))
while words:
start, end = words.pop()
sequence = find_solution(start, end, dictionary)
if not sequence:
print('No solution.')
else:
[print(w) for w in sequence]
if words:
print()