Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solutions for advent of code, day 4 - 13. #4750

Open
wants to merge 12 commits into
base: trunk
Choose a base branch
from
65 changes: 18 additions & 47 deletions examples/advent2024/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,21 @@ utils = [
"sort.carbon",
]

carbon_binary(
name = "day1_part1",
srcs = [
"day1_common.carbon",
"day1_part1.carbon",
] + utils,
)

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,
)
# 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 = []

# Produce a binary "dayX_partY" for each matching `.carbon` file.
[
zygoloid marked this conversation as resolved.
Show resolved Hide resolved
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
]
6 changes: 6 additions & 0 deletions examples/advent2024/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
31 changes: 31 additions & 0 deletions examples/advent2024/day10_common.carbon
Original file line number Diff line number Diff line change
@@ -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/10

// https://adventofcode.com/2024/day/1

library "day10_common";

import Core library "io";
import library "io_utils";

class Terrain {
Copy link
Contributor

@jonmeow jonmeow Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth having any documentation in these files? A lot of these get fairly complex, including when you get into hex representations of characters. Where do you see the balance of maintenance and discarding if the code needs updated? (maybe it's more on the latter side, due to a lack of tests?)

Copy link
Contributor Author

@zygoloid zygoloid Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding documentation: while we are asked not to distribute the test inputs or the problem description, I think it'd be fine to include links to the problems. I've gone ahead and done that, but that only helps for part 1 -- the part 2 description is unavailable unless you are logged in and have solved part 1.

I've been a bit wary of including too much description in these because of the request to not distribute the problems, but perhaps I'm being too cautious. I'm intending to do some more maintenance of these examples over time (using new Carbon features as they become available, for example), and will think about striking a better balance here as I rework these.

Regarding maintenance versus discarding: I've added some instructions to README.md for how to react to build breaks. I'm leaning towards disabling rather than deleting the examples when they break, but I don't mind much either way; it's easy to get them back from git history if we'd prefer to delete them immediately.

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];
}
101 changes: 101 additions & 0 deletions examples/advent2024/day10_part1.carbon
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// 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

// https://adventofcode.com/2024/day/1

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));
}
74 changes: 74 additions & 0 deletions examples/advent2024/day10_part2.carbon
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// 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

// https://adventofcode.com/2024/day/1

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);
}
33 changes: 33 additions & 0 deletions examples/advent2024/day11_common.carbon
Original file line number Diff line number Diff line change
@@ -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/11

// https://adventofcode.com/2024/day/1

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);
}
22 changes: 22 additions & 0 deletions examples/advent2024/day11_part1.carbon
Original file line number Diff line number Diff line change
@@ -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/11

// https://adventofcode.com/2024/day/1

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);
}
Loading
Loading