Skip to content

Commit

Permalink
2024/12
Browse files Browse the repository at this point in the history
  • Loading branch information
tbali0524 committed Dec 12, 2024
1 parent 854e5f3 commit b792273
Show file tree
Hide file tree
Showing 11 changed files with 376 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![php v8.4](https://shields.io/badge/php-8.4-blue?logo=php)
![build](https://img.shields.io/github/actions/workflow/status/tbali0524/advent-of-code-solutions/qa.yml)
![AoC stars](https://img.shields.io/badge/total%20AoC%20⭐-472-green)
![AoC stars](https://img.shields.io/badge/total%20AoC%20⭐-474-green)
![license](https://img.shields.io/github/license/tbali0524/advent-of-code-solutions)

* [AoC website](https://adventofcode.com/)
Expand Down
140 changes: 140 additions & 0 deletions input/2024/Aoc2024Day12.txt

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions input/2024/Aoc2024Day12ex1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
AAAA
BBCD
BBCC
EEEC
5 changes: 5 additions & 0 deletions input/2024/Aoc2024Day12ex2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
OOOOO
OXOXO
OOOOO
OXOXO
OOOOO
10 changes: 10 additions & 0 deletions input/2024/Aoc2024Day12ex3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
RRRRIICCFF
RRRRIICCCF
VVRRRCCFFF
VVRCCCJFFF
VVVVCJJCFE
VVIVCCJJEE
VVIIICJJEE
MIIIIIJJEE
MIIISIJEEE
MMMISSJEEE
5 changes: 5 additions & 0 deletions input/2024/Aoc2024Day12ex4.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
EEEEE
EXXXX
EEEEE
EXXXX
EEEEE
6 changes: 6 additions & 0 deletions input/2024/Aoc2024Day12ex5.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
AAAAAA
AAABBA
AAABBA
ABBAAA
ABBAAA
AAAAAA
6 changes: 3 additions & 3 deletions puzzles.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
|[2021](#2021)|![+](https://img.shields.io/badge/stars%20⭐-50-green) |
|[2022](#2022)|![+](https://img.shields.io/badge/stars%20⭐-50-green) |
|[2023](#2023)|![+](https://img.shields.io/badge/stars%20⭐-50-green) |
|[2024](#2024)|![+](https://img.shields.io/badge/stars%20⭐-20-yellow) |
|__Total__ |![total](https://img.shields.io/badge/stars%20⭐-472-green) |
|[2024](#2024)|![+](https://img.shields.io/badge/stars%20⭐-24-yellow) |
|__Total__ |![total](https://img.shields.io/badge/stars%20⭐-474-green) |

## Puzzles

Expand Down Expand Up @@ -321,7 +321,7 @@ Hint from `subreddit` was used for Day 12 part 2, Day 24 part 2 and Day 25.
| + |2024| 9|Disk Fragmenter | |
| + |2024| 10|Hoof It |BFS |
| + |2024| 11|Plutonian Pebbles |recursion, memoization |
| - |2024| 12| | |
| + |2024| 12|Garden Groups | |
| - |2024| 13| | |
| - |2024| 14| | |
| - |2024| 15| | |
Expand Down
12 changes: 8 additions & 4 deletions results.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Results for all seasons

* Output of local run using PHP `8.4.1` with `php src/aoc.php` on `2024.12.11`.
* Output of local run using PHP `8.4.1` with `php src/aoc.php` on `2024.12.12`.
* Total running time:
* with AocRunner (PHP + JIT): `133 sec`
* with PhpUnit (XDebug + coverage): `39 sec` (less puzzles, 707 tests)
* with AocRunner (PHP + JIT): `141 sec`
* with PhpUnit (XDebug + coverage): `39 sec` (less puzzles, 714 tests)

```txt
Advent of Code - batch solution runner, (c) 2024 by TBali
Expand Down Expand Up @@ -912,7 +912,11 @@ Advent of Code - batch solution runner, (c) 2024 by TBali
[ OK ] Puzzle examples (2) passed.
[ OK ] 197157
[ OK ] 234430066982597
======= Total: 236 solutions (12 skipped) [time: 147.633 sec; max memory: 1610 MB]
=== AoC 2024 Day 12 [time: 0.068 sec; memory: 72 Mbytes] Garden Groups
[ OK ] Puzzle examples (5) passed.
[ OK ] 1344578
[ OK ] 814302
======= Total: 237 solutions (12 skipped) [time: 140.839 sec; max memory: 1610 MB]
[ OK ] All tests passed.
```
122 changes: 122 additions & 0 deletions src/Aoc2024/Aoc2024Day12.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?php

declare(strict_types=1);

namespace TBali\Aoc2024;

use TBali\Aoc\SolutionBase;

/**
* AoC 2024 Day 12: Garden Groups.
*
* @see https://adventofcode.com/2024/day/12
*/
final class Aoc2024Day12 extends SolutionBase
{
public const YEAR = 2024;
public const DAY = 12;
public const TITLE = 'Garden Groups';
public const SOLUTIONS = [1344578, 814302];
public const EXAMPLE_SOLUTIONS = [[140, 80], [772, 436], [1930, 1206], [0, 236], [0, 368]];

/**
* Solve both parts of the puzzle for a given input, without IO.
*
* @param array<int, string> $input The lines of the input, without LF
*
* @return array<int, string> The answers for Part 1 and Part 2 (as strings)
*
* @phpstan-return array{string, string}
*/
public function solve(array $input): array
{
// ---------- Parse input
$max_y = count($input);
$max_x = strlen($input[0]);
if (array_any(array_map(strlen(...), $input), static fn (int $x): bool => $x != $max_x)) {
throw new \Exception('grid must be rectangular');
}
// ---------- Part 1 + 2
$region_grid = array_fill(0, $max_y, array_fill(0, $max_x, -1));
$side_grid = array_fill(0, $max_y, array_fill(0, $max_x, [-1, -1, -1, -1]));
$areas = [];
$perimeters = [];
$count_regions = 0;
for ($start_y = 0; $start_y < $max_y; ++$start_y) {
for ($start_x = 0; $start_x < $max_x; ++$start_x) {
if ($region_grid[$start_y][$start_x] >= 0) {
continue;
}
++$count_regions;
$region_char = $input[$start_y][$start_x];
$areas[] = 0;
$perimeters[] = 0;
$q = [[$start_x, $start_y]];
$region_grid[$start_y][$start_x] = $count_regions - 1;
$idx_read = 0;
while ($idx_read < count($q)) {
[$x, $y] = $q[$idx_read];
++$idx_read;
++$areas[$count_regions - 1];
foreach ([[1, 0], [0, 1], [-1, 0], [0, -1]] as $dir => [$dx, $dy]) {
$x1 = $x + $dx;
$y1 = $y + $dy;
if (
$x1 < 0
|| $x1 >= $max_x
|| $y1 < 0
|| $y1 >= $max_y
|| $input[$y1][$x1] != $region_char
) {
++$perimeters[$count_regions - 1];
$side_grid[$y][$x][$dir] = $count_regions - 1;
continue;
}
if ($region_grid[$y1][$x1] >= 0) {
continue;
}
$region_grid[$y1][$x1] = $count_regions - 1;
$q[] = [$x1, $y1];
}
}
}
}
$ans1 = 0;
for ($i = 0; $i < $count_regions; ++$i) {
$ans1 += $areas[$i] * $perimeters[$i];
}
$sides = array_fill(0, $count_regions, 0);
for ($dir = 0; $dir < 4; ++$dir) {
if ($dir % 2 == 0) {
for ($x = 0; $x < $max_x; ++$x) {
for ($y = 0; $y < $max_y; ++$y) {
$idx_region = $side_grid[$y][$x][$dir];
if ($idx_region < 0) {
continue;
}
if ($y == 0 || $side_grid[$y - 1][$x][$dir] != $idx_region) {
++$sides[$idx_region];
}
}
}
} else {
for ($y = 0; $y < $max_y; ++$y) {
for ($x = 0; $x < $max_x; ++$x) {
$idx_region = $side_grid[$y][$x][$dir];
if ($idx_region < 0) {
continue;
}
if ($x == 0 || $side_grid[$y][$x - 1][$dir] != $idx_region) {
++$sides[$idx_region];
}
}
}
}
}
$ans2 = 0;
for ($i = 0; $i < $count_regions; ++$i) {
$ans2 += $areas[$i] * $sides[$i];
}
return [strval($ans1), strval($ans2)];
}
}
72 changes: 72 additions & 0 deletions tests/Aoc2024Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use TBali\Aoc2024\Aoc2024Day09;
use TBali\Aoc2024\Aoc2024Day10;
use TBali\Aoc2024\Aoc2024Day11;
use TBali\Aoc2024\Aoc2024Day12;

/**
* Unit tests for Advent of Code season 2024.
Expand All @@ -43,6 +44,7 @@
#[CoversClass(Aoc2024Day09::class)]
#[CoversClass(Aoc2024Day10::class)]
#[CoversClass(Aoc2024Day11::class)]
#[CoversClass(Aoc2024Day12::class)]
final class Aoc2024Test extends TestCase
{
// --------------------------------------------------------------------
Expand Down Expand Up @@ -523,4 +525,74 @@ public function testDay11InvalidInput1(): void
}

// --------------------------------------------------------------------

public function testDay12Example1(): void
{
$solver = new Aoc2024Day12();
$input = $solver->readInput($solver->inputBaseFileName() . 'ex1.txt');
[$ans1, $ans2] = $solver->solve($input);
[$expected1, $expected2] = $solver::EXAMPLE_SOLUTIONS[0];
self::assertSame(strval($expected1), $ans1);
self::assertSame(strval($expected2), $ans2);
}

public function testDay12Example2(): void
{
$solver = new Aoc2024Day12();
$input = $solver->readInput($solver->inputBaseFileName() . 'ex2.txt');
[$ans1, $ans2] = $solver->solve($input);
[$expected1, $expected2] = $solver::EXAMPLE_SOLUTIONS[1];
self::assertSame(strval($expected1), $ans1);
self::assertSame(strval($expected2), $ans2);
}

public function testDay12Example3(): void
{
$solver = new Aoc2024Day12();
$input = $solver->readInput($solver->inputBaseFileName() . 'ex3.txt');
[$ans1, $ans2] = $solver->solve($input);
[$expected1, $expected2] = $solver::EXAMPLE_SOLUTIONS[2];
self::assertSame(strval($expected1), $ans1);
self::assertSame(strval($expected2), $ans2);
}

public function testDay12Example4(): void
{
$solver = new Aoc2024Day12();
$input = $solver->readInput($solver->inputBaseFileName() . 'ex4.txt');
[$ans1, $ans2] = $solver->solve($input);
[$expected1, $expected2] = $solver::EXAMPLE_SOLUTIONS[3];
// self::assertSame(strval($expected1), $ans1);
self::assertSame(strval($expected2), $ans2);
}

public function testDay12Example5(): void
{
$solver = new Aoc2024Day12();
$input = $solver->readInput($solver->inputBaseFileName() . 'ex5.txt');
[$ans1, $ans2] = $solver->solve($input);
[$expected1, $expected2] = $solver::EXAMPLE_SOLUTIONS[4];
// self::assertSame(strval($expected1), $ans1);
self::assertSame(strval($expected2), $ans2);
}

public function testDay12(): void
{
$solver = new Aoc2024Day12();
$input = $solver->readInput($solver->inputBaseFileName() . '.txt');
[$ans1, $ans2] = $solver->solve($input);
[$expected1, $expected2] = $solver::SOLUTIONS;
self::assertSame(strval($expected1), $ans1);
self::assertSame(strval($expected2), $ans2);
}

public function testDay12InvalidInput1(): void
{
$solver = new Aoc2024Day12();
$input = ['AB', 'A'];
$this->expectException(\Exception::class);
[$ans1, $ans2] = $solver->solve($input);
}

// --------------------------------------------------------------------
}

0 comments on commit b792273

Please sign in to comment.