|
@@ -1,13 +1,19 @@
|
1
|
1
|
use std::error::Error;
|
2
|
2
|
use std::fs::File;
|
3
|
3
|
use std::io::{BufRead, BufReader};
|
|
4
|
+use std::collections::HashSet;
|
4
|
5
|
|
5
|
6
|
const INPUT: &str = "inputs/1.txt";
|
|
7
|
+const LOOP_LIMIT: u16 = 1000;
|
6
|
8
|
|
7
|
|
-pub fn solve() -> Result<i32, Box<Error>> {
|
|
9
|
+pub fn solve_part1() -> Result<i32, Box<Error>> {
|
8
|
10
|
calculate_resulting_frequency(INPUT)
|
9
|
11
|
}
|
10
|
12
|
|
|
13
|
+pub fn solve_part2() -> Result<Option<i32>, Box<Error>> {
|
|
14
|
+ find_repeating_frequency(INPUT)
|
|
15
|
+}
|
|
16
|
+
|
11
|
17
|
fn calculate_resulting_frequency(filename: &str) -> Result<i32, Box<Error>> {
|
12
|
18
|
let mut freq: i32 = 0;
|
13
|
19
|
let file = File::open(filename)?;
|
|
@@ -18,14 +24,65 @@ fn calculate_resulting_frequency(filename: &str) -> Result<i32, Box<Error>> {
|
18
|
24
|
Ok(freq)
|
19
|
25
|
}
|
20
|
26
|
|
|
27
|
+fn find_repeating_frequency(filename: &str) -> Result<Option<i32>, Box<Error>> {
|
|
28
|
+ let freqs = read_frequencies(filename)?;
|
|
29
|
+ let mut result_freqs = HashSet::new();
|
|
30
|
+ let mut freq: i32 = 0;
|
|
31
|
+ let mut loop_count = 0;
|
|
32
|
+ while loop_count < LOOP_LIMIT {
|
|
33
|
+ for adjustment in &freqs {
|
|
34
|
+ freq += adjustment;
|
|
35
|
+ if result_freqs.contains(&freq) {
|
|
36
|
+ return Ok(Some(freq))
|
|
37
|
+ } else {
|
|
38
|
+ result_freqs.insert(freq);
|
|
39
|
+ }
|
|
40
|
+ }
|
|
41
|
+ loop_count += 1
|
|
42
|
+ }
|
|
43
|
+ Ok(None)
|
|
44
|
+}
|
|
45
|
+
|
|
46
|
+fn read_frequencies(filename: &str) -> Result<Vec<i32>, Box<Error>> {
|
|
47
|
+ let mut freqs: Vec<i32> = Vec::new();
|
|
48
|
+ let file = File::open(filename)?;
|
|
49
|
+ for line in BufReader::new(file).lines() {
|
|
50
|
+ freqs.push(line?.parse()?);
|
|
51
|
+ }
|
|
52
|
+ Ok(freqs)
|
|
53
|
+}
|
|
54
|
+
|
21
|
55
|
#[cfg(test)]
|
22
|
56
|
mod tests {
|
23
|
57
|
use super::*;
|
24
|
58
|
|
25
|
59
|
const TEST_INPUT: &str = "inputs/1_test.txt";
|
|
60
|
+ const TEST_INPUT_PART_2: &str = "inputs/1_test_part2.txt";
|
|
61
|
+ const TEST_INPUT_PART_2_2: &str = "inputs/1_test_part2_2.txt";
|
|
62
|
+ const TEST_INPUT_PART_2_3: &str = "inputs/1_test_part2_3.txt";
|
26
|
63
|
|
27
|
64
|
#[test]
|
28
|
65
|
fn finds_resulting_frequency() {
|
29
|
66
|
assert_eq!(calculate_resulting_frequency(TEST_INPUT).unwrap(), 3);
|
30
|
67
|
}
|
|
68
|
+
|
|
69
|
+ #[test]
|
|
70
|
+ fn finds_repeating_frequency() {
|
|
71
|
+ assert_eq!(find_repeating_frequency(TEST_INPUT_PART_2).unwrap().unwrap(), 14);
|
|
72
|
+ }
|
|
73
|
+
|
|
74
|
+ #[test]
|
|
75
|
+ fn finds_repeating_frequency_2() {
|
|
76
|
+ assert_eq!(find_repeating_frequency(TEST_INPUT_PART_2_2).unwrap().unwrap(), 10);
|
|
77
|
+ }
|
|
78
|
+
|
|
79
|
+ #[test]
|
|
80
|
+ fn finds_repeating_frequency_3() {
|
|
81
|
+ assert_eq!(find_repeating_frequency(TEST_INPUT_PART_2_3).unwrap().unwrap(), 5);
|
|
82
|
+ }
|
|
83
|
+
|
|
84
|
+ #[test]
|
|
85
|
+ fn reads_frequencies_file() {
|
|
86
|
+ assert_eq!(read_frequencies(TEST_INPUT).unwrap(), vec![5, -5, 3]);
|
|
87
|
+ }
|
31
|
88
|
}
|