Skip to content

Commit 5f0d199

Browse files
committed
756 Pyramid Transition Matrix
1 parent 9ff06d4 commit 5f0d199

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

756 Pyramid Transition Matrix.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#!/usr/bin/python3
2+
"""
3+
We are stacking blocks to form a pyramid. Each block has a color which is a one
4+
letter string.
5+
6+
We are allowed to place any color block C on top of two adjacent blocks of
7+
colors A and B, if and only if ABC is an allowed triple.
8+
9+
We start with a bottom row of bottom, represented as a single string. We also
10+
start with a list of allowed triples allowed. Each allowed triple is represented
11+
as a string of length 3.
12+
13+
Return true if we can build the pyramid all the way to the top, otherwise false.
14+
15+
Example 1:
16+
17+
Input: bottom = "BCD", allowed = ["BCG", "CDE", "GEA", "FFF"]
18+
Output: true
19+
Explanation:
20+
We can stack the pyramid like this:
21+
A
22+
/ \
23+
G E
24+
/ \ / \
25+
B C D
26+
27+
We are allowed to place G on top of B and C because BCG is an allowed triple.
28+
Similarly, we can place E on top of C and D, then A on top of G and E.
29+
30+
31+
Example 2:
32+
33+
Input: bottom = "AABA", allowed = ["AAA", "AAB", "ABA", "ABB", "BAC"]
34+
Output: false
35+
Explanation:
36+
We can't stack the pyramid to the top.
37+
Note that there could be allowed triples (A, B, C) and (A, B, D) with C != D.
38+
39+
40+
Note:
41+
42+
bottom will be a string with length in range [2, 8].
43+
allowed will have length in range [0, 200].
44+
Letters in all strings will be chosen from the set {'A', 'B', 'C', 'D', 'E',
45+
'F', 'G'}.
46+
"""
47+
import itertools
48+
from typing import List
49+
from collections import defaultdict
50+
51+
52+
class Solution:
53+
def pyramidTransition(self, bottom: str, allowed: List[str]) -> bool:
54+
"""
55+
Need search, since multiple placements are possible
56+
The order of allowed matters
57+
"""
58+
T = defaultdict(set) # transition matrix
59+
for a, b, c in allowed:
60+
T[a, b].add(c)
61+
62+
return self.dfs(T, bottom)
63+
64+
def dfs(self, T, level) -> bool:
65+
if len(level) == 1:
66+
return True
67+
68+
# for nxt_level in self.gen_nxt_level(T, level, 0):
69+
for nxt_level in itertools.product(
70+
*[T[a, b] for a, b in zip(level, level[1:])]
71+
):
72+
if self.dfs(T, nxt_level):
73+
return True
74+
75+
return False
76+
77+
def gen_nxt_level(self, T, level, lo):
78+
"""
79+
equiv to itertools.product - nested for-loops in a generator expression
80+
Cartesian product
81+
"""
82+
if lo + 1 >= len(level):
83+
yield ""
84+
return
85+
86+
for head in T[level[lo], level[lo + 1]]:
87+
for tail in self.gen_nxt_level(T, level, lo + 1):
88+
yield head + tail
89+
90+
91+
def dfs_deep(self, T, level, lo, nxt_level) -> bool:
92+
if lo + 1 == len(level):
93+
return True
94+
95+
for nxt in T[level[lo], level[lo + 1]]:
96+
nxt_level.append(nxt)
97+
if self.dfs(T, level, lo + 1, nxt_level):
98+
# Too deep - check till top
99+
if self.dfs(T, nxt_level, 0, []):
100+
return True
101+
nxt_level.pop()
102+
103+
return False
104+
105+
106+
if __name__ == "__main__":
107+
assert Solution().pyramidTransition("BCD", ["BCG", "CDE", "GEA", "FFF"]) == True
108+
assert Solution().pyramidTransition("AABA", ["AAA", "AAB", "ABA", "ABB", "BAC"]) == False

0 commit comments

Comments
 (0)