101 lines
2.6 KiB
Rust
101 lines
2.6 KiB
Rust
use std::iter::zip;
|
|
|
|
use nom::{
|
|
bytes::complete::tag,
|
|
character::complete::{multispace0, multispace1, u64},
|
|
multi::separated_list1,
|
|
sequence::tuple,
|
|
IResult,
|
|
};
|
|
|
|
fn parse_input(input: &str) -> IResult<&str, Vec<(u64, u64)>> {
|
|
let (input, result) = tuple((
|
|
tag("Time:"),
|
|
multispace0,
|
|
separated_list1(multispace1, u64),
|
|
multispace0,
|
|
tag("Distance:"),
|
|
multispace0,
|
|
separated_list1(multispace1, u64),
|
|
))(input)
|
|
.map(|(i, (_, _, times, _, _, _, distances))| (i, (times, distances)))?;
|
|
|
|
let result = zip(result.0, result.1).collect();
|
|
|
|
Ok((input, result))
|
|
}
|
|
|
|
fn record_beating_ways(time_distance_pair: (u64, u64)) -> usize {
|
|
(1..=time_distance_pair.0)
|
|
.into_iter()
|
|
.filter(|&time_charging| {
|
|
(time_distance_pair.0 - time_charging) * time_charging > time_distance_pair.1
|
|
})
|
|
.count()
|
|
}
|
|
|
|
fn solve_1(time_distance_pairs: &[(u64, u64)]) -> u64 {
|
|
time_distance_pairs
|
|
.iter()
|
|
.map(|&pair| record_beating_ways(pair) as u64)
|
|
.product()
|
|
}
|
|
|
|
fn solve_2(time_distance_pairs: &[(u64, u64)]) -> u64 {
|
|
let time_distance_pair = time_distance_pairs.iter().fold(
|
|
(0, 0),
|
|
|(output_time, output_distance), &(time, distance)| {
|
|
let time_len = (time as f64).log10().floor() as u32 + 1;
|
|
let distance_len = (distance as f64).log10().floor() as u32 + 1;
|
|
|
|
(
|
|
output_time * 10u64.pow(time_len) as u64 + time,
|
|
output_distance * 10u64.pow(distance_len) as u64 + distance,
|
|
)
|
|
},
|
|
);
|
|
|
|
record_beating_ways(time_distance_pair) as u64
|
|
}
|
|
|
|
fn main() {
|
|
println!("Hello, this is Patrick!");
|
|
|
|
let input_text = include_str!("../input.txt");
|
|
|
|
let (_, time_distance_pairs) = parse_input(input_text).unwrap();
|
|
|
|
println!(
|
|
"The product of the number of ways you could beat the record is {}",
|
|
solve_1(&time_distance_pairs[..])
|
|
);
|
|
|
|
println!(
|
|
"The longer race can be won in {} ways",
|
|
solve_2(&time_distance_pairs[..])
|
|
);
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_1() {
|
|
let input_text = include_str!("../test_input.txt");
|
|
|
|
let (_, time_distance_pairs) = parse_input(input_text).unwrap();
|
|
|
|
assert_eq!(solve_1(&time_distance_pairs[..]), 288);
|
|
}
|
|
|
|
#[test]
|
|
fn test_2() {
|
|
let input_text = include_str!("../test_input.txt");
|
|
|
|
let (_, time_distance_pairs) = parse_input(input_text).unwrap();
|
|
|
|
assert_eq!(solve_2(&time_distance_pairs[..]), 71503);
|
|
}
|
|
}
|