/ day12 / src / main.rs
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  }