|
|
@@ -0,0 +1,64 @@ |
|
|
|
import re |
|
|
|
import sys |
|
|
|
|
|
|
|
|
|
|
|
def display(state): |
|
|
|
ele, floors = state |
|
|
|
for i, floor in list(enumerate(floors))[::-1]: |
|
|
|
_ = ['E' if ele == i else ' '] |
|
|
|
_ += [d if d in floor else '..' for d in sorted(devices)] |
|
|
|
print(' '.join(_)) |
|
|
|
print() |
|
|
|
|
|
|
|
|
|
|
|
def checks(elevator, floors): |
|
|
|
for fl in floors: |
|
|
|
vulnerable = {d for d in fl if d == d.lower() and d.upper() not in fl} |
|
|
|
dangerous = {d for d in fl if d == d.upper()} |
|
|
|
if vulnerable and dangerous: |
|
|
|
yield False |
|
|
|
|
|
|
|
|
|
|
|
def moves(ith, floors): |
|
|
|
for jth in {ith - 1, ith + 1} - {-1, 4}: |
|
|
|
for stuff in [{a, b} for a in floors[ith] for b in floors[ith]]: |
|
|
|
new = (jth, tuple( |
|
|
|
(floor | stuff) if ith == jth else (floor - stuff) |
|
|
|
for ith, floor in enumerate(floors) |
|
|
|
)) |
|
|
|
if all(checks(*new)): |
|
|
|
yield new |
|
|
|
|
|
|
|
|
|
|
|
text = sys.stdin.read() |
|
|
|
start = [ |
|
|
|
frozenset( |
|
|
|
word[:2].upper() if not word.endswith('-') else word[:2] |
|
|
|
for word in re.findall(r'\w+ium-?', ln) |
|
|
|
) |
|
|
|
for ln in text.splitlines() |
|
|
|
] |
|
|
|
start[2] -= {'PR', 'RU', 'pr', 'ru'} |
|
|
|
# start[0] |= {'EE', 'ee', 'DD', 'dd'} |
|
|
|
devices = frozenset({device for floor in start for device in floor}) |
|
|
|
|
|
|
|
edge = {(0, tuple(start))} |
|
|
|
goal = (3, tuple([frozenset(), frozenset(), frozenset(), devices])) |
|
|
|
seen = {} |
|
|
|
while goal not in seen: |
|
|
|
edge = {new: old for old in edge for new in moves(*old) if new not in seen} |
|
|
|
if not edge: |
|
|
|
raise RuntimeError('empty') |
|
|
|
seen = {**edge, **seen} |
|
|
|
print(len(edge)) |
|
|
|
|
|
|
|
seq = [] |
|
|
|
while goal != (0, tuple(start)): |
|
|
|
seq.append(goal) |
|
|
|
goal = seen[goal] |
|
|
|
seq.append(goal) |
|
|
|
seq.reverse() |
|
|
|
|
|
|
|
for i, state in enumerate(seq): |
|
|
|
print(i) |
|
|
|
display(state) |