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