advent_of_code/year2021/
day13.rs1use crate::common::character_recognition::{recognize, CHAR_HEIGHT, CHAR_WIDTH};
2use crate::input::Input;
3
4pub fn solve(input: &Input) -> Result<String, String> {
5 const NUM_LETTERS: usize = 8;
6 let mut dots = Vec::new();
7
8 let parse_number = |num_str: &str| {
9 num_str
10 .parse::<u16>()
11 .map_err(|_| "Invalid number - not an u16")
12 };
13
14 for line in input.text.lines() {
15 if let Some((x, y)) = line.split_once(',') {
16 let x = parse_number(x)?;
17 let y = parse_number(y)?;
18 dots.push((x, y));
19 } else if let Some((prefix, coord)) = line.split_once('=') {
20 let coord = parse_number(coord)?;
21 let updater = |n: &mut u16| {
22 if *n > coord {
23 if *n > 2 * coord {
24 return Err("Folding would create dot with negative coordinate".to_string());
25 }
26 *n = 2 * coord - *n;
27 }
28 Ok(())
29 };
30
31 if prefix.ends_with('x') {
32 for p in dots.iter_mut() {
33 updater(&mut p.0)?;
34 }
35 } else if prefix.ends_with('y') {
36 for p in dots.iter_mut() {
37 updater(&mut p.1)?;
38 }
39 } else {
40 return Err("Invalid line not ending width x=.. or y=..".to_string());
41 }
42
43 if input.is_part_one() {
44 dots.sort_unstable();
45 dots.dedup();
46 return Ok(dots.len().to_string());
47 }
48 }
49 }
50
51 let mut screen = [false; NUM_LETTERS * CHAR_HEIGHT * CHAR_WIDTH];
52 for (x, y) in dots {
53 if x >= (NUM_LETTERS * CHAR_WIDTH) as u16 || y >= CHAR_HEIGHT as u16 {
54 return Err("Dot outside of range".into());
55 }
56 screen[usize::from(y) * NUM_LETTERS * CHAR_WIDTH + usize::from(x)] = true;
57 }
58 recognize(&screen)
59}
60
61#[test]
62pub fn tests() {
63 use crate::input::{test_part_one, test_part_one_error, test_part_two};
64
65 let example = "6,10
660,14
679,10
680,3
6910,4
704,11
716,0
726,12
734,1
740,13
7510,12
763,4
773,0
788,4
791,10
802,14
818,10
829,0
83
84fold along y=7
85fold along x=5";
86 test_part_one!(example => "17".to_string());
87
88 let real_input = include_str!("day13_input.txt");
89 test_part_one!(real_input => "763".to_string());
90 test_part_two!(real_input => "RHALRCRA".to_string());
91
92 test_part_one_error!("189,403" => "Dot outside of range".to_string());
93 test_part_one_error!("189,4" => "Dot outside of range".to_string());
94}