mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Compare commits
2 Commits
fdaadfe184
...
be2244eca9
| Author | SHA1 | Date | |
|---|---|---|---|
| be2244eca9 | |||
| 395463dc4a |
@@ -2,17 +2,24 @@ variable "prev" {
|
|||||||
type = map(number)
|
type = map(number)
|
||||||
}
|
}
|
||||||
|
|
||||||
module "transform" {
|
|
||||||
source = "../transform"
|
|
||||||
for_each = var.prev
|
|
||||||
|
|
||||||
num = each.key
|
|
||||||
}
|
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
|
not_a_module = {
|
||||||
|
for num, _ in var.prev : num => (
|
||||||
|
tonumber(num) == 0
|
||||||
|
? [1]
|
||||||
|
: (
|
||||||
|
length(tostring(num)) % 2 == 0
|
||||||
|
? [
|
||||||
|
tonumber(substr(tostring(num), 0, length(tostring(num)) / 2)),
|
||||||
|
tonumber(substr(tostring(num), length(tostring(num)) / 2, length(tostring(num)) / 2)),
|
||||||
|
]
|
||||||
|
: [num * 2024]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
by_value = flatten([
|
by_value = flatten([
|
||||||
for key, value in module.transform :
|
for key, value in local.not_a_module :
|
||||||
[for result in value.result : { num = result, count = var.prev[key] }]
|
[for result in value : { num = result, count = var.prev[key] }]
|
||||||
])
|
])
|
||||||
|
|
||||||
grouped = { for kv in local.by_value : kv.num => kv.count... }
|
grouped = { for kv in local.by_value : kv.num => kv.count... }
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
variable "num" {
|
|
||||||
type = number
|
|
||||||
}
|
|
||||||
|
|
||||||
locals {
|
|
||||||
as_str = tostring(var.num)
|
|
||||||
len = length(local.as_str)
|
|
||||||
half = floor(length(local.as_str) / 2)
|
|
||||||
first = try(tonumber(substr(local.as_str, 0, local.half)), -1)
|
|
||||||
second = try(tonumber(substr(local.as_str, local.half, local.half)), -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
output "result" {
|
|
||||||
value = var.num == 0 ? [1] : local.len % 2 == 0 ? [local.first, local.second] : [var.num * 2024]
|
|
||||||
}
|
|
||||||
82
2024/src/aoc/days/day20.py
Normal file
82
2024/src/aoc/days/day20.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
import itertools
|
||||||
|
|
||||||
|
import numpy
|
||||||
|
|
||||||
|
from . import SeparateRunner
|
||||||
|
|
||||||
|
DIRECTIONS = [
|
||||||
|
(-1, 0),
|
||||||
|
(1, 0),
|
||||||
|
(0, -1),
|
||||||
|
(0, 1),
|
||||||
|
]
|
||||||
|
|
||||||
|
CHEATS = [
|
||||||
|
(-2, 0),
|
||||||
|
(2, 0),
|
||||||
|
(0, -2),
|
||||||
|
(0, 2),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def parse_path(input: str) -> dict[tuple[int, int], int]:
|
||||||
|
grid = numpy.array(list(map(list, input.strip().split("\n"))))
|
||||||
|
|
||||||
|
ys, xs = numpy.nonzero(grid == "S")
|
||||||
|
sx, sy = int(xs[0]), int(ys[0])
|
||||||
|
|
||||||
|
nx, ny = sx, sy
|
||||||
|
|
||||||
|
path = {
|
||||||
|
(sx, sy): 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
while grid[ny, nx] != "E":
|
||||||
|
x, y = nx, ny
|
||||||
|
|
||||||
|
for dx, dy in DIRECTIONS:
|
||||||
|
if grid[y + dy, x + dx] == "#" or (x + dx, y + dy) in path:
|
||||||
|
continue
|
||||||
|
nx = x + dx
|
||||||
|
ny = y + dy
|
||||||
|
break
|
||||||
|
|
||||||
|
path[nx, ny] = len(path)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def get_savings(a: tuple[tuple[int, int], int], b: tuple[tuple[int, int], int]) -> int:
|
||||||
|
(ax, ay), ad = a
|
||||||
|
(bx, by), bd = b
|
||||||
|
|
||||||
|
dist = abs(bx - ax) + abs(by - ay)
|
||||||
|
if dist <= 20:
|
||||||
|
return bd - ad - dist
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
class DayRunner(SeparateRunner):
|
||||||
|
@classmethod
|
||||||
|
def part1(cls, input: str, limit: int = 100) -> int:
|
||||||
|
path = parse_path(input)
|
||||||
|
|
||||||
|
total = 0
|
||||||
|
|
||||||
|
for (px, py), dist in path.items():
|
||||||
|
for dx, dy in CHEATS:
|
||||||
|
if (other := path.get((px + dx, py + dy))) is not None:
|
||||||
|
savings = dist - other - 2
|
||||||
|
if savings >= limit:
|
||||||
|
total += 1
|
||||||
|
|
||||||
|
return total
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def part2(cls, input: str, limit: int = 100) -> int:
|
||||||
|
path = parse_path(input)
|
||||||
|
|
||||||
|
return sum(
|
||||||
|
get_savings(a, b) >= limit
|
||||||
|
for a, b in itertools.combinations(path.items(), 2)
|
||||||
|
)
|
||||||
15
2024/tests/samples/20.txt
Normal file
15
2024/tests/samples/20.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
###############
|
||||||
|
#...#...#.....#
|
||||||
|
#.#.#.#.#.###.#
|
||||||
|
#S#...#.#.#...#
|
||||||
|
#######.#.#.###
|
||||||
|
#######.#.#...#
|
||||||
|
#######.#.###.#
|
||||||
|
###..E#...#...#
|
||||||
|
###.#######.###
|
||||||
|
#...###...#...#
|
||||||
|
#.#####.#.###.#
|
||||||
|
#.#...#.#.#...#
|
||||||
|
#.#.#.#.#.#.###
|
||||||
|
#...#...#...###
|
||||||
|
###############
|
||||||
11
2024/tests/test_day20.py
Normal file
11
2024/tests/test_day20.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from aoc.days.day20 import DayRunner
|
||||||
|
|
||||||
|
from . import get_data
|
||||||
|
|
||||||
|
|
||||||
|
def test_sample_part1() -> None:
|
||||||
|
assert DayRunner.part1(get_data(20), limit=1) == 44
|
||||||
|
|
||||||
|
|
||||||
|
def test_sample_part2() -> None:
|
||||||
|
assert DayRunner.part2(get_data(20), limit=50) == 285
|
||||||
Reference in New Issue
Block a user