-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday16.rs
134 lines (113 loc) · 3.11 KB
/
day16.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//! [Day 16: Flawed Frequency Transmission](https://adventofcode.com/2019/day/16)
//!
//! Solve the day16 puzzle of Advent of Code 2019
/// Get the puzzle input into a vector of integer.
fn parse_data(data: &str) -> Vec<u8> {
data.chars()
.filter_map(|x| {
let digit = (x as u32).wrapping_sub('0' as u32);
if digit < 10 {
u8::try_from(digit).ok()
} else {
None
}
})
.collect()
}
/// Compute a phase of the Flawed Frequency Transmission (FFT)
fn fft(signal: &mut [u8]) {
let pattern = [0, 1, 0, -1];
let phase = signal.to_owned();
for n in 0..signal.len() {
let mut s = 0;
for i in 0..signal.len() {
s += pattern[(1 + i) / (1 + n) % 4] * i32::from(phase[i]);
}
signal[n] = u8::try_from(s.abs() % 10).unwrap();
}
}
/// Solve part one: compute the 100th phase of the signal.
fn part1(data: &[u8]) -> u32 {
let mut p = data.to_owned();
for _ in 0..100 {
fft(&mut p);
}
p[0..8].iter().fold(0, |acc, d| acc * 10 + u32::from(*d))
}
/// Solve part two: find the eight-digit message embedded in the final output list.
fn part2(data: &[u8]) -> u32 {
let offset = data[0..7].iter().fold(0, |acc, d| acc * 10 + (*d as usize));
let n = data.len() * 10_000 - offset;
let mut p = vec![0u8; n];
let mut t = vec![0u8; n];
for i in 0..n {
p[i] = data[(i + offset) % data.len()];
}
for _ in 0..100 {
// value is the sum of all values at its right modulo 10
let mut s = 0;
for i in (0..n).rev() {
s = (s + p[i]) % 10;
t[i] = s;
}
p.clone_from(&t);
}
p[0..8].iter().fold(0, |acc, d| acc * 10 + u32::from(*d))
}
fn main() {
let args = aoc::parse_args();
let data = parse_data(&args.input);
println!("{}", part1(&data));
println!("{}", part2(&data));
}
#[test]
fn test_parse_data() {
assert_eq!(parse_data("123"), [1u8, 2u8, 3u8]);
}
#[test]
fn test_part1() {
// values given as examples in the puzzle
assert_eq!(
part1(&parse_data("80871224585914546619083218645595")),
24176176
);
assert_eq!(
part1(&parse_data("19617804207202209144916044189917")),
73745418
);
assert_eq!(
part1(&parse_data("69317163492948606335995924319873")),
52432133
);
}
#[test]
fn test_part2() {
// values given as examples in the puzzle
assert_eq!(
part2(&parse_data("03036732577212944063491565474664")),
84462026
);
assert_eq!(
part2(&parse_data("02935109699940807407585447034323")),
78725270
);
assert_eq!(
part2(&parse_data("03081770884921959731165446850517")),
53553731
);
}
#[test]
fn test_fft() {
// values given as examples in the puzzle
let mut signal = parse_data("12345678");
let phases = [
parse_data("48226158"),
parse_data("34040438"),
parse_data("03415518"),
parse_data("01029498"),
];
for i in 0..3 {
fft(&mut signal);
assert_eq!(signal, phases[i]);
}
}