From 4dc83760b7219927b681ebe0e6db5326e36dedf9 Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Fri, 11 Dec 2020 11:00:59 +0100 Subject: [PATCH 1/4] day11: slightly faster (and actually correct) --- day11.py | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/day11.py b/day11.py index 07f0bfc..31698f6 100644 --- a/day11.py +++ b/day11.py @@ -6,6 +6,7 @@ DAY = 11 TEST_SOLUTION_PART1 = 37 TEST_SOLUTION_PART2 = 26 INT_INDEX = ['L', '#', '.'] +MAP_INDEX = [False, True, None] def printLayout(layout, max_x, max_y): @@ -17,20 +18,21 @@ def printLayout(layout, max_x, max_y): def prepareLayout(raw_input): - int_layout = defaultdict(lambda: 2) + int_layout = defaultdict(lambda: None) for y, line in enumerate(raw_input): 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 def simulate(layout, max_x, max_y, wide=False): - num_seats_occupied = 0 - new_layout = defaultdict(lambda: 2) + max_seats_occupied = (5 if wide else 4) + max_xy = max(max_x, max_y) + new_layout = defaultdict(lambda: None) for x in range(0, max_x): for y in range(0, max_y): - if layout[(x, y)] == 2: + if layout[(x, y)] is None: continue occupied_seats = 0 @@ -38,29 +40,28 @@ def simulate(layout, max_x, max_y, wide=False): for cy in [-1, 0, 1]: if cx == 0 and cy == 0: continue + if not wide: - if layout[(x + cx, y + cy)] == 1: + if layout[(x + cx, y + cy)]: occupied_seats += 1 else: - for d in range(1, max(max_x, max_y)): - if d * cy + y >= max_x or d * cx + x >= max_y: + for d in range(1, max_xy): + test_x = d * cx + x + test_y = d * cy + y + if test_x >= max_x or test_y >= max_y: break - if layout[(d * cx + x, d * cy + y)] == 2: + if layout[(test_x, test_y)] is None: continue - if layout[(d * cx + x, d * cy + y)] < 2: - occupied_seats += layout[(d * cx + x, d * cy + y)] + else: + occupied_seats += layout[(test_x, test_y)] break - if layout[(x, y)] and occupied_seats >= (5 if wide else 4): - new_layout[(x, y)] = 0 - elif not layout[(x, y)] and occupied_seats == 0: - new_layout[(x, y)] = 1 + if (layout[(x, y)] and occupied_seats >= max_seats_occupied) or (not layout[(x, y)] and occupied_seats == 0): + new_layout[(x, y)] = not layout[(x, y)] else: new_layout[(x, y)] = layout[(x, y)] - num_seats_occupied += new_layout[(x, y)] - - return new_layout, num_seats_occupied + return new_layout def part1(test_mode=False, wide=False): @@ -71,10 +72,14 @@ def part1(test_mode=False, wide=False): cellcount_y = len(my_input) curr_occupied = 0 last_occupied = -1 + generation_counter = 0 while curr_occupied != last_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 From c3cced9c4d7132b148e2ac473773899edeae4ae8 Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Fri, 11 Dec 2020 11:58:35 +0100 Subject: [PATCH 2/4] day11: down to ~2s (and found the flaw in p2) --- day11.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/day11.py b/day11.py index 31698f6..d202087 100644 --- a/day11.py +++ b/day11.py @@ -28,7 +28,6 @@ def prepareLayout(raw_input): def simulate(layout, max_x, max_y, wide=False): max_seats_occupied = (5 if wide else 4) - max_xy = max(max_x, max_y) new_layout = defaultdict(lambda: None) for x in range(0, max_x): for y in range(0, max_y): @@ -41,15 +40,16 @@ def simulate(layout, max_x, max_y, wide=False): if cx == 0 and cy == 0: continue - if not wide: - if layout[(x + cx, y + cy)]: - occupied_seats += 1 - else: - for d in range(1, max_xy): - test_x = d * cx + x - test_y = d * cy + y - if test_x >= max_x or test_y >= max_y: - break + test_x = x + cx + test_y = y + cy + check_value = layout[(test_x, test_y)] + + if check_value is not None: + occupied_seats += check_value + elif wide: + while 0 <= test_x <= max_x and 0 <= test_y <= max_y: + test_x += cx + test_y += cy if layout[(test_x, test_y)] is None: continue else: @@ -73,6 +73,9 @@ def part1(test_mode=False, wide=False): curr_occupied = 0 last_occupied = -1 generation_counter = 0 + + # Yes, this is relying on the assumption that there are no + # two different patterns with the same number of occupants. while curr_occupied != last_occupied: last_occupied = curr_occupied generation_counter += 1 From 6df1f468d33841a0bb5c5ab26025c046c555a984 Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Fri, 11 Dec 2020 12:35:36 +0100 Subject: [PATCH 3/4] day11: ever so slightly faster - still 2s +/- 0.2 --- day11.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/day11.py b/day11.py index d202087..7b48fae 100644 --- a/day11.py +++ b/day11.py @@ -35,23 +35,22 @@ def simulate(layout, max_x, max_y, wide=False): continue occupied_seats = 0 - for cx in [-1, 0, 1]: - for cy in [-1, 0, 1]: - if cx == 0 and cy == 0: + for cx in [x-1, x, x+1]: + for cy in [y-1, y, y+1]: + if cx == x and cy == y: continue - test_x = x + cx - test_y = y + cy - check_value = layout[(test_x, test_y)] + check_value = layout[(cx, cy)] if check_value is not None: occupied_seats += check_value elif wide: + test_x = cx + (cx - x) + test_y = cy + (cy - y) while 0 <= test_x <= max_x and 0 <= test_y <= max_y: - test_x += cx - test_y += cy if layout[(test_x, test_y)] is None: - continue + test_x += (cx - x) + test_y += (cy - y) else: occupied_seats += layout[(test_x, test_y)] break From 033a31a7c06456525184b4500067e6d87d20eb2d Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Fri, 11 Dec 2020 13:52:48 +0100 Subject: [PATCH 4/4] day11: remove another 2 dict-accesses --- day11.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/day11.py b/day11.py index 7b48fae..4998031 100644 --- a/day11.py +++ b/day11.py @@ -55,8 +55,10 @@ def simulate(layout, max_x, max_y, wide=False): occupied_seats += layout[(test_x, test_y)] break - if (layout[(x, y)] and occupied_seats >= max_seats_occupied) or (not layout[(x, y)] and occupied_seats == 0): - new_layout[(x, y)] = not layout[(x, y)] + if occupied_seats >= max_seats_occupied: + new_layout[(x, y)] = False + elif occupied_seats == 0: + new_layout[(x, y)] = True else: new_layout[(x, y)] = layout[(x, y)]