advent_of_code_ocr/
lib.rs1use std::collections::HashMap;
2
3use itertools::Itertools;
4use phf::phf_map;
5
6static CHARACTER_MAP: phf::Map<&'static str, char> = phf_map! {
7 ".##.\n#..#\n#..#\n####\n#..#\n#..#" => 'A',
8 "###.\n#..#\n###.\n#..#\n#..#\n###." => 'B',
9 ".##.\n#..#\n#...\n#...\n#..#\n.##." => 'C',
10 "####\n#...\n###.\n#...\n#...\n####" => 'E',
11 "####\n#...\n###.\n#...\n#...\n#..." => 'F',
12 ".##.\n#..#\n#...\n#.##\n#..#\n.###" => 'G',
13 "#..#\n#..#\n####\n#..#\n#..#\n#..#" => 'H',
14 ".###\n..#.\n..#.\n..#.\n..#.\n.###" => 'I',
15 "..##\n...#\n...#\n...#\n#..#\n.##." => 'J',
16 "#..#\n#.#.\n##..\n#.#.\n#.#.\n#..#" => 'K',
17 "#...\n#...\n#...\n#...\n#...\n####" => 'L',
18 ".##.\n#..#\n#..#\n#..#\n#..#\n.##." => 'O',
19 "###.\n#..#\n#..#\n###.\n#...\n#..." => 'P',
20 "###.\n#..#\n#..#\n###.\n#.#.\n#..#" => 'R',
21 ".###\n#...\n#...\n.##.\n...#\n###." => 'S',
22 "#..#\n#..#\n#..#\n#..#\n#..#\n.##." => 'U',
23 "#...\n#...\n.#.#\n..#.\n..#.\n..#." => 'Y',
24 "####\n...#\n..#.\n.#..\n#...\n####" => 'Z',
25};
26
27pub fn parse_letter(letter: &str) -> Option<char> {
37 CHARACTER_MAP.get(letter).copied()
38}
39
40pub fn parse_string_to_letters(s: &str) -> String {
62 split_screen(s)
63 .iter()
64 .filter_map(|x| parse_letter(x.as_str()))
65 .collect()
66}
67
68pub fn split_screen(s: &str) -> Vec<String> {
93 s.lines()
94 .fold(HashMap::<usize, Vec<char>>::new(), |letters, line| {
95 line.chars().chunks(5).into_iter().enumerate().fold(
96 letters,
97 |mut letters, (n, chunk)| {
98 if letters.contains_key(&n) {
99 letters.get_mut(&n).unwrap().push('\n');
100 letters.get_mut(&n).unwrap().extend(chunk.take(4));
101 } else {
102 letters.entry(n).or_insert_with(|| chunk.take(4).collect());
103 }
104 letters
105 },
106 )
107 })
108 .iter()
109 .sorted_by_key(|(n, _)| **n)
110 .map(|(_, v)| v)
111 .map(|x| x.iter().collect::<String>())
112 .collect()
113}
114
115#[cfg(test)]
116mod test {
117 use super::*;
118
119 #[test]
120 fn map_letter() {
121 let a = ".##.
122#..#
123#..#
124####
125#..#
126#..#";
127
128 assert_eq!(parse_letter(a), Some('A'));
129 }
130
131 #[test]
132 fn split_screen_to_sections() {
133 let screen = "####.###....##.###..###..#..#..##..#..#.\n#....#..#....#.#..#.#..#.#.#..#..#.#..#.\n###..#..#....#.###..#..#.##...#..#.####.\n#....###.....#.#..#.###..#.#..####.#..#.\n#....#....#..#.#..#.#.#..#.#..#..#.#..#.\n####.#.....##..###..#..#.#..#.#..#.#..#.";
134
135 let binding = split_screen(screen);
136 let mut it = binding.iter();
137 assert_eq!(
138 it.next(),
139 Some(&"####\n#...\n###.\n#...\n#...\n####".to_string())
140 );
141 assert_eq!(
142 it.next(),
143 Some(&"###.\n#..#\n#..#\n###.\n#...\n#...".to_string())
144 );
145 assert_eq!(
146 it.next(),
147 Some(&"..##\n...#\n...#\n...#\n#..#\n.##.".to_string())
148 );
149 assert_eq!(
150 it.next(),
151 Some(&"###.\n#..#\n###.\n#..#\n#..#\n###.".to_string())
152 );
153 assert_eq!(
154 it.next(),
155 Some(&"###.\n#..#\n#..#\n###.\n#.#.\n#..#".to_string())
156 );
157 assert_eq!(
158 it.next(),
159 Some(&"#..#\n#.#.\n##..\n#.#.\n#.#.\n#..#".to_string())
160 );
161 assert_eq!(
162 it.next(),
163 Some(&".##.\n#..#\n#..#\n####\n#..#\n#..#".to_string())
164 );
165 assert_eq!(
166 it.next(),
167 Some(&"#..#\n#..#\n####\n#..#\n#..#\n#..#".to_string())
168 );
169 assert_eq!(it.next(), None);
170 }
171}