add: day 19, part2 not working
This commit is contained in:
Generated
+125
@@ -7,6 +7,7 @@ name = "advent-of-code-2024"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"good_lp",
|
"good_lp",
|
||||||
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"threadpool",
|
"threadpool",
|
||||||
]
|
]
|
||||||
@@ -26,6 +27,18 @@ version = "0.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
|
checksum = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "coin_cbc"
|
name = "coin_cbc"
|
||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
@@ -57,6 +70,17 @@ version = "0.3.55"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
|
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "good_lp"
|
name = "good_lp"
|
||||||
version = "1.10.0"
|
version = "1.10.0"
|
||||||
@@ -129,6 +153,63 @@ version = "0.3.31"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.92"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.11.1"
|
version = "1.11.1"
|
||||||
@@ -158,6 +239,17 @@ version = "0.8.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.90"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "threadpool"
|
name = "threadpool"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
@@ -166,3 +258,36 @@ checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
good_lp = {version = "1.10.0", features = ["lpsolve"]}
|
good_lp = {version = "1.10.0", features = ["lpsolve"]}
|
||||||
|
rand = "0.8.5"
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
threadpool = "1.8.1"
|
threadpool = "1.8.1"
|
||||||
|
|||||||
+73
-19
@@ -6,6 +6,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use advent_of_code_2024::{make_main, SResult};
|
use advent_of_code_2024::{make_main, SResult};
|
||||||
|
use rand::{thread_rng, RngCore};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use threadpool::ThreadPool;
|
use threadpool::ThreadPool;
|
||||||
|
|
||||||
@@ -26,14 +27,15 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use dynamic programming; start by constructing the puzzle forwards backwards
|
||||||
fn run_to_end(&mut self) -> Vec<usize> {
|
fn run_to_end(&mut self) -> Vec<usize> {
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while self.pointer < self.program.len() {
|
while self.pointer < self.program.len() {
|
||||||
if let Some(val) = self.opcode() {
|
if let Some(val) = self.opcode() {
|
||||||
if val != self.program[i] {
|
/*if val != self.program[i] {
|
||||||
break;
|
break;
|
||||||
}
|
}*/
|
||||||
results.push(val);
|
results.push(val);
|
||||||
i += 1;
|
i += 1;
|
||||||
if i == self.program.len() {
|
if i == self.program.len() {
|
||||||
@@ -127,26 +129,59 @@ fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
|
|||||||
println!();
|
println!();
|
||||||
|
|
||||||
let pool = ThreadPool::new(20);
|
let pool = ThreadPool::new(20);
|
||||||
//let mut n = 3536000000;
|
let mut incr = 8usize.pow(program.len() as u32 - 2);
|
||||||
let mut n = 0;
|
let mut count = program.len() - 1;
|
||||||
let mut prev_best = 0;
|
let mut n = incr;
|
||||||
let program: &'static mut [usize] = program.leak();
|
|
||||||
loop {
|
loop {
|
||||||
let values = State::new(&program, [n, 0, 0]).run_to_end();
|
let values = State::new(&program, [n, 0, 0]).run_to_end();
|
||||||
if values.len() > prev_best {
|
//println!("{} {count} {:?}", n, values);
|
||||||
println!("{} => {:?}", n, values);
|
if values == program {
|
||||||
prev_best = values.len();
|
println!("found at {n}");
|
||||||
|
println!("Matched (n={n} incr={incr}) {:?}, {:?}", values, program);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
while &values == program {
|
//println!("{} vs {}", values[count], program[count]);
|
||||||
println!("finished at {}", n);
|
if values.len() > count && &values[count..] == &program[count..] {
|
||||||
//exit(n as i32);
|
count -= 1;
|
||||||
}
|
if count > 2 {
|
||||||
n += 1;
|
incr = 8usize.pow(count as u32 - 2);
|
||||||
if n % 1000000 == 0 {
|
} else {
|
||||||
println!("n = {}", n);
|
incr = 1;
|
||||||
|
}
|
||||||
|
println!("Matched (n={n} incr={incr}) {:?}, {:?}", values, program);
|
||||||
}
|
}
|
||||||
|
n += incr;
|
||||||
}
|
}
|
||||||
Ok((values.len(), n))
|
println!("{} => {:?}", n, values);
|
||||||
|
//let mut n = 3_536_000_000;
|
||||||
|
//let mut n = 0;
|
||||||
|
/*
|
||||||
|
let program: &'static mut [usize] = program.leak();
|
||||||
|
let mut handles = vec!();
|
||||||
|
for part in 0..20 {
|
||||||
|
let program: &'static [usize] = program;
|
||||||
|
let h = thread::spawn(move || {
|
||||||
|
let mut prev_best = 0;
|
||||||
|
let mut n = thread_rng().next_u64() as usize;
|
||||||
|
loop {
|
||||||
|
let values = State::new(&program, [n, 0, 0]).run_to_end();
|
||||||
|
if values.len() > prev_best {
|
||||||
|
println!("{} => {:?}", n, values);
|
||||||
|
prev_best = values.len();
|
||||||
|
}
|
||||||
|
while &values == program {
|
||||||
|
println!("finished at {}", n);
|
||||||
|
//exit(n as i32);
|
||||||
|
}
|
||||||
|
n = (thread_rng().next_u64() as usize % (usize::MAX / 20)) + (usize::MAX * part);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
handles.push(h);
|
||||||
|
}
|
||||||
|
for h in handles {
|
||||||
|
h.join().unwrap();
|
||||||
|
}*/
|
||||||
|
Ok((values.len(), 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -158,13 +193,32 @@ mod tests {
|
|||||||
fn d17i1() {
|
fn d17i1() {
|
||||||
let strings: Vec<String> = input!("d17i1.txt");
|
let strings: Vec<String> = input!("d17i1.txt");
|
||||||
let got = solve(strings).unwrap();
|
let got = solve(strings).unwrap();
|
||||||
assert_eq!(got, (4, 117440));
|
assert_eq!(got, (4, 0));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn d17i2() {
|
fn d17i2() {
|
||||||
|
// This never ends
|
||||||
return;
|
return;
|
||||||
let strings: Vec<String> = input!("d17i2.txt");
|
let strings: Vec<String> = input!("d17i2.txt");
|
||||||
let got = solve(strings).unwrap();
|
let got = solve(strings).unwrap();
|
||||||
assert_eq!(got, (4, 117440));
|
assert_eq!(got, (4, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
5 => [2]
|
||||||
|
27 => [2, 4]
|
||||||
|
2234 => [2, 4, 1]
|
||||||
|
35002 => [2, 4, 1, 1]
|
||||||
|
39098 => [2, 4, 1, 1, 7]
|
||||||
|
|
||||||
|
3536000005 => [2]
|
||||||
|
3536000027 => [2, 4]
|
||||||
|
3536000283 => [2, 4, 1]
|
||||||
|
3536095418 => [2, 4, 1, 1]
|
||||||
|
3536099514 => [2, 4, 1, 1, 7]
|
||||||
|
|
||||||
|
18155064657419344382 => [2, 4, 1, 1, 7, 5, 0, 3, 4, 3, 1, 6]
|
||||||
|
|
||||||
|
*/
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
use std::{
|
||||||
|
cmp::Reverse, collections::{BinaryHeap, HashMap, HashSet}, process::exit, thread, time::Duration
|
||||||
|
};
|
||||||
|
|
||||||
|
use advent_of_code_2024::{make_main, next, next2, Pair, SResult};
|
||||||
|
use rand::{thread_rng, RngCore};
|
||||||
|
use regex::Regex;
|
||||||
|
use threadpool::ThreadPool;
|
||||||
|
|
||||||
|
make_main!();
|
||||||
|
|
||||||
|
fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
|
||||||
|
let (ans1, ans2) = solve2(lines, (71, 71), 1024)?;
|
||||||
|
println!("Ans2: {},{}", ans2.0, ans2.1);
|
||||||
|
Ok((ans1, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve2(lines: Vec<String>, dims: Pair, time: usize) -> SResult<(usize, Pair)> {
|
||||||
|
let mut blocks: Vec<(usize, usize)> = Vec::with_capacity(lines.len());
|
||||||
|
for line in lines {
|
||||||
|
let (left, right) = line.split_once(",").unwrap();
|
||||||
|
blocks.push((right.parse().unwrap(), left.parse().unwrap()));
|
||||||
|
}
|
||||||
|
let mut grid = make_grid(dims);
|
||||||
|
for i in 0..time {
|
||||||
|
grid[blocks[i].1][blocks[i].0] = '#';
|
||||||
|
}
|
||||||
|
|
||||||
|
// A* search where we order things by their distance to the target
|
||||||
|
let target = (dims.0-1, dims.1-1);
|
||||||
|
let mut heap = BinaryHeap::new();
|
||||||
|
heap.push(Reverse(Pos::new((0, 0), target, 0)));
|
||||||
|
let mut visited: HashMap<Pair, usize> = HashMap::default();
|
||||||
|
|
||||||
|
let mut found = None;
|
||||||
|
while let Some(item) = heap.pop() {
|
||||||
|
let item = item.0;
|
||||||
|
for vel in [(1, 0), (-1, 0), (0, 1), (0, -1)] {
|
||||||
|
if let Some(pos) = next2(item.loc, vel, dims) {
|
||||||
|
if pos == target {
|
||||||
|
found = Some(item.steps+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if grid[pos.0][pos.1] != '#' && *visited.get(&pos).unwrap_or(&usize::MAX) > item.steps+1 {
|
||||||
|
heap.push(Reverse(Pos::new(pos, target, item.steps+1)));
|
||||||
|
visited.insert(pos, item.steps+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the second part, do the same thing, but drop blocks until we can't reach the exist
|
||||||
|
let mut grid = make_grid(dims);
|
||||||
|
let mut blocker = None;
|
||||||
|
for time in 0..blocks.len() {
|
||||||
|
grid[blocks[time].1][blocks[time].0] = '#';
|
||||||
|
let target = (dims.0-1, dims.1-1);
|
||||||
|
let mut heap = BinaryHeap::new();
|
||||||
|
heap.push(Reverse(Pos::new((0, 0), target, 0)));
|
||||||
|
let mut visited: HashMap<Pair, usize> = HashMap::default();
|
||||||
|
|
||||||
|
let mut found = None;
|
||||||
|
while let Some(item) = heap.pop() {
|
||||||
|
let item = item.0;
|
||||||
|
for vel in [(1, 0), (-1, 0), (0, 1), (0, -1)] {
|
||||||
|
if let Some(pos) = next2(item.loc, vel, dims) {
|
||||||
|
if pos == target {
|
||||||
|
found = Some(item.steps+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if grid[pos.0][pos.1] != '#' && *visited.get(&pos).unwrap_or(&usize::MAX) > item.steps+1 {
|
||||||
|
heap.push(Reverse(Pos::new(pos, target, item.steps+1)));
|
||||||
|
visited.insert(pos, item.steps+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if found.is_none() {
|
||||||
|
blocker = Some((blocks[time].1, blocks[time].0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok((found.unwrap(), blocker.unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_grid(dims: Pair) -> Vec<Vec<char>> {
|
||||||
|
let mut grid = Vec::with_capacity(dims.0);
|
||||||
|
for _ in 0..dims.0 {
|
||||||
|
let mut row = Vec::with_capacity(dims.1);
|
||||||
|
for _ in 0..dims.1 {
|
||||||
|
row.push('.');
|
||||||
|
}
|
||||||
|
grid.push(row);
|
||||||
|
}
|
||||||
|
grid
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_grid(grid: &[Vec<char>], visited: HashMap<Pair, usize>) {
|
||||||
|
println!();
|
||||||
|
for i in 0..grid.len() {
|
||||||
|
for j in 0..grid[i].len() {
|
||||||
|
if visited.contains_key(&(i, j)) {
|
||||||
|
print!("O");
|
||||||
|
} else {
|
||||||
|
print!("{}", grid[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, PartialOrd, Debug, Eq)]
|
||||||
|
struct Pos {
|
||||||
|
loc: Pair,
|
||||||
|
target: Pair,
|
||||||
|
steps: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pos {
|
||||||
|
fn new(loc: Pair, target: Pair, steps: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
steps,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn distance_to_target(&self) -> f64 {
|
||||||
|
let (x1, y1) = (self.loc.0 as f64, self.loc.1 as f64);
|
||||||
|
let (x2, y2) = (self.target.0 as f64, self.target.1 as f64);
|
||||||
|
((x1-x2).powi(2) + (y1-y2).powi(2)).sqrt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Pos {
|
||||||
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
|
let sdist = self.distance_to_target();
|
||||||
|
let odist = other.distance_to_target();
|
||||||
|
if (sdist - odist).abs() < 1.0 {
|
||||||
|
self.steps.cmp(&other.steps)
|
||||||
|
} else {
|
||||||
|
sdist.total_cmp(&odist)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use advent_of_code_2024::input;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn d18i1() {
|
||||||
|
let strings: Vec<String> = input!("d18i1.txt");
|
||||||
|
let got = solve2(strings, (7, 7), 12).unwrap();
|
||||||
|
assert_eq!(got, (22, (6, 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use advent_of_code_2024::{make_main, SResult};
|
||||||
|
|
||||||
|
make_main!();
|
||||||
|
|
||||||
|
fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
|
||||||
|
let mut patterns: Vec<&str> = lines[0].split(",").map(|s| s.trim()).collect();
|
||||||
|
|
||||||
|
let mut memo: HashMap<&str, usize> = HashMap::default();
|
||||||
|
memo.insert("", 1);
|
||||||
|
|
||||||
|
// See if we can elimate any patterns; sort by length, and for each pattern,
|
||||||
|
// see if we can form it using shorter patterns. If we can, ignore it.
|
||||||
|
patterns.sort_by(|a, b| a.len().cmp(&b.len()));
|
||||||
|
// Stores a mapping of 'char' => (pattern, larger_patterns)
|
||||||
|
let mut new_patterns: HashMap<char, Vec<(&str, HashSet<&str>)>> = HashMap::default();
|
||||||
|
let mut small_patterns = HashSet::new();
|
||||||
|
for pattern in &patterns {
|
||||||
|
if let Some(c) = rec(&pattern, &new_patterns, &mut memo) {
|
||||||
|
*memo.entry(&pattern).or_insert(0) = c + 1;
|
||||||
|
} else {
|
||||||
|
let start = pattern.chars().next().unwrap();
|
||||||
|
new_patterns.entry(start).or_insert_with(Vec::new).push((pattern, HashSet::new()));
|
||||||
|
small_patterns.insert(pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (_, v) in new_patterns.iter_mut() {
|
||||||
|
v.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
|
|
||||||
|
for v in v {
|
||||||
|
for pattern in &patterns {
|
||||||
|
if small_patterns.contains(pattern) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(_) = pattern.strip_prefix(v.0) {
|
||||||
|
v.1.insert(pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Patterns: {:?}", new_patterns);
|
||||||
|
|
||||||
|
let mut memo_vec: Vec<(&str, usize)> = memo.clone().into_iter().collect();
|
||||||
|
memo_vec.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
|
println!("Memo: {:?}", memo_vec);
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
let mut count2 = 0;
|
||||||
|
for (i, line) in (&lines[2..]).iter().enumerate() {
|
||||||
|
//println!("Line {} of {}", i, lines.len()-2);
|
||||||
|
if let Some(c) = rec(&line, &new_patterns, &mut memo) {
|
||||||
|
count += 1;
|
||||||
|
count2 += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut memo_vec: Vec<(&str, usize)> = memo.into_iter().collect();
|
||||||
|
memo_vec.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
|
println!("Memo: {:?}", memo_vec);
|
||||||
|
Ok((count, count2))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rec<'a>(left: &'a str, patterns: &HashMap<char, Vec<(&'a str, HashSet<&'a str>)>>, memo: &mut HashMap<&'a str, usize>) -> Option<usize> {
|
||||||
|
if let Some(val) = memo.get(&left) {
|
||||||
|
return Some(*val);
|
||||||
|
}
|
||||||
|
let mut count = 0;
|
||||||
|
let start = left.chars().next().unwrap();
|
||||||
|
for (pattern, large_patterns) in patterns.get(&start).unwrap_or(&vec!()) {
|
||||||
|
if let Some(substr) = left.strip_prefix(pattern) {
|
||||||
|
if let Some(c) = rec(substr, patterns, memo) {
|
||||||
|
count += c;
|
||||||
|
// Can we match any larger patterns?
|
||||||
|
for pat2 in large_patterns {
|
||||||
|
if let Some(substr) = left.strip_prefix(pat2) {
|
||||||
|
if let Some(c) = rec(substr, patterns, memo) {
|
||||||
|
count += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if count == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
memo.insert(left, count);
|
||||||
|
Some(count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use advent_of_code_2024::input;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn d19i1() {
|
||||||
|
let strings: Vec<String> = input!("d19i1.txt");
|
||||||
|
let got = solve(strings).unwrap();
|
||||||
|
assert_eq!(got, (6, 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
r, wr, b, g, bwu, rb, gb, br
|
||||||
|
|
||||||
|
brwrr
|
||||||
|
bggr
|
||||||
|
gbbr
|
||||||
|
rrbgbr
|
||||||
|
ubwu
|
||||||
|
bwurrg
|
||||||
|
brgr
|
||||||
|
bbrgwb
|
||||||
Reference in New Issue
Block a user