You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
75 lines
1.4 KiB
75 lines
1.4 KiB
3 years ago
|
|
||
|
|
||
|
cmdToDir = {
|
||
|
"se": (0, -1),
|
||
|
"nw": (0, 1),
|
||
|
"sw": (-1, -1),
|
||
|
"ne": (1, 1),
|
||
|
"e": (1, 0),
|
||
|
"w": (-1, 0)
|
||
|
}
|
||
|
|
||
|
|
||
|
def getPos(c: str):
|
||
|
commands = []
|
||
|
i = 0
|
||
|
while i < len(c):
|
||
|
if c[i] in ("s", "n"):
|
||
|
commands.append(c[i:i + 2])
|
||
|
i += 2
|
||
|
elif c[i] in ("w", "e"):
|
||
|
commands.append(c[i])
|
||
|
i += 1
|
||
|
x, y = 0, 0
|
||
|
for command in commands:
|
||
|
dx, dy = cmdToDir[command]
|
||
|
x += dx
|
||
|
y += dy
|
||
|
return x, y
|
||
|
|
||
|
|
||
|
def solveTask1(codes):
|
||
|
blacks = set()
|
||
|
for code in codes:
|
||
|
pos = getPos(code)
|
||
|
if pos in blacks:
|
||
|
blacks.remove(pos)
|
||
|
else:
|
||
|
blacks.add(pos)
|
||
|
return blacks
|
||
|
|
||
|
|
||
|
def getAdjacent(pos):
|
||
|
x, y = pos
|
||
|
adjacent = [(x + dx, y + dy) for dx, dy in cmdToDir.values()]
|
||
|
return set(adjacent)
|
||
|
|
||
|
|
||
|
def solveTask2(codes):
|
||
|
blacks = solveTask1(codes)
|
||
|
|
||
|
for _ in range(100):
|
||
|
|
||
|
flipsToBlack, flipsToWhite = set(), set()
|
||
|
|
||
|
for blackTile in blacks:
|
||
|
adjacent = getAdjacent(blackTile)
|
||
|
adjacentAndBlack = adjacent.intersection(blacks)
|
||
|
if len(adjacentAndBlack) == 0 or len(adjacentAndBlack) > 2:
|
||
|
flipsToWhite.add(blackTile)
|
||
|
for whiteTile in adjacent.difference(blacks):
|
||
|
adjacentAndBlack = getAdjacent(whiteTile).intersection(blacks)
|
||
|
if len(adjacentAndBlack) == 2:
|
||
|
flipsToBlack.add(whiteTile)
|
||
|
|
||
|
blacks = blacks.difference(flipsToWhite).union(flipsToBlack)
|
||
|
|
||
|
return blacks
|
||
|
|
||
|
|
||
|
with open("input") as file:
|
||
|
rawCodes = file.read().splitlines()
|
||
|
|
||
|
print(len(solveTask1(rawCodes)))
|
||
|
print(len(solveTask2(rawCodes)))
|