tangled
alpha
login
or
join now
jonas.tngl.sh
/
advent-of-code
0
fork
atom
Advent of Code solutions in Rust
0
fork
atom
overview
issues
pulls
pipelines
feat: part 1 of day 13 of AoC 2020
jonas.tngl.sh
4 months ago
33260893
e6afa7ce
1/1
rust.yml
success
6m 27s
+93
-2
2 changed files
expand all
collapse all
unified
split
aoc_2020
src
day13.rs
main.rs
+91
aoc_2020/src/day13.rs
···
1
1
+
use anyhow::{Context, anyhow, bail};
2
2
+
use aoc_companion::prelude::*;
3
3
+
use itertools::Itertools as _;
4
4
+
use std::str::FromStr;
5
5
+
6
6
+
pub(crate) struct Door {
7
7
+
arrival_time: u64,
8
8
+
bus_schedule: Vec<BusLine>,
9
9
+
}
10
10
+
11
11
+
impl<'input> Solution<'input> for Door {
12
12
+
fn parse(input: &'input str) -> Result<Self> {
13
13
+
let Some((arrival_line, buses_line)) = input.split_once('\n') else {
14
14
+
bail!(
15
15
+
"expected exactly two lines, got {} lines",
16
16
+
input.lines().count()
17
17
+
)
18
18
+
};
19
19
+
20
20
+
Ok(Self {
21
21
+
arrival_time: arrival_line.parse().context("invalid arrival time")?,
22
22
+
bus_schedule: buses_line.split(',').map(str::parse).try_collect()?,
23
23
+
})
24
24
+
}
25
25
+
26
26
+
fn part1(&self) -> Result<u64> {
27
27
+
earliest_departure(self.arrival_time, &self.bus_schedule)
28
28
+
.ok_or_else(|| anyhow!("no buses scheduled"))
29
29
+
}
30
30
+
}
31
31
+
32
32
+
enum BusLine {
33
33
+
BusId(u64),
34
34
+
Omission,
35
35
+
}
36
36
+
37
37
+
impl FromStr for BusLine {
38
38
+
type Err = anyhow::Error;
39
39
+
40
40
+
fn from_str(s: &str) -> Result<Self> {
41
41
+
Ok(match s {
42
42
+
"x" => BusLine::Omission,
43
43
+
_ => BusLine::BusId(
44
44
+
s.parse()
45
45
+
.context("bus line must be either 'x' or a positive number")?,
46
46
+
),
47
47
+
})
48
48
+
}
49
49
+
}
50
50
+
51
51
+
impl BusLine {
52
52
+
fn id(&self) -> Option<u64> {
53
53
+
match self {
54
54
+
BusLine::BusId(id) => Some(*id),
55
55
+
BusLine::Omission => None,
56
56
+
}
57
57
+
}
58
58
+
}
59
59
+
60
60
+
fn earliest_departure(arrival: u64, schedule: &[BusLine]) -> Option<u64> {
61
61
+
schedule
62
62
+
.iter()
63
63
+
.filter_map(|bus| bus.id())
64
64
+
.min_by_key(|id| id - arrival % id)
65
65
+
.map(|min_id| min_id * (min_id - arrival % min_id))
66
66
+
}
67
67
+
68
68
+
#[cfg(test)]
69
69
+
mod tests {
70
70
+
use super::*;
71
71
+
72
72
+
const EXAMPLE_ARRIVAL: u64 = 939;
73
73
+
const EXAMPLE_SCHEDULE: [BusLine; 8] = [
74
74
+
BusLine::BusId(7),
75
75
+
BusLine::BusId(13),
76
76
+
BusLine::Omission,
77
77
+
BusLine::Omission,
78
78
+
BusLine::BusId(59),
79
79
+
BusLine::Omission,
80
80
+
BusLine::BusId(31),
81
81
+
BusLine::BusId(19),
82
82
+
];
83
83
+
84
84
+
#[test]
85
85
+
fn find_earliest_bus_in_example() {
86
86
+
assert_eq!(
87
87
+
earliest_departure(EXAMPLE_ARRIVAL, &EXAMPLE_SCHEDULE),
88
88
+
Some(295)
89
89
+
);
90
90
+
}
91
91
+
}
+2
-2
aoc_2020/src/main.rs
···
12
12
mod day10;
13
13
mod day11;
14
14
mod day12;
15
15
-
// mod day13;
15
15
+
mod day13;
16
16
// mod day14;
17
17
// mod day15;
18
18
// mod day16;
···
43
43
door!(2020-12-10 ~> day10),
44
44
door!(2020-12-11 ~> day11),
45
45
door!(2020-12-12 ~> day12),
46
46
-
// door!(2020-12-13 ~> day13),
46
46
+
door!(2020-12-13 ~> day13),
47
47
// door!(2020-12-14 ~> day14),
48
48
// door!(2020-12-15 ~> day15),
49
49
// door!(2020-12-16 ~> day16),