Files
carbon-lang/examples/advent2024/day12_common.carbon
T
Richard SmithandGeoff Romer ce50f181f1 Add an interface for initialization of vars without an explicit initializer (#6934)
When a `var` is not explicitly given an initializer, initialize it in
one of two ways:

* If its type implements the new interface `Core.Default`, call
`Core.Default.Op` to initialize it.
* Otherwise, if its type implements `UnformedInit`, leave it in an
unformed state. For now, this is always an uninitialized state, but that
will change in the future.
* If neither of those apply, the `var` declaration is ill-formed.

This is a step towards implementing leads decision #6739 and proposals
#257 and #5913.

Assisted-by: Gemini 3.1 Pro via Antigravity

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2026-03-19 23:46:06 +00:00

114 lines
2.9 KiB
Plaintext

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// https://adventofcode.com/2024/day/12
library "day12_common";
import Core library "io";
import Core library "range";
import library "io_utils";
class Map {
impl as Core.UnformedInit {}
fn Read() -> Map {
returned var me: Self;
for (y: i32 in Core.Range(140)) {
for (x: i32 in Core.Range(140)) {
me.kind[x][y] = ReadChar() as i32;
}
SkipNewline();
}
return var;
}
fn At[self: Self](x: i32, y: i32) -> i32 {
return if x < 0 or x >= 140 or y < 0 or y >= 140
then -1
else self.kind[x][y];
}
var kind: array(array(i32, 140), 140);
}
class DisjointSetForest {
impl as Core.UnformedInit {}
fn Make() -> DisjointSetForest {
returned var me: Self;
for (i: i32 in Core.Range(140 * 140)) {
me.nodes[i].next = i;
me.nodes[i].weight = 1;
me.nodes[i].unions = 0;
}
return var;
}
fn Lookup[ref self: Self](a: i32) -> i32 {
let next: i32 = self.nodes[a].next;
if (next == a) {
return next;
}
let resolved: i32 = self.Lookup(next);
self.nodes[a].next = resolved;
return resolved;
}
fn Unions[self: Self](canon_a: i32) -> i32 {
return self.nodes[canon_a].unions;
}
fn Weight[self: Self](canon_a: i32) -> i32 {
return self.nodes[canon_a].weight;
}
fn Union[ref self: Self](a: i32, b: i32) {
let canon_b: i32 = self.Lookup(b);
self.Set(a, canon_b);
++self.nodes[canon_b].unions;
}
private fn Set[ref self: Self](a: i32, canon_b: i32) {
let next: i32 = self.nodes[a].next;
self.nodes[a].next = canon_b;
if (next == a) {
if (a != canon_b) {
self.nodes[canon_b].weight += self.nodes[a].weight;
self.nodes[canon_b].unions += self.nodes[a].unions;
}
} else {
self.Set(next, canon_b);
}
}
// TODO: Consider adding ranked choice.
// TODO: Make this generic in the payload data.
var nodes: array({.next: i32, .weight: i32, .unions: i32}, 140 * 140);
}
fn MakeRegions(map: Map) -> DisjointSetForest {
returned var forest: DisjointSetForest =
DisjointSetForest.Make();
for (x: i32 in Core.Range(140)) {
for (y: i32 in Core.Range(140)) {
for (a: i32 in Core.Range(2)) {
// TODO: Crashes toolchain:
// let adj: (i32, i32) = if a == 0 then (x - 1, y) else (x, y - 1);
// if (map.At(adj.0, adj.1) == map.At(x, y)) {
// forest.Union(y * 140 + x, adj.1 * 140 + adj.0);
// }
let adj_x: i32 = if a == 0 then x - 1 else x;
let adj_y: i32 = if a == 0 then y else y - 1;
if (map.At(adj_x, adj_y) == map.At(x, y)) {
forest.Union(y * 140 + x, adj_y * 140 + adj_x);
}
}
}
}
return var;
}