This commit is contained in:
RingOfStorms (Joshua Bell) 2023-12-06 00:20:31 -06:00
parent ff43610821
commit 8a1cc61578
3 changed files with 107 additions and 27 deletions

2
aoc_puzzle_cache/day_6 Normal file
View file

@ -0,0 +1,2 @@
Time: 53 91 67 68
Distance: 250 1330 1081 1025

View file

@ -176,6 +176,7 @@ fn part2(input: String) -> Result<usize> {
.map(|s| s.parse::<usize>().expect("failed to parse seed as number")) .map(|s| s.parse::<usize>().expect("failed to parse seed as number"))
.tuples() .tuples()
.flat_map(|(start, length)| start..start + length) .flat_map(|(start, length)| start..start + length)
.take(3000)
// Squeeze with rayon for brute force approach // Squeeze with rayon for brute force approach
.par_bridge() .par_bridge()
.map(|source| almanac.map_source(source, "seed", "location")) .map(|source| almanac.map_source(source, "seed", "location"))

View file

@ -7,41 +7,66 @@ use std::{str::FromStr, time::Instant};
static DAY: u8 = 6; static DAY: u8 = 6;
#[derive(Debug, Builder, Clone)] #[derive(Debug, Builder, Clone)]
struct Todo {} struct Race {
time: usize,
record_distance: usize,
}
impl FromStr for Todo { impl Race {
type Err = BoxE; fn get_roots(&self) -> (usize, usize) {
let a = -1.0;
let b = self.time as f64;
let c = -(self.record_distance as f64);
let n1 = (-b + f64::sqrt(b * b - (4.0 * a * c))) / (2.0 * a);
let n2 = (-b - f64::sqrt(b * b - (4.0 * a * c))) / (2.0 * a);
if n1 < n2 {
// floor and round up to ensure we win
let n1 = f64::floor(n1) as usize + 1;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { // ceil and round down to ensure we don't exceed time cap
let mut builder = TodoBuilder::default(); let n2 = f64::ceil(n2) as usize - 1;
Ok(builder.build()?) (n1, n2)
} else {
let n1 = f64::ceil(n1) as usize - 1;
let n2 = f64::floor(n2) as usize + 1;
(n2, n1)
}
}
fn get_ways_to_beat_count(&self) -> usize {
let (n1, n2) = self.get_roots();
if self.time < n1 {
0
} else {
let n2 = usize::min(self.time, n2);
n2 - n1 + 1
}
} }
} }
fn part1(input: String) -> Result<usize> { fn part1(races: &[Race]) -> Result<usize> {
// parse
let start = Instant::now();
let todo: Todo = input.parse()?;
let parsed_time = start.elapsed();
// algo // algo
let start = Instant::now(); let start = Instant::now();
let answer = 0; let mut answer = 1;
for race in races {
let ways_to_beat = race.get_ways_to_beat_count();
println!(
"Race: {:?}, roots: {:?}, ways to beat: {:?}",
race,
race.get_roots(),
race.get_ways_to_beat_count()
);
answer *= ways_to_beat;
}
let algo_time = start.elapsed(); let algo_time = start.elapsed();
// output // output
println!("part 1: {answer}"); println!("part 1: {answer}");
println!("\tparse: {parsed_time:?}");
println!("\talgo: {algo_time:?}"); println!("\talgo: {algo_time:?}");
Ok(answer) Ok(answer)
} }
fn part2(input: String) -> Result<usize> { fn part2(races: &[Race]) -> Result<usize> {
// parse
let start = Instant::now();
let todo: Todo = input.parse()?;
let parsed_time = start.elapsed();
// algo // algo
let start = Instant::now(); let start = Instant::now();
let answer = 0; let answer = 0;
@ -49,18 +74,57 @@ fn part2(input: String) -> Result<usize> {
// output // output
println!("part 2: {answer}"); println!("part 2: {answer}");
println!("\tparse: {parsed_time:?}");
println!("\talgo: {algo_time:?}"); println!("\talgo: {algo_time:?}");
Ok(answer) Ok(answer)
} }
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
let input = utils::aoc::get_puzzle_input(DAY).await?; // let input = utils::aoc::get_puzzle_input(DAY).await?;
println!("Day {DAY}"); println!("Day {DAY}");
println!("====="); println!("=====");
part1(input.clone())?; let races: [Race; 4] = [
part2(input.clone())?; Race {
time: 53,
record_distance: 250,
},
Race {
time: 91,
record_distance: 1330,
},
Race {
time: 67,
record_distance: 1081,
},
Race {
time: 68,
record_distance: 1025,
},
];
let races: [Race; 1] = [Race {
time: 53916768,
record_distance: 250133010811025,
}];
let races: [Race; 3] = [
Race {
time: 7,
record_distance: 9,
},
Race {
time: 15,
record_distance: 40,
},
Race {
time: 30,
record_distance: 200,
},
];
let races: [Race; 1] = [Race {
time: 71530,
record_distance: 940200,
}];
part1(&races)?;
part2(&races)?;
Ok(()) Ok(())
} }
@ -68,17 +132,30 @@ async fn main() -> Result<()> {
mod tests { mod tests {
use super::*; use super::*;
static DATA: &'static str = "TODO_REPLACE"; static RACES: [Race; 3] = [
Race {
time: 7,
record_distance: 9,
},
Race {
time: 15,
record_distance: 40,
},
Race {
time: 30,
record_distance: 200,
},
];
#[test] #[test]
fn test_part_1() -> Result<()> { fn test_part_1() -> Result<()> {
assert_eq!(part1(DATA.to_owned())?, 0); assert_eq!(part1(&RACES)?, 288);
Ok(()) Ok(())
} }
#[test] #[test]
fn test_part_2() -> Result<()> { fn test_part_2() -> Result<()> {
assert_eq!(part2(DATA.to_owned())?, 0); assert_eq!(part2(&RACES)?, 0);
Ok(()) Ok(())
} }
} }