day-6 done
This commit is contained in:
12
2023/day-6/Cargo.toml
Normal file
12
2023/day-6/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "day-6"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
nom.workspace = true
|
||||||
|
itertools.workspace = true
|
||||||
4
2023/day-6/src/lib.rs
Normal file
4
2023/day-6/src/lib.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
pub mod part1;
|
||||||
|
pub use crate::part1::*;
|
||||||
|
pub mod part2;
|
||||||
|
pub use crate::part2::*;
|
||||||
12
2023/day-6/src/main.rs
Normal file
12
2023/day-6/src/main.rs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#![warn(clippy::all, clippy::pedantic)]
|
||||||
|
|
||||||
|
use day_6::part1;
|
||||||
|
use day_6::part2;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let input = include_str!("./input.txt");
|
||||||
|
let part1_result = part1(input);
|
||||||
|
println!("part 1: {part1_result}");
|
||||||
|
let part2_result = part2(input);
|
||||||
|
println!("part 2: {part2_result}");
|
||||||
|
}
|
||||||
65
2023/day-6/src/part1.rs
Normal file
65
2023/day-6/src/part1.rs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#![warn(clippy::all, clippy::pedantic)]
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
use nom::{
|
||||||
|
bytes::complete::tag,
|
||||||
|
character::complete,
|
||||||
|
multi::separated_list1,
|
||||||
|
sequence::{pair, preceded},
|
||||||
|
IResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn part1(input: &str) -> String {
|
||||||
|
let (_, races) = parse_input(input).expect("input expected");
|
||||||
|
races
|
||||||
|
.iter()
|
||||||
|
.map(|(time, distance)| {
|
||||||
|
(0..=*time)
|
||||||
|
.filter_map(|x| {
|
||||||
|
if (time - x) * x > *distance {
|
||||||
|
Some(())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.count()
|
||||||
|
})
|
||||||
|
.product::<usize>()
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(input: &str) -> IResult<&str, Vec<(u64, u64)>> {
|
||||||
|
let (input, time) = preceded(
|
||||||
|
pair(tag("Time:"), complete::space1),
|
||||||
|
separated_list1(complete::space1, complete::u64),
|
||||||
|
)(input)?;
|
||||||
|
let (input, _) = complete::line_ending(input)?;
|
||||||
|
let (input, distance) = preceded(
|
||||||
|
pair(tag("Distance:"), complete::space1),
|
||||||
|
separated_list1(complete::space1, complete::u64),
|
||||||
|
)(input)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
time.iter()
|
||||||
|
.interleave(distance.iter())
|
||||||
|
.map(|x| *x)
|
||||||
|
.tuples()
|
||||||
|
.collect(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INPUT: &str = "Time: 7 15 30
|
||||||
|
Distance: 9 40 200";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_works() {
|
||||||
|
let result = part1(INPUT);
|
||||||
|
assert_eq!(result, "288".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
65
2023/day-6/src/part2.rs
Normal file
65
2023/day-6/src/part2.rs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#![warn(clippy::all, clippy::pedantic)]
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
use nom::{
|
||||||
|
bytes::complete::tag,
|
||||||
|
character::complete,
|
||||||
|
multi::separated_list1,
|
||||||
|
sequence::{pair, preceded},
|
||||||
|
IResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn part2(input: &str) -> String {
|
||||||
|
let (_, race) = parse_input(input).expect("input expected");
|
||||||
|
(0..=race.0)
|
||||||
|
.filter_map(|x| {
|
||||||
|
if (race.0 - x) * x > race.1 {
|
||||||
|
Some(())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.count()
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(input: &str) -> IResult<&str, (u64, u64)> {
|
||||||
|
let (input, time) = preceded(
|
||||||
|
pair(tag("Time:"), complete::space1),
|
||||||
|
separated_list1(complete::space1, complete::u64),
|
||||||
|
)(input)?;
|
||||||
|
let (input, _) = complete::line_ending(input)?;
|
||||||
|
let (input, distance) = preceded(
|
||||||
|
pair(tag("Distance:"), complete::space1),
|
||||||
|
separated_list1(complete::space1, complete::u64),
|
||||||
|
)(input)?;
|
||||||
|
let distance = distance
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.to_string())
|
||||||
|
.join("")
|
||||||
|
.parse::<u64>()
|
||||||
|
.expect("is a number");
|
||||||
|
let time = time
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.to_string())
|
||||||
|
.join("")
|
||||||
|
.parse::<u64>()
|
||||||
|
.expect("is a number");
|
||||||
|
|
||||||
|
Ok((input, (time, distance)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INPUT: &str = "Time: 7 15 30
|
||||||
|
Distance: 9 40 200";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_works() {
|
||||||
|
let result = part2(INPUT);
|
||||||
|
assert_eq!(result, "71503".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user