-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolution_2019_16.rs
121 lines (104 loc) · 3.19 KB
/
solution_2019_16.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
use itertools::Itertools;
const BASE_PATTERN: [i32; 4] = [0, 1, 0, -1];
fn coef(index: usize, phase: usize) -> i32 {
BASE_PATTERN[((index + 1) / (phase + 1)) % 4]
}
fn apply_phase_1(numbers: &[u8]) -> Vec<u8> {
numbers
.iter()
.enumerate()
.map(|(phase, _)| {
println!("Phase {phase}");
let summed: i32 = numbers
.iter()
.enumerate()
.map(|(index, n)| i32::from(*n) * coef(index, phase))
.sum();
u8::try_from(summed.abs() % 10).unwrap()
})
.collect()
}
fn parse(data: &str) -> Vec<u8> {
data.trim().chars().map(|x| (x as u8) - b'0').collect()
}
fn display(v: &[u8]) -> String {
v.iter().map(|n| (n + b'0') as char).join("")
}
fn solve_1(data: &str, phases: u8) -> String {
let numbers: Vec<_> = parse(data);
let result = apply_phases_1(numbers, phases);
display(&result)
}
fn apply_phases_1(numbers: Vec<u8>, phases: u8) -> Vec<u8> {
(0 .. phases).fold(numbers, |a, phase| {
println!("Applying phase {phase}");
apply_phase_1(&a)
})
}
fn apply_phase_2(numbers: &[u8]) -> Vec<u8> {
let mut sum: i32 = numbers.iter().map(|x| i32::from(*x)).sum();
let mut out: Vec<u8> = Vec::new();
for x in numbers {
let res = u8::try_from(sum % 10).unwrap();
out.push(res);
sum -= i32::from(*x);
}
out
}
fn apply_phases_2(numbers: Vec<u8>, phases: u8) -> Vec<u8> {
(0 .. phases).fold(numbers, |a, phase| {
println!("Applying phase {phase}");
apply_phase_2(&a)
})
}
fn solve_2(data: &str, repeat: usize, phases: u8) -> String {
let single: Vec<u8> = parse(data);
let repeated: Vec<u8> = single
.iter()
.cycle()
.take(repeat * single.len())
.copied()
.collect();
println!("{}", repeated.len());
let result = apply_phases_2(repeated, phases);
display(&result)
}
fn part_1() {
let data = include_str!("../../resources/16.txt");
let result = &solve_1(data, 100)[.. 8];
println!("Part 1: {result}");
assert_eq!(result, "68764632");
}
fn part_2() {
let data = include_str!("../../resources/16.txt");
let message_offset: usize = (data[.. 7]).parse::<usize>().unwrap();
println!("Message offset: {message_offset}");
let result = solve_2(data, 10000, 100);
let message = &result[message_offset .. message_offset + 8];
println!("Part 2: {message}");
assert_eq!(message, "52825021");
}
fn main() {
part_1();
part_2();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_solve_1() {
assert_eq!(solve_1("12345678", 1), "48226158");
assert_eq!(solve_1("12345678", 2), "34040438");
assert_eq!(solve_1("12345678", 3), "03415518");
assert_eq!(solve_1("12345678", 4), "01029498");
assert!(solve_1("80871224585914546619083218645595", 100).starts_with("24176176"));
assert!(solve_1("19617804207202209144916044189917", 100).starts_with("73745418"));
assert!(solve_1("69317163492948606335995924319873", 100).starts_with("52432133"));
part_1();
}
#[test]
#[ignore] // Slow
fn test_solve_2() {
part_2();
}
}