Add 2021-20 in Python
Signed-off-by: AKU <tom@tdpain.net>
This commit is contained in:
parent
5737ee036b
commit
0f81ecaab5
7 changed files with 206 additions and 21 deletions
2
challenges/2021/20-trenchMap/README.md
Normal file
2
challenges/2021/20-trenchMap/README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# [Day <n>: <Day Title>](https://adventofcode.com/<year>/day/<n>)
|
||||
|
15
challenges/2021/20-trenchMap/benchmark.json
Normal file
15
challenges/2021/20-trenchMap/benchmark.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"day": 20,
|
||||
"dir": "challenges/2021/20-trenchMap",
|
||||
"implementations": {
|
||||
"Python": {
|
||||
"part.1.avg": 0.0832568073272705,
|
||||
"part.1.max": 0.11255383491516113,
|
||||
"part.1.min": 0.07309865951538086,
|
||||
"part.2.avg": 4.895450177192688,
|
||||
"part.2.max": 7.253676652908325,
|
||||
"part.2.min": 4.276515483856201
|
||||
}
|
||||
},
|
||||
"numRuns": 50
|
||||
}
|
20
challenges/2021/20-trenchMap/info.json
Normal file
20
challenges/2021/20-trenchMap/info.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"inputFile": "input.txt",
|
||||
"testCases": {
|
||||
"one": [
|
||||
{
|
||||
"input": "..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#\n\n#..#.\n#....\n##..#\n..#..\n..###",
|
||||
"expected": "35"
|
||||
}
|
||||
],
|
||||
"two": [
|
||||
{
|
||||
"input": "..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#\n\n#..#.\n#....\n##..#\n..#..\n..###",
|
||||
"expected": "3351"
|
||||
}
|
||||
]
|
||||
},
|
||||
"incorrect": {
|
||||
"one": ["6275"]
|
||||
}
|
||||
}
|
99
challenges/2021/20-trenchMap/py/__init__.py
Normal file
99
challenges/2021/20-trenchMap/py/__init__.py
Normal file
|
@ -0,0 +1,99 @@
|
|||
from typing import Dict, List, Tuple
|
||||
from aocpy import BaseChallenge
|
||||
|
||||
|
||||
LIT = "#"
|
||||
UNLIT = "."
|
||||
|
||||
|
||||
Point = Tuple[int, int]
|
||||
Image = Dict[Point, str]
|
||||
|
||||
|
||||
def parse(instr: str) -> Tuple[str, Image]:
|
||||
algo, image = instr.strip().split("\n\n")
|
||||
|
||||
image_dict = {}
|
||||
|
||||
for y, line in enumerate(image.splitlines()):
|
||||
for x, char in enumerate(line):
|
||||
if char == LIT:
|
||||
image_dict[(x, y)] = char
|
||||
|
||||
return algo, image_dict
|
||||
|
||||
|
||||
def get_adjacent_points(center_point: Point) -> List[Point]:
|
||||
x, y = center_point
|
||||
return [
|
||||
(x - 1, y - 1),
|
||||
(x, y - 1),
|
||||
(x + 1, y - 1),
|
||||
(x - 1, y),
|
||||
(x, y),
|
||||
(x + 1, y),
|
||||
(x - 1, y + 1),
|
||||
(x, y + 1),
|
||||
(x + 1, y + 1),
|
||||
]
|
||||
|
||||
|
||||
def enhance_n(image: Image, algorithm: str, n: int):
|
||||
# one does not simply "enhance" the image...
|
||||
|
||||
for i in range(n):
|
||||
min_x = min(x for x, _ in image)
|
||||
max_x = max(x for x, _ in image)
|
||||
min_y = min(y for _, y in image)
|
||||
max_y = max(y for _, y in image)
|
||||
|
||||
changes = {}
|
||||
for y in range(min_y - 2, max_y + 3):
|
||||
for x in range(min_x - 2, max_x + 3):
|
||||
p = (x, y)
|
||||
|
||||
n = 0
|
||||
for point in get_adjacent_points(p):
|
||||
px, py = point
|
||||
|
||||
is_lit = False
|
||||
|
||||
# If the first component of the algorithm (the one that's
|
||||
# used when no lit pixels are present) is lit, we can
|
||||
# assume that on every other iteration, the infinite dim
|
||||
# pixels are going to alternate between being lit and dim,
|
||||
# hence this weirdness.
|
||||
|
||||
if algorithm[0] == LIT and not (
|
||||
min_x <= px <= max_x and min_y <= py <= max_y
|
||||
):
|
||||
is_lit = i % 2 != 0
|
||||
else:
|
||||
is_lit = image.get(point, UNLIT) == LIT
|
||||
|
||||
n = (n << 1) | (0b1 if is_lit else 0b0)
|
||||
|
||||
changes[p] = algorithm[n]
|
||||
|
||||
for point in changes:
|
||||
change = changes[point]
|
||||
if change == UNLIT and point in image:
|
||||
del image[point]
|
||||
elif change == LIT:
|
||||
image[point] = LIT
|
||||
|
||||
|
||||
class Challenge(BaseChallenge):
|
||||
@staticmethod
|
||||
def core(instr: str, n: int) -> int:
|
||||
algorithm, image = parse(instr)
|
||||
enhance_n(image, algorithm, n)
|
||||
return len(image) # only lit pixels are included
|
||||
|
||||
@staticmethod
|
||||
def one(instr: str) -> int:
|
||||
return Challenge.core(instr, 2)
|
||||
|
||||
@staticmethod
|
||||
def two(instr: str) -> int:
|
||||
return Challenge.core(instr, 50)
|
48
challenges/2021/20-trenchMap/soln.py
Normal file
48
challenges/2021/20-trenchMap/soln.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
import sys
|
||||
|
||||
|
||||
def parse(f):
|
||||
yield [char == "#" for char in f.readline().rstrip()]
|
||||
f.readline()
|
||||
yield {
|
||||
(x, y) for y, line in enumerate(f) for x, char in enumerate(line) if char == "#"
|
||||
}
|
||||
|
||||
|
||||
def index(x, y, is_light):
|
||||
i = 0
|
||||
for ny in range(y - 1, y + 2):
|
||||
for nx in range(x - 1, x + 2):
|
||||
i = i << 1 | is_light(nx, ny)
|
||||
return i
|
||||
|
||||
|
||||
def enhance(light, algo, step):
|
||||
xmin = min(x for x, y in light)
|
||||
xmax = max(x for x, y in light)
|
||||
ymin = min(y for x, y in light)
|
||||
ymax = max(y for x, y in light)
|
||||
|
||||
def is_light(x, y):
|
||||
if algo[0] and not (xmin <= x <= xmax and ymin <= y <= ymax):
|
||||
return step % 2
|
||||
return (x, y) in light
|
||||
|
||||
return {
|
||||
(x, y)
|
||||
for y in range(ymin - 1, ymax + 2)
|
||||
for x in range(xmin - 1, xmax + 2)
|
||||
if algo[index(x, y, is_light)]
|
||||
}
|
||||
|
||||
|
||||
def enhance_times(light, algo, times):
|
||||
for step in range(times):
|
||||
light = enhance(light, algo, step)
|
||||
return light
|
||||
|
||||
|
||||
with open("input.txt") as f:
|
||||
algo, light = parse(f)
|
||||
print(len(enhance_times(light, algo, 2)))
|
||||
print(len(enhance_times(light, algo, 50)))
|
|
@ -10,27 +10,28 @@ Solutions to the [2021 Advent of Code](https://adventofcode.com/2021).
|
|||
|
||||
<!-- PARSE START -->
|
||||
|
||||
| Day | Status | Solutions | Notes |
|
||||
| ----------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 01 - Sonar Sweep | ★ ★ | [Python](01-sonarSweep/py), [Go](01-sonarSweep/go), [Nim](01-sonarSweep/nim) | Numbers and sliding windows. |
|
||||
| 02 - Dive! | ★ ★ | [Python](02-dive/py), [Go](02-dive/go) | Have this set of instructions and do something sensible with it. |
|
||||
| 03 - Binary Diagnostic | ★ ★ | [Python](03-binaryDiagnostic/py), [Nim](03-binaryDiagnostic/nim) | Bit twiddling aplenty! |
|
||||
| 04 - Giant Squid | ★ ★ | [Python](04-giantSquid/py) | B-I-N-G-O, B-I-N-G-O, B-I-N-G-O and Bingo was his name-o! |
|
||||
| 05 - Hydrothermal Venture | ★ ★ | [Python](05-hydrothermalVenture/py), [Go](05-hydrothermalVenture/go), [Nim](05-hydrothermalVenture/nim) | Pointy. |
|
||||
| 06 - Lanternfish | ★ ★ | [Python](06-lanternfish/py) | At this rate, the mass of the fish would surpass that of the Earth pretty quickly. |
|
||||
| 07 - The Treachery of Whales | ★ ★ | [Python](07-theTreacheryOfWhales/py) | I'm not 100% sure my solution for part two is valid for all possible inputs. |
|
||||
| 08 - Seven Segment Search | ★ ★ | [Python](08-sevenSegmentSearch/py), [Go](08-sevenSegmentSearch) | I may have taken the easy way out for part two, but it does work! No-one ever said the smart solution is the best solution, anyway. |
|
||||
| 09 - Smoke Basin \* | ★ ★ | [Python](09-smokeBasin/py) | Schmokey! Also, as it turns out, I struggle to implement basic logic. Fun. |
|
||||
| 10 - Syntax Scoring | ★ ★ | [Python](10-syntaxScoring/py) | I can't say I've ever broken something so thoroughly that it has a syntax error on *every* line... |
|
||||
| 11 - Dumbo Octopus | ★ ★ | [Python](11-dumboOctopus/py), [Nim](11-dumboOctopus/nim) | Cellular automata my beloved <3 |
|
||||
| 12 - Passage Pathing | ★ ★ | [Go](12-passagePathing/go) | I couldn't tell you how it works, but it does kinda work and I think I have a vague idea (external help was used). |
|
||||
| 13 - Transparent Origami | ★ ★ | [Python](13-transparentOrigami/py), [Nim](13-transparentOrigami/nim) | I got stuck for hours on an intermittent off-by-one error. :( |
|
||||
| 14 - Extended Polymerization | ★ ★ | [Python](14-extendedPolymerization/py) | Another off-by-one error, but this time it was because of dodgy division. Wonderful. |
|
||||
| 15 - Chiton | ★ ★ | [Python](15-chiton/py) | Pathfinding is hard |
|
||||
| 16 - Packet Decoder | ★ ★ | [Python](16-packetDecoder/py) | Parsing and interpreting stuff is surprisingly enjoyable |
|
||||
| 17 - Trick Shot | Unattempted | | |
|
||||
| 18 - Snailfish | Could not solve | | |
|
||||
| 19 - Beacon Scanner | Unattempted | | |
|
||||
| Day | Status | Solutions | Notes |
|
||||
| ----------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 01 - Sonar Sweep | ★ ★ | [Python](01-sonarSweep/py), [Go](01-sonarSweep/go), [Nim](01-sonarSweep/nim) | Numbers and sliding windows. |
|
||||
| 02 - Dive! | ★ ★ | [Python](02-dive/py), [Go](02-dive/go) | Have this set of instructions and do something sensible with it. |
|
||||
| 03 - Binary Diagnostic | ★ ★ | [Python](03-binaryDiagnostic/py), [Nim](03-binaryDiagnostic/nim) | Bit twiddling aplenty! |
|
||||
| 04 - Giant Squid | ★ ★ | [Python](04-giantSquid/py) | B-I-N-G-O, B-I-N-G-O, B-I-N-G-O and Bingo was his name-o! |
|
||||
| 05 - Hydrothermal Venture | ★ ★ | [Python](05-hydrothermalVenture/py), [Go](05-hydrothermalVenture/go), [Nim](05-hydrothermalVenture/nim) | Pointy. |
|
||||
| 06 - Lanternfish | ★ ★ | [Python](06-lanternfish/py) | At this rate, the mass of the fish would surpass that of the Earth pretty quickly. |
|
||||
| 07 - The Treachery of Whales | ★ ★ | [Python](07-theTreacheryOfWhales/py) | I'm not 100% sure my solution for part two is valid for all possible inputs. |
|
||||
| 08 - Seven Segment Search | ★ ★ | [Python](08-sevenSegmentSearch/py), [Go](08-sevenSegmentSearch) | I may have taken the easy way out for part two, but it does work! No-one ever said the smart solution is the best solution, anyway. |
|
||||
| 09 - Smoke Basin \* | ★ ★ | [Python](09-smokeBasin/py) | Schmokey! Also, as it turns out, I struggle to implement basic logic. Fun. |
|
||||
| 10 - Syntax Scoring | ★ ★ | [Python](10-syntaxScoring/py) | I can't say I've ever broken something so thoroughly that it has a syntax error on *every* line... |
|
||||
| 11 - Dumbo Octopus | ★ ★ | [Python](11-dumboOctopus/py), [Nim](11-dumboOctopus/nim) | Cellular automata my beloved <3 |
|
||||
| 12 - Passage Pathing | ★ ★ | [Go](12-passagePathing/go) | I couldn't tell you how it works, but it does kinda work and I think I have a vague idea (external help was used). |
|
||||
| 13 - Transparent Origami | ★ ★ | [Python](13-transparentOrigami/py), [Nim](13-transparentOrigami/nim) | I got stuck for hours on an intermittent off-by-one error. :( |
|
||||
| 14 - Extended Polymerization | ★ ★ | [Python](14-extendedPolymerization/py) | Another off-by-one error, but this time it was because of dodgy division. Wonderful. |
|
||||
| 15 - Chiton | ★ ★ | [Python](15-chiton/py) | Pathfinding is hard |
|
||||
| 16 - Packet Decoder | ★ ★ | [Python](16-packetDecoder/py) | Parsing and interpreting stuff is surprisingly enjoyable |
|
||||
| 17 - Trick Shot | Unattempted | | |
|
||||
| 18 - Snailfish | Could not solve | | |
|
||||
| 19 - Beacon Scanner | Unattempted | | |
|
||||
| 20 - Trench Map | ★ ★ | [Python](20-trenchMap/py) | Took a moment to realise that the infinite grid alternates between lit and unlit, and even then I had to look at someone else's solution to realise it. |
|
||||
|
||||
<!-- PARSE END -->
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 38 KiB |
Loading…
Add table
Add a link
Reference in a new issue