-
Notifications
You must be signed in to change notification settings - Fork 0
/
06.rs
94 lines (80 loc) · 1.9 KB
/
06.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#![feature(test, isqrt)]
#[derive(Debug)]
struct Input {
races: Vec<Race>,
part2: Race,
}
#[derive(Debug, Clone, Copy)]
struct Race {
time: u64,
distance: u64,
}
fn setup(input: &str) -> Input {
let mut lines = input.lines();
let mut parse_line = || {
lines
.next()
.unwrap()
.split_whitespace()
.skip(1)
.map(|x| x.parse().unwrap())
};
let races = parse_line()
.zip(parse_line())
.map(|(t, d)| Race {
time: t,
distance: d,
})
.collect();
let mut lines = input.lines();
let mut parse_line = || {
lines
.next()
.unwrap()
.split(':')
.nth(1)
.unwrap()
.replace(' ', "")
.parse()
.unwrap()
};
let part2 = Race {
time: parse_line(),
distance: parse_line(),
};
Input { races, part2 }
}
fn solve(Race { time, distance }: Race) -> u64 {
let Some(x) = (time * time).checked_sub(distance * 4) else {
return 0;
};
let root = x.isqrt();
let root_is_int = (root * root == x) as u64;
root + (time + root + 1 + root_is_int) % 2 - root_is_int
}
fn part1(input: &Input) -> u64 {
input
.races
.iter()
.map(|&race| solve(race))
.filter(|&x| x > 0)
.product()
}
fn part2(input: &Input) -> u64 {
solve(input.part2)
}
aoc::main!(2023, 6, ex: 1);
#[cfg(test)]
mod tests {
use proptest::{prop_assert_eq, proptest};
use super::*;
proptest! {
#[test]
fn proptest_solve(t in (0u64..=200000), d in (0u64..=1000000)) {
let race = Race { time: t, distance: d };
let expected = (0..=t).filter(|i| i * (t - i) > d).count() as u64;
let result = solve(race);
prop_assert_eq!(result, expected);
}
}
}