Skip to content

Commit 14f6920

Browse files
committed
2018 day 1
1 parent 44e7a24 commit 14f6920

File tree

7 files changed

+151
-3
lines changed

7 files changed

+151
-3
lines changed

Cargo.lock

Lines changed: 9 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/aoc/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ utils = { path = "../utils", default-features = false }
1313
year2015 = { path = "../year2015", optional = true }
1414
year2016 = { path = "../year2016", optional = true }
1515
year2017 = { path = "../year2017", optional = true }
16+
year2018 = { path = "../year2018", optional = true }
1617
year2024 = { path = "../year2024", optional = true }
1718

1819
[features]
@@ -21,8 +22,8 @@ const_lut = ["year2024?/const_lut"]
2122
all-simd = ["utils/all-simd"]
2223
test-runner = []
2324
# xtask update features
24-
all-years = ["year2015", "year2016", "year2017", "year2024"]
25-
unsafe = ["year2015?/unsafe", "year2016?/unsafe", "year2017?/unsafe", "year2024?/unsafe", "utils/unsafe"]
25+
all-years = ["year2015", "year2016", "year2017", "year2018", "year2024"]
26+
unsafe = ["year2015?/unsafe", "year2016?/unsafe", "year2017?/unsafe", "year2018?/unsafe", "year2024?/unsafe", "utils/unsafe"]
2627

2728
[lints]
2829
workspace = true

crates/aoc/src/years.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ pub mod year2016 {
2323
pub mod year2017 {
2424
pub use ::utils::puzzles_noop as puzzles;
2525
}
26+
#[cfg(not(feature = "year2018"))]
27+
pub mod year2018 {
28+
pub use ::utils::puzzles_noop as puzzles;
29+
}
2630
#[cfg(not(feature = "year2024"))]
2731
pub mod year2024 {
2832
pub use ::utils::puzzles_noop as puzzles;
@@ -33,6 +37,8 @@ pub use ::year2015;
3337
pub use ::year2016;
3438
#[cfg(feature = "year2017")]
3539
pub use ::year2017;
40+
#[cfg(feature = "year2018")]
41+
pub use ::year2018;
3642
#[cfg(feature = "year2024")]
3743
pub use ::year2024;
3844

@@ -104,6 +110,7 @@ macro_rules! all_puzzles {
104110
$crate::year2015::puzzles,
105111
$crate::year2016::puzzles,
106112
$crate::year2017::puzzles,
113+
$crate::year2018::puzzles,
107114
$crate::year2024::puzzles,
108115

109116
$callback

crates/year2018/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "year2018"
3+
authors = { workspace = true }
4+
edition = { workspace = true }
5+
license = { workspace = true }
6+
publish = { workspace = true }
7+
repository = { workspace = true }
8+
rust-version = { workspace = true }
9+
10+
[dependencies]
11+
utils = { path = "../utils", default-features = false }
12+
13+
[features]
14+
unsafe = ["utils/unsafe"]

crates/year2018/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Solutions for [Advent of Code 2018](https://adventofcode.com/2018)

crates/year2018/src/day01.rs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use std::iter;
2+
use utils::prelude::*;
3+
4+
/// Finding the first repeat.
5+
#[derive(Clone, Debug)]
6+
pub struct Day01 {
7+
changes: Vec<i32>,
8+
total: i32,
9+
}
10+
11+
impl Day01 {
12+
pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
13+
let changes = parser::i32().parse_lines(input)?;
14+
Ok(Self {
15+
total: changes.iter().sum(),
16+
changes,
17+
})
18+
}
19+
20+
#[must_use]
21+
pub fn part1(&self) -> i32 {
22+
self.total
23+
}
24+
25+
#[must_use]
26+
pub fn part2(&self) -> i32 {
27+
if self.total == 0 {
28+
let mut frequencies = iter::once(0)
29+
.chain(self.changes.iter().scan(0i32, |sum, &c| {
30+
*sum += c;
31+
Some(*sum)
32+
}))
33+
.enumerate()
34+
.collect::<Vec<_>>();
35+
36+
frequencies.sort_unstable_by_key(|&(idx, freq)| (freq, idx));
37+
38+
frequencies
39+
.windows(2)
40+
.filter_map(|w| {
41+
let (_, freq1) = w[0];
42+
let (idx2, freq2) = w[1];
43+
if freq1 == freq2 {
44+
Some((idx2, freq1))
45+
} else {
46+
None
47+
}
48+
})
49+
.min()
50+
} else {
51+
let mut remainders = self
52+
.changes
53+
.iter()
54+
.enumerate()
55+
.scan(0i32, |freq, (t, &change)| {
56+
let curr = *freq;
57+
*freq += change;
58+
Some((curr.rem_euclid(self.total), curr, t))
59+
})
60+
.collect::<Vec<_>>();
61+
62+
remainders.sort_unstable();
63+
64+
remainders
65+
.chunk_by(|&(r1, _, _), &(r2, _, _)| r1 == r2)
66+
.flat_map(|chunk| {
67+
chunk.iter().enumerate().flat_map(|(i, &r1)| {
68+
chunk.iter().skip(i + 1).filter_map(move |&r2| {
69+
let ((_, freq1, t1), (_, freq2, _)) =
70+
if self.total > 0 { (r1, r2) } else { (r2, r1) };
71+
72+
let freq_difference = freq2 - freq1;
73+
let iterations = freq_difference / self.total;
74+
if freq_difference.rem_euclid(self.total) == 0 && iterations >= 0 {
75+
let iterations = iterations as usize;
76+
Some((iterations * self.changes.len() + t1, freq2))
77+
} else {
78+
None
79+
}
80+
})
81+
})
82+
})
83+
.min()
84+
}
85+
.map(|(_, freq)| freq)
86+
.expect("no solution found")
87+
}
88+
}
89+
90+
examples!(Day01 -> (i32, i32) [
91+
{input: "+1\n-2\n+3\n+1", part1: 3, part2: 2},
92+
{input: "+1\n+1\n+1", part1: 3},
93+
{input: "+1\n+1\n-2", part1: 0},
94+
{input: "-1\n-2\n-3", part1: -6},
95+
{input: "+1\n-1", part2: 0},
96+
{input: "+3\n+3\n+4\n-2\n-4", part2: 10},
97+
{input: "-6\n+3\n+8\n+5\n-6", part2: 5},
98+
{input: "+7\n+7\n-2\n-7\n-4", part2: 14},
99+
// Negative versions of the above
100+
{input: "-1\n+2\n-3\n-1", part1: -3, part2: -2},
101+
{input: "-1\n+1", part2: 0},
102+
{input: "-3\n-3\n-4\n+2\n+4", part2: -10},
103+
{input: "+6\n-3\n-8\n-5\n+6", part2: -5},
104+
{input: "-7\n-7\n+2\n+7\n+4", part2: -14},
105+
// Custom examples
106+
{input: "+2\n+3\n-8", part2: 2},
107+
{input: "+0", part2: 0},
108+
{input: "+1000000\n-999999", part2: 1000000},
109+
{input: "+1\n-2\n+2\n-2\n+3", part2: 1},
110+
{input: "+1\n-2\n+2\n-2\n-5", part2: 1},
111+
]);

crates/year2018/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![doc = include_str!("../README.md")]
2+
#![cfg_attr(not(feature = "unsafe"), forbid(unsafe_code))]
3+
4+
utils::year!(2018 => year2018, ${
5+
1 => day01::Day01,
6+
});

0 commit comments

Comments
 (0)