Compare commits

...

2 commits

Author SHA1 Message Date
018514a9f9 Solve day 18 2024-12-18 22:37:49 +01:00
f3c1072d08 Partial solve day 17 2024-12-18 21:54:34 +01:00
9 changed files with 3716 additions and 0 deletions

1
Cargo.lock generated
View file

@ -15,6 +15,7 @@ dependencies = [
"image", "image",
"itertools 0.13.0", "itertools 0.13.0",
"memoize", "memoize",
"rayon",
"regex", "regex",
] ]

View file

@ -7,4 +7,5 @@ edition = "2021"
image = "0.25.5" image = "0.25.5"
itertools = "0.13.0" itertools = "0.13.0"
memoize = "0.4.2" memoize = "0.4.2"
rayon = "1.10.0"
regex = "1.11.1" regex = "1.11.1"

5
input/17-0a.in Normal file
View file

@ -0,0 +1,5 @@
Register A: 729
Register B: 0
Register C: 0
Program: 0,1,5,4,3,0

5
input/17-0b.in Normal file
View file

@ -0,0 +1,5 @@
Register A: 2024
Register B: 0
Register C: 0
Program: 0,3,5,4,3,0

5
input/17-1.in Normal file
View file

@ -0,0 +1,5 @@
Register A: 27575648
Register B: 0
Register C: 0
Program: 2,4,1,2,7,5,4,1,1,3,5,5,0,3,3,0

25
input/18-0.in Normal file
View file

@ -0,0 +1,25 @@
5,4
4,2
4,5
3,0
2,1
6,3
2,4
1,5
0,6
3,3
2,6
5,1
1,2
5,5
2,5
6,5
1,4
0,4
6,4
1,1
6,1
1,0
0,5
1,6
2,0

3450
input/18-1.in Normal file

File diff suppressed because it is too large Load diff

166
src/bin/17.rs Normal file
View file

@ -0,0 +1,166 @@
use rayon::prelude::*;
fn combo_operand(operand: u8, a: u64, b: u64, c: u64) -> u64 {
match operand {
0..4 => operand as u64,
4 => a,
5 => b,
6 => c,
_ => unreachable!(),
}
}
fn run_program(program: &[u8], mut a: u64, mut b: u64, mut c: u64) -> Vec<u8> {
let mut i = 0;
let mut output = Vec::new();
while let Some((&opcode, &operand)) = program.get(i).zip(program.get(i + 1)) {
// dbg!(i, a, b, c, opcode, operand);
match opcode {
0 => {
a = a / (2u64.pow(combo_operand(operand, a, b, c) as u32));
i += 2
}
1 => {
b ^= operand as u64;
i += 2;
}
2 => {
b = combo_operand(operand, a, b, c) % 8;
i += 2
}
3 => {
if a != 0 {
i = operand as usize
} else {
i += 2;
}
}
4 => {
b ^= c;
i += 2;
}
5 => {
output.push((combo_operand(operand, a, b, c) % 8) as u8);
i += 2;
}
6 => {
b = a / (2u64.pow(combo_operand(operand, a, b, c) as u32));
i += 2
}
7 => {
c = a / (2u64.pow(combo_operand(operand, a, b, c) as u32));
i += 2
}
_ => unreachable!(),
}
}
output
}
fn run_program_output(program: &[u8], mut a: u64, mut b: u64, mut c: u64) -> bool {
let mut i = 0;
let mut o = 0;
while let Some((&opcode, &operand)) = program.get(i).zip(program.get(i + 1)) {
// dbg!(i, a, b, c, opcode, operand);
match opcode {
0 => {
a = a / (2u64.pow(combo_operand(operand, a, b, c) as u32));
i += 2
}
1 => {
b ^= operand as u64;
i += 2;
}
2 => {
b = combo_operand(operand, a, b, c) % 8;
i += 2
}
3 => {
if a != 0 {
i = operand as usize
} else {
i += 2;
}
}
4 => {
b ^= c;
i += 2;
}
5 => {
if program.len() >= o && program[o] != (combo_operand(operand, a, b, c) % 8) as u8 {
return false;
}
o += 1;
i += 2;
}
6 => {
b = a / (2u64.pow(combo_operand(operand, a, b, c) as u32));
i += 2
}
7 => {
c = a / (2u64.pow(combo_operand(operand, a, b, c) as u32));
i += 2
}
_ => unreachable!(),
}
}
o == program.len()
}
fn main() {
let text = std::fs::read_to_string("input/17-1.in").unwrap();
let mut lines = text.lines();
let start_a = lines
.next()
.unwrap()
.split_once(": ")
.unwrap()
.1
.parse::<u64>()
.unwrap();
let start_b = lines
.next()
.unwrap()
.split_once(": ")
.unwrap()
.1
.parse::<u64>()
.unwrap();
let start_c = lines
.next()
.unwrap()
.split_once(": ")
.unwrap()
.1
.parse::<u64>()
.unwrap();
let program = lines
.nth(1)
.unwrap()
.split_once(": ")
.unwrap()
.1
.split(',')
.map(|c| c.parse::<u8>().unwrap())
.collect::<Vec<_>>();
println!("{:?}", run_program(&program, start_a, start_b, start_c));
let start = 1_000_000_000_000u64;
let t = (start..start * 10)
.into_par_iter()
.find_first(|&i| run_program_output(&program, i, 0, 0))
.unwrap();
println!("{t}");
}

58
src/bin/18.rs Normal file
View file

@ -0,0 +1,58 @@
use std::collections::{HashMap, HashSet, VecDeque};
static DIRECTIONS: [(isize, isize); 4] = [(0, -1), (1, 0), (0, 1), (-1, 0)];
fn dijkstra(map: &HashSet<(usize, usize)>, size: usize) -> Option<usize> {
let mut queue = VecDeque::new();
queue.push_back((0usize, 0usize, 0usize));
let mut visited = HashSet::new();
while let Some((cx, cy, steps)) = queue.pop_front() {
if cx == size - 1 && cy == size - 1 {
return Some(steps);
}
if visited.insert((cx, cy)) {
for (nx, ny) in DIRECTIONS.iter().filter_map(|&(dx, dy)| {
Option::zip(
cx.checked_add_signed(dx).filter(|&s| s < size),
cy.checked_add_signed(dy).filter(|&s| s < size),
)
}) {
if !visited.contains(&(nx, ny)) && map.get(&(nx, ny)).is_none() {
queue.push_back((nx, ny, steps + 1));
}
}
}
}
None
}
fn main() {
// let text = std::fs::read_to_string("input/18-0.in").unwrap();
// let size = 7;
// let first = 12;
let text = std::fs::read_to_string("input/18-1.in").unwrap();
let size = 71;
let first = 1024;
let mut iter = text.lines().map(|l| {
let (x, y) = l.split_once(',').unwrap();
(x.parse::<usize>().unwrap(), y.parse::<usize>().unwrap())
});
let mut map = iter.by_ref().take(first).collect::<HashSet<_>>();
let t = dijkstra(&map, size);
println!("{t:?}");
for d in iter {
map.insert(d);
if dijkstra(&map, size).is_none() {
println!("{d:?}");
break;
}
}
}