day12_common.carbon 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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 library "io_utils";
  8. class Map {
  9. fn Read() -> Map {
  10. returned var me: Self;
  11. var y: i32 = 0;
  12. while (y < 140) {
  13. var x: i32 = 0;
  14. while (x < 140) {
  15. me.kind[x][y] = ReadChar();
  16. ++x;
  17. }
  18. SkipNewline();
  19. ++y;
  20. }
  21. return var;
  22. }
  23. fn At[self: Self](x: i32, y: i32) -> i32 {
  24. return if x < 0 or x >= 140 or y < 0 or y >= 140
  25. then -1
  26. else self.kind[x][y];
  27. }
  28. var kind: [[i32; 140]; 140];
  29. }
  30. class DisjointSetForest {
  31. fn Make() -> DisjointSetForest {
  32. returned var me: Self;
  33. var i: i32 = 0;
  34. while (i < 140 * 140) {
  35. me.nodes[i].next = i;
  36. me.nodes[i].weight = 1;
  37. me.nodes[i].unions = 0;
  38. ++i;
  39. }
  40. return var;
  41. }
  42. fn Lookup[addr self: Self*](a: i32) -> i32 {
  43. let next: i32 = self->nodes[a].next;
  44. if (next == a) {
  45. return next;
  46. }
  47. let resolved: i32 = self->Lookup(next);
  48. self->nodes[a].next = resolved;
  49. return resolved;
  50. }
  51. fn Unions[self: Self](canon_a: i32) -> i32 {
  52. return self.nodes[canon_a].unions;
  53. }
  54. fn Weight[self: Self](canon_a: i32) -> i32 {
  55. return self.nodes[canon_a].weight;
  56. }
  57. fn Union[addr self: Self*](a: i32, b: i32) {
  58. let canon_b: i32 = self->Lookup(b);
  59. self->Set(a, canon_b);
  60. ++self->nodes[canon_b].unions;
  61. }
  62. private fn Set[addr self: Self*](a: i32, canon_b: i32) {
  63. let next: i32 = self->nodes[a].next;
  64. self->nodes[a].next = canon_b;
  65. if (next == a) {
  66. if (a != canon_b) {
  67. self->nodes[canon_b].weight += self->nodes[a].weight;
  68. self->nodes[canon_b].unions += self->nodes[a].unions;
  69. }
  70. } else {
  71. self->Set(next, canon_b);
  72. }
  73. }
  74. // TODO: Consider adding ranked choice.
  75. // TODO: Make this generic in the payload data.
  76. var nodes: [{.next: i32, .weight: i32, .unions: i32}; 140 * 140];
  77. }
  78. fn MakeRegions(map: Map) -> DisjointSetForest {
  79. returned var forest: DisjointSetForest =
  80. DisjointSetForest.Make();
  81. var x: i32 = 0;
  82. while (x < 140) {
  83. var y: i32 = 0;
  84. while (y < 140) {
  85. var a: i32 = 0;
  86. while (a < 2) {
  87. // TODO: Crashes toolchain:
  88. // let adj: (i32, i32) = if a == 0 then (x - 1, y) else (x, y - 1);
  89. // if (map.At(adj.0, adj.1) == map.At(x, y)) {
  90. // forest.Union(y * 140 + x, adj.1 * 140 + adj.0);
  91. // }
  92. let adj_x: i32 = if a == 0 then x - 1 else x;
  93. let adj_y: i32 = if a == 0 then y else y - 1;
  94. if (map.At(adj_x, adj_y) == map.At(x, y)) {
  95. forest.Union(y * 140 + x, adj_y * 140 + adj_x);
  96. }
  97. ++a;
  98. }
  99. ++y;
  100. }
  101. ++x;
  102. }
  103. return var;
  104. }