Skip to content

Commit ba60d34

Browse files
committed
2023 day 6.
1 parent d085a54 commit ba60d34

File tree

9 files changed

+197
-0
lines changed

9 files changed

+197
-0
lines changed

2023/06/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "y2023d06"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]
7+
lazy-regex = "3.4.1"

2023/06/data/example1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Time: 7 15 30
2+
Distance: 9 40 200

2023/06/data/input

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Time: 53 91 67 68
2+
Distance: 250 1330 1081 1025

2023/06/src/data.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#[cfg(test)]
2+
pub const EXAMPLE1: &'static str = include_str!("../data/example1");
3+
4+
#[allow(unused)]
5+
pub const INPUT: &'static str = include_str!("../data/input");

2023/06/src/main.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
mod data;
2+
mod part1;
3+
mod part2;
4+
mod puzzle;
5+
6+
fn main() {
7+
use data::INPUT;
8+
println!("Part 1: {}", part1::run(INPUT));
9+
println!("Part 2: {}", part2::run(INPUT));
10+
}

2023/06/src/part1/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use crate::puzzle::Puzzle;
2+
3+
pub fn run(input: &str) -> u64 {
4+
let puzzle: Puzzle = input.parse().expect("parse failed");
5+
puzzle.races.into_iter().map(|race| race.ways()).product()
6+
}
7+
8+
#[cfg(test)]
9+
mod test {
10+
use super::*;
11+
use crate::data::EXAMPLE1;
12+
13+
#[test]
14+
fn test1() {
15+
assert_eq!(run(EXAMPLE1), 288);
16+
}
17+
}

2023/06/src/part2/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use crate::puzzle::Puzzle;
2+
3+
pub fn run(input: &str) -> u64 {
4+
let puzzle: Puzzle = input
5+
.replace(' ', "")
6+
.replace(':', ": ")
7+
.parse()
8+
.expect("parse failed");
9+
puzzle.races.into_iter().map(|race| race.ways()).product()
10+
}
11+
12+
#[cfg(test)]
13+
mod test {
14+
use super::*;
15+
use crate::data::EXAMPLE1;
16+
17+
#[test]
18+
fn test1() {
19+
assert_eq!(run(EXAMPLE1), 71503);
20+
}
21+
}

2023/06/src/puzzle.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use std::{iter::zip, str::FromStr};
2+
3+
use lazy_regex::regex_captures;
4+
5+
#[derive(Debug)]
6+
pub struct Puzzle {
7+
pub races: Vec<Race>,
8+
}
9+
10+
#[derive(Debug)]
11+
pub struct Race {
12+
pub time: u64,
13+
pub distance: u64,
14+
}
15+
16+
impl Race {
17+
pub fn ways(&self) -> u64 {
18+
let q = ceil_sqrt(self.time * self.time - 4 * self.distance);
19+
q - ((self.time ^ q ^ 1) & 1)
20+
}
21+
}
22+
23+
#[test]
24+
fn test_race_ways() {
25+
assert_eq!(
26+
Race {
27+
time: 7,
28+
distance: 9,
29+
}
30+
.ways(),
31+
4
32+
);
33+
assert_eq!(
34+
Race {
35+
time: 15,
36+
distance: 40,
37+
}
38+
.ways(),
39+
8
40+
);
41+
assert_eq!(
42+
Race {
43+
time: 30,
44+
distance: 200,
45+
}
46+
.ways(),
47+
9
48+
);
49+
assert_eq!(
50+
Race {
51+
time: 71530,
52+
distance: 940200,
53+
}
54+
.ways(),
55+
71503
56+
);
57+
}
58+
59+
fn ceil_sqrt(n: u64) -> u64 {
60+
return (n - 1).isqrt() + 1;
61+
}
62+
63+
#[test]
64+
fn test_ceil_sqrt() {
65+
for i in 0u64..5 {
66+
for n in i.pow(2) + 1..=(i + 1).pow(2) {
67+
assert_eq!(ceil_sqrt(n), i + 1);
68+
}
69+
}
70+
}
71+
72+
#[derive(Debug)]
73+
pub struct ParseError;
74+
75+
impl FromStr for Puzzle {
76+
type Err = ParseError;
77+
78+
fn from_str(s: &str) -> Result<Self, Self::Err> {
79+
let (_, time, distance) = regex_captures!(
80+
r#"Time:\s+(\d+(?:\s+\d+)*)\nDistance:\s+(\d+(?:\s+\d+)*)"#,
81+
s
82+
)
83+
.ok_or(ParseError)?;
84+
let times: Vec<u64> = time
85+
.split_ascii_whitespace()
86+
.map(|s| s.parse())
87+
.collect::<Result<_, _>>()
88+
.map_err(|_| ParseError)?;
89+
let distances: Vec<u64> = distance
90+
.split_ascii_whitespace()
91+
.map(|s| s.parse())
92+
.collect::<Result<_, _>>()
93+
.map_err(|_| ParseError)?;
94+
if times.len() != distances.len() {
95+
return Err(ParseError);
96+
}
97+
Ok(Puzzle {
98+
races: zip(times, distances)
99+
.map(|(time, distance)| Race { time, distance })
100+
.collect(),
101+
})
102+
}
103+
}

Cargo.lock

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)