Browse Source

Day 2 part 2

Tyler Hallada 5 years ago
parent
commit
b7b9654a00
3 changed files with 111 additions and 5 deletions
  1. 7 0
      inputs/2_test_part2.txt
  2. 102 4
      src/day2.rs
  3. 2 1
      src/main.rs

+ 7 - 0
inputs/2_test_part2.txt

@@ -0,0 +1,7 @@
1
+abcde
2
+fghij
3
+klmno
4
+pqrst
5
+fguij
6
+axcye
7
+wvxyz

+ 102 - 4
src/day2.rs

@@ -1,14 +1,18 @@
1
+use std::collections::HashMap;
1 2
 use std::error::Error;
2 3
 use std::fs::File;
3 4
 use std::io::{BufRead, BufReader};
4
-use std::collections::HashMap;
5 5
 
6 6
 const INPUT: &str = "inputs/2.txt";
7 7
 
8
-pub fn solve() -> Result<usize, Box<Error>> {
8
+pub fn solve_part1() -> Result<usize, Box<Error>> {
9 9
     calculate_checksum(INPUT)
10 10
 }
11 11
 
12
+pub fn solve_part2() -> Result<Option<String>, Box<Error>> {
13
+    find_most_common_id_overlap(INPUT)
14
+}
15
+
12 16
 fn calculate_checksum(filename: &str) -> Result<usize, Box<Error>> {
13 17
     let mut two_count = 0;
14 18
     let mut three_count = 0;
@@ -30,14 +34,108 @@ fn calculate_checksum(filename: &str) -> Result<usize, Box<Error>> {
30 34
     Ok(two_count * three_count)
31 35
 }
32 36
 
37
+fn find_most_common_id_overlap(filename: &str) -> Result<Option<String>, Box<Error>> {
38
+    let file = File::open(filename)?;
39
+    let mut read_lines: Vec<String> = Vec::new();
40
+    for line in BufReader::new(file).lines() {
41
+        let line_ref = &line?;
42
+        for line_before in read_lines.iter() {
43
+            match ids_are_diff_by_n(line_ref, &line_before, 1) {
44
+                Some(common) => return Ok(Some(common)),
45
+                None => (),
46
+            }
47
+        }
48
+
49
+        read_lines.push(line_ref.to_owned());
50
+    }
51
+    Ok(None)
52
+}
53
+
54
+fn ids_are_diff_by_n(first: &String, second: &String, n: usize) -> Option<String> {
55
+    if first.len() != second.len() {
56
+        return None;
57
+    }
58
+
59
+    let mut diff_count = 0;
60
+    let mut common = String::new();
61
+    let mut first_chars = first.chars();
62
+    let mut second_chars = second.chars();
63
+
64
+    for _ in 0..first.len() {
65
+        let first_char = first_chars.next();
66
+        let second_char = second_chars.next();
67
+
68
+        if first_char != second_char {
69
+            diff_count += 1
70
+        } else {
71
+            common.push(first_char?);
72
+        }
73
+
74
+        if diff_count > n {
75
+            return None;
76
+        }
77
+    }
78
+
79
+    Some(common)
80
+}
81
+
33 82
 #[cfg(test)]
34 83
 mod tests {
35 84
     use super::*;
36 85
 
37
-    const TEST_INPUT: &str = "inputs/2_test.txt";
86
+    const TEST_INPUT_PART_1: &str = "inputs/2_test.txt";
87
+    const TEST_INPUT_PART_2: &str = "inputs/2_test_part2.txt";
38 88
 
39 89
     #[test]
40 90
     fn calculates_correct_checksum() {
41
-        assert_eq!(calculate_checksum(TEST_INPUT).unwrap(), 12);
91
+        assert_eq!(calculate_checksum(TEST_INPUT_PART_1).unwrap(), 12);
92
+    }
93
+
94
+    #[test]
95
+    fn ids_are_diff_by_1() {
96
+        assert_eq!(
97
+            ids_are_diff_by_n(&String::from("abcdef"), &String::from("abbdef"), 1).unwrap(),
98
+            "abdef"
99
+        );
100
+        assert_eq!(
101
+            ids_are_diff_by_n(&String::from("abcdef"), &String::from("abcdee"), 1).unwrap(),
102
+            "abcde"
103
+        );
104
+        assert_eq!(
105
+            ids_are_diff_by_n(&String::from("abcdef"), &String::from("bbcdef"), 1).unwrap(),
106
+            "bcdef"
107
+        );
108
+    }
109
+
110
+    #[test]
111
+    fn ids_are_diff_by_2() {
112
+        assert_eq!(
113
+            ids_are_diff_by_n(&String::from("abcdef"), &String::from("abbdxf"), 2).unwrap(),
114
+            "abdf"
115
+        );
116
+    }
117
+
118
+    #[test]
119
+    fn ids_are_diff_by_n_len_unequal_false() {
120
+        assert_eq!(
121
+            ids_are_diff_by_n(&String::from("abcdef"), &String::from("abbdeff"), 1),
122
+            None
123
+        );
124
+    }
125
+
126
+    #[test]
127
+    fn ids_are_diff_by_1_too_many_diffs() {
128
+        assert_eq!(
129
+            ids_are_diff_by_n(&String::from("abcdef"), &String::from("abbdxf"), 1),
130
+            None
131
+        );
132
+    }
133
+
134
+    #[test]
135
+    fn finds_most_common_id_overlap() {
136
+        assert_eq!(
137
+            find_most_common_id_overlap(TEST_INPUT_PART_2).unwrap().unwrap(),
138
+            "fgij"
139
+        );
42 140
     }
43 141
 }

+ 2 - 1
src/main.rs

@@ -5,5 +5,6 @@ fn main() {
5 5
     println!("Day 1:");
6 6
     println!("{}", day1::solve().unwrap());
7 7
     println!("Day 2:");
8
-    println!("{}", day2::solve().unwrap());
8
+    println!("{}", day2::solve_part1().unwrap());
9
+    println!("{}", day2::solve_part2().unwrap().unwrap());
9 10
 }