day 6
This commit is contained in:
parent
ff43610821
commit
8a1cc61578
3 changed files with 107 additions and 27 deletions
2
aoc_puzzle_cache/day_6
Normal file
2
aoc_puzzle_cache/day_6
Normal file
|
@ -0,0 +1,2 @@
|
|||
Time: 53 91 67 68
|
||||
Distance: 250 1330 1081 1025
|
|
@ -176,6 +176,7 @@ fn part2(input: String) -> Result<usize> {
|
|||
.map(|s| s.parse::<usize>().expect("failed to parse seed as number"))
|
||||
.tuples()
|
||||
.flat_map(|(start, length)| start..start + length)
|
||||
.take(3000)
|
||||
// Squeeze with rayon for brute force approach
|
||||
.par_bridge()
|
||||
.map(|source| almanac.map_source(source, "seed", "location"))
|
||||
|
|
129
src/bin/day6.rs
129
src/bin/day6.rs
|
@ -7,41 +7,66 @@ use std::{str::FromStr, time::Instant};
|
|||
static DAY: u8 = 6;
|
||||
|
||||
#[derive(Debug, Builder, Clone)]
|
||||
struct Todo {}
|
||||
struct Race {
|
||||
time: usize,
|
||||
record_distance: usize,
|
||||
}
|
||||
|
||||
impl FromStr for Todo {
|
||||
type Err = BoxE;
|
||||
impl Race {
|
||||
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> {
|
||||
let mut builder = TodoBuilder::default();
|
||||
Ok(builder.build()?)
|
||||
// ceil and round down to ensure we don't exceed time cap
|
||||
let n2 = f64::ceil(n2) as usize - 1;
|
||||
(n1, n2)
|
||||
} else {
|
||||
let n1 = f64::ceil(n1) as usize - 1;
|
||||
let n2 = f64::floor(n2) as usize + 1;
|
||||
(n2, n1)
|
||||
}
|
||||
}
|
||||
|
||||
fn part1(input: String) -> Result<usize> {
|
||||
// parse
|
||||
let start = Instant::now();
|
||||
let todo: Todo = input.parse()?;
|
||||
let parsed_time = start.elapsed();
|
||||
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(races: &[Race]) -> Result<usize> {
|
||||
// algo
|
||||
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();
|
||||
|
||||
// output
|
||||
println!("part 1: {answer}");
|
||||
println!("\tparse: {parsed_time:?}");
|
||||
println!("\talgo: {algo_time:?}");
|
||||
Ok(answer)
|
||||
}
|
||||
|
||||
fn part2(input: String) -> Result<usize> {
|
||||
// parse
|
||||
let start = Instant::now();
|
||||
let todo: Todo = input.parse()?;
|
||||
let parsed_time = start.elapsed();
|
||||
|
||||
fn part2(races: &[Race]) -> Result<usize> {
|
||||
// algo
|
||||
let start = Instant::now();
|
||||
let answer = 0;
|
||||
|
@ -49,18 +74,57 @@ fn part2(input: String) -> Result<usize> {
|
|||
|
||||
// output
|
||||
println!("part 2: {answer}");
|
||||
println!("\tparse: {parsed_time:?}");
|
||||
println!("\talgo: {algo_time:?}");
|
||||
Ok(answer)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
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!("=====");
|
||||
part1(input.clone())?;
|
||||
part2(input.clone())?;
|
||||
let races: [Race; 4] = [
|
||||
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(())
|
||||
}
|
||||
|
||||
|
@ -68,17 +132,30 @@ async fn main() -> Result<()> {
|
|||
mod tests {
|
||||
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]
|
||||
fn test_part_1() -> Result<()> {
|
||||
assert_eq!(part1(DATA.to_owned())?, 0);
|
||||
assert_eq!(part1(&RACES)?, 288);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2() -> Result<()> {
|
||||
assert_eq!(part2(DATA.to_owned())?, 0);
|
||||
assert_eq!(part2(&RACES)?, 0);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue