Add 2021-20 in Python

Signed-off-by: AKU <tom@tdpain.net>
This commit is contained in:
akp 2021-12-20 10:54:16 +00:00
parent 5737ee036b
commit 0f81ecaab5
No known key found for this signature in database
GPG key ID: AA5726202C8879B7
7 changed files with 206 additions and 21 deletions

View file

@ -0,0 +1,2 @@
# [Day <n>: <Day Title>](https://adventofcode.com/<year>/day/<n>)

View 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
}

View 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"]
}
}

View 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)

View 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)))

View file

@ -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

Before After
Before After