Skip to content

Commit 501e3c1

Browse files
committed
Year 2017 Day 22
1 parent 33f80b9 commit 501e3c1

File tree

7 files changed

+90
-0
lines changed

7 files changed

+90
-0
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ Performance is reasonable even on older hardware, for example a 2011 MacBook Pro
257257
| 19 | [A Series of Tubes](https://adventofcode.com/2017/day/19) | [Source](src/year2017/day19.rs) | 20 |
258258
| 20 | [Particle Swarm](https://adventofcode.com/2017/day/20) | [Source](src/year2017/day20.rs) | 234 |
259259
| 21 | [Fractal Art](https://adventofcode.com/2017/day/21) | [Source](src/year2017/day21.rs) | 4 |
260+
| 22 | [Sporifica Virus](https://adventofcode.com/2017/day/22) | [Source](src/year2017/day22.rs) | 36000 |
260261
| 23 | [Coprocessor Conflagration](https://adventofcode.com/2017/day/23) | [Source](src/year2017/day23.rs) | 55 |
261262
| 24 | [Electromagnetic Moat](https://adventofcode.com/2017/day/24) | [Source](src/year2017/day24.rs) | 280 |
262263
| 25 | [The Halting Problem](https://adventofcode.com/2017/day/25) | [Source](src/year2017/day25.rs) | 3597 |

Diff for: benches/benchmark.rs

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ mod year2017 {
122122
benchmark!(year2017, day19);
123123
benchmark!(year2017, day20);
124124
benchmark!(year2017, day21);
125+
benchmark!(year2017, day22);
125126
benchmark!(year2017, day23);
126127
benchmark!(year2017, day24);
127128
benchmark!(year2017, day25);

Diff for: src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ pub mod year2017 {
104104
pub mod day19;
105105
pub mod day20;
106106
pub mod day21;
107+
pub mod day22;
107108
pub mod day23;
108109
pub mod day24;
109110
pub mod day25;

Diff for: src/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ fn year2017() -> Vec<Solution> {
169169
solution!(year2017, day19),
170170
solution!(year2017, day20),
171171
solution!(year2017, day21),
172+
solution!(year2017, day22),
172173
solution!(year2017, day23),
173174
solution!(year2017, day24),
174175
solution!(year2017, day25),

Diff for: src/year2017/day22.rs

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//! # Sporifica Virus
2+
//!
3+
//! Brute force solution using a fixed size grid, relying on the properties of the input to never
4+
//! exceed the bounds. Some bit manipulation tricks are used to speeds things up slightly.
5+
use crate::util::grid::*;
6+
use crate::util::point::*;
7+
8+
pub fn parse(input: &str) -> Grid<u8> {
9+
Grid::parse(input)
10+
}
11+
12+
pub fn part1(input: &Grid<u8>) -> usize {
13+
simulate(input, 10_000, 2)
14+
}
15+
16+
pub fn part2(input: &Grid<u8>) -> usize {
17+
simulate(input, 10_000_000, 1)
18+
}
19+
20+
fn simulate(input: &Grid<u8>, bursts: usize, delta: usize) -> usize {
21+
// Assume that the carrier will never go outside the range [0, 512] in both x and y axis.
22+
// starting at the center (256, 256).
23+
let full = 512;
24+
let half = 256;
25+
// Right, Down, Left, Up
26+
let offsets = [1, full, 0_usize.wrapping_sub(1), 0_usize.wrapping_sub(full)];
27+
28+
// Copy input
29+
let mut grid = vec![1; full * full];
30+
let offset = half - (input.width / 2) as usize;
31+
32+
for x in 0..input.width {
33+
for y in 0..input.height {
34+
if input[Point::new(x, y)] == b'#' {
35+
let index = full * (offset + y as usize) + (offset + x as usize);
36+
grid[index] = 3; // Infected
37+
}
38+
}
39+
}
40+
41+
let mut index = full * half + half; // Center
42+
let mut direction = 3; // Up
43+
let mut result = 0;
44+
45+
for _ in 0..bursts {
46+
// Change state by adding either `2` for part one (flipping between clean and infected)
47+
// or `1` for part two (using all four states).
48+
// Clean => 1
49+
// Weakened => 2
50+
// Infected => 3
51+
// Flagged => 0
52+
let current = grid[index] as usize;
53+
let next = (current + delta) & 0x3;
54+
grid[index] = next as u8;
55+
// Infected nodes result in a value of 4 >> 2 = 1, all other nodes result in 0.
56+
result += (next + 1) >> 2;
57+
// Change direction by adding an index modulo 4 depending on node type.
58+
// Clean => 1 + 2 => 3 (left)
59+
// Weakened => 2 + 2 => 0 (straight)
60+
// Infected => 3 + 2 => 1 (right)
61+
// Flagged => 0 + 2 => 2 (reverse)
62+
direction = (direction + current + 2) & 0x3;
63+
index = index.wrapping_add(offsets[direction]);
64+
}
65+
66+
result
67+
}

Diff for: tests/test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ mod year2017 {
106106
mod day19_test;
107107
mod day20_test;
108108
mod day21_test;
109+
mod day22_test;
109110
mod day23_test;
110111
mod day24_test;
111112
mod day25_test;

Diff for: tests/year2017/day22_test.rs

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

0 commit comments

Comments
 (0)