Skip to content

Commit

Permalink
2024/15
Browse files Browse the repository at this point in the history
  • Loading branch information
tbali0524 committed Dec 15, 2024
1 parent cfd8946 commit f65dd8f
Show file tree
Hide file tree
Showing 11 changed files with 435 additions and 7 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⭐-478-green)
![AoC stars](https://img.shields.io/badge/total%20AoC%20⭐-480-green)
![license](https://img.shields.io/github/license/tbali0524/advent-of-code-solutions)

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

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions input/2024/Aoc2024Day15ex1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
########
#..O.O.#
##@.O..#
#...O..#
#.#.O..#
#...O..#
#......#
########

<^^>>>vv<v>>v<<
21 changes: 21 additions & 0 deletions input/2024/Aoc2024Day15ex2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
##########
#..O..O.O#
#......O.#
#.OO..O.O#
#[email protected].#
#O#..O...#
#O..O..O.#
#.OO.O.OO#
#....O...#
##########

<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^
9 changes: 9 additions & 0 deletions input/2024/Aoc2024Day15ex3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#######
#...#.#
#.....#
#..OO@#
#..O..#
#.....#
#######

<vv<<^^<<^^
8 changes: 4 additions & 4 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⭐-28-yellow) |
|__Total__ |![total](https://img.shields.io/badge/stars%20⭐-478-green) |
|[2024](#2024)|![+](https://img.shields.io/badge/stars%20⭐-30-yellow) |
|__Total__ |![total](https://img.shields.io/badge/stars%20⭐-480-green) |

## Puzzles

Expand Down Expand Up @@ -324,7 +324,7 @@ Hint from `subreddit` was used for Day 12 part 2, Day 24 part 2 and Day 25.
| + |2024| 12|Garden Groups | |
| + |2024| 13|Claw Contraption | |
| + |2024| 14|Restroom Redoubt | |
| - |2024| 15| | |
| + |2024| 15|Warehouse Woes | |
| - |2024| 16| | |
| - |2024| 17| | |
| - |2024| 18| | |
Expand All @@ -336,4 +336,4 @@ Hint from `subreddit` was used for Day 12 part 2, Day 24 part 2 and Day 25.
| - |2024| 24| | |
| - |2024| 25| | |

No external hint was used in this season.
Hint from `subreddit` was used for Day 14 part 2 (what shape to look for).
8 changes: 6 additions & 2 deletions results.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Results for all seasons

* Output of local run using PHP `8.4.1` with `php src/aoc.php` on `2024.12.14`.
* Output of local run using PHP `8.4.1` with `php src/aoc.php` on `2024.12.15`.
* Total running time:
* with AocRunner (PHP + JIT): `149 sec`
* with PhpUnit (XDebug + coverage): `39 sec` (less puzzles, 725 tests)
Expand Down Expand Up @@ -924,7 +924,11 @@ Advent of Code - batch solution runner, (c) 2024 by TBali
[ OK ] Puzzle example passed.
[ OK ] 229069152
[ OK ] 7383
======= Total: 239 solutions (12 skipped) [time: 149.819 sec; max memory: 1610 MB]
=== AoC 2024 Day 15 [time: 0.044 sec; memory: 68 Mbytes] Warehouse Woes
[ OK ] Puzzle examples (3) passed.
[ OK ] 1383666
[ OK ] 1412866
======= Total: 240 solutions (12 skipped) [time: 180.990 sec; max memory: 1610 MB]
[ OK ] All tests passed.
```
1 change: 1 addition & 0 deletions src/Aoc2024/Aoc2024Day13.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public function solve(array $input): array
*/
public function __construct(array $input, int $from = 0)
{
// ---------- Parse input
if ($from + 2 >= count($input)) {
// @codeCoverageIgnoreStart
throw new \Exception('missing line in claw machine definition');
Expand Down
1 change: 1 addition & 0 deletions src/Aoc2024/Aoc2024Day14.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ final class Aoc2024Day14 extends SolutionBase
*/
public function solve(array $input): array
{
// ---------- Parse input
$positions = [];
$velocities = [];
foreach ($input as $row) {
Expand Down
227 changes: 227 additions & 0 deletions src/Aoc2024/Aoc2024Day15.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
<?php

declare(strict_types=1);

namespace TBali\Aoc2024;

use TBali\Aoc\SolutionBase;

/**
* AoC 2024 Day 15: Warehouse Woes.
*
* @see https://adventofcode.com/2024/day/15
*/
final class Aoc2024Day15 extends SolutionBase
{
public const YEAR = 2024;
public const DAY = 15;
public const TITLE = 'Warehouse Woes';
public const SOLUTIONS = [1383666, 1412866];
public const EXAMPLE_SOLUTIONS = [[2028, 0], [10092, 9021], [0, 618]];

public const EMPTY = '.';
public const WALL = '#';
public const START = '@';
public const BOX = 'O';
public const BOX_LEFT = '[';
public const BOX_RIGHT = ']';

/**
* 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
$grid = [];
$max_y = 0;
$max_x = 0;
$start_x = -1;
$start_y = -1;
$i = 0;
while (($i < count($input)) and ($input[$i] != '')) {
$grid[] = $input[$i];
for ($x = 0; $x < strlen($input[$i]); ++$x) {
if ($grid[$i][$x] == self::START) {
$start_x = $x;
$start_y = $i;
$grid[$i][$x] = '.';
}
if (!str_contains('.#O', $grid[$i][$x])) {
throw new \Exception('invalid character in grid');
}
}
if ($i == 0) {
$max_x = strlen($grid[0]);
} elseif (strlen($grid[$i]) != $max_x) {
throw new \Exception('grid must be rectangular');
}
++$max_y;
++$i;
}
if ($start_y < 0) {
throw new \Exception('missing start position in grid');
}
if ($i == count($input)) {
throw new \Exception('instructions must be separated from the map by an empty line');
}
$instructions = [];
while ($i < count($input)) {
for ($j = 0; $j < strlen($input[$i]); ++$j) {
$dxy = match ($input[$i][$j]) {
'>' => [1, 0],
'v' => [0, 1],
'<' => [-1, 0],
'^' => [0, -1],
default => throw new \Exception('invalid character in instruction'),
};
$instructions[] = $dxy;
}
++$i;
}
// ---------- Part 1
$start_grid = $grid;
$x = $start_x;
$y = $start_y;
foreach ($instructions as [$dx, $dy]) {
$is_ok = true;
$x1 = $x;
$y1 = $y;
while (true) {
$x1 += $dx;
$y1 += $dy;
if ($y1 < 0 || $y1 >= $max_y || $x1 < 0 || $x1 >= $max_x) {
// @codeCoverageIgnoreStart
$is_ok = false;
break;
// @codeCoverageIgnoreEnd
}
if ($grid[$y1][$x1] == self::EMPTY) {
break;
}
if ($grid[$y1][$x1] == self::WALL) {
$is_ok = false;
break;
}
}
if (!$is_ok) {
continue;
}
$x += $dx;
$y += $dy;
if (($y != $y1) or ($x != $x1)) {
$grid[$y][$x] = self::EMPTY;
$grid[$y1][$x1] = self::BOX;
}
}
$ans1 = 0;
for ($y = 0; $y < $max_y; ++$y) {
for ($x = 0; $x < $max_x; ++$x) {
if ($grid[$y][$x] == self::BOX) {
$ans1 += 100 * $y + $x;
}
}
}
// ---------- Part 2
$grid = [];
for ($y = 0; $y < $max_y; ++$y) {
$grid[] = '';
for ($x = 0; $x < $max_x; ++$x) {
$grid[$y] .= match ($start_grid[$y][$x]) {
self::EMPTY => self::EMPTY . self::EMPTY,
self::BOX => self::BOX_LEFT . self::BOX_RIGHT,
self::WALL => self::WALL . self::WALL,
// @codeCoverageIgnoreStart
default => '',
// @codeCoverageIgnoreEnd
};
}
}
$start_x *= 2;
$max_x *= 2;
$x = $start_x;
$y = $start_y;
foreach ($instructions as [$dx, $dy]) {
$x1 = $x + $dx;
$y1 = $y + $dy;
if ($y1 < 0 || $y1 >= $max_y || $x1 < 0 || $x1 >= $max_x) {
// @codeCoverageIgnoreStart
continue;
// @codeCoverageIgnoreEnd
}
$moving_boxes = [];
if ($grid[$y1][$x1] == self::WALL) {
continue;
}
if ($grid[$y1][$x1] == self::EMPTY) {
$x = $x1;
$y = $y1;
continue;
}
if ($grid[$y1][$x1] == self::BOX_LEFT) {
$moving_boxes[] = [$x1, $y1];
}
if ($grid[$y1][$x1] == self::BOX_RIGHT) {
$moving_boxes[] = [$x1 - 1, $y1];
}
$is_ok = true;
$idx = 0;
while ($idx < count($moving_boxes)) {
[$xb, $yb] = $moving_boxes[$idx];
++$idx;
$x1 = $xb + $dx;
$y1 = $yb + $dy;
if ($y1 < 0 || $y1 >= $max_y || $x1 < 0 || $x1 >= $max_x - 1) {
// @codeCoverageIgnoreStart
$is_ok = false;
break;
// @codeCoverageIgnoreEnd
}
$c1 = $grid[$y1][$x1];
$c2 = $grid[$y1][$x1 + 1];
if ($c1 == self::WALL || $c2 == self::WALL) {
$is_ok = false;
break;
}
if ($c1 == self::BOX_LEFT) {
$moving_boxes[] = [$x1, $y1];
}
if ($c1 == self::BOX_RIGHT && ($x1 != $xb + 1 || $y1 != $yb)) {
$moving_boxes[] = [$x1 - 1, $y1];
}
if ($c2 == self::BOX_LEFT && ($x1 + 1 != $xb || $y1 != $yb)) {
$moving_boxes[] = [$x1 + 1, $y1];
}
}
if (!$is_ok) {
continue;
}
foreach ($moving_boxes as [$xb, $yb]) {
$grid[$yb][$xb] = self::EMPTY;
$grid[$yb][$xb + 1] = self::EMPTY;
}
foreach ($moving_boxes as [$xb, $yb]) {
$x1 = $xb + $dx;
$y1 = $yb + $dy;
$grid[$y1][$x1] = self::BOX_LEFT;
$grid[$y1][$x1 + 1] = self::BOX_RIGHT;
}
$x += $dx;
$y += $dy;
}
$ans2 = 0;
for ($y = 0; $y < $max_y; ++$y) {
for ($x = 0; $x < $max_x; ++$x) {
if ($grid[$y][$x] == self::BOX_LEFT) {
$ans2 += 100 * $y + $x;
}
}
}
return [strval($ans1), strval($ans2)];
}
}
Loading

0 comments on commit f65dd8f

Please sign in to comment.