Skip to content

Commit 3c6a67a

Browse files
author
Matthieu Michon
committed
Add 2021 day 11 part one
1 parent ef33a0a commit 3c6a67a

File tree

5 files changed

+179
-13
lines changed

5 files changed

+179
-13
lines changed

Diff for: 2021/README.md

+14-13
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,20 @@ Annual editions in Python: **2021**, [2020](/2020), [2019](/2019).
66

77
> Santa has become stranded at the edge of the Solar System while delivering presents to other planets! To accurately calculate his position in space, safely align his warp drive, and return to Earth in time to save Christmas, he needs you to bring him *measurements* from fifty stars.
88
9-
Day | Puzzle Title | Links | Topics | Part One | Part Two | Runtime
10-
|--------------------|-------------------------|---------------------------------------------------|--------------------------|----------|----------| ---
11-
| [1](/2021/day-1) | Sonar Sweep | [AoC][aoc-2021-1] - [Reddit][reddit-aoc-2021-1] | List manipulation | ⭐ | ⭐ | 20.8 ms
12-
| [2](/2021/day-2) | Dive! | [AoC][aoc-2021-2] - [Reddit][reddit-aoc-2021-2] | List iteration | ⭐ | ⭐ | 23.2 ms
13-
| [3](/2021/day-3) | Binary Diagnostic | [AoC][aoc-2021-3] - [Reddit][reddit-aoc-2021-3] | List iteration | ⭐ | ⭐ | 46.4 ms
14-
| [4](/2021/day-4) | Giant Squid | [AoC][aoc-2021-4] - [Reddit][reddit-aoc-2021-4] | Data structure iteration | ⭐ | ⭐⭐ | 137.7 ms
15-
| [5](/2021/day-5) | Hydrothermal Venture | [AoC][aoc-2021-5] - [Reddit][reddit-aoc-2021-5] | Arrays | ⭐ | ⭐ | 1714.2 ms
16-
| [6](/2021/day-6) | Lanternfish | [AoC][aoc-2021-6] - [Reddit][reddit-aoc-2021-6] | Optimization | ⭐ | ⭐⭐ | 7.7 ms
17-
| [7](/2021/day-7) | The Treachery of Whales | [AoC][aoc-2021-7] - [Reddit][reddit-aoc-2021-7] | List iteration | ⭐ | ⭐ | 1955.9 ms
18-
| [8](/2021/day-8) | Seven Segment Search | [AoC][aoc-2021-8] - [Reddit][reddit-aoc-2021-8] | Data structures | ⭐ | ⭐⭐ | 17 ms
19-
| [9](/2021/day-9) | Smoke Basin | [AoC][aoc-2021-9] - [Reddit][reddit-aoc-2021-9] | Fill algorithm | ⭐ | ⭐ | 160 ms
20-
| [10](/2021/day-10) | Syntax Scoring | [AoC][aoc-2021-10] - [Reddit][reddit-aoc-2021-10] | Tokenization | ⭐ | ⭐ | 1.4 ms
21-
| [xx](/2021/day-xx) | tbd | [AoC][aoc-2021-x] - [Reddit][reddit-aoc-2021-x] | tbd | tbd | tbd | tbd
9+
| Day | Puzzle Title | Links | Topics | Part One | Part Two | Runtime |
10+
|--------------------|-------------------------|---------------------------------------------------|--------------------------|----------|----------|-----------|
11+
| [1](/2021/day-1) | Sonar Sweep | [AoC][aoc-2021-1] - [Reddit][reddit-aoc-2021-1] | List manipulation ||| 20.8 ms |
12+
| [2](/2021/day-2) | Dive! | [AoC][aoc-2021-2] - [Reddit][reddit-aoc-2021-2] | List iteration ||| 23.2 ms |
13+
| [3](/2021/day-3) | Binary Diagnostic | [AoC][aoc-2021-3] - [Reddit][reddit-aoc-2021-3] | List iteration ||| 46.4 ms |
14+
| [4](/2021/day-4) | Giant Squid | [AoC][aoc-2021-4] - [Reddit][reddit-aoc-2021-4] | Data structure iteration || ⭐⭐ | 137.7 ms |
15+
| [5](/2021/day-5) | Hydrothermal Venture | [AoC][aoc-2021-5] - [Reddit][reddit-aoc-2021-5] | Arrays ||| 1714.2 ms |
16+
| [6](/2021/day-6) | Lanternfish | [AoC][aoc-2021-6] - [Reddit][reddit-aoc-2021-6] | Optimization || ⭐⭐ | 7.7 ms |
17+
| [7](/2021/day-7) | The Treachery of Whales | [AoC][aoc-2021-7] - [Reddit][reddit-aoc-2021-7] | List iteration ||| 1955.9 ms |
18+
| [8](/2021/day-8) | Seven Segment Search | [AoC][aoc-2021-8] - [Reddit][reddit-aoc-2021-8] | Data structures || ⭐⭐ | 17 ms |
19+
| [9](/2021/day-9) | Smoke Basin | [AoC][aoc-2021-9] - [Reddit][reddit-aoc-2021-9] | Fill algorithm ||| 160 ms |
20+
| [10](/2021/day-10) | Syntax Scoring | [AoC][aoc-2021-10] - [Reddit][reddit-aoc-2021-10] | Tokenization ||| 1.4 ms |
21+
| [11](/2021/day-11) | Dumbo Octopus | [AoC][aoc-2021-11] - [Reddit][reddit-aoc-2021-11] | tbd || tbd | 10.7 ms |
22+
| [xx](/2021/day-xx) | tbd | [AoC][aoc-2021-x] - [Reddit][reddit-aoc-2021-x] | tbd | tbd | tbd | tbd |
2223

