main.rs
1 use std::{ 2 collections::{HashMap, HashSet}, 3 str, 4 }; 5 6 fn main() { 7 let mut chars: HashSet<char> = HashSet::new(); 8 let map = str::from_utf8(include_bytes!("input")) 9 .unwrap() 10 .lines() 11 .map(|l| l.chars().collect::<Vec<char>>()) 12 .collect::<Vec<Vec<char>>>(); 13 let mut sums: HashMap<char, u128> = HashMap::new(); 14 for l in &map { 15 for c in l { 16 chars.insert(*c); 17 sums.insert(*c, 0); 18 } 19 } 20 let mut positions: HashSet<(usize, usize)> = HashSet::new(); 21 for (y, l) in map.iter().enumerate() { 22 for (x, c) in l.iter().enumerate() { 23 if !positions.contains(&(x, y)) { 24 let (gates, areas) = count((x, y), *c, &mut positions, &map); 25 *sums.get_mut(c).unwrap() += (gates * areas) as u128; 26 } 27 } 28 } 29 let mut sum = 0; 30 for (_, v) in sums { 31 sum += v; 32 } 33 println!("Part 1 : {sum}"); 34 let mut sums: HashMap<char, u128> = HashMap::new(); 35 for l in &map { 36 for c in l { 37 chars.insert(*c); 38 sums.insert(*c, 0); 39 } 40 } 41 let mut positions: HashSet<(usize, usize)> = HashSet::new(); 42 for (y, l) in map.iter().enumerate() { 43 for (x, c) in l.iter().enumerate() { 44 if !positions.contains(&(x, y)) { 45 let mut positions_sides: HashSet<(usize, usize, Side)> = HashSet::new(); 46 let (gates, areas) = count2((x, y), *c, &mut positions, &mut positions_sides, &map); 47 *sums.get_mut(c).unwrap() += (gates * areas) as u128; 48 } 49 } 50 } 51 let mut sum = 0; 52 for (_, v) in sums { 53 sum += v; 54 } 55 println!("Part 2 : {sum}"); 56 } 57 58 fn count( 59 pos: (usize, usize), 60 c: char, 61 positions: &mut HashSet<(usize, usize)>, 62 map: &Vec<Vec<char>>, 63 ) -> (u32, u32) { 64 let (x, y) = pos; 65 let mut gates = 0; 66 let mut areas = 0; 67 if !((0..map[0].len()).contains(&x) && (0..map.len()).contains(&y)) { 68 gates += 1; 69 return (gates, areas); 70 } 71 if map[y][x] != c { 72 gates += 1; 73 return (gates, areas); 74 } 75 if positions.contains(&(x, y)) { 76 return (gates, areas); 77 } else { 78 positions.insert((x, y)); 79 areas += 1; 80 } 81 let _c = count((x - 1, y), c, positions, map); 82 gates += _c.0; 83 areas += _c.1; 84 let _c = count((x + 1, y), c, positions, map); 85 gates += _c.0; 86 areas += _c.1; 87 let _c = count((x, y - 1), c, positions, map); 88 gates += _c.0; 89 areas += _c.1; 90 let _c = count((x, y + 1), c, positions, map); 91 gates += _c.0; 92 areas += _c.1; 93 return (gates, areas); 94 } 95 96 #[derive(Hash, PartialEq, Eq)] 97 enum Side { 98 Down, 99 Up, 100 Right, 101 Left, 102 } 103 104 fn count2( 105 pos: (usize, usize), 106 c: char, 107 positions: &mut HashSet<(usize, usize)>, 108 positions_sides_to_not_count: &mut HashSet<(usize, usize, Side)>, 109 map: &Vec<Vec<char>>, 110 ) -> (u32, u32) { 111 let (x, y) = pos; 112 let mut gates = 0; 113 let mut areas = 0; 114 if !((0..map[0].len()).contains(&x) && (0..map.len()).contains(&y)) { 115 gates += 1; 116 return (gates, areas); 117 } 118 if map[y][x] != c { 119 gates += 1; 120 return (gates, areas); 121 } 122 if positions.contains(&(x, y)) { 123 return (gates, areas); 124 } else { 125 positions.insert((x, y)); 126 areas += 1; 127 } 128 let _c = count2((x - 1, y), c, positions, positions_sides_to_not_count, map); 129 areas += _c.1; 130 if _c == (1, 0) { 131 if !(positions_sides_to_not_count.contains(&(x, y, Side::Left))) { 132 gates += _c.0; 133 } 134 let mut i = 0; 135 while (0..map.len()).contains(&(y + i)) 136 && map[y + i][x] == c 137 && (!(0..map[0].len()).contains(&(x - 1)) || map[y + i][x - 1] != c) 138 { 139 positions_sides_to_not_count.insert((x, y + i, Side::Left)); 140 i += 1; 141 } 142 let mut i = 0; 143 while (0..map.len()).contains(&(y + i)) 144 && map[y + i][x] == c 145 && (!(0..map[0].len()).contains(&(x - 1)) || map[y + i][x - 1] != c) 146 { 147 positions_sides_to_not_count.insert((x, y + i, Side::Left)); 148 i -= 1; 149 } 150 } else { 151 gates += _c.0; 152 } 153 let _c = count2((x + 1, y), c, positions, positions_sides_to_not_count, map); 154 areas += _c.1; 155 if _c == (1, 0) { 156 if !(positions_sides_to_not_count.contains(&(x, y, Side::Right))) { 157 gates += _c.0; 158 } 159 let mut i = 0; 160 while (0..map.len()).contains(&(y + i)) 161 && map[y + i][x] == c 162 && (!(0..map[0].len()).contains(&(x + 1)) || map[y + i][x + 1] != c) 163 { 164 positions_sides_to_not_count.insert((x, y + i, Side::Right)); 165 i += 1; 166 } 167 let mut i = 0; 168 while (0..map.len()).contains(&(y + i)) 169 && map[y + i][x] == c 170 && (!(0..map[0].len()).contains(&(x + 1)) || map[y + i][x + 1] != c) 171 { 172 positions_sides_to_not_count.insert((x, y + i, Side::Right)); 173 i -= 1; 174 } 175 } else { 176 gates += _c.0; 177 } 178 let _c = count2((x, y - 1), c, positions, positions_sides_to_not_count, map); 179 areas += _c.1; 180 if _c == (1, 0) { 181 if !(positions_sides_to_not_count.contains(&(x, y, Side::Up))) { 182 gates += _c.0; 183 } 184 let mut i = 0; 185 while (0..map[0].len()).contains(&(x + i)) 186 && map[y][x + i] == c 187 && (!(0..map.len()).contains(&(y - 1)) || map[y - 1][x + i] != c) 188 { 189 positions_sides_to_not_count.insert((x + i, y, Side::Up)); 190 i += 1; 191 } 192 let mut i = 0; 193 while (0..map[0].len()).contains(&(x + i)) 194 && map[y][x + i] == c 195 && (!(0..map.len()).contains(&(y - 1)) || map[y - 1][x + i] != c) 196 { 197 positions_sides_to_not_count.insert((x + i, y, Side::Up)); 198 i -= 1; 199 } 200 } else { 201 gates += _c.0; 202 } 203 let _c = count2((x, y + 1), c, positions, positions_sides_to_not_count, map); 204 areas += _c.1; 205 if _c == (1, 0) { 206 if !(positions_sides_to_not_count.contains(&(x, y, Side::Down))) { 207 gates += _c.0; 208 } 209 let mut i = 0; 210 while (0..map[0].len()).contains(&(x + i)) 211 && map[y][x + i] == c 212 && (!(0..map.len()).contains(&(y + 1)) || map[y + 1][x + i] != c) 213 { 214 positions_sides_to_not_count.insert((x + i, y, Side::Down)); 215 i += 1; 216 } 217 let mut i = 0; 218 while (0..map[0].len()).contains(&(x + i)) 219 && map[y][x + i] == c 220 && (!(0..map.len()).contains(&(y + 1)) || map[y + 1][x + i] != c) 221 { 222 positions_sides_to_not_count.insert((x + i, y, Side::Down)); 223 i -= 1; 224 } 225 } else { 226 gates += _c.0; 227 } 228 return (gates, areas); 229 }