Rewrote part 2 using Chinese Remainder theorem
This commit is contained in:
parent
f87e5ea0af
commit
fdbbd934a4
|
@ -55,6 +55,7 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"nom",
|
"nom",
|
||||||
"num",
|
"num",
|
||||||
|
"num-modular",
|
||||||
"regex",
|
"regex",
|
||||||
"topological-sort",
|
"topological-sort",
|
||||||
]
|
]
|
||||||
|
@ -169,6 +170,12 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-modular"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-rational"
|
name = "num-rational"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
|
|
@ -9,5 +9,6 @@ aoc-runner-derive = "0.3.0"
|
||||||
hashbrown = "0.15.2"
|
hashbrown = "0.15.2"
|
||||||
nom = "7.1.3"
|
nom = "7.1.3"
|
||||||
num = "0.4.3"
|
num = "0.4.3"
|
||||||
|
num-modular = "0.6.1"
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
topological-sort = "0.2.2"
|
topological-sort = "0.2.2"
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::sync::OnceLock;
|
|
||||||
|
|
||||||
use aoc_runner_derive::{aoc, aoc_generator};
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
|
||||||
use nom::{
|
use nom::{
|
||||||
|
@ -10,6 +8,8 @@ use nom::{
|
||||||
sequence::{preceded, separated_pair},
|
sequence::{preceded, separated_pair},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use num_modular::ModularPow;
|
||||||
|
|
||||||
type Input = Vec<((i64, i64), (i64, i64))>;
|
type Input = Vec<((i64, i64), (i64, i64))>;
|
||||||
|
|
||||||
#[aoc_generator(day14)]
|
#[aoc_generator(day14)]
|
||||||
|
@ -54,43 +54,42 @@ fn part1(input: &Input) -> i64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[aoc(day14, part2)]
|
#[aoc(day14, part2)]
|
||||||
fn part2(input: &Input) -> usize {
|
fn part2(input: &Input) -> i64 {
|
||||||
let (w, h) = (101, 103);
|
let (w, h) = (101, 103);
|
||||||
|
|
||||||
let mut input = input.clone();
|
let mut offset_x = 0;
|
||||||
|
let mut min_var = f64::INFINITY;
|
||||||
let mut iter = 0;
|
for t in 0..w {
|
||||||
|
let values = input.iter().map(|((p, _), (v, _))| (p + t * (v + w)) % w);
|
||||||
loop {
|
let mean = values.clone().sum::<i64>() as f64 / input.len() as f64;
|
||||||
iter += 1;
|
let variance = values
|
||||||
|
.map(|v| (v as f64 - mean) * (v as f64 - mean))
|
||||||
let mut total = (0f64, 0f64);
|
|
||||||
input = input
|
|
||||||
.into_iter()
|
|
||||||
.map(|((px, py), (vx, vy))| {
|
|
||||||
let (px, py) = ((px + vx + w) % w, (py + vy + h) % h);
|
|
||||||
total.0 += px as f64;
|
|
||||||
total.1 += py as f64;
|
|
||||||
((px, py), (vx, vy))
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let mean = (total.0 / input.len() as f64, total.1 / input.len() as f64);
|
|
||||||
let variance = input
|
|
||||||
.iter()
|
|
||||||
.map(|((px, py), _)| {
|
|
||||||
let dx = *px as f64 - mean.0;
|
|
||||||
let dy = *py as f64 - mean.1;
|
|
||||||
dx * dx + dy * dy
|
|
||||||
})
|
|
||||||
.sum::<f64>()
|
.sum::<f64>()
|
||||||
/ input.len() as f64;
|
/ input.len() as f64;
|
||||||
|
if variance < min_var {
|
||||||
if variance < 1000.0 {
|
min_var = variance;
|
||||||
break;
|
offset_x = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iter
|
let mut offset_y = 0;
|
||||||
|
let mut min_var = f64::INFINITY;
|
||||||
|
for t in 0..h {
|
||||||
|
let values = input.iter().map(|((_, p), (_, v))| (p + t * (v + h)) % h);
|
||||||
|
let mean = values.clone().sum::<i64>() as f64 / input.len() as f64;
|
||||||
|
let variance = values
|
||||||
|
.map(|v| (v as f64 - mean) * (v as f64 - mean))
|
||||||
|
.sum::<f64>()
|
||||||
|
/ input.len() as f64;
|
||||||
|
if variance < min_var {
|
||||||
|
min_var = variance;
|
||||||
|
offset_y = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let invmod_x = (w as u64).powm((h - 2) as u64, &(h as u64)) as i64;
|
||||||
|
let invmod_y = (h as u64).powm((w - 2) as u64, &(w as u64)) as i64;
|
||||||
|
(offset_x * h * invmod_x + offset_y * w * invmod_y) % (w * h)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Reference in New Issue