2324
# Resources
2425

Diff for: 2021/day-11/README.md

Whitespace-only changes.

Diff for: 2021/day-11/day_11.py

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#!/usr/bin/env python
2+
3+
"""Advent of Code Programming Puzzles
4+
5+
2021 Edition - Day 11
6+
Puzzle Solution in Python
7+
"""
8+
9+
import copy
10+
import logging
11+
import sys
12+
import time
13+
from collections import namedtuple
14+
15+
from pathlib import Path
16+
from typing import Iterator
17+
18+
from common.support import parse_arguments, configure_logger
19+
from itertools import product
20+
21+
log = logging.getLogger(__name__)
22+
23+
DEFAULT_FILE = 'example-input.txt'
24+
DEFAULT_FILE = 'input.txt'
25+
EXIT_SUCCESS = 0
26+
27+
Position = namedtuple('Position', ['col', 'row'])
28+
29+
30+
def load_contents(filename: Path) -> dict[Position: int]:
31+
"""Load and convert contents from file
32+
33+
:param filename: input filename
34+
:return: contents structured as a map
35+
"""
36+
37+
with open(filename, encoding='utf-8') as buffer:
38+
contents = {Position(col, row):
39+
{"energy": int(level), "flashes": 0, "flashed": False}
40+
for row, line in enumerate(buffer.readlines())
41+
for col, level in enumerate(line.strip())}
42+
return contents
43+
44+
45+
AXIS = 2
46+
STENCILS = tuple(c for c in product((-1, 0, 1), repeat=AXIS) if any(c))
47+
48+
49+
def compute_neighbors(pos: tuple[int]) -> tuple:
50+
"""Compute neighbors
51+
52+
:param pos: point coordinates
53+
:return: list of neighbors
54+
"""
55+
neighbors = tuple(tuple([sum(x) for x in zip(pos, s)]) for s in STENCILS)
56+
return neighbors
57+
58+
59+
def solve_first_part(contents: any) -> int:
60+
"""Solve the first part of the challenge
61+
62+
:param contents: decoded contents
63+
:return: answer for the first part
64+
"""
65+
66+
THRESHOLD = 9
67+
68+
def step(octopuses_: dict) -> dict:
69+
# increment energy level of all octopuses_
70+
for pos in octopuses_:
71+
octopuses_[pos]['energy'] += 1
72+
octopuses_[pos]['flashed'] = False
73+
while any(v['energy'] > THRESHOLD for v in octopuses_.values()):
74+
# propagate flushing to neighbors
75+
for pos in octopuses_:
76+
flushing = octopuses_[pos]['energy'] > THRESHOLD and not octopuses_[pos]['flashed']
77+
if not flushing:
78+
continue
79+
for n in compute_neighbors(pos=pos):
80+
if n in octopuses_:
81+
if not octopuses_[n]['flashed']:
82+
octopuses_[n]['energy'] += 1
83+
octopuses_[pos]['energy'] = 0
84+
octopuses_[pos]['flashes'] += 1
85+
octopuses_[pos]['flashed'] = True
86+
return octopuses_
87+
88+
octopuses = contents
89+
STEPS = 100
90+
for i in range(STEPS):
91+
octopuses = step(octopuses_=octopuses)
92+
answer = sum(v['flashes'] for v in octopuses.values())
93+
return answer
94+
95+
96+
def dump_octopuses_levels(octopuses: dict) -> None:
97+
row = 0
98+
while any(row in p for p in octopuses):
99+
col = 0
100+
while any(col in p for p in octopuses):
101+
energy = octopuses[Position(col=col, row=row)]['energy']
102+
print(energy if energy < 10 else '#', end='')
103+
col += 1
104+
print('')
105+
row += 1
106+
107+
108+
def main() -> int:
109+
"""Script main method
110+
111+
:return: script exit code returned to the shell
112+
"""
113+
114+
args = parse_arguments()
115+
configure_logger(verbose=args.verbose)
116+
log.debug(f'called with {args=}')
117+
118+
start_time = time.perf_counter()
119+
120+
contents = load_contents(filename=args.filename)
121+
compute_first_part = \
122+
'solve_first_part' in globals() and (not args.part or args.part == 1)
123+
compute_second_part = \
124+
'solve_second_part' in globals() and (not args.part or args.part == 2)
125+
answer_part_one = \
126+
solve_first_part(contents=contents) if compute_first_part else 0
127+
answer_part_two = \
128+
solve_second_part(contents=contents) if compute_second_part else 0
129+
130+
elapsed_time = time.perf_counter() - start_time
131+
132+
print(f'{answer_part_one=}')
133+
print(f'{answer_part_two=}')
134+
print(f'done in {1000 * elapsed_time:0.1f} milliseconds')
135+
136+
return EXIT_SUCCESS
137+
138+
139+
if __name__ == '__main__':
140+
"""Standalone entry-point"""
141+
NO_INPUT_FILE = 1 == len(sys.argv)
142+
if NO_INPUT_FILE:
143+
default_input = Path(__file__).parent / DEFAULT_FILE
144+
sys.argv.append(str(default_input))
145+
sys.exit(main())

Diff for: 2021/day-11/example-input.txt

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
5483143223
2+
2745854711
3+
5264556173
4+
6141336146
5+
6357385478
6+
4167524645
7+
2176841721
8+
6882881134
9+
4846848554
10+
5283751526

Diff for: 2021/day-11/input.txt

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
4438624262
2+
6263251864
3+
2618812434
4+
2134264565
5+
1815131247
6+
2612457325
7+
8585767584
8+
7217134556
9+
2825456563
10+
8248473584

0 commit comments

Comments
 (0)