# AoC 2024: Day 12

**URL:** <https://ziggit.dev/t/aoc-2024-day-12/7288>\
**Category:** Brainstorming\
**Tags:** advent-of-code\
**Created:** [December 12, 2024, 5:05am UTC](https://ziggit.dev/t/aoc-2024-day-12/7288 "2024-12-12T05:05:59Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Calder-Ty](https://ziggit.dev/user_avatar/ziggit.dev/calder-ty/32/10237_2.png) [@Calder-Ty](https://ziggit.dev/u/Calder-Ty)\
**Post date:** [December 12, 2024, 5:05am UTC](https://ziggit.dev/t/aoc-2024-day-12/7288/1 "2024-12-12T05:05:59Z")

</div>

Main thread for Day 12 of the 2024 advent of code. Feel free to discuss the challenge and ask questions. If particular discussions become large, we can break them off into new threads.

Some Rules:

1. Please try to keep spoilers within spoiler tags. This is done by typing [spoiler]text to be blurred[\spoiler]. If you have longer sections you can also use the [details=“Title”] tags.
2. Have Fun

[Day 12 Challenge](https://adventofcode.com/2024/day/12)

Templates:

- [GitHub - JacobCrabill/AdventOfCode-2024: My solutions for Advent of Code, 2024](https://github.com/JacobCrabill/AdventOfCode-2024)
- [GitHub - SpexGuy/Zig-AoC-Template: A template for Advent of Code participants using Zig](https://github.com/SpexGuy/Zig-AoC-Template)

Resources:

- [Advent of Code in Zig | Loris Cro's Blog](https://kristoff.it/blog/advent-of-code-zig) :Advice and Tips on How to do AoC with Zig
- [https://zigbin.io](https://zigbin.io) : A website for sharing zig code
- [Documentation - The Zig Programming Language](https://ziglang.org/documentation/master/) : Zig Language Reference
- [Zig Documentation](https://ziglang.org/documentation/master/std/) : Zig Standard Library Docs
- [Docs](https://ziggit.dev/docs) : Community Created Docs and Tutorials
- Private Leaderboard (189 Seats left) code: 1910115-f465b6d3

> **Previous days discussions**
>
> Day 1: [AoC 2024: Day 1](https://ziggit.dev/t/aoc-2024-day-1/7100)  
> Day 2: [AoC 2024: Day 2](https://ziggit.dev/t/aoc-2024-day-2/7119)  
> Day 3: [AoC 2024: Day 3](https://ziggit.dev/t/aoc-2024-day-3/7136)  
> Day 4: [AoC 2024: Day 4](https://ziggit.dev/t/aoc-2024-day-4/7150)  
> Day 5: [AoC 2024: Day 5](https://ziggit.dev/t/aoc-2024-day-5/7167)  
> Day 6: [AoC 2024: Day 6](https://ziggit.dev/t/aoc-2024-day-6/7183)  
> Day 7: [AoC 2024: Day 7](https://ziggit.dev/t/aoc-2024-day-7/7196)  
> Day 8: [AoC 2024: Day 8](https://ziggit.dev/t/aoc-2024-day-8/7207)  
> Day 9: [AoC 2024: Day 9](https://ziggit.dev/t/aoc-2024-day-9/7226)  
> Day 10: [AoC 2024: Day 10](https://ziggit.dev/t/aoc-2024-day-10/7244)  
> Day 11: [AoC 2024: Day 11](https://ziggit.dev/t/aoc-2024-day-11/7264)

---

<div class="post-metadata">

**Author:** ![gonzo](https://ziggit.dev/user_avatar/ziggit.dev/gonzo/32/54_2.png) [@gonzo](https://ziggit.dev/u/gonzo)\
**Post date:** [December 12, 2024, 12:40pm UTC](https://ziggit.dev/t/aoc-2024-day-12/7288/2 "2024-12-12T12:40:53Z")

</div>

I see zero traffic for this day’s problem. I found it required a lot of thinking before jumping into the code. I found two key observations that helped me:

- Trivial, useful for parts 1 and 2: Using flood fill to find each region.
- Sophisticated, vital for part 2: Counting corners is the same as counting straight edges.

Good luck!

---

<div class="post-metadata">

**Author:** ![maxsch](https://ziggit.dev/user_avatar/ziggit.dev/maxsch/32/3887_2.png) [@maxsch](https://ziggit.dev/u/maxsch)\
**Post date:** [December 12, 2024, 1:12pm UTC](https://ziggit.dev/t/aoc-2024-day-12/7288/3 "2024-12-12T13:12:02Z")

</div>

Very ugly p2 but i guess it fine for small inputs like this.

> **Part 1 & 2**
>
> ```zig
> const std = @import("std");
> 
> const util = @import("util.zig");
> const gpa = util.gpa;
> 
> const data = @embedFile("data/day12.txt");
> 
> const Point = struct { x: usize, y: usize };
> 
> const lim = 140;
> var grid = [_][lim]u8{[_]u8{undefined} **lim}** lim;
> var visited = [_][lim]bool{[_]bool{false} **lim}** lim;
> 
> pub fn main() !void {
> var p1: u32 = 0;
> var p2: u32 = 0;
> 
> var idx: usize = 0;
> var lines = std.mem.tokenizeScalar(u8, data, '\n');
> while (lines.next()) |line| : (idx += 1) {
> grid[idx] = line[0..lim].*;
> }
> 
> for (0..lim) |i| {
> for (0..lim) |j| {
> const res = try region_cost(i, j);
> p1 += res.p1;
> p2 += res.p2;
> }
> }
> 
> std.debug.print("part1: {}\n", .{p1});
> std.debug.print("part2: {}\n", .{p2});
> }
> 
> fn region_cost(x_start: usize, y_start: usize) !struct { p1: u32, p2: u32 } {
> if (visited[x_start][y_start]) return .{ .p1 = 0, .p2 = 0 };
> 
> var stack = std.ArrayList(Point).init(gpa);
> try stack.append(Point{ .x = x_start, .y = y_start });
> const char = grid[x_start][y_start];
> visited[x_start][y_start] = true;
> 
> var area: u32 = 0;
> var borders_count: u32 = 0;
> 
> var borders: [4]std.ArrayList(Point) = undefined;
> for (0..4) |i| {
> borders[i] = std.ArrayList(Point).init(gpa);
> }
> 
> while (stack.items.len != 0) {
> const current = stack.pop();
> const x = current.x;
> const y = current.y;
> area += 1;
> borders_count += try check_borders(x, y, char, &borders);
> 
> if (x > 0 and grid[x - 1][y] == char and !visited[x - 1][y]) {
> visited[x - 1][y] = true;
> try stack.append(.{ .x = x - 1, .y = y });
> }
> 
> if (x < lim - 1 and grid[x + 1][y] == char and !visited[x + 1][y]) {
> visited[x + 1][y] = true;
> try stack.append(Point{ .x = x + 1, .y = y });
> }
> 
> if (y > 0 and grid[x][y - 1] == char and !visited[x][y - 1]) {
> visited[x][y - 1] = true;
> try stack.append(Point{ .x = x, .y = y - 1 });
> }
> 
> if (y < lim - 1 and grid[x][y + 1] == char and !visited[x][y + 1]) {
> visited[x][y + 1] = true;
> try stack.append(Point{ .x = x, .y = y + 1 });
> }
> }
> 
> std.mem.sort(Point, borders[0].items, {}, cmp_y);
> std.mem.sort(Point, borders[0].items, {}, cmp_x);
> std.mem.sort(Point, borders[1].items, {}, cmp_y);
> std.mem.sort(Point, borders[1].items, {}, cmp_x);
> std.mem.sort(Point, borders[2].items, {}, cmp_x);
> std.mem.sort(Point, borders[2].items, {}, cmp_y);
> std.mem.sort(Point, borders[3].items, {}, cmp_x);
> std.mem.sort(Point, borders[3].items, {}, cmp_y);
> 
> var sides: u32 = 4;
> for (0..4) |i| {
> for (0..borders[i].items.len - 1) |j| {
> if (i < 2) {
> if (borders[i].items[j].y + 1 != borders[i].items[j + 1].y or borders[i].items[j].x != borders[i].items[j + 1].x)
> sides += 1;
> } else {
> if (borders[i].items[j].x + 1 != borders[i].items[j + 1].x or borders[i].items[j].y != borders[i].items[j + 1].y)
> sides += 1;
> }
> }
> }
> 
> return .{ .p1 = area * borders_count, .p2 = area * sides };
> }
> 
> fn check_borders(x: usize, y: usize, char: u8, borders: *[4]std.ArrayList(Point)) !u32 {
> var borders_count: u32 = 0;
> 
> if (x == 0 or grid[x - 1][y] != char) {
> try borders[0].append(Point{ .x = x, .y = y });
> borders_count += 1;
> }
> if (x == lim - 1 or grid[x + 1][y] != char) {
> try borders[1].append(Point{ .x = x, .y = y });
> borders_count += 1;
> }
> if (y == 0 or grid[x][y - 1] != char) {
> try borders[2].append(Point{ .x = x, .y = y });
> borders_count += 1;
> }
> if (y == lim - 1 or grid[x][y + 1] != char) {
> try borders[3].append(Point{ .x = x, .y = y });
> borders_count += 1;
> }
> 
> return borders_count;
> }
> 
> fn cmp_x(_: void, a: Point, b: Point) bool {
> return a.x < b.x;
> }
> 
> fn cmp_y(_: void, a: Point, b: Point) bool {
> return a.y < b.y;
> }
> 
> ```

---

<div class="post-metadata">

**Author:** ![erikwastaken](https://ziggit.dev/letter_avatar_proxy/v4/letter/e/8baadc/32.png) [@erikwastaken](https://ziggit.dev/u/erikwastaken)\
**Post date:** [December 12, 2024, 1:49pm UTC](https://ziggit.dev/t/aoc-2024-day-12/7288/4 "2024-12-12T13:49:20Z")

</div>

Starting to get a little trickier, or I’m just slow today. There is a more convenient way to write the if statements for part 2, for sure.

[https://zigbin.io/5a88d7](https://zigbin.io/5a88d7)

---

<div class="post-metadata">

**Author:** ![tgirod](https://ziggit.dev/user_avatar/ziggit.dev/tgirod/32/3744_2.png) [@tgirod](https://ziggit.dev/u/tgirod)\
**Post date:** [December 12, 2024, 8:36pm UTC](https://ziggit.dev/t/aoc-2024-day-12/7288/5 "2024-12-12T20:36:12Z")

</div>

Part two was tough! First, I wanted to walk around the edge of each region but it looked like a huge headache. So instead I thought I could scan the whole map line by line to detect horizontal borders, then vertically to detect vertical borders.

---

<div class="post-metadata">

**Author:** ![Southporter](https://ziggit.dev/user_avatar/ziggit.dev/southporter/32/2500_2.png) [@Southporter](https://ziggit.dev/u/Southporter)\
**Post date:** [December 12, 2024, 9:29pm UTC](https://ziggit.dev/t/aoc-2024-day-12/7288/6 "2024-12-12T21:29:33Z")

</div>

I could probably simplify the if chains. Its ugly, but it works.

[https://zigbin.io/5d3ef1](https://zigbin.io/5d3ef1)

---

<div class="post-metadata">

**Author:** ![ProfBof](https://ziggit.dev/letter_avatar_proxy/v4/letter/p/a88e4f/32.png) [@ProfBof](https://ziggit.dev/u/ProfBof)\
**Post date:** [December 13, 2024, 1:48am UTC](https://ziggit.dev/t/aoc-2024-day-12/7288/7 "2024-12-13T01:48:28Z")

</div>

450us. I tried my best to make the code as understandable as possible. For part 2 I tried to focus on finding the different ways a fence can be _not the first one of a straight line when going clockwise_. So the whole thing is just one pass. .

I don’t know if I am the only one, but I got into the habit of naming _all_ my loops so it is very clear from what I am breaking or continuing.

Also at the end of a block I just call something like _continue :loop\_on\_directions_ so I know where I am and have no headaches when closing a bunch of braces. I am not afraid of going indentation deep (_main_ is all you need), but at the same time try to break early to return left as soon as possible. Enough rambling, see you tomorrow…

[https://zigbin.io/e4e04e](https://zigbin.io/e4e04e)
