|
|
|
|
|
|
|
|
import sys |
|
|
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 freeze(state): |
|
|
|
|
|
return tuple(frozenset(fl) for fl in state) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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: |
|
|
|
|
|
|
|
|
def thaw(state): |
|
|
|
|
|
return [set(fl) for fl in state] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def checks(state): |
|
|
|
|
|
for fl in state: |
|
|
|
|
|
dangerous = {d[:-1] for d in fl if d.endswith('+')} |
|
|
|
|
|
vulnerable = {d[:-1] for d in fl if d.endswith('-')} - dangerous |
|
|
|
|
|
if dangerous and vulnerable: |
|
|
yield False |
|
|
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 |
|
|
|
|
|
|
|
|
def advance(pair): |
|
|
|
|
|
f0, state = pair |
|
|
|
|
|
for devices in {frozenset({a, b}) for a in state[f0] for b in state[f0]}: |
|
|
|
|
|
for f1 in {f0 + 1, f0 - 1} - {-1, 4}: |
|
|
|
|
|
if len(devices) == 1 or f1 > f0: |
|
|
|
|
|
new = thaw(state) |
|
|
|
|
|
new[f0] -= devices |
|
|
|
|
|
new[f1] |= devices |
|
|
|
|
|
if all(checks(new)): |
|
|
|
|
|
yield f1, freeze(new) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
text = sys.stdin.read() |
|
|
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) |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
state = [ |
|
|
|
|
|
{a + (b or '+') for a, b in re.findall(r'(\w{2})\w+ium(-)?', ln)} |
|
|
for ln in text.splitlines() |
|
|
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 = {} |
|
|
|
|
|
|
|
|
goal = (3, freeze([{}, {}, {}, {d for fl in state for d in fl}])) |
|
|
|
|
|
edge = {(0, freeze(state))} |
|
|
|
|
|
seen = set() |
|
|
|
|
|
ans1 = 0 |
|
|
while goal not in 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) |
|
|
|
|
|
|
|
|
edge = {new for old in edge for new in advance(old)} - seen |
|
|
|
|
|
seen |= edge |
|
|
|
|
|
ans1 += 1 |
|
|
|
|
|
print(ans1) |
|
|
|
|
|
print(ans1 + 12 * 2) |