day12_common.carbon 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. // https://adventofcode.com/2024/day/12
  5. library "day12_common";
  6. import Core library "io";
  7. import Core library "range";
  8. import library "io_utils";
  9. class Map {
  10. impl as Core.UnformedInit {}
  11. fn Read() -> Map {
  12. returned var me: Self;
  13. for (y: i32 in Core.Range(140)) {
  14. for (x: i32 in Core.Range(140)) {
  15. me.kind[x][y] = ReadChar() as i32;
  16. }
  17. SkipNewline();
  18. }
  19. return var;
  20. }
  21. fn At[self: Self](x: i32, y: i32) -> i32 {
  22. return if x < 0 or x >= 140 or y < 0 or y >= 140
  23. then -1
  24. else self.kind[x][y];
  25. }
  26. var kind: array(array(i32, 140), 140);
  27. }
  28. class DisjointSetForest {
  29. impl as Core.UnformedInit {}
  30. fn Make() -> DisjointSetForest {
  31. returned var me: Self;
  32. for (i: i32 in Core.Range(140 * 140)) {
  33. me.nodes[i].next = i;
  34. me.nodes[i].weight = 1;
  35. me.nodes[i].unions = 0;
  36. }
  37. return var;
  38. }
  39. fn Lookup[ref self: Self](a: i32) -> i32 {
  40. let next: i32 = self.nodes[a].next;
  41. if (next == a) {
  42. return next;
  43. }
  44. let resolved: i32 = self.Lookup(next);
  45. self.nodes[a].next = resolved;
  46. return resolved;
  47. }
  48. fn Unions[self: Self](canon_a: i32) -> i32 {
  49. return self.nodes[canon_a].unions;
  50. }
  51. fn Weight[self: Self](canon_a: i32) -> i32 {
  52. return self.nodes[canon_a].weight;
  53. }
  54. fn Union[ref self: Self](a: i32, b: i32) {
  55. let canon_b: i32 = self.Lookup(b);
  56. self.Set(a, canon_b);
  57. ++self.nodes[canon_b].unions;
  58. }
  59. private fn Set[ref self: Self](a: i32, canon_b: i32) {
  60. let next: i32 = self.nodes[a].next;
  61. self.nodes[a].next = canon_b;
  62. if (next == a) {
  63. if (a != canon_b) {
  64. self.nodes[canon_b].weight += self.nodes[a].weight;
  65. self.nodes[canon_b].unions += self.nodes[a].unions;
  66. }
  67. } else {
  68. self.Set(next, canon_b);
  69. }
  70. }
  71. // TODO: Consider adding ranked choice.
  72. // TODO: Make this generic in the payload data.
  73. var nodes: array({.next: i32, .weight: i32, .unions: i32}, 140 * 140);
  74. }
  75. fn MakeRegions(map: Map) -> DisjointSetForest {
  76. returned var forest: DisjointSetForest =
  77. DisjointSetForest.Make();
  78. for (x: i32 in Core.Range(140)) {
  79. for (y: i32 in Core.Range(140)) {
  80. for (a: i32 in Core.Range(2)) {
  81. // TODO: Crashes toolchain:
  82. // let adj: (i32, i32) = if a == 0 then (x - 1, y) else (x, y - 1);
  83. // if (map.At(adj.0, adj.1) == map.At(x, y)) {
  84. // forest.Union(y * 140 + x, adj.1 * 140 + adj.0);
  85. // }
  86. let adj_x: i32 = if a == 0 then x - 1 else x;
  87. let adj_y: i32 = if a == 0 then y else y - 1;
  88. if (map.At(adj_x, adj_y) == map.At(x, y)) {
  89. forest.Union(y * 140 + x, adj_y * 140 + adj_x);
  90. }
  91. }
  92. }
  93. }
  94. return var;
  95. }