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
use crate::Input; pub fn solve(input: &mut Input) -> Result<usize, String> { let mut points: Vec<(i32, i32, i32, i32, usize)> = input .text .lines() .enumerate() .map(|(i, line)| { let line_number = i + 1; let parts: Vec<&str> = line.split(',').collect(); if parts.len() != 4 { return Err(format!( "Invalid input at line {} - not 4 comma-separated values", line_number )); } let error = |e| format!("Invalid input at line {}: {}", line_number, e); Ok(( parts[0].parse::<i32>().map_err(error)?, parts[1].parse::<i32>().map_err(error)?, parts[2].parse::<i32>().map_err(error)?, parts[3].parse::<i32>().map_err(error)?, i, )) }) .collect::<Result<_, _>>()?; for i in 0..points.len() { for j in i + 1..points.len() { let a = points[i]; let b = points[j]; if ((a.0 - b.0).abs() + (a.1 - b.1).abs() + (a.2 - b.2).abs() + (a.3 - b.3).abs()) <= 3 { for p in points.iter_mut().filter(|p| p.4 == b.4) { p.4 = a.4; } } } } points.sort_by(|a, b| a.4.cmp(&b.4)); points.dedup_by(|a, b| a.4 == b.4); Ok(points.len()) } #[test] fn tests() { use crate::test_part_one; test_part_one!("0,0,0,0 3,0,0,0 0,3,0,0 0,0,3,0 0,0,0,3 0,0,0,6 9,0,0,0 12,0,0,0" => 2); test_part_one!("-1,2,2,0 0,0,2,-2 0,0,0,-2 -1,2,0,0 -2,-2,-2,2 3,0,2,-1 -1,3,2,2 -1,0,-1,0 0,2,1,-2 3,0,0,0" => 4); test_part_one!("1,-1,0,1 2,0,-1,0 3,2,-1,0 0,0,3,1 0,0,-1,-1 2,3,-2,0 -2,2,0,0 2,-2,0,-1 1,-1,0,-1 3,2,0,2" => 3); test_part_one!("1,-1,-1,-2 -2,-2,0,1 0,2,1,3 -2,3,-2,1 0,2,3,-2 -1,-1,1,-2 0,-2,-1,0 -2,2,3,-1 1,2,2,0 -1,-2,0,-2" => 8); let input = include_str!("day25_input.txt"); test_part_one!(input => 399); }