day11: slightly faster (and actually correct)

This commit is contained in:
Stefan Harmuth 2020-12-11 11:00:59 +01:00
parent ef7fb6e53e
commit 4dc83760b7

View File

@ -6,6 +6,7 @@ DAY = 11
TEST_SOLUTION_PART1 = 37 TEST_SOLUTION_PART1 = 37
TEST_SOLUTION_PART2 = 26 TEST_SOLUTION_PART2 = 26
INT_INDEX = ['L', '#', '.'] INT_INDEX = ['L', '#', '.']
MAP_INDEX = [False, True, None]
def printLayout(layout, max_x, max_y): def printLayout(layout, max_x, max_y):
@ -17,20 +18,21 @@ def printLayout(layout, max_x, max_y):
def prepareLayout(raw_input): def prepareLayout(raw_input):
int_layout = defaultdict(lambda: 2) int_layout = defaultdict(lambda: None)
for y, line in enumerate(raw_input): for y, line in enumerate(raw_input):
for x, char in enumerate(line): for x, char in enumerate(line):
int_layout[(x, y)] = INT_INDEX.index(char) int_layout[(x, y)] = MAP_INDEX[INT_INDEX.index(char)]
return int_layout return int_layout
def simulate(layout, max_x, max_y, wide=False): def simulate(layout, max_x, max_y, wide=False):
num_seats_occupied = 0 max_seats_occupied = (5 if wide else 4)
new_layout = defaultdict(lambda: 2) max_xy = max(max_x, max_y)
new_layout = defaultdict(lambda: None)
for x in range(0, max_x): for x in range(0, max_x):
for y in range(0, max_y): for y in range(0, max_y):
if layout[(x, y)] == 2: if layout[(x, y)] is None:
continue continue
occupied_seats = 0 occupied_seats = 0
@ -38,29 +40,28 @@ def simulate(layout, max_x, max_y, wide=False):
for cy in [-1, 0, 1]: for cy in [-1, 0, 1]:
if cx == 0 and cy == 0: if cx == 0 and cy == 0:
continue continue
if not wide: if not wide:
if layout[(x + cx, y + cy)] == 1: if layout[(x + cx, y + cy)]:
occupied_seats += 1 occupied_seats += 1
else: else:
for d in range(1, max(max_x, max_y)): for d in range(1, max_xy):
if d * cy + y >= max_x or d * cx + x >= max_y: test_x = d * cx + x
test_y = d * cy + y
if test_x >= max_x or test_y >= max_y:
break break
if layout[(d * cx + x, d * cy + y)] == 2: if layout[(test_x, test_y)] is None:
continue continue
if layout[(d * cx + x, d * cy + y)] < 2: else:
occupied_seats += layout[(d * cx + x, d * cy + y)] occupied_seats += layout[(test_x, test_y)]
break break
if layout[(x, y)] and occupied_seats >= (5 if wide else 4): if (layout[(x, y)] and occupied_seats >= max_seats_occupied) or (not layout[(x, y)] and occupied_seats == 0):
new_layout[(x, y)] = 0 new_layout[(x, y)] = not layout[(x, y)]
elif not layout[(x, y)] and occupied_seats == 0:
new_layout[(x, y)] = 1
else: else:
new_layout[(x, y)] = layout[(x, y)] new_layout[(x, y)] = layout[(x, y)]
num_seats_occupied += new_layout[(x, y)] return new_layout
return new_layout, num_seats_occupied
def part1(test_mode=False, wide=False): def part1(test_mode=False, wide=False):
@ -71,10 +72,14 @@ def part1(test_mode=False, wide=False):
cellcount_y = len(my_input) cellcount_y = len(my_input)
curr_occupied = 0 curr_occupied = 0
last_occupied = -1 last_occupied = -1
generation_counter = 0
while curr_occupied != last_occupied: while curr_occupied != last_occupied:
last_occupied = curr_occupied last_occupied = curr_occupied
curr_layout, curr_occupied = simulate(curr_layout, cellcount_x, cellcount_y, wide) generation_counter += 1
curr_layout = simulate(curr_layout, cellcount_x, cellcount_y, wide)
curr_occupied = sum(filter(None, curr_layout.values()))
print("Generations simulated: %d" % generation_counter)
return curr_occupied return curr_occupied