Solve 10
This commit is contained in:
parent
257c7e5cb6
commit
8673603676
3 changed files with 267 additions and 7 deletions
128
Cargo.lock
generated
128
Cargo.lock
generated
|
|
@ -34,9 +34,16 @@ dependencies = [
|
||||||
"cached",
|
"cached",
|
||||||
"glam",
|
"glam",
|
||||||
"itertools",
|
"itertools",
|
||||||
|
"microlp",
|
||||||
"rayon",
|
"rayon",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.19.0"
|
version = "3.19.0"
|
||||||
|
|
@ -208,6 +215,74 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matrixmultiply"
|
||||||
|
version = "0.3.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "microlp"
|
||||||
|
version = "0.2.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51d1790c73b93164ff65868f63164497cb32339458a9297e17e212d91df62258"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"sprs",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ndarray"
|
||||||
|
version = "0.17.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c7c9125e8f6f10c9da3aad044cc918cf8784fa34de857b1aa68038eb05a50a9"
|
||||||
|
dependencies = [
|
||||||
|
"matrixmultiply",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"portable-atomic",
|
||||||
|
"portable-atomic-util",
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.20.2"
|
version = "1.20.2"
|
||||||
|
|
@ -215,23 +290,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "portable-atomic"
|
||||||
version = "1.0.92"
|
version = "1.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic-util"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
|
||||||
|
dependencies = [
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.103"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.37"
|
version = "1.0.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rawpointer"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
|
|
@ -258,6 +354,24 @@ version = "1.0.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.15.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sprs"
|
||||||
|
version = "0.11.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6dca58a33be2188d4edc71534f8bafa826e787cc28ca1c47f31be3423f0d6e55"
|
||||||
|
dependencies = [
|
||||||
|
"ndarray",
|
||||||
|
"num-complex",
|
||||||
|
"num-traits",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
|
|
@ -266,9 +380,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.89"
|
version = "2.0.111"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
|
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ anyhow = "1.0.100"
|
||||||
cached = "0.56.0"
|
cached = "0.56.0"
|
||||||
glam = "0.30.9"
|
glam = "0.30.9"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
|
microlp = "0.2.11"
|
||||||
rayon = "1.11.0"
|
rayon = "1.11.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
|
|
||||||
145
src/bin/10.rs
Normal file
145
src/bin/10.rs
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
use aoc::*;
|
||||||
|
use microlp::{ComparisonOp, OptimizationDirection, Problem};
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
const INPUT: &str = include_str!("../../input/10");
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Part 1: {}", part1(INPUT));
|
||||||
|
println!("Part 2: {}", part2(INPUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example() {
|
||||||
|
assert_example!(part1, "10-test", 7);
|
||||||
|
assert_example!(part2, "10-test", 33);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(input: &str) -> usize {
|
||||||
|
parse_input(input).iter().map(minimum_light_presses).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(input: &str) -> usize {
|
||||||
|
parse_input(input).iter().map(minimum_joltage_presses).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
struct Machine {
|
||||||
|
required_lights: Vec<bool>,
|
||||||
|
buttons: Vec<Button>,
|
||||||
|
required_joltages: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Machine {
|
||||||
|
fn parse(input: &str) -> Self {
|
||||||
|
let mut m = Machine::default();
|
||||||
|
for part in input.split_whitespace() {
|
||||||
|
if part.starts_with('[') {
|
||||||
|
m.required_lights = parse_lights(part);
|
||||||
|
} else if part.starts_with('(') {
|
||||||
|
m.buttons.push(parse_button(part));
|
||||||
|
} else if part.starts_with('{') {
|
||||||
|
m.required_joltages = parse_joltages(part);
|
||||||
|
} else {
|
||||||
|
panic!("Unknown part '{}'", part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn minimum_light_presses(machine: &Machine) -> usize {
|
||||||
|
let mut work = VecDeque::new();
|
||||||
|
work.push_back((vec![false; machine.required_lights.len()], 0usize));
|
||||||
|
|
||||||
|
while let Some((lights, presses)) = work.pop_front() {
|
||||||
|
let matches = lights.iter().eq(&machine.required_lights);
|
||||||
|
if matches {
|
||||||
|
return presses;
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_lights = machine
|
||||||
|
.buttons
|
||||||
|
.iter()
|
||||||
|
.map(|b| (press_light(&lights, b), presses + 1));
|
||||||
|
work.extend(new_lights);
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn minimum_joltage_presses(machine: &Machine) -> usize {
|
||||||
|
let mut problem = Problem::new(OptimizationDirection::Minimize);
|
||||||
|
let mut buttons_vars = Vec::new();
|
||||||
|
for _ in 0..machine.buttons.len() {
|
||||||
|
let var = problem.add_integer_var(1.0, (0, i32::MAX));
|
||||||
|
buttons_vars.push(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, joltage) in machine.required_joltages.iter().copied().enumerate() {
|
||||||
|
let vars = buttons_vars
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.zip(&machine.buttons)
|
||||||
|
.filter(|(_var, button)| button.contains(&i))
|
||||||
|
.map(|(var, _button)| (var, 1.0));
|
||||||
|
problem.add_constraint(vars, ComparisonOp::Eq, joltage as f64);
|
||||||
|
}
|
||||||
|
|
||||||
|
let solution = problem.solve().unwrap();
|
||||||
|
buttons_vars
|
||||||
|
.into_iter()
|
||||||
|
.map(|var| solution[var].round() as usize)
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn press_light(lights: &[bool], button: &Button) -> Vec<bool> {
|
||||||
|
let mut lights = lights.to_vec();
|
||||||
|
for &b in button {
|
||||||
|
lights[b] ^= true;
|
||||||
|
}
|
||||||
|
lights
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_lights(input: &str) -> Vec<bool> {
|
||||||
|
input
|
||||||
|
.strip_prefix('[')
|
||||||
|
.unwrap()
|
||||||
|
.strip_suffix(']')
|
||||||
|
.unwrap()
|
||||||
|
.chars()
|
||||||
|
.map(|c| match c {
|
||||||
|
'.' => false,
|
||||||
|
'#' => true,
|
||||||
|
other => panic!("unknown light char '{other}'"),
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Button = Vec<usize>;
|
||||||
|
|
||||||
|
fn parse_button(input: &str) -> Button {
|
||||||
|
input
|
||||||
|
.strip_prefix('(')
|
||||||
|
.unwrap()
|
||||||
|
.strip_suffix(')')
|
||||||
|
.unwrap()
|
||||||
|
.split(',')
|
||||||
|
.map(|c| c.parse().unwrap())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_joltages(input: &str) -> Vec<usize> {
|
||||||
|
input
|
||||||
|
.strip_prefix('{')
|
||||||
|
.unwrap()
|
||||||
|
.strip_suffix('}')
|
||||||
|
.unwrap()
|
||||||
|
.split(',')
|
||||||
|
.map(|c| c.parse().unwrap())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(input: &str) -> Vec<Machine> {
|
||||||
|
input.lines().map(Machine::parse).collect()
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue