Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e3296a3

Browse files
Year 2018 Day 1
1 parent 2699473 commit e3296a3

File tree

7 files changed

+118
-0
lines changed

7 files changed

+118
-0
lines changed

‎README.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ Performance is reasonable even on older hardware, for example a 2011 MacBook Pro
6868
| [2021](#2021) | 10 |
6969
| [2020](#2020) | 286 |
7070
| [2019](#2019) | 22 |
71+
| [2018](#2018) | in progress |
7172
| [2017](#2017) | 515 |
7273
| [2016](#2016) | 663 |
7374
| [2015](#2015) | 87 |
@@ -232,6 +233,12 @@ Performance is reasonable even on older hardware, for example a 2011 MacBook Pro
232233
| 24 | [Planet of Discord](https://adventofcode.com/2019/day/24) | [Source](src/year2019/day24.rs) | 139 |
233234
| 25 | [Cryostasis](https://adventofcode.com/2019/day/25) | [Source](src/year2019/day25.rs) | 2721 |
234235

236+
## 2018
237+
238+
| Day | Problem | Solution | Benchmark (μs) |
239+
| --- | --- | --- | --: |
240+
| 1 | [Chronal Calibration](https://adventofcode.com/2018/day/1) | [Source](src/year2018/day01.rs) | 15 |
241+
235242
## 2017
236243

237244
![pie-2017]

‎benches/benchmark.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ mod year2017 {
128128
benchmark!(year2017, day25);
129129
}
130130

131+
mod year2018 {
132+
benchmark!(year2018, day01);
133+
}
134+
131135
mod year2019 {
132136
benchmark!(year2019, day01);
133137
benchmark!(year2019, day02);

‎src/lib.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ pub mod year2017 {
110110
pub mod day25;
111111
}
112112

113+
/// # Travel through time to restore the seasonal timeline.
114+
pub mod year2018 {
115+
pub mod day01;
116+
}
117+
113118
/// # Rescue Santa from deep space with a solar system adventure.
114119
pub mod year2019 {
115120
pub mod day01;

‎src/main.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ fn main() {
2424
.chain(year2015())
2525
.chain(year2016())
2626
.chain(year2017())
27+
.chain(year2018())
2728
.chain(year2019())
2829
.chain(year2020())
2930
.chain(year2021())
@@ -176,6 +177,10 @@ fn year2017() -> Vec<Solution> {
176177
]
177178
}
178179

180+
fn year2018() -> Vec<Solution> {
181+
vec![solution!(year2018, day01)]
182+
}
183+
179184
fn year2019() -> Vec<Solution> {
180185
vec![
181186
solution!(year2019, day01),

‎src/year2018/day01.rs‎

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//! # Chronal Calibration
2+
//!
3+
//! The simplest approach to part two is to store previously seen numbers in a `HashSet` then
4+
//! stop once a duplicate is found. However this approach requires scanning the input of ~1,000
5+
//! numbers multiple times, around 150 times for my input.
6+
//!
7+
//! A much faster `O(nlogn)` approach relies on the fact that each frequency increases by the same
8+
//! amount (the sum of all deltas) each time the list of numbers is processed. For example:
9+
//!
10+
//! ```none
11+
//! Deltas: +1, -2, +3, +1 =>
12+
//! 0 1 -1 2
13+
//! 3 4 2 5
14+
//! ```
15+
//!
16+
//! Two frequencies that are a multiple of the sum will eventually repeat. First we group each
17+
//! frequencies by its remainder modulo the sum, using `rem_euclid` to handle negative frequencies
18+
//! correctly, Then we sort, first by the remainder to group frequencies that can repeat together,
19+
//! then by the frequency increasing in order to help find the smallest gap between similar
20+
//! frequencies, then lastly by index as this is needed in the next step.
21+
//!
22+
//! For the example this produces `[(0, 0, 0), (1, 1, 1), (2, -1, 2), (2, 2, 3)]`. Then we use
23+
//! a sliding windows of size two to compare each pair of adjacent canditates, considering only
24+
//! candidates with the same remainder. For each valid pair we then produce a tuple of
25+
//! `(frequency gap, index, frequency)`.
26+
//!
27+
//! Finally we sort the tuples in ascending order, first by smallest frequency gap, breaking any
28+
//! ties using the index to find frequencies that appear earlier in the list. The first tuple
29+
//! in the list gives the result, in the example this is `[(3, 2, 2)]`.
30+
use crate::util::parse::*;
31+
32+
pub fn parse(input: &str) -> Vec<i32> {
33+
input.iter_signed().collect()
34+
}
35+
36+
pub fn part1(input: &[i32]) -> i32 {
37+
input.iter().sum()
38+
}
39+
40+
pub fn part2(input: &[i32]) -> i32 {
41+
// The frequencies increase by this amount each pass through the list of deltas.
42+
let total: i32 = input.iter().sum();
43+
44+
// Calculate tuples of `(frequency gap, index, frequency)` then sort to group frequencies that
45+
// can collide together.
46+
let mut frequency: i32 = 0;
47+
let mut seen = Vec::with_capacity(input.len());
48+
49+
for n in input {
50+
seen.push((frequency.rem_euclid(total), frequency, seen.len()));
51+
frequency += n;
52+
}
53+
54+
seen.sort_unstable();
55+
56+
// Compare each adjacent pair of tuples to find candidates, then sort by smallest gap first,
57+
// tie breaking with index if needed.
58+
let mut pairs = Vec::new();
59+
60+
for window in seen.windows(2) {
61+
let (remainder0, freq0, index0) = window[0];
62+
let (remainder1, freq1, _) = window[1];
63+
64+
if remainder0 == remainder1 {
65+
pairs.push((freq1 - freq0, index0, freq1));
66+
}
67+
}
68+
69+
pairs.sort_unstable();
70+
71+
// Result is the frequency of the first tuple.
72+
let (_, _, freq) = pairs[0];
73+
freq
74+
}

‎tests/test.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ mod year2017 {
112112
mod day25_test;
113113
}
114114

115+
mod year2018 {
116+
mod day01_test;
117+
}
118+
115119
mod year2019 {
116120
mod day01_test;
117121
mod day02_test;

‎tests/year2018/day01_test.rs‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use aoc::year2018::day01::*;
2+
3+
const EXAMPLE: &str = "\
4+
+1
5+
-2
6+
+3
7+
+1";
8+
9+
#[test]
10+
fn part1_test() {
11+
let input = parse(EXAMPLE);
12+
assert_eq!(part1(&input), 3);
13+
}
14+
15+
#[test]
16+
fn part2_test() {
17+
let input = parse(EXAMPLE);
18+
assert_eq!(part2(&input), 2);
19+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /