| 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) |