mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 19:50:14 +01:00
Solutions for advent of code, day 4 - 13. (#4750)
A collection of additional Carbon examples demonstrating current language capabilities and some limitations of the current state of the toolchain. --------- Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
co-authored by
Jon Ross-Perkins
parent
9b28d3ad78
commit
d2d5c5520b
+17
-46
@@ -9,50 +9,21 @@ utils = [
|
||||
"sort.carbon",
|
||||
]
|
||||
|
||||
carbon_binary(
|
||||
name = "day1_part1",
|
||||
srcs = [
|
||||
"day1_common.carbon",
|
||||
"day1_part1.carbon",
|
||||
] + utils,
|
||||
)
|
||||
# A list of examples that should be excluded because they don't build any more.
|
||||
# For example, to exclude day3_part2, use:
|
||||
# excluded = [(3, 2)]
|
||||
excluded = []
|
||||
|
||||
carbon_binary(
|
||||
name = "day1_part2",
|
||||
srcs = [
|
||||
"day1_common.carbon",
|
||||
"day1_part2.carbon",
|
||||
] + utils,
|
||||
)
|
||||
|
||||
carbon_binary(
|
||||
name = "day2_part1",
|
||||
srcs = [
|
||||
"day2_common.carbon",
|
||||
"day2_part1.carbon",
|
||||
] + utils,
|
||||
)
|
||||
|
||||
carbon_binary(
|
||||
name = "day2_part2",
|
||||
srcs = [
|
||||
"day2_common.carbon",
|
||||
"day2_part2.carbon",
|
||||
] + utils,
|
||||
)
|
||||
|
||||
carbon_binary(
|
||||
name = "day3_part1",
|
||||
srcs = [
|
||||
"day3_common.carbon",
|
||||
"day3_part1.carbon",
|
||||
] + utils,
|
||||
)
|
||||
|
||||
carbon_binary(
|
||||
name = "day3_part2",
|
||||
srcs = [
|
||||
"day3_common.carbon",
|
||||
"day3_part2.carbon",
|
||||
] + utils,
|
||||
)
|
||||
# Produce a binary "dayX_partY" for each matching `.carbon` file.
|
||||
[
|
||||
carbon_binary(
|
||||
name = "day{0}_part{1}".format(day, part),
|
||||
srcs = [
|
||||
"day{0}_common.carbon".format(day),
|
||||
"day{0}_part{1}.carbon".format(day, part),
|
||||
] + utils,
|
||||
)
|
||||
for day in range(1, 14)
|
||||
for part in range(1, 3)
|
||||
if (day, part) not in excluded
|
||||
]
|
||||
|
||||
@@ -15,3 +15,9 @@ style and idioms. Instead, the purpose of these examples are to test the current
|
||||
state of the toolchain against larger code examples than those that are present
|
||||
in the toolchain's own tests, to find bugs in the toolchain, and to drive
|
||||
feature development in the toolchain by presenting somewhat realistic testcases.
|
||||
|
||||
If one of these examples stops building after a change to the toolchain, please:
|
||||
|
||||
- Make sure that the build break is an expected consequence of the change.
|
||||
- Update the `BUILD` file to exclude that example.
|
||||
- File an issue and assign it to @zygoloid.
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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/10
|
||||
|
||||
library "day10_common";
|
||||
|
||||
import Core library "io";
|
||||
import library "io_utils";
|
||||
|
||||
class Terrain {
|
||||
fn Read() -> Terrain {
|
||||
returned var me: Terrain;
|
||||
var y: i32 = 0;
|
||||
while (y < 43) {
|
||||
var x: i32 = 0;
|
||||
while (x < 43) {
|
||||
me.height[x][y] = ReadChar() - 0x30;
|
||||
++x;
|
||||
}
|
||||
SkipNewline();
|
||||
++y;
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
var height: [[i32; 43]; 43];
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// 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/10
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day10_common";
|
||||
import library "io_utils";
|
||||
|
||||
// TODO: Add this to the prelude.
|
||||
fn PopCount(n: u256) -> i32 {
|
||||
var bit: u256 = 1;
|
||||
var total: i32 = 0;
|
||||
while (bit != 0) {
|
||||
if (n & bit != 0) {
|
||||
++total;
|
||||
}
|
||||
bit = bit << 1;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
class Reachable {
|
||||
fn Make(terrain: Terrain) -> Reachable {
|
||||
returned var me: Reachable;
|
||||
var next: u256 = 1;
|
||||
var y: i32 = 0;
|
||||
while (y < 43) {
|
||||
var x: i32 = 0;
|
||||
while (x < 43) {
|
||||
if (terrain.height[x][y] == 0) {
|
||||
me.trailheads[x][y] = next;
|
||||
next = next << 1;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
fn AddLevel[addr self: Self*](terrain: Terrain, level: i32) {
|
||||
let adj: [(i32, i32); 4] = ((-1, 0), (0, -1), (1, 0), (0, 1));
|
||||
var y: i32 = 0;
|
||||
while (y < 43) {
|
||||
var x: i32 = 0;
|
||||
while (x < 43) {
|
||||
if (terrain.height[x][y] == level) {
|
||||
var reach: u256 = 0;
|
||||
var i: i32 = 0;
|
||||
while (i < 4) {
|
||||
let adj_x: i32 = x + adj[i].0;
|
||||
let adj_y: i32 = y + adj[i].1;
|
||||
if (adj_x >= 0 and adj_x < 43 and
|
||||
adj_y >= 0 and adj_y < 43 and
|
||||
terrain.height[adj_x][adj_y] == level - 1) {
|
||||
reach = reach | self->trailheads[adj_x][adj_y];
|
||||
}
|
||||
++i;
|
||||
}
|
||||
self->trailheads[x][y] = reach;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
}
|
||||
|
||||
fn Count[self: Self](terrain: Terrain, level: i32) -> i32 {
|
||||
var total: i32 = 0;
|
||||
var y: i32 = 0;
|
||||
while (y < 43) {
|
||||
var x: i32 = 0;
|
||||
while (x < 43) {
|
||||
if (terrain.height[x][y] == level) {
|
||||
total += PopCount(self.trailheads[x][y]);
|
||||
}
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
var trailheads: [[u256; 43]; 43];
|
||||
}
|
||||
|
||||
fn Run() {
|
||||
var terrain: Terrain = Terrain.Read();
|
||||
var reachable: Reachable = Reachable.Make(terrain);
|
||||
var i: i32 = 1;
|
||||
while (i <= 9) {
|
||||
reachable.AddLevel(terrain, i);
|
||||
++i;
|
||||
}
|
||||
Core.Print(reachable.Count(terrain, 9));
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// 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/10
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day10_common";
|
||||
import library "io_utils";
|
||||
|
||||
class PathsToTop {
|
||||
fn Make(terrain: Terrain) -> PathsToTop {
|
||||
returned var me: PathsToTop;
|
||||
var y: i32 = 0;
|
||||
while (y < 43) {
|
||||
var x: i32 = 0;
|
||||
while (x < 43) {
|
||||
// TODO: We shouldn't need an explicit cast here.
|
||||
me.paths[x][y] =
|
||||
if terrain.height[x][y] == 9 then 1 as i64 else 0;
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
fn AddLevel[addr self: Self*](terrain: Terrain, level: i32) -> i64 {
|
||||
var total: i64 = 0;
|
||||
let adj: [(i32, i32); 4] = ((-1, 0), (0, -1), (1, 0), (0, 1));
|
||||
var y: i32 = 0;
|
||||
while (y < 43) {
|
||||
var x: i32 = 0;
|
||||
while (x < 43) {
|
||||
if (terrain.height[x][y] == level) {
|
||||
var paths: i64 = 0;
|
||||
var i: i32 = 0;
|
||||
while (i < 4) {
|
||||
let adj_x: i32 = x + adj[i].0;
|
||||
let adj_y: i32 = y + adj[i].1;
|
||||
if (adj_x >= 0 and adj_x < 43 and
|
||||
adj_y >= 0 and adj_y < 43 and
|
||||
terrain.height[adj_x][adj_y] == level + 1) {
|
||||
paths = paths + self->paths[adj_x][adj_y];
|
||||
}
|
||||
++i;
|
||||
}
|
||||
self->paths[x][y] = paths;
|
||||
total = total + paths;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
var paths: [[i64; 43]; 43];
|
||||
}
|
||||
|
||||
fn Run() {
|
||||
var terrain: Terrain = Terrain.Read();
|
||||
var paths: PathsToTop = PathsToTop.Make(terrain);
|
||||
var i: i32 = 8;
|
||||
var total: i64;
|
||||
while (i >= 0) {
|
||||
total = paths.AddLevel(terrain, i);
|
||||
--i;
|
||||
}
|
||||
PrintInt64(total);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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/11
|
||||
|
||||
library "day11_common";
|
||||
|
||||
import Core library "io";
|
||||
import library "io_utils";
|
||||
|
||||
fn Next(n: i64) -> (i64, i64) {
|
||||
if (n == 0) { return (1, -1); }
|
||||
var pow10: i64 = 10;
|
||||
var pow100: i64 = 1;
|
||||
while (n / pow100 >= 100) {
|
||||
pow100 = pow100 * 100;
|
||||
pow10 = pow10 * 10;
|
||||
}
|
||||
if (n / pow100 >= 10) {
|
||||
return (n / pow10, n % pow10);
|
||||
}
|
||||
return (n * 2024, -1);
|
||||
}
|
||||
|
||||
fn Count(n: i64, depth: i32) -> i32 {
|
||||
if (n == -1) { return 0; }
|
||||
if (depth == 0) { return 1; }
|
||||
let next: (i64, i64) = Next(n);
|
||||
return Count(next.0, depth - 1) + Count(next.1, depth - 1);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// 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/11
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day11_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var n: i64;
|
||||
var total: i32 = 0;
|
||||
while (ReadInt64(&n)) {
|
||||
total = total + Count(n, 25);
|
||||
SkipSpaces();
|
||||
}
|
||||
Core.Print(total);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// 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/11
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day11_common";
|
||||
import library "io_utils";
|
||||
|
||||
class Digits {
|
||||
fn Make() -> Digits {
|
||||
returned var me: Digits;
|
||||
var digit: i32 = 0;
|
||||
while (digit < 10) {
|
||||
var depth: i32 = 0;
|
||||
while (depth < 75) {
|
||||
me.count[digit][depth] = 0;
|
||||
++depth;
|
||||
}
|
||||
++digit;
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
fn Print[self: Self](max_depth: i32) {
|
||||
var digit: i32 = 0;
|
||||
while (digit < 10) {
|
||||
Core.PrintChar(digit + 0x30);
|
||||
Core.PrintChar(0x3A);
|
||||
var depth: i32 = 0;
|
||||
while (depth <= max_depth) {
|
||||
Core.PrintChar(0x20);
|
||||
PrintInt64NoNewline(self.count[digit][depth]);
|
||||
++depth;
|
||||
}
|
||||
Core.PrintChar(0x0A);
|
||||
++digit;
|
||||
}
|
||||
Core.PrintChar(0x0A);
|
||||
}
|
||||
|
||||
var count: [[i64; 75]; 10];
|
||||
}
|
||||
|
||||
// TODO: Add a builtin to perform integer conversion / truncation.
|
||||
fn I64DigitToI32(a: i64) -> i32 {
|
||||
if (a == 0) { return 0; }
|
||||
if (a == 1) { return 1; }
|
||||
if (a == 2) { return 2; }
|
||||
if (a == 3) { return 3; }
|
||||
if (a == 4) { return 4; }
|
||||
if (a == 5) { return 5; }
|
||||
if (a == 6) { return 6; }
|
||||
if (a == 7) { return 7; }
|
||||
if (a == 8) { return 8; }
|
||||
return 9;
|
||||
}
|
||||
|
||||
fn ReduceToDigits(n: i64, depth: i32, multiplicity: i64, digits: Digits*) -> i64 {
|
||||
if (n == -1) { return 0; }
|
||||
if (depth == 0) { return multiplicity; }
|
||||
if (n < 10) {
|
||||
let count: i64* = &digits->count[I64DigitToI32(n)][depth - 1];
|
||||
*count = *count + multiplicity;
|
||||
return 0;
|
||||
}
|
||||
let next: (i64, i64) = Next(n);
|
||||
return ReduceToDigits(next.0, depth - 1, multiplicity, digits) +
|
||||
ReduceToDigits(next.1, depth - 1, multiplicity, digits);
|
||||
}
|
||||
|
||||
fn Run() {
|
||||
let max_depth: i32 = 75;
|
||||
var total: i64 = 0;
|
||||
var digits: Digits = Digits.Make();
|
||||
|
||||
var n: i64;
|
||||
while (ReadInt64(&n)) {
|
||||
total = total + ReduceToDigits(n, max_depth, 1, &digits);
|
||||
PrintInt64(total);
|
||||
digits.Print(max_depth - 1);
|
||||
SkipSpaces();
|
||||
}
|
||||
|
||||
var depth: i32 = max_depth - 1;
|
||||
while (depth >= 0) {
|
||||
PrintInt64(total);
|
||||
digits.Print(depth);
|
||||
var digit: i64 = 0;
|
||||
while (digit < 10) {
|
||||
let m: i64 = digits.count[I64DigitToI32(digit)][depth];
|
||||
if (m > 0) {
|
||||
let next: (i64, i64) = Next(digit);
|
||||
total = total +
|
||||
ReduceToDigits(next.0, depth, m, &digits) +
|
||||
ReduceToDigits(next.1, depth, m, &digits);
|
||||
}
|
||||
digit = digit + 1;
|
||||
}
|
||||
--depth;
|
||||
}
|
||||
|
||||
PrintInt64(total);
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
// 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 library "io_utils";
|
||||
|
||||
class Map {
|
||||
fn Read() -> Map {
|
||||
returned var me: Self;
|
||||
var y: i32 = 0;
|
||||
while (y < 140) {
|
||||
var x: i32 = 0;
|
||||
while (x < 140) {
|
||||
me.kind[x][y] = ReadChar();
|
||||
++x;
|
||||
}
|
||||
SkipNewline();
|
||||
++y;
|
||||
}
|
||||
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: [[i32; 140]; 140];
|
||||
}
|
||||
|
||||
class DisjointSetForest {
|
||||
fn Make() -> DisjointSetForest {
|
||||
returned var me: Self;
|
||||
var i: i32 = 0;
|
||||
while (i < 140 * 140) {
|
||||
me.nodes[i].next = i;
|
||||
me.nodes[i].weight = 1;
|
||||
me.nodes[i].unions = 0;
|
||||
++i;
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
fn Lookup[addr 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[addr 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[addr 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: [{.next: i32, .weight: i32, .unions: i32}; 140 * 140];
|
||||
}
|
||||
|
||||
fn MakeRegions(map: Map) -> DisjointSetForest {
|
||||
returned var forest: DisjointSetForest =
|
||||
DisjointSetForest.Make();
|
||||
|
||||
var x: i32 = 0;
|
||||
while (x < 140) {
|
||||
var y: i32 = 0;
|
||||
while (y < 140) {
|
||||
var a: i32 = 0;
|
||||
while (a < 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);
|
||||
}
|
||||
++a;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
|
||||
return var;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// 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
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day12_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var map: Map = Map.Read();
|
||||
var regions: DisjointSetForest = MakeRegions(map);
|
||||
|
||||
var total: i32 = 0;
|
||||
|
||||
var i: i32 = 0;
|
||||
while (i < 140 * 140) {
|
||||
if (regions.Lookup(i) == i) {
|
||||
let area: i32 = regions.Weight(i);
|
||||
let internal_edges: i32 = regions.Unions(i);
|
||||
let perimeter: i32 = area * 4 - internal_edges * 2;
|
||||
total += area * perimeter;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
Core.Print(total);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// 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
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day12_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn CountExtensions(map: Map, regions: DisjointSetForest*) -> [i32; 140 * 140] {
|
||||
returned var extensions: [i32; 140 * 140];
|
||||
var i: i32 = 0;
|
||||
while (i < 140 * 140) {
|
||||
extensions[i] = 0;
|
||||
++i;
|
||||
}
|
||||
|
||||
var ext: [{.same: (i32, i32), .adj: (i32, i32)}; 4] = (
|
||||
{.same = (-1, 0), .adj = (0, -1)},
|
||||
{.same = (-1, 0), .adj = (0, 1)},
|
||||
{.same = (0, -1), .adj = (-1, 0)},
|
||||
{.same = (0, -1), .adj = (1, 0)},
|
||||
);
|
||||
|
||||
var x: i32 = 0;
|
||||
while (x < 140) {
|
||||
var y: i32 = 0;
|
||||
while (y < 140) {
|
||||
let kind: i32 = map.At(x, y);
|
||||
var e: i32 = 0;
|
||||
while (e < 4) {
|
||||
if (map.At(x + ext[e].same.0, y + ext[e].same.1) == kind and
|
||||
map.At(x + ext[e].adj.0, y + ext[e].adj.1) != kind and
|
||||
map.At(x + ext[e].same.0 + ext[e].adj.0,
|
||||
y + ext[e].same.1 + ext[e].adj.1) != kind) {
|
||||
++extensions[regions->Lookup(y * 140 + x)];
|
||||
}
|
||||
++e;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
fn Run() {
|
||||
var map: Map = Map.Read();
|
||||
var regions: DisjointSetForest = MakeRegions(map);
|
||||
var ext: [i32; 140 * 140] = CountExtensions(map, ®ions);
|
||||
|
||||
var total: i32 = 0;
|
||||
|
||||
var i: i32 = 0;
|
||||
while (i < 140 * 140) {
|
||||
if (regions.Lookup(i) == i) {
|
||||
let area: i32 = regions.Weight(i);
|
||||
let internal_edges: i32 = regions.Unions(i);
|
||||
let extensions: i32 = ext[i];
|
||||
let perimeter: i32 = area * 4 - internal_edges * 2 - extensions;
|
||||
total += area * perimeter;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
Core.Print(total);
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
// 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/13
|
||||
|
||||
library "day13_common";
|
||||
|
||||
import Core library "io";
|
||||
import library "io_utils";
|
||||
|
||||
// Returns m and n so that am + bn = gcd.
|
||||
fn Euclid(a: i64, b: i64) -> {.m: i64, .n: i64, .gcd: i64} {
|
||||
if (a < b) {
|
||||
let reverse: {.m: i64, .n: i64, .gcd: i64} = Euclid(b, a);
|
||||
return {.m = reverse.n, .n = reverse.m, .gcd = reverse.gcd};
|
||||
}
|
||||
if (b == 0) {
|
||||
return {.m = 1, .n = 0, .gcd = a};
|
||||
}
|
||||
let next: {.m: i64, .n: i64, .gcd: i64} = Euclid(b, a % b);
|
||||
return {.m = next.n, .n = next.m - next.n * (a / b), .gcd = next.gcd};
|
||||
}
|
||||
|
||||
class Machine {
|
||||
fn Read() -> Machine {
|
||||
returned var me: Machine;
|
||||
// "Button A: X+"
|
||||
SkipNChars(12);
|
||||
ReadInt64(&me.a.0);
|
||||
// ", Y+"
|
||||
SkipNChars(4);
|
||||
ReadInt64(&me.a.1);
|
||||
// "\nButton B: X+"
|
||||
SkipNChars(13);
|
||||
ReadInt64(&me.b.0);
|
||||
// ", Y+"
|
||||
SkipNChars(4);
|
||||
ReadInt64(&me.b.1);
|
||||
// "\nPrize: X="
|
||||
SkipNChars(10);
|
||||
ReadInt64(&me.prize.0);
|
||||
// ", Y="
|
||||
SkipNChars(4);
|
||||
ReadInt64(&me.prize.1);
|
||||
SkipNewline();
|
||||
return var;
|
||||
}
|
||||
|
||||
var a: (i64, i64);
|
||||
var b: (i64, i64);
|
||||
var prize: (i64, i64);
|
||||
}
|
||||
|
||||
// Set of solutions to 'm a + n b = c'.
|
||||
class BezoutSolutionSet {
|
||||
fn Make(a: i64, b: i64, c: i64) -> BezoutSolutionSet {
|
||||
var e: {.m: i64, .n: i64, .gcd: i64} = Euclid(a, b);
|
||||
if (c % e.gcd != 0) {
|
||||
// Impossible.
|
||||
return {.m0 = -1, .n0 = -1, .m_step = -1, .n_step = -1};
|
||||
}
|
||||
|
||||
// Find an initial solution. Note that m and n might be negative.
|
||||
let num_gcds: i64 = c / e.gcd;
|
||||
e.m = e.m * num_gcds;
|
||||
e.n = e.n * num_gcds;
|
||||
|
||||
// Pick the smallest positive m we can.
|
||||
let a_over_gcd: i64 = a / e.gcd;
|
||||
let b_over_gcd: i64 = b / e.gcd;
|
||||
var adj: i64 = 0;
|
||||
// This is e.m / b rounded towards -inf.
|
||||
// TODO: Should there be a way of expressing this directly?
|
||||
if (e.m < 0) {
|
||||
adj = (e.m - b_over_gcd + 1) / b_over_gcd;
|
||||
} else {
|
||||
adj = e.m / b_over_gcd;
|
||||
}
|
||||
e.m = e.m - adj * b_over_gcd;
|
||||
e.n = e.n + adj * a_over_gcd;
|
||||
return {.m0 = e.m, .n0 = e.n,
|
||||
.m_step = b_over_gcd, .n_step = -a_over_gcd};
|
||||
}
|
||||
|
||||
fn Valid[self: Self]() -> bool {
|
||||
return self.m_step >= 0;
|
||||
}
|
||||
|
||||
fn Solution[self: Self](k: i64) -> (i64, i64) {
|
||||
return (self.m0 + k * self.m_step, self.n0 + k * self.n_step);
|
||||
}
|
||||
|
||||
// m_k * a + n_k * b == c, where:
|
||||
// m_k = m0 + k * m_step
|
||||
// n_k = n0 * k * n_step
|
||||
// m0 is the minimum non-negative m value, and n_step is negative.
|
||||
var m0: i64;
|
||||
var n0: i64;
|
||||
var m_step: i64;
|
||||
var n_step: i64;
|
||||
}
|
||||
|
||||
// Given two sets of points s and t, find the intersection in the first quadrant
|
||||
// with the minimum x coordinate. Returns the intersection point, or (-1, -1) if
|
||||
// there is no intersection.
|
||||
fn FirstIntersection(s: BezoutSolutionSet, t: BezoutSolutionSet) -> (i64, i64) {
|
||||
if (not s.Valid() or not t.Valid()) {
|
||||
// One of the sets is empty.
|
||||
return (-1, -1);
|
||||
}
|
||||
|
||||
// Easy case: lines meet at a point. This happens unless the lines are
|
||||
// parallel.
|
||||
let d: i64 = s.m_step * t.n_step - t.m_step * s.n_step;
|
||||
if (d != 0) {
|
||||
let u: i64 = (t.m0 - s.m0) * t.n_step - (t.n0 - s.n0) * t.m_step;
|
||||
if (u % d != 0) {
|
||||
// Lines don't meet at an integer point.
|
||||
return (-1, -1);
|
||||
}
|
||||
let j: i64 = u / d;
|
||||
if (j < 0 or s.n0 + j * s.n_step < 0) {
|
||||
// Lines don't meet in first quadrant.
|
||||
return (-1, -1);
|
||||
}
|
||||
return s.Solution(j);
|
||||
}
|
||||
|
||||
// Hard case: lines are parallel. We also get here if either "line" is a
|
||||
// point, but that doesn't happen in this exercise. We know all integer points
|
||||
// on the line are solutions, so the first intersection is the greater of the
|
||||
// first point in s and the first point in t, if that point is on both lines.
|
||||
if (s.m0 < t.m0) {
|
||||
// (t.m0, t.n0) is the solution if it's in s.
|
||||
if ((t.m0 - s.m0) % s.m_step == 0 and
|
||||
(t.n0 - s.n0) % s.n_step == 0) {
|
||||
return (t.m0, t.n0);
|
||||
}
|
||||
} else {
|
||||
// (s.m0, s.n0) is the solution if it's in t.
|
||||
if ((s.m0 - t.m0) % t.m_step == 0 and
|
||||
(s.n0 - t.n0) % t.n_step == 0) {
|
||||
return (s.m0, s.n0);
|
||||
}
|
||||
}
|
||||
return (-1, -1);
|
||||
}
|
||||
|
||||
fn CostIfPossible(m: Machine) -> i64 {
|
||||
let x: BezoutSolutionSet = BezoutSolutionSet.Make(m.a.0, m.b.0, m.prize.0);
|
||||
let y: BezoutSolutionSet = BezoutSolutionSet.Make(m.a.1, m.b.1, m.prize.1);
|
||||
let ab: (i64, i64) = FirstIntersection(x, y);
|
||||
if (ab.0 == -1) { return 0; }
|
||||
return ab.0 * 3 + ab.1;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// 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/13
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day13_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var total_cost: i64 = 0;
|
||||
while (true) {
|
||||
var m: Machine = Machine.Read();
|
||||
total_cost = total_cost + CostIfPossible(m);
|
||||
if (not SkipNewline()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
PrintInt64(total_cost);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// 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/13
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day13_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var total_cost: i64 = 0;
|
||||
while (true) {
|
||||
var m: Machine = Machine.Read();
|
||||
m.prize.0 = m.prize.0 + 10000000000000;
|
||||
m.prize.1 = m.prize.1 + 10000000000000;
|
||||
total_cost = total_cost + CostIfPossible(m);
|
||||
if (not SkipNewline()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
PrintInt64(total_cost);
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// https://adventofcode.com/2024/day/1
|
||||
|
||||
library "day1_common";
|
||||
|
||||
import library "io_utils";
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// https://adventofcode.com/2024/day/1
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day1_common";
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// https://adventofcode.com/2024/day/1
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day1_common";
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// https://adventofcode.com/2024/day/2
|
||||
|
||||
library "day2_common";
|
||||
|
||||
fn Abs(n: i32) -> i32 {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// https://adventofcode.com/2024/day/2
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day2_common";
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// https://adventofcode.com/2024/day/2
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day2_common";
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// https://adventofcode.com/2024/day/3
|
||||
|
||||
library "day3_common";
|
||||
|
||||
import library "io_utils";
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// https://adventofcode.com/2024/day/3
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day3_common";
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// https://adventofcode.com/2024/day/3
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day3_common";
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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/4
|
||||
|
||||
library "day4_common";
|
||||
|
||||
import library "io_utils";
|
||||
|
||||
class Wordsearch {
|
||||
fn Read() -> Wordsearch {
|
||||
returned var s: Wordsearch;
|
||||
// TODO: Use for loops once they're implemented.
|
||||
var y: i32 = 0;
|
||||
while (y < 140) {
|
||||
var x: i32 = 0;
|
||||
while (x < 140) {
|
||||
// TODO: Assert on failure.
|
||||
s.grid[x][y] = ReadChar();
|
||||
++x;
|
||||
}
|
||||
// TODO: Assert on failure.
|
||||
SkipNewline();
|
||||
++y;
|
||||
}
|
||||
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.grid[x][y];
|
||||
}
|
||||
|
||||
// TODO: Make this generic in the length of the search query.
|
||||
fn Check4[self: Self](xmas: [i32; 4], x: i32, y: i32, dx: i32, dy: i32) -> bool {
|
||||
var i: i32 = 0;
|
||||
while (i < 4) {
|
||||
if (self.At(x + i * dx, y + i * dy) != xmas[i]) {
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn Check3[self: Self](mas: [i32; 3], x: i32, y: i32, dx: i32, dy: i32) -> bool {
|
||||
var i: i32 = 0;
|
||||
while (i < 3) {
|
||||
if (self.At(x + i * dx, y + i * dy) != mas[i]) {
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var grid: [[i32; 140]; 140];
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// 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/4
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day4_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var search: Wordsearch = Wordsearch.Read();
|
||||
var xmas: [i32; 4] = (0x58, 0x4D, 0x41, 0x53);
|
||||
var found: i32 = 0;
|
||||
|
||||
// TODO: Use for loops once they're implemented.
|
||||
var y: i32 = 0;
|
||||
while (y < 140) {
|
||||
var x: i32 = 0;
|
||||
while (x < 140) {
|
||||
var dy: i32 = -1;
|
||||
while (dy <= 1) {
|
||||
var dx: i32 = -1;
|
||||
while (dx <= 1) {
|
||||
if (search.Check4(xmas, x, y, dx, dy)) {
|
||||
++found;
|
||||
}
|
||||
++dx;
|
||||
}
|
||||
++dy;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
Core.Print(found);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// 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/4
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day4_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var search: Wordsearch = Wordsearch.Read();
|
||||
var mas: [i32; 3] = (0x4D, 0x41, 0x53);
|
||||
var found: i32 = 0;
|
||||
|
||||
// TODO: Use for loops once they're implemented.
|
||||
var y: i32 = 1;
|
||||
while (y < 139) {
|
||||
var x: i32 = 1;
|
||||
while (x < 139) {
|
||||
if ((search.Check3(mas, x - 1, y - 1, 1, 1) or
|
||||
search.Check3(mas, x + 1, y + 1, -1, -1)) and
|
||||
(search.Check3(mas, x - 1, y + 1, 1, -1) or
|
||||
search.Check3(mas, x + 1, y - 1, -1, 1))) {
|
||||
++found;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
Core.Print(found);
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
// 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/5
|
||||
|
||||
library "day5_common";
|
||||
|
||||
import library "io_utils";
|
||||
|
||||
// fn LeftShift(a: Core.UInt(100), b: i32) -> Core.UInt(100) = "int.left_shift";
|
||||
fn LeftShift_u100(a: Core.UInt(100), b: Core.UInt(100)) -> Core.UInt(100) = "int.left_shift";
|
||||
|
||||
// TODO: Add a builtin that can do this!
|
||||
fn Promote(a: i32) -> Core.UInt(100) {
|
||||
var result: Core.UInt(100) = 0;
|
||||
var bit_i32: i32 = 1;
|
||||
var bit_u100: Core.UInt(100) = 1;
|
||||
while (bit_i32 != 0) {
|
||||
if (a & bit_i32 != 0) {
|
||||
result = result | bit_u100;
|
||||
}
|
||||
bit_i32 <<= 1;
|
||||
// TODO: bit_u100 <<= 1;
|
||||
bit_u100 = bit_u100 << 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn LeftShift(a: Core.UInt(100), b: i32) -> Core.UInt(100) {
|
||||
return LeftShift_u100(a, Promote(b));
|
||||
}
|
||||
|
||||
fn PageMask(page: i32) -> Core.UInt(100) {
|
||||
return LeftShift(1 as Core.UInt(100), page);
|
||||
}
|
||||
|
||||
class Rules {
|
||||
fn Read() -> Rules {
|
||||
returned var rules: Rules;
|
||||
var i: i32 = 0;
|
||||
while (i < 100) {
|
||||
rules.disallowed_before[i] = 0;
|
||||
++i;
|
||||
}
|
||||
|
||||
var a: i32;
|
||||
var b: i32;
|
||||
while (ReadInt(&a) and ConsumeChar(0x7C) and ReadInt(&b)) {
|
||||
// TODO: rules.disallowed_before[a] |= PageMask(b);
|
||||
rules.disallowed_before[a] = rules.disallowed_before[a] | PageMask(b);
|
||||
SkipNewline();
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
fn IsValidOrder[self: Self](a: i32, b: i32) -> bool {
|
||||
return self.disallowed_before[b] & PageMask(a) == 0;
|
||||
}
|
||||
|
||||
var disallowed_before: [Core.UInt(100); 100];
|
||||
};
|
||||
|
||||
class PageList {
|
||||
fn Empty() -> PageList {
|
||||
returned var me: PageList;
|
||||
me.num_pages = 0;
|
||||
return var;
|
||||
}
|
||||
|
||||
fn Read() -> PageList {
|
||||
returned var me: PageList = Empty();
|
||||
|
||||
var page: i32;
|
||||
if (not ReadInt(&page)) {
|
||||
return var;
|
||||
}
|
||||
me.Add(page);
|
||||
while (ConsumeChar(0x2C)) {
|
||||
ReadInt(&page);
|
||||
me.Add(page);
|
||||
}
|
||||
SkipNewline();
|
||||
return var;
|
||||
}
|
||||
|
||||
fn Add[addr self: Self*](page: i32) {
|
||||
self->pages[self->num_pages] = page;
|
||||
++self->num_pages;
|
||||
}
|
||||
|
||||
fn FollowsRules[self: Self](rules: Rules) -> bool {
|
||||
var seen: Core.UInt(100) = 0;
|
||||
var i: i32 = 0;
|
||||
while (i < self.num_pages) {
|
||||
let page: i32 = self.pages[i];
|
||||
if (seen & rules.disallowed_before[page] != 0) {
|
||||
return false;
|
||||
}
|
||||
// TODO: seen |= PageMask(page);
|
||||
seen = seen | PageMask(page);
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn IsPossibleFirstPage[self: Self](rules: Rules, page: i32) -> bool {
|
||||
var i: i32 = 0;
|
||||
while (i < self.num_pages) {
|
||||
if (not rules.IsValidOrder(page, self.pages[i])) {
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn ExtractPossibleFirstPage[addr self: Self*](rules: Rules) -> i32 {
|
||||
var i: i32 = 0;
|
||||
while (i < self->num_pages) {
|
||||
var page: i32 = self->pages[i];
|
||||
if (self->IsPossibleFirstPage(rules, page)) {
|
||||
self->pages[i] = self->pages[self->num_pages - 1];
|
||||
--self->num_pages;
|
||||
return page;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
// TODO: Assert.
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn MiddlePage[self: Self]() -> i32 {
|
||||
return self.pages[self.num_pages / 2];
|
||||
}
|
||||
|
||||
var pages: [i32; 24];
|
||||
var num_pages: i32;
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
// 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/5
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day5_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var rules: Rules = Rules.Read();
|
||||
SkipNewline();
|
||||
var total: i32 = 0;
|
||||
while (true) {
|
||||
var page_list: PageList = PageList.Read();
|
||||
if (page_list.num_pages == 0) {
|
||||
break;
|
||||
}
|
||||
if (page_list.FollowsRules(rules)) {
|
||||
total += page_list.MiddlePage();
|
||||
}
|
||||
}
|
||||
Core.Print(total);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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/5
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day5_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var rules: Rules = Rules.Read();
|
||||
SkipNewline();
|
||||
var total: i32 = 0;
|
||||
while (true) {
|
||||
var page_list: PageList = PageList.Read();
|
||||
if (page_list.num_pages == 0) {
|
||||
break;
|
||||
}
|
||||
if (page_list.FollowsRules(rules)) {
|
||||
continue;
|
||||
}
|
||||
var new_page_list: PageList = PageList.Empty();
|
||||
while (page_list.num_pages != 0) {
|
||||
new_page_list.Add(page_list.ExtractPossibleFirstPage(rules));
|
||||
}
|
||||
total += new_page_list.MiddlePage();
|
||||
}
|
||||
Core.Print(total);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
// 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/6
|
||||
|
||||
library "day6_common";
|
||||
|
||||
import Core library "io";
|
||||
import library "io_utils";
|
||||
|
||||
// TODO: Use a choice type.
|
||||
fn Empty() -> i8 { return 0; }
|
||||
fn Visited() -> i8 { return 1; }
|
||||
fn Wall() -> i8 { return 2; }
|
||||
|
||||
class Maze {
|
||||
fn Read() -> Maze {
|
||||
returned var me: Maze;
|
||||
|
||||
var y: i32 = 0;
|
||||
while (y < 130) {
|
||||
var x: i32 = 0;
|
||||
while (x < 130) {
|
||||
var cell: i32 = Core.ReadChar();
|
||||
if (cell == 0x23) {
|
||||
me.data[x][y] = Wall();
|
||||
} else if (cell == 0x5E) {
|
||||
// TODO: Handle other starting directions?
|
||||
me.data[x][y] = Visited();
|
||||
me.loc = (x, y);
|
||||
me.dir = (0, -1);
|
||||
} else {
|
||||
me.data[x][y] = Empty();
|
||||
}
|
||||
++x;
|
||||
}
|
||||
SkipNewline();
|
||||
++y;
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
fn Copy[self: Self]() -> Maze {
|
||||
returned var copy: Maze;
|
||||
var y: i32 = 0;
|
||||
while (y < 130) {
|
||||
var x: i32 = 0;
|
||||
while (x < 130) {
|
||||
copy.data[x][y] = self.data[x][y];
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
copy.loc = self.loc;
|
||||
copy.dir = self.dir;
|
||||
return var;
|
||||
}
|
||||
|
||||
fn Step[addr self: Self*]() -> bool {
|
||||
let x: i32 = self->loc.0 + self->dir.0;
|
||||
let y: i32 = self->loc.1 + self->dir.1;
|
||||
if (x < 0 or x >= 130 or y < 0 or y >= 130) {
|
||||
return false;
|
||||
}
|
||||
if (self->data[x][y] == Wall()) {
|
||||
// TODO: Should this work?
|
||||
// self->dir = (-self->dir.1, self->dir.0);
|
||||
let d: (i32, i32) = self->dir;
|
||||
self->dir = (-d.1, d.0);
|
||||
} else {
|
||||
self->loc = (x, y);
|
||||
self->data[x][y] = Visited();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn AddObstacle[addr self: Self*]() -> bool {
|
||||
let x: i32 = self->loc.0 + self->dir.0;
|
||||
let y: i32 = self->loc.1 + self->dir.1;
|
||||
if (x < 0 or x >= 130 or y < 0 or y >= 130) {
|
||||
return false;
|
||||
}
|
||||
if (self->data[x][y] != Empty()) {
|
||||
return false;
|
||||
}
|
||||
self->data[x][y] = Wall();
|
||||
return true;
|
||||
}
|
||||
|
||||
fn CountVisited[self: Self]() -> i32 {
|
||||
var total: i32 = 0;
|
||||
var y: i32 = 0;
|
||||
while (y < 130) {
|
||||
var x: i32 = 0;
|
||||
while (x < 130) {
|
||||
if (self.data[x][y] == Visited()) {
|
||||
++total;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
var data: [[i8; 130]; 130];
|
||||
var loc: (i32, i32);
|
||||
var dir: (i32, i32);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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/6
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day6_common";
|
||||
|
||||
fn Run() {
|
||||
var maze: Maze = Maze.Read();
|
||||
while (maze.Step()) {
|
||||
}
|
||||
Core.Print(maze.CountVisited());
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// 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/6
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day6_common";
|
||||
|
||||
class LoopDetector {
|
||||
fn Make() -> LoopDetector {
|
||||
return {.last = ((-1, -1), (-1, -1)), .steps = 1, .next_steps = 1};
|
||||
}
|
||||
|
||||
fn Check[addr self: Self*](next: ((i32, i32), (i32, i32))) -> bool {
|
||||
// TODO: if (next == self->last) {
|
||||
// TODO: The lexer mishandles `next.0.0` as `next` `.` `0.0`.
|
||||
if (next.0 .0 == self->last.0 .0 and next.0 .1 == self->last.0 .1 and
|
||||
next.1 .0 == self->last.1 .0 and next.1 .1 == self->last.1 .1) {
|
||||
return true;
|
||||
}
|
||||
--self->steps;
|
||||
if (self->steps == 0) {
|
||||
self->steps = self->next_steps;
|
||||
self->next_steps <<= 1;
|
||||
self->last = next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var last: ((i32, i32), (i32, i32));
|
||||
var steps: i32;
|
||||
var next_steps: i32;
|
||||
}
|
||||
|
||||
fn AddingObstacleMakesALoop(position: Maze) -> bool {
|
||||
var maze: Maze = position.Copy();
|
||||
var loop: LoopDetector = LoopDetector.Make();
|
||||
if (not maze.AddObstacle()) {
|
||||
return false;
|
||||
}
|
||||
while (maze.Step()) {
|
||||
if (loop.Check((maze.loc, maze.dir))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn Run() {
|
||||
var maze: Maze = Maze.Read();
|
||||
var loops: i32 = 0;
|
||||
while (true) {
|
||||
if (AddingObstacleMakesALoop(maze)) {
|
||||
++loops;
|
||||
}
|
||||
if (not maze.Step()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Core.Print(loops);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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/7
|
||||
|
||||
library "day7_common";
|
||||
|
||||
import Core library "io";
|
||||
import library "io_utils";
|
||||
|
||||
fn Concat(a_val: i64, b_val: i64) -> i64 {
|
||||
var a: i64 = a_val;
|
||||
var b: i64 = b_val;
|
||||
if (b == 0) {
|
||||
return a * 10;
|
||||
}
|
||||
while (b != 0) {
|
||||
a = a * 10;
|
||||
b = b / 10;
|
||||
}
|
||||
return a + b_val;
|
||||
}
|
||||
|
||||
class Equation {
|
||||
fn Read() -> Equation {
|
||||
returned var me: Equation;
|
||||
me.num_operands = 0;
|
||||
ReadInt64(&me.result);
|
||||
ConsumeChar(0x3A);
|
||||
while (ConsumeChar(0x20)) {
|
||||
ReadInt64(&me.operands[me.num_operands]);
|
||||
++me.num_operands;
|
||||
}
|
||||
while (SkipNewline()) {}
|
||||
return var;
|
||||
}
|
||||
|
||||
fn SolveFrom[self: Self](start: i32, value: i64, concat: bool) -> bool {
|
||||
if (value > self.result) {
|
||||
return false;
|
||||
}
|
||||
if (start == self.num_operands) {
|
||||
return value == self.result;
|
||||
}
|
||||
return self.SolveFrom(start + 1, value + self.operands[start], concat) or
|
||||
self.SolveFrom(start + 1, value * self.operands[start], concat) or
|
||||
(concat and self.SolveFrom(start + 1, Concat(value, self.operands[start]), true));
|
||||
}
|
||||
|
||||
fn Solve[self: Self](concat: bool) -> bool {
|
||||
return self.SolveFrom(1, self.operands[0], concat);
|
||||
}
|
||||
|
||||
var operands: [i64; 16];
|
||||
var num_operands: i32;
|
||||
var result: i64;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// 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/7
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day7_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var total: i64 = 0;
|
||||
while (PeekChar() != Core.EOF()) {
|
||||
var eq: Equation = Equation.Read();
|
||||
if (eq.Solve(false)) {
|
||||
// TODO: total += eq.result;
|
||||
total = total + eq.result;
|
||||
}
|
||||
}
|
||||
PrintInt64(total);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// 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/7
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day7_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var total: i64 = 0;
|
||||
while (PeekChar() != Core.EOF()) {
|
||||
var eq: Equation = Equation.Read();
|
||||
if (eq.Solve(true)) {
|
||||
// TODO: total += eq.result;
|
||||
total = total + eq.result;
|
||||
}
|
||||
}
|
||||
PrintInt64(total);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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/8
|
||||
|
||||
library "day8_common";
|
||||
|
||||
import Core library "io";
|
||||
import library "io_utils";
|
||||
|
||||
class Grid {
|
||||
fn Read() -> Grid {
|
||||
returned var me: Grid;
|
||||
var y: i32 = 0;
|
||||
while (y < 50) {
|
||||
var x: i32 = 0;
|
||||
while (x < 50) {
|
||||
me.data[x][y] = ReadChar();
|
||||
++x;
|
||||
}
|
||||
SkipNewline();
|
||||
++y;
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
var data: [[i32; 50]; 50];
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// 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/8
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day8_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn IsAntinode(grid: Grid, ox: i32, oy: i32) -> bool {
|
||||
var ay: i32 = 0;
|
||||
while (ay < 50) {
|
||||
let by: i32 = ay * 2 - oy;
|
||||
if (by >= 0 and by < 50) {
|
||||
var ax: i32 = 0;
|
||||
while (ax < 50) {
|
||||
let bx: i32 = ax * 2 - ox;
|
||||
if (bx >= 0 and bx < 50 and (ax != bx or ay != by)) {
|
||||
if (grid.data[ax][ay] != 0x2E and
|
||||
grid.data[ax][ay] == grid.data[bx][by]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
++ax;
|
||||
}
|
||||
}
|
||||
++ay;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn CountAntinodes(grid: Grid) -> i32 {
|
||||
var count: i32 = 0;
|
||||
var y: i32 = 0;
|
||||
while (y < 50) {
|
||||
var x: i32 = 0;
|
||||
while (x < 50) {
|
||||
if (IsAntinode(grid, x, y)) {
|
||||
++count;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
fn Run() {
|
||||
Core.Print(CountAntinodes(Grid.Read()));
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// 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/8
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day8_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn MarkAndCount(marks: [[bool; 50]; 50]*, x: i32, y: i32) -> i32 {
|
||||
if (not (*marks)[x][y]) {
|
||||
(*marks)[x][y] = true;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn MarkAndCountAntinodesFor(grid: Grid, marks: [[bool; 50]; 50]*, ax: i32, ay: i32) -> i32 {
|
||||
var count: i32 = 0;
|
||||
var by: i32 = 0;
|
||||
while (by < 50) {
|
||||
var bx: i32 = 0;
|
||||
while (bx < 50) {
|
||||
let dx: i32 = bx - ax;
|
||||
let dy: i32 = by - ay;
|
||||
if (grid.data[bx][by] != grid.data[ax][ay] or (dx == 0 and dy == 0)) {
|
||||
++bx;
|
||||
continue;
|
||||
}
|
||||
|
||||
var x: i32 = bx;
|
||||
var y: i32 = by;
|
||||
while (x >= 0 and x < 50 and y >= 0 and y < 50) {
|
||||
count += MarkAndCount(marks, x, y);
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
++bx;
|
||||
}
|
||||
++by;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
fn MarkAndCountAntinodes(grid: Grid, marks: [[bool; 50]; 50]*) -> i32 {
|
||||
var count: i32 = 0;
|
||||
var y: i32 = 0;
|
||||
while (y < 50) {
|
||||
var x: i32 = 0;
|
||||
while (x < 50) {
|
||||
if (grid.data[x][y] != 0x2E) {
|
||||
count += MarkAndCountAntinodesFor(grid, marks, x, y);
|
||||
}
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
fn Run() {
|
||||
var marks: [[bool; 50]; 50];
|
||||
var y: i32 = 0;
|
||||
while (y < 50) {
|
||||
var x: i32 = 0;
|
||||
while (x < 50) {
|
||||
marks[x][y] = false;
|
||||
++x;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
|
||||
Core.Print(MarkAndCountAntinodes(Grid.Read(), &marks));
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
// 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/9
|
||||
|
||||
library "day9_common";
|
||||
|
||||
import Core library "io";
|
||||
import library "io_utils";
|
||||
|
||||
// TODO: Add a builtin that can do this!
|
||||
fn Promote(a: i32) -> i64 {
|
||||
var result: i64 = 0;
|
||||
var bit_i32: i32 = 1;
|
||||
var bit_i64: i64 = 1;
|
||||
while (bit_i32 != 0) {
|
||||
if (a & bit_i32 != 0) {
|
||||
result = result | bit_i64;
|
||||
}
|
||||
bit_i32 <<= 1;
|
||||
// TODO: bit_i64 <<= 1;
|
||||
bit_i64 = bit_i64 << 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class SectorList {
|
||||
fn Read() -> SectorList {
|
||||
returned var me: SectorList;
|
||||
me.size = 0;
|
||||
var sector: i32 = 0;
|
||||
var used: bool = true;
|
||||
// TODO: An assignment expression would be useful here.
|
||||
var c: i32 = ReadChar();
|
||||
while (c != Core.EOF() and c != 0xA) {
|
||||
let v: i32 = if used then sector else -1;
|
||||
var n: i32 = c - 0x30;
|
||||
while (n > 0) {
|
||||
me.data[me.size] = v;
|
||||
++me.size;
|
||||
--n;
|
||||
}
|
||||
if (used) {
|
||||
++sector;
|
||||
}
|
||||
used = not used;
|
||||
c = ReadChar();
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
fn DefragBlocks[addr self: Self*]() {
|
||||
var i: i32 = 0;
|
||||
var j: i32 = self->size - 1;
|
||||
while (j > i) {
|
||||
if (self->data[i] != -1) {
|
||||
++i;
|
||||
} else if (self->data[j] == -1) {
|
||||
--j;
|
||||
} else {
|
||||
self->data[i] = self->data[j];
|
||||
++i;
|
||||
--j;
|
||||
}
|
||||
}
|
||||
self->size = j;
|
||||
}
|
||||
|
||||
fn HasSpace[addr self: Self*](start: i32, size: i32) -> bool {
|
||||
var i: i32 = start;
|
||||
while (i < start + size) {
|
||||
if (self->data[i] != -1) {
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn Fill[addr self: Self*](start: i32, size: i32, sector: i32) {
|
||||
var i: i32 = start;
|
||||
while (i < start + size) {
|
||||
self->data[i] = sector;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
fn DefragFiles[addr self: Self*]() {
|
||||
var j: i32 = self->size - 1;
|
||||
while (j >= 0) {
|
||||
// Skip empty sectors.
|
||||
while (j >= 0 and self->data[j] == -1) {
|
||||
--j;
|
||||
}
|
||||
|
||||
// Find the file size and sector and delete the file.
|
||||
let last: i32 = j;
|
||||
let sector: i32 = self->data[last];
|
||||
while (j >= 0 and self->data[j] == sector) {
|
||||
self->data[j] = -1;
|
||||
--j;
|
||||
}
|
||||
let first: i32 = j + 1;
|
||||
let size: i32 = last - first + 1;
|
||||
|
||||
// Find the first available space for the file.
|
||||
var i: i32 = 0;
|
||||
while (not self->HasSpace(i, size)) {
|
||||
++i;
|
||||
if (i + size > first) {
|
||||
// If it doesn't fit to the left of its old position, put it back
|
||||
// where it was.
|
||||
i = first;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert it.
|
||||
self->Fill(i, size, sector);
|
||||
}
|
||||
}
|
||||
|
||||
fn Checksum[self: Self]() -> i64 {
|
||||
var total: i64 = 0;
|
||||
var i: i32 = 0;
|
||||
while (i < self.size) {
|
||||
if (self.data[i] != -1) {
|
||||
total = total + Promote(i * self.data[i]);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
var data: [i32; 200000];
|
||||
var size: i32;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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/9
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day9_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var list: SectorList = SectorList.Read();
|
||||
list.DefragBlocks();
|
||||
PrintInt64(list.Checksum());
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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/9
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day9_common";
|
||||
import library "io_utils";
|
||||
|
||||
fn Run() {
|
||||
var list: SectorList = SectorList.Read();
|
||||
list.DefragFiles();
|
||||
PrintInt64(list.Checksum());
|
||||
}
|
||||
@@ -26,6 +26,7 @@ fn UnreadChar(c: i32) {
|
||||
unread_char = c + 2;
|
||||
}
|
||||
|
||||
// TODO: Make generic.
|
||||
fn ReadInt(p: i32*) -> bool {
|
||||
var read_any_digits: bool = false;
|
||||
*p = 0;
|
||||
@@ -44,6 +45,71 @@ fn ReadInt(p: i32*) -> bool {
|
||||
return read_any_digits;
|
||||
}
|
||||
|
||||
fn ReadInt64(p: i64*) -> bool {
|
||||
var read_any_digits: bool = false;
|
||||
*p = 0;
|
||||
|
||||
while (true) {
|
||||
var c: i32 = ReadChar();
|
||||
if (c < 0x30 or c > 0x39) {
|
||||
UnreadChar(c);
|
||||
break;
|
||||
}
|
||||
// TODO: Check for overflow.
|
||||
*p = *p * 10;
|
||||
if (c == 0x31) {
|
||||
*p = *p + 1;
|
||||
} else if (c == 0x32) {
|
||||
*p = *p + 2;
|
||||
} else if (c == 0x33) {
|
||||
*p = *p + 3;
|
||||
} else if (c == 0x34) {
|
||||
*p = *p + 4;
|
||||
} else if (c == 0x35) {
|
||||
*p = *p + 5;
|
||||
} else if (c == 0x36) {
|
||||
*p = *p + 6;
|
||||
} else if (c == 0x37) {
|
||||
*p = *p + 7;
|
||||
} else if (c == 0x38) {
|
||||
*p = *p + 8;
|
||||
} else if (c == 0x39) {
|
||||
*p = *p + 9;
|
||||
}
|
||||
read_any_digits = true;
|
||||
}
|
||||
return read_any_digits;
|
||||
}
|
||||
|
||||
fn PrintInt64NoNewline(n_val: i64) {
|
||||
var pow10: i64 = 1;
|
||||
var n: i64 = n_val;
|
||||
while (n / 10 >= pow10) {
|
||||
pow10 = pow10 * 10;
|
||||
}
|
||||
while (pow10 != 0) {
|
||||
let d: i64 = n / pow10;
|
||||
// TODO: Core.PrintChar(0x30 + (d as i32));
|
||||
if (d == 0) { Core.PrintChar(0x30); }
|
||||
else if (d == 1) { Core.PrintChar(0x31); }
|
||||
else if (d == 2) { Core.PrintChar(0x32); }
|
||||
else if (d == 3) { Core.PrintChar(0x33); }
|
||||
else if (d == 4) { Core.PrintChar(0x34); }
|
||||
else if (d == 5) { Core.PrintChar(0x35); }
|
||||
else if (d == 6) { Core.PrintChar(0x36); }
|
||||
else if (d == 7) { Core.PrintChar(0x37); }
|
||||
else if (d == 8) { Core.PrintChar(0x38); }
|
||||
else if (d == 9) { Core.PrintChar(0x39); }
|
||||
n = n % pow10;
|
||||
pow10 = pow10 / 10;
|
||||
}
|
||||
}
|
||||
|
||||
fn PrintInt64(n_val: i64) {
|
||||
PrintInt64NoNewline(n_val);
|
||||
Core.PrintChar(0xA);
|
||||
}
|
||||
|
||||
fn PeekChar() -> i32 {
|
||||
var next: i32 = ReadChar();
|
||||
UnreadChar(next);
|
||||
@@ -74,3 +140,14 @@ fn SkipNewline() -> bool {
|
||||
// TODO: Unread the CR if it was present?
|
||||
return ConsumeChar(0x0A);
|
||||
}
|
||||
|
||||
fn SkipNChars(n: i32) -> bool {
|
||||
var i: i32 = 0;
|
||||
while (i < n) {
|
||||
if (ReadChar() == Core.EOF()) {
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user