|
1 | 1 | import time |
2 | 2 |
|
3 | | -from icecream import ic |
| 3 | +from collections import deque |
| 4 | +from typing import Deque, List, Tuple |
| 5 | + |
| 6 | +# from icecream import ic |
4 | 7 |
|
5 | 8 | CHALLENGE_DAY = 4 |
6 | 9 |
|
|
21 | 24 | # ic(input_lines) |
22 | 25 |
|
23 | 26 |
|
| 27 | +""" |
| 28 | +Credits: <https://openwebui.gmacario.it/c/c19b36fc-d4fe-4bdc-9ca9-f6b178edf237> |
| 29 | +
|
| 30 | +Prompt: |
| 31 | +
|
| 32 | +Solve Part Two of the following challenge by creating a Python function with the following signature: |
| 33 | +
|
| 34 | +```python |
| 35 | +def solve_part2_with_ai(input_lines: List[str]) -> int |
| 36 | +``` |
| 37 | +
|
| 38 | +where `input_lines` is a list of string produced by reading the input file as per the provided example: |
| 39 | +
|
| 40 | +(paste contents of day04/sample_day04.txt) |
| 41 | +
|
| 42 | +Here is the full text of the challenge: |
| 43 | +
|
| 44 | +(paste contents of day04/README.md) |
| 45 | +""" |
| 46 | +def solve_part2_with_ai(input_lines: List[str]) -> int: |
| 47 | + """ |
| 48 | + Implements the Part 2 solution described above. |
| 49 | + Returns the total number of '@' cells that can be removed. |
| 50 | + """ |
| 51 | + if not input_lines: |
| 52 | + return 0 |
| 53 | + |
| 54 | + rows = len(input_lines) |
| 55 | + cols = len(input_lines[0]) |
| 56 | + |
| 57 | + # 1. parse the grid |
| 58 | + paper = [[c == '@' for c in line] for line in input_lines] |
| 59 | + |
| 60 | + # 2. auxiliary structures |
| 61 | + removed = [[False] * cols for _ in range(rows)] |
| 62 | + deg = [[0] * cols for _ in range(rows)] |
| 63 | + |
| 64 | + # 8 possible neighbour offsets |
| 65 | + neigh_offsets = [(-1, -1), (-1, 0), (-1, 1), |
| 66 | + (0, -1), (0, 1), |
| 67 | + (1, -1), (1, 0), (1, 1)] |
| 68 | + |
| 69 | + # 3. initial degree computation |
| 70 | + for i in range(rows): |
| 71 | + for j in range(cols): |
| 72 | + if not paper[i][j]: |
| 73 | + continue |
| 74 | + cnt = 0 |
| 75 | + for di, dj in neigh_offsets: |
| 76 | + ni, nj = i + di, j + dj |
| 77 | + if 0 <= ni < rows and 0 <= nj < cols and paper[ni][nj]: |
| 78 | + cnt += 1 |
| 79 | + deg[i][j] = cnt |
| 80 | + |
| 81 | + # 4. initialise queue with cells of degree < 4 |
| 82 | + q: Deque[Tuple[int, int]] = deque() |
| 83 | + for i in range(rows): |
| 84 | + for j in range(cols): |
| 85 | + if paper[i][j] and deg[i][j] < 4: |
| 86 | + q.append((i, j)) |
| 87 | + |
| 88 | + removed_cnt = 0 |
| 89 | + |
| 90 | + # 5. iterative removal |
| 91 | + while q: |
| 92 | + i, j = q.popleft() |
| 93 | + if removed[i][j]: |
| 94 | + continue # may have been queued earlier |
| 95 | + removed[i][j] = True |
| 96 | + removed_cnt += 1 |
| 97 | + |
| 98 | + # decrease degree of still‑present neighbours |
| 99 | + for di, dj in neigh_offsets: |
| 100 | + ni, nj = i + di, j + dj |
| 101 | + if 0 <= ni < rows and 0 <= nj < cols: |
| 102 | + if paper[ni][nj] and not removed[ni][nj]: |
| 103 | + deg[ni][nj] -= 1 |
| 104 | + # we only need to enqueue when it just crossed the threshold |
| 105 | + if deg[ni][nj] == 3: |
| 106 | + q.append((ni, nj)) |
| 107 | + |
| 108 | + return removed_cnt |
| 109 | + |
| 110 | + |
24 | 111 | def solve_part1(): |
25 | 112 | tm_start = time.time() |
26 | 113 | # result_part1 = 0 |
@@ -87,7 +174,8 @@ def solve_part2(): |
87 | 174 | tm_start = time.time() |
88 | 175 | result_part2 = 0 |
89 | 176 |
|
90 | | - ic("DEBUG: TODO solve_part2()") |
| 177 | + # ic("DEBUG: TODO solve_part2()") |
| 178 | + result_part2 = solve_part2_with_ai(input_lines) |
91 | 179 |
|
92 | 180 | tm_end = time.time() |
93 | 181 | print(f"DEBUG: solve_part2 Begin: {time.ctime(tm_start)}") |
|
0 commit comments