add other days

This commit is contained in:
Sijmen Schoon 2021-12-14 14:27:07 +01:00
parent b4877b5cac
commit 1fc6832960
Signed by: vijfhoek
GPG key ID: DAF7821E067D9C48
10 changed files with 482 additions and 3 deletions

View file

@ -1,7 +1,9 @@
(import (chicken io)) (import (chicken io))
(import (chicken string)) (import (chicken string))
(import (chicken format)) (import (chicken format))
(import srfi-113)
(import srfi-1) (import srfi-1)
(import srfi-128)
(define (summap a b) (foldl + 0 (map a b))) (define (summap a b) (foldl + 0 (map a b)))
@ -11,6 +13,7 @@
(let ((halves (string-split line "|"))) (let ((halves (string-split line "|")))
(map string-split halves))) (map string-split halves)))
;; PART 1
(define (is-1478 pattern) (define (is-1478 pattern)
(let ((len (string-length pattern))) (let ((len (string-length pattern)))
(not (or (eq? len 5) (eq? len 6))))) (not (or (eq? len 5) (eq? len 6)))))
@ -19,6 +22,9 @@
(let-values (((patterns output) (apply values parsed))) (let-values (((patterns output) (apply values parsed)))
(count is-1478 output))) (count is-1478 output)))
(let* ((lines (read-lines)) (define lines (read-lines))
(separated (map split-line lines))) (define parsed-lines (map split-line lines))
(displayln (summap count-1478 separated)))
(let ((part1 (summap count-1478 parsed-lines)))
(display "part1: ")
(displayln part1))

59
day08_2.py Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}