add other days
This commit is contained in:
parent
b4877b5cac
commit
1fc6832960
10 changed files with 482 additions and 3 deletions
12
day08.scm
12
day08.scm
|
@ -1,7 +1,9 @@
|
|||
(import (chicken io))
|
||||
(import (chicken string))
|
||||
(import (chicken format))
|
||||
(import srfi-113)
|
||||
(import srfi-1)
|
||||
(import srfi-128)
|
||||
|
||||
(define (summap a b) (foldl + 0 (map a b)))
|
||||
|
||||
|
@ -11,6 +13,7 @@
|
|||
(let ((halves (string-split line "|")))
|
||||
(map string-split halves)))
|
||||
|
||||
;; PART 1
|
||||
(define (is-1478 pattern)
|
||||
(let ((len (string-length pattern)))
|
||||
(not (or (eq? len 5) (eq? len 6)))))
|
||||
|
@ -19,6 +22,9 @@
|
|||
(let-values (((patterns output) (apply values parsed)))
|
||||
(count is-1478 output)))
|
||||
|
||||
(let* ((lines (read-lines))
|
||||
(separated (map split-line lines)))
|
||||
(displayln (summap count-1478 separated)))
|
||||
(define lines (read-lines))
|
||||
(define parsed-lines (map split-line lines))
|
||||
|
||||
(let ((part1 (summap count-1478 parsed-lines)))
|
||||
(display "part1: ")
|
||||
(displayln part1))
|
||||
|
|
59
day08_2.py
Normal file
59
day08_2.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env python3
|
||||
import fileinput
|
||||
import time
|
||||
|
||||
|
||||
lines = list(fileinput.input())
|
||||
|
||||
t = time.time_ns()
|
||||
|
||||
part2 = 0
|
||||
for line in lines:
|
||||
poss = {}
|
||||
|
||||
digits, output = (l.split() for l in str(line).split(" | "))
|
||||
|
||||
one = set(next(digit for digit in digits if len(digit) == 2))
|
||||
four = set(next(digit for digit in digits if len(digit) == 4))
|
||||
|
||||
for digit in digits:
|
||||
digit = "".join(sorted(digit))
|
||||
digit_set = set(digit)
|
||||
|
||||
overlap_one = len(digit_set & one)
|
||||
overlap_four = len(digit_set & four)
|
||||
|
||||
if len(digit) == 2: # 1
|
||||
poss[digit] = 1
|
||||
elif len(digit) == 3: # 7
|
||||
poss[digit] = 7
|
||||
elif len(digit) == 4: # 4
|
||||
poss[digit] = 4
|
||||
elif len(digit) == 5: # 2, 3, 5, 6
|
||||
if overlap_four == 2:
|
||||
poss[digit] = 2
|
||||
elif overlap_one == 1:
|
||||
poss[digit] = 5
|
||||
else:
|
||||
poss[digit] = 3
|
||||
elif len(digit) == 6: # 0, 6, 9
|
||||
if overlap_four == 4:
|
||||
poss[digit] = 9
|
||||
elif overlap_one == 2:
|
||||
poss[digit] = 0
|
||||
else:
|
||||
poss[digit] = 6
|
||||
elif len(digit) == 7:
|
||||
poss[digit] = 8
|
||||
|
||||
result = 0
|
||||
for digit in output:
|
||||
digit = "".join(sorted(digit))
|
||||
result = (result * 10) + poss[digit]
|
||||
|
||||
part2 += result
|
||||
|
||||
t2 = time.time_ns()
|
||||
print(part2)
|
||||
print(t2 - t, "ns")
|
||||
print((t2 - t) // 1000, "µs")
|
45
day09.py
Normal file
45
day09.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/env python3
|
||||
import fileinput
|
||||
import heapq
|
||||
from typing import Generator, Tuple
|
||||
|
||||
heightmap = []
|
||||
for line in fileinput.input():
|
||||
heightmap.append([int(c) for c in line.strip()])
|
||||
|
||||
def neighborhood(x: int, y: int) -> Generator[Tuple[int, int], None, None]:
|
||||
global heightmap
|
||||
if x > 0:
|
||||
yield (x - 1, y)
|
||||
if x < len(heightmap[0]) - 1:
|
||||
yield (x + 1, y)
|
||||
if y > 0:
|
||||
yield (x, y - 1)
|
||||
if y < len(heightmap) - 1:
|
||||
yield (x, y + 1)
|
||||
|
||||
lowpoints = list()
|
||||
for y, row in enumerate(heightmap):
|
||||
for x, height in enumerate(row):
|
||||
if height < min(heightmap[y_][x_] for x_, y_ in neighborhood(x, y)):
|
||||
lowpoints.append((x, y))
|
||||
|
||||
print("part 1:", sum(1 + heightmap[y][x] for x, y in lowpoints))
|
||||
|
||||
basins = []
|
||||
for lowpoint in lowpoints:
|
||||
stack = [lowpoint]
|
||||
visited = set()
|
||||
while stack:
|
||||
x, y = stack.pop()
|
||||
if (x, y) in visited or heightmap[y][x] == 9:
|
||||
continue
|
||||
visited.add((x, y))
|
||||
|
||||
for neighbor in neighborhood(x, y):
|
||||
stack.append(neighbor)
|
||||
|
||||
heapq.heappush(basins, len(visited))
|
||||
|
||||
a, b, c, *_ = heapq.nlargest(3, basins)
|
||||
print("part 2:", a * b * c)
|
41
day10.py
Normal file
41
day10.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env python3
|
||||
import fileinput
|
||||
from collections import deque
|
||||
from timeit import timeit
|
||||
from typing import Tuple
|
||||
|
||||
lines = list(fileinput.input())
|
||||
|
||||
opposites = {"[": "]", "(": ")", "{": "}", "<": ">"}
|
||||
part1_points = {")": 3, "]": 57, "}": 1197, ">": 25137}
|
||||
part2_points = {"(": 1, "[": 2, "{": 3, "<": 4}
|
||||
|
||||
def main() -> Tuple[int, int]:
|
||||
part1 = 0
|
||||
part2_scores = []
|
||||
|
||||
for line_ in lines:
|
||||
line = str(line_).strip()
|
||||
stack = deque()
|
||||
for c in line:
|
||||
if c in "[({<":
|
||||
stack.appendleft(c)
|
||||
elif opposites[stack[0]] != c:
|
||||
part1 += part1_points[c]
|
||||
break
|
||||
else:
|
||||
stack.popleft()
|
||||
else:
|
||||
score = 0
|
||||
for c in stack:
|
||||
score = score * 5 + part2_points[c]
|
||||
part2_scores.append(score)
|
||||
|
||||
part2_scores.sort()
|
||||
part2 = part2_scores[len(part2_scores) // 2]
|
||||
|
||||
return (part1, part2)
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(main())
|
||||
print(f"{timeit(main, number=1000):.3f} ms")
|
69
day11.py
Normal file
69
day11.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/env python3
|
||||
import fileinput
|
||||
from pprint import pprint
|
||||
from typing import List, Tuple, Any, Set, Generator
|
||||
from timeit import timeit
|
||||
|
||||
|
||||
lines = list(fileinput.input())
|
||||
|
||||
|
||||
def neighborhood(
|
||||
m: List[List[int]], x: int, y: int
|
||||
) -> Generator[Tuple[int, int], None, None]:
|
||||
h = ((-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1))
|
||||
yield from (
|
||||
(x_ + x, y_ + y)
|
||||
for x_, y_ in h
|
||||
if 0 <= x_ + x < len(m[0]) and 0 <= y_ + y < len(m)
|
||||
)
|
||||
|
||||
|
||||
def step(field):
|
||||
for y in range(len(field)):
|
||||
for x in range(len(field[y])):
|
||||
field[y][x] += 1
|
||||
|
||||
flash_queue = [
|
||||
(x, y)
|
||||
for y in range(len(field))
|
||||
for x in range(len(field[y]))
|
||||
if field[y][x] > 9
|
||||
]
|
||||
|
||||
flashed = set()
|
||||
while flash_queue:
|
||||
x, y = flash_queue.pop()
|
||||
if (x, y) in flashed:
|
||||
continue
|
||||
flashed.add((x, y))
|
||||
|
||||
for x_, y_ in neighborhood(field, x, y):
|
||||
field[y_][x_] += 1
|
||||
if field[y_][x_] > 9 and (x_, y_) not in flashed:
|
||||
flash_queue.append((x_, y_))
|
||||
|
||||
for x, y in flashed:
|
||||
field[y][x] = 0
|
||||
|
||||
return len(flashed)
|
||||
|
||||
|
||||
def main() -> Tuple[int, int]:
|
||||
field = [[int(c) for c in line.strip()] for line in lines]
|
||||
len_ = len(field) * len(field[0])
|
||||
|
||||
part1 = 0
|
||||
part2 = 0
|
||||
for part2 in range(100):
|
||||
part1 += step(field)
|
||||
|
||||
while step(field) != len_ and sum(sum(row) for row in field) != 0:
|
||||
part2 += 1
|
||||
|
||||
return part1, part2 + 2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(main())
|
||||
print(f"{timeit(main, number=100) * 10:.3f} ms")
|
64
day12.py
Normal file
64
day12.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env python3
|
||||
import fileinput
|
||||
from timeit import timeit
|
||||
from typing import FrozenSet, List, Optional, Tuple, Union
|
||||
from collections import defaultdict
|
||||
|
||||
lines = list(fileinput.input())
|
||||
|
||||
|
||||
def main():
|
||||
# parse
|
||||
graph = defaultdict(list)
|
||||
for line in lines:
|
||||
fro, to = str(line).strip().split("-")
|
||||
graph[fro].append(to)
|
||||
graph[to].append(fro)
|
||||
|
||||
# part 1
|
||||
stack: List[Tuple[str, FrozenSet[str]]] = [("start", frozenset())]
|
||||
part1 = 0
|
||||
while stack:
|
||||
pos, visited = stack.pop()
|
||||
if pos.islower() and pos in visited:
|
||||
continue
|
||||
visited = visited | {pos}
|
||||
|
||||
if pos == "end":
|
||||
part1 += 1
|
||||
continue
|
||||
|
||||
for next_pos in graph[pos]:
|
||||
stack.append((next_pos, visited))
|
||||
|
||||
stack2: List[Tuple[str, FrozenSet[str], Optional[str]]] = [
|
||||
("start", frozenset(), None)
|
||||
]
|
||||
part2 = 0
|
||||
while stack2:
|
||||
pos, visited, doubled = stack2.pop()
|
||||
|
||||
if pos.islower() and pos in visited:
|
||||
if doubled is None:
|
||||
stack2.append((pos, visited, pos))
|
||||
continue
|
||||
if doubled != pos:
|
||||
continue
|
||||
doubled = ""
|
||||
|
||||
visited = visited | {pos}
|
||||
|
||||
if pos == "end":
|
||||
part2 += 1
|
||||
continue
|
||||
|
||||
for next_pos in graph[pos]:
|
||||
if next_pos != "start":
|
||||
stack2.append((next_pos, visited, doubled))
|
||||
|
||||
return part1, part2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(main())
|
||||
print(f"{timeit(main, number=20) * 50:.3f} ms")
|
62
day13.py
Normal file
62
day13.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env python3
|
||||
import fileinput
|
||||
from pprint import pprint
|
||||
from timeit import timeit
|
||||
|
||||
lines = list(fileinput.input())
|
||||
|
||||
|
||||
def main():
|
||||
h = 0
|
||||
w = 0
|
||||
|
||||
dots = set()
|
||||
folds = []
|
||||
part1 = 0
|
||||
for line in lines:
|
||||
line = str(line)
|
||||
if line[0].isdigit():
|
||||
x, y = (int(n) for n in line.split(","))
|
||||
h = max(x + 1, h)
|
||||
w = max(y + 1, w)
|
||||
dots.add((x, y))
|
||||
elif line[0] == "f":
|
||||
c, n = line.split("=")
|
||||
folds.append((c[-1], int(n)))
|
||||
|
||||
for dir, pos in folds:
|
||||
folded = set()
|
||||
if dir == "y":
|
||||
for x, y in dots:
|
||||
if y > pos:
|
||||
y2 = 2 * pos - y
|
||||
folded.add((x, y2))
|
||||
else:
|
||||
folded.add((x, y))
|
||||
else:
|
||||
for x, y in dots:
|
||||
if x > pos:
|
||||
x2 = 2 * pos - x
|
||||
folded.add((x2, y))
|
||||
else:
|
||||
folded.add((x, y))
|
||||
dots = folded
|
||||
|
||||
if part1 == 0:
|
||||
part1 = len(dots)
|
||||
|
||||
xs, ys = zip(*dots)
|
||||
sheet = [[" "] * (max(xs) + 1) for _ in range(max(ys) + 1)]
|
||||
for x, y in dots:
|
||||
sheet[y][x] = "#"
|
||||
|
||||
return part1, ["".join(row).replace("#", "█") for row in sheet]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
a, b = main()
|
||||
print("part 1:", a)
|
||||
print("part 2:")
|
||||
print("\n".join(b))
|
||||
|
||||
print(f"{timeit(main, number=1000):.3f} ms")
|
25
rust/Cargo.lock
generated
Normal file
25
rust/Cargo.lock
generated
Normal file
|
@ -0,0 +1,25 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aoc_rust"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
9
rust/Cargo.toml
Normal file
9
rust/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "aoc_rust"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
fxhash = "0.2.1"
|
99
rust/src/main.rs
Normal file
99
rust/src/main.rs
Normal file
|
@ -0,0 +1,99 @@
|
|||
use std::io::BufRead;
|
||||
use std::time::Instant;
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
||||
fn main() {
|
||||
let mut graph = [0usize; 32];
|
||||
let stdin = std::io::stdin();
|
||||
let lines = stdin.lock().lines();
|
||||
|
||||
let mut nodes = HashMap::new();
|
||||
let mut is_small = 0u32;
|
||||
|
||||
let instant = Instant::now();
|
||||
for line in lines {
|
||||
let line = line.unwrap();
|
||||
let split = line.split("-").collect::<Vec<_>>();
|
||||
|
||||
let next_a = nodes.len();
|
||||
let a = *nodes.entry(split[0].to_string()).or_insert(next_a);
|
||||
|
||||
let next_b = nodes.len();
|
||||
let b = *nodes.entry(split[1].to_string()).or_insert(next_b);
|
||||
|
||||
graph[a] |= 1 << b;
|
||||
graph[b] |= 1 << a;
|
||||
|
||||
if split[0].find(char::is_uppercase).is_none() {
|
||||
is_small |= 1 << a;
|
||||
}
|
||||
if split[1].find(char::is_uppercase).is_none() {
|
||||
is_small |= 1 << b;
|
||||
}
|
||||
}
|
||||
|
||||
let start = nodes["start"];
|
||||
let end = nodes["end"];
|
||||
|
||||
let mut stack = vec![(start, 0u32)];
|
||||
let mut part1 = 0;
|
||||
while stack.len() != 0 {
|
||||
let (pos, visited) = stack.pop().unwrap();
|
||||
let pos_mask = 1 << pos;
|
||||
if (is_small & visited) & pos_mask != 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
if pos == end {
|
||||
part1 += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut next = graph[pos];
|
||||
while next != 0 {
|
||||
let next_pos = next.trailing_zeros();
|
||||
stack.push((next_pos as usize, visited | pos_mask));
|
||||
next &= !(1 << next_pos);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Copy, Clone)]
|
||||
enum Doubled {
|
||||
None,
|
||||
Done,
|
||||
Some(usize),
|
||||
}
|
||||
|
||||
let mut stack = vec![(start, 0u32, Doubled::None)];
|
||||
let mut part2 = 0;
|
||||
while stack.len() != 0 {
|
||||
let (pos, visited, mut doubled) = stack.pop().unwrap();
|
||||
let pos_mask = 1 << pos;
|
||||
if (is_small & visited) & pos_mask != 0 {
|
||||
if doubled == Doubled::None {
|
||||
stack.push((pos, visited, Doubled::Some(pos)));
|
||||
continue;
|
||||
} else if doubled != Doubled::Some(pos) {
|
||||
continue;
|
||||
} else {
|
||||
doubled = Doubled::Done;
|
||||
}
|
||||
}
|
||||
|
||||
if pos == end {
|
||||
part2 += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut next = graph[pos] & !(1 << start);
|
||||
while next != 0 {
|
||||
let next_pos = next.trailing_zeros();
|
||||
stack.push((next_pos as usize, visited | pos_mask, doubled));
|
||||
next &= !(1 << next_pos);
|
||||
}
|
||||
}
|
||||
|
||||
let elapsed = instant.elapsed();
|
||||
dbg!(part1, part2, elapsed);
|
||||
}
|
Loading…
Reference in a new issue