Skip to content

Commit 1175051

Browse files
committed
Year 2017 Day 6
1 parent 9ef9d22 commit 1175051

File tree

8 files changed

+109
-0
lines changed

8 files changed

+109
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ pie
245245
| 3 | [Spiral Memory](https://adventofcode.com/2017/day/3) | [Source](src/year2017/day03.rs) | 2 |
246246
| 4 | [High-Entropy Passphrases](https://adventofcode.com/2017/day/4) | [Source](src/year2017/day04.rs) | 94 |
247247
| 5 | [A Maze of Twisty Trampolines, All Alike](https://adventofcode.com/2017/day/5) | [Source](src/year2017/day05.rs) | 48000 |
248+
| 6 | [Memory Reallocation](https://adventofcode.com/2017/day/6) | [Source](src/year2017/day06.rs) | 81 |
248249

249250
## 2016
250251

benches/benchmark.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ mod year2017 {
9797
benchmark!(year2017, day03);
9898
benchmark!(year2017, day04);
9999
benchmark!(year2017, day05);
100+
benchmark!(year2017, day06);
100101
}
101102

102103
mod year2019 {

input/year2017/day06.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
14 0 15 12 11 11 3 5 1 6 8 4 9 1 8 4

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ pub mod year2017 {
8686
pub mod day03;
8787
pub mod day04;
8888
pub mod day05;
89+
pub mod day06;
8990
}
9091

9192
/// # Rescue Santa from deep space with a solar system adventure.

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ fn year2017() -> Vec<Solution> {
147147
solution!(year2017, day03),
148148
solution!(year2017, day04),
149149
solution!(year2017, day05),
150+
solution!(year2017, day06),
150151
]
151152
}
152153

src/year2017/day06.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//! # Memory Reallocation
2+
//!
3+
//! Looking at the input and the reallocation rules, we make an assertion:
4+
//!
5+
//! * No memory bank will ever exceed 15 blocks.
6+
//!
7+
//! This has a nice effect that we can store the entire memory layout packed into a single
8+
//! `u64` with each memory bank represented by a nibble.
9+
//!
10+
//! This makes it very fast to find the highest nibble using bitwise logic. To detect the cycle
11+
//! a [`FastMap`] stores each previously seen memory layout along with the cycle that it first
12+
//! appeared.
13+
use crate::util::hash::*;
14+
use crate::util::parse::*;
15+
16+
type Input = (u32, u32);
17+
18+
/// Reallocate a bank and set to zero by rotating this mask the correct number of bits.
19+
const REMOVE: usize = 0x0fffffffffffffff;
20+
/// The highest number of banks possible is 15, so each bank will add at most 1 to each of
21+
/// the banks that come after it.
22+
const SPREAD: [usize; 16] = [
23+
0x0000000000000000,
24+
0x0100000000000000,
25+
0x0110000000000000,
26+
0x0111000000000000,
27+
0x0111100000000000,
28+
0x0111110000000000,
29+
0x0111111000000000,
30+
0x0111111100000000,
31+
0x0111111110000000,
32+
0x0111111111000000,
33+
0x0111111111100000,
34+
0x0111111111110000,
35+
0x0111111111111000,
36+
0x0111111111111100,
37+
0x0111111111111110,
38+
0x0111111111111111,
39+
];
40+
41+
pub fn parse(input: &str) -> Input {
42+
// Accumulate the input into a single `u64`.
43+
let mut memory: usize = input.iter_unsigned::<usize>().fold(0, |acc, n| (acc << 4) + n);
44+
// Store previously seen configurations for cycle detection.
45+
let mut seen = FastMap::with_capacity(20_000);
46+
let mut cycles = 0;
47+
48+
seen.insert(memory, cycles);
49+
50+
loop {
51+
// Find the highest nibble in the integer.
52+
// We check each of the 4 bits for all nibbles in descending order by bitwise ANDing with
53+
// the mask.
54+
// If the mask is zero, then this implies that no nibbles have that bit set so we leave
55+
// the mask unchanged.
56+
// If some nibbles have that bit set, then we will "narrow" the mask to only consider
57+
// those nibbles.
58+
let mut mask = 0x8888888888888888;
59+
60+
let first = memory & mask;
61+
mask = if first == 0 { mask } else { first };
62+
63+
let second = (memory << 1) & mask;
64+
mask = if second == 0 { mask } else { second };
65+
66+
let third = (memory << 2) & mask;
67+
mask = if third == 0 { mask } else { third };
68+
69+
let fourth = (memory << 3) & mask;
70+
mask = if fourth == 0 { mask } else { fourth };
71+
72+
// The mask will have a 1 bit set for each of the joint highest values.
73+
// Choose the lowest index which is the most significant bit set.
74+
let offset = mask.leading_zeros();
75+
let max = memory.rotate_left(offset + 4) & 0xf;
76+
77+
// Empty the largest memory bank and reallocate its contents to the following banks.
78+
memory = (memory & REMOVE.rotate_right(offset)) + SPREAD[max].rotate_right(offset);
79+
cycles += 1;
80+
81+
// Check if we've seen this configuration before
82+
if let Some(previous) = seen.insert(memory, cycles) {
83+
break (cycles, cycles - previous);
84+
}
85+
}
86+
}
87+
88+
pub fn part1(input: &Input) -> u32 {
89+
input.0
90+
}
91+
92+
pub fn part2(input: &Input) -> u32 {
93+
input.1
94+
}

tests/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ mod year2017 {
9090
mod day03_test;
9191
mod day04_test;
9292
mod day05_test;
93+
mod day06_test;
9394
}
9495

9596
mod year2019 {

tests/year2017/day06_test.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#[test]
2+
fn part1_test() {
3+
// No example data
4+
}
5+
6+
#[test]
7+
fn part2_test() {
8+
// No example data
9+
}

0 commit comments

Comments
 (0)