Add day 6

This commit is contained in:
2023-12-06 08:51:31 +01:00
committed by Hannes Körber
parent 41c97f0d7a
commit 4db2256836
4 changed files with 210 additions and 0 deletions

1
2023/day6/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target/

39
2023/day6/Cargo.lock generated Normal file
View File

@@ -0,0 +1,39 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day6"
version = "0.1.0"
dependencies = [
"indoc",
"nom",
]
[[package]]
name = "indoc"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8"
[[package]]
name = "memchr"
version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]

10
2023/day6/Cargo.toml Normal file
View File

@@ -0,0 +1,10 @@
[package]
name = "day6"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
indoc = "2.0.4"
nom = "7.1.3"

160
2023/day6/src/main.rs Normal file
View File

@@ -0,0 +1,160 @@
use nom::{
bytes::complete::tag,
character::complete::{char, digit1, multispace0, newline},
combinator::map,
multi::{many1, separated_list1},
sequence::{delimited, preceded, separated_pair, tuple},
IResult,
};
fn number(i: &str) -> IResult<&str, usize> {
map(digit1, |f: &str| f.parse::<usize>().unwrap())(i)
}
fn spaces(i: &str) -> IResult<&str, Vec<char>> {
many1(char(' '))(i)
}
#[derive(Debug)]
struct Race {
time: usize,
distance: usize,
}
#[derive(Debug)]
struct RaceSheet {
races: Vec<Race>,
}
impl RaceSheet {
fn parse(s: &str) -> IResult<&str, Self> {
let (rest, (times, distances)) = delimited(
multispace0,
separated_pair(
preceded(
tuple((tag("Time:"), spaces)),
separated_list1(spaces, number),
),
newline,
preceded(
tuple((tag("Distance:"), spaces)),
separated_list1(spaces, number),
),
),
multispace0,
)(s)?;
let races = times
.into_iter()
.zip(distances)
.map(|(time, distance)| Race { time, distance })
.collect::<Vec<Race>>();
Ok((rest, Self { races }))
}
}
fn part1(input: &str) -> Result<usize, String> {
let (rest, racesheet) = RaceSheet::parse(input).map_err(|e| e.to_string())?;
if !rest.is_empty() {
eprintln!("parsing rest found: {rest}");
panic!();
}
let result = racesheet
.races
.into_iter()
.map(|race| {
(0..=race.time)
.filter(|hold_time| {
let time_travelled = race.time - hold_time;
let speed = hold_time;
let distance_travelled = time_travelled * speed;
distance_travelled > race.distance
})
.collect::<Vec<_>>()
.len()
})
.product();
Ok(result)
}
fn part2(input: &str) -> Result<usize, String> {
let (rest, racesheet) = RaceSheet::parse(input).map_err(|e| e.to_string())?;
if !rest.is_empty() {
eprintln!("parsing rest found: {rest}");
panic!();
}
let time = racesheet
.races
.iter()
.map(|race| race.time.to_string())
.collect::<String>()
.parse::<usize>()
.unwrap();
let distance = racesheet
.races
.iter()
.map(|race| race.distance.to_string())
.collect::<String>()
.parse::<usize>()
.unwrap();
let result = (0..=time)
.filter(|hold_time| {
let time_travelled = time - hold_time;
let speed = hold_time;
let distance_travelled = time_travelled * speed;
distance_travelled > distance
})
.collect::<Vec<_>>()
.len();
Ok(result)
}
fn main() -> Result<(), String> {
let input = include_str!("../input");
let args = std::env::args().skip(1).collect::<Vec<String>>();
let part = args[0].parse::<usize>().unwrap();
if part == 1 {
println!("Part 1 : {}", part1(input)?);
} else if part == 2 {
println!("Part 2 : {}", part2(input)?);
} else {
panic!("unknown part")
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use indoc::indoc;
#[test]
fn example_01() {
let input = indoc! {"
Time: 7 15 30
Distance: 9 40 200
"};
assert_eq!(part1(&input).unwrap(), 288);
}
#[test]
fn example_02() {
let input = indoc! {"
Time: 7 15 30
Distance: 9 40 200
"};
assert_eq!(part2(&input).unwrap(), 71503);
}
}