Day 23 - Advent of Code 2022
Working solutions for the day 23 puzzles.
Part One
""" day_23_01.py """
# usage: python3 day_23_01.py < input
import sys
def parse(raw_location_data):
""" create object """
output = set()
x, y = 0, 0
for item in raw_location_data:
if item == '\n':
x, y = 0, y + 1
continue
if item == '#':
output.add((x, y))
x += 1
return output
deltas = {'n': (0, -1), 'ne': (1, -1), 'e': (1, 0), 'se': (1, 1),
's': (0, 1), 'sw': (-1, 1), 'w': (-1, 0), 'nw': (-1, -1)}
def adjacent(dirs, point, elf_data):
""" count adjacent to point in dirs """
tally = 0
for d in dirs:
dx, dy = deltas[d]
if (point[0] + dx, point[1] + dy) in elf_data:
tally += 1
return tally
elves = parse(sys.stdin.read())
options = {'all': ['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'],
0: ['n', 'ne', 'nw'], 1: ['s', 'se', 'sw'],
2: ['w', 'nw', 'sw'], 3: ['e', 'ne', 'se']}
option = 0
rounds = 10
while rounds > 0:
rounds -= 1
proposed = {}
for elf in elves:
count = adjacent(options['all'], elf, elves)
if count == 0:
continue
for i in range(option, option + 4):
count = adjacent(options[i % 4], elf, elves)
if count == 0:
proposed[elf] = deltas[options[i % 4][0]]
break
option = (option + 1) % 4
if not proposed:
break
moves = [(x + dx, y + dy) for (x, y), (dx, dy) in proposed.items()]
for elf in elves.copy():
if elf in proposed:
move = elf[0] + proposed[elf][0], elf[1] + proposed[elf][1]
if moves.count(move) == 1:
elves.remove(elf)
elves.add(move)
x_range, y_range = [x for x, _ in elves], [y for _, y in elves]
count = 0
for x_coord in range(min(x_range), max(x_range) + 1):
for y_coord in range(min(y_range), max(y_range) + 1):
if (x_coord, y_coord) not in elves:
count += 1
print(count)
Part Two
""" day_23_02.py """
# usage: python3 day_23_02.py < input
import sys
def parse(raw_location_data):
""" create object """
output = set()
x, y = 0, 0
for item in raw_location_data:
if item == '\n':
x, y = 0, y + 1
continue
if item == '#':
output.add((x, y))
x += 1
return output
deltas = {'n': (0, -1), 'ne': (1, -1), 'e': (1, 0), 'se': (1, 1),
's': (0, 1), 'sw': (-1, 1), 'w': (-1, 0), 'nw': (-1, -1)}
def adjacent(dirs, point, elf_data):
""" count adjacent to point in dirs """
tally = 0
for d in dirs:
dx, dy = deltas[d]
if (point[0] + dx, point[1] + dy) in elf_data:
tally += 1
return tally
elves = parse(sys.stdin.read())
options = {'all': ['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'],
0: ['n', 'ne', 'nw'], 1: ['s', 'se', 'sw'],
2: ['w', 'nw', 'sw'], 3: ['e', 'ne', 'se']}
option = 0
rounds = 0
while True:
rounds += 1
proposed = {}
for elf in elves:
count = adjacent(options['all'], elf, elves)
if count == 0:
continue
for i in range(option, option + 4):
count = adjacent(options[i % 4], elf, elves)
if count == 0:
proposed[elf] = deltas[options[i % 4][0]]
break
option = (option + 1) % 4
if not proposed:
break
moves = [(x + dx, y + dy) for (x, y), (dx, dy) in proposed.items()]
for elf in elves.copy():
if elf in proposed:
move = elf[0] + proposed[elf][0], elf[1] + proposed[elf][1]
if moves.count(move) == 1:
elves.remove(elf)
elves.add(move)
print(rounds)