diff options
Diffstat (limited to 'php/2024')
| -rw-r--r-- | php/2024/.envrc | 1 | ||||
| -rw-r--r-- | php/2024/README.md | 11 | ||||
| -rw-r--r-- | php/2024/day_04/Grid.php | 69 | ||||
| -rw-r--r-- | php/2024/day_04/Input.php | 25 | ||||
| -rw-r--r-- | php/2024/day_04/Position.php | 79 | ||||
| -rw-r--r-- | php/2024/day_04/part_01.php | 94 | ||||
| -rw-r--r-- | php/2024/flake.lock | 27 | ||||
| -rw-r--r-- | php/2024/flake.nix | 43 |
8 files changed, 349 insertions, 0 deletions
diff --git a/php/2024/.envrc b/php/2024/.envrc new file mode 100644 index 0000000..cffc922 --- /dev/null +++ b/php/2024/.envrc @@ -0,0 +1 @@ +use flake . --impure diff --git a/php/2024/README.md b/php/2024/README.md new file mode 100644 index 0000000..6aeb9d6 --- /dev/null +++ b/php/2024/README.md @@ -0,0 +1,11 @@ +# PHP 2024 + +## Getting Started + +### How to Run + +Run the php script directly, e.g. + +```sh +php day_XX/part_YY.php +``` diff --git a/php/2024/day_04/Grid.php b/php/2024/day_04/Grid.php new file mode 100644 index 0000000..75d531b --- /dev/null +++ b/php/2024/day_04/Grid.php @@ -0,0 +1,69 @@ +<?php + +declare(strict_types=1); + +class Grid implements Stringable +{ + /** + * @param string[][] $data + */ + public function __construct(public array $data) + { + } + + public function __toString(): string + { + $rowToLine = fn (array $row): string => array_reduce( + array: $row, + callback: fn (string $acc, string $character): string => $acc . $character, + initial: "", + ); + + return array_reduce( + array: $this->data, + callback: fn (string $acc, array $row): string => $acc . $rowToLine($row) . PHP_EOL, + initial: "", + ); + } + + public function getCharacterAtPosition(Position $position): string + { + if ($this->isInBounds($position)) { + return $this->data[$position->y][$position->x]; + } + + return "."; + } + + /** + * @param Position[] $positions + */ + public function getStringFromPositions(array $positions): string + { + $characters = array_map( + callback: fn (Position $position): string => $this->getCharacterAtPosition($position), + array: $positions, + ); + + $string = array_reduce( + array: $characters, + callback: fn (string $acc, string $character): string => $acc . $character, + initial: "", + ); + + return $string; + } + + public function isInBounds(Position $position): bool + { + if (!array_key_exists($position->y, $this->data)) { + return false; + } + + if (!array_key_exists($position->x, $this->data[$position->y])) { + return false; + } + + return true; + } +} diff --git a/php/2024/day_04/Input.php b/php/2024/day_04/Input.php new file mode 100644 index 0000000..60a16a0 --- /dev/null +++ b/php/2024/day_04/Input.php @@ -0,0 +1,25 @@ +<?php + +declare(strict_types=1); + +class Input +{ + public string $contents; + + public function __construct(private string $fileName) + { + $contents = file_get_contents($this->fileName, use_include_path: true); + $this->contents = $contents === false ? "" : $contents; + } + + public function toGrid(): Grid + { + $lines = explode("\n", $this->contents); + $gridArray = array_map( + callback: fn (string $line): array => str_split(trim($line)), + array: $lines + ); + + return new Grid($gridArray); + } +} diff --git a/php/2024/day_04/Position.php b/php/2024/day_04/Position.php new file mode 100644 index 0000000..0dcf96c --- /dev/null +++ b/php/2024/day_04/Position.php @@ -0,0 +1,79 @@ +<?php + +declare(strict_types=1); + +class Position implements Stringable +{ + public function __construct(public $x, public $y) + { + } + + public function __toString(): string + { + return "({$this->x}, {$this->y})"; + } + + /** + * Not validated + */ + public function getNorth(): self + { + return new self($this->x, $this->y - 1); + } + + /** + * Not validated + */ + public function getNorthEast(): self + { + return new self($this->x + 1, $this->y - 1); + } + + /** + * Not validated + */ + public function getEast(): self + { + return new self($this->x + 1, $this->y); + } + + /** + * Not validated + */ + public function getSouthEast(): self + { + return new self($this->x + 1, $this->y + 1); + } + + /** + * Not validated + */ + public function getSouth(): self + { + return new self($this->x, $this->y + 1); + } + + /** + * Not validated + */ + public function getSouthWest(): self + { + return new self($this->x - 1, $this->y + 1); + } + + /** + * Not validated + */ + public function getWest(): self + { + return new self($this->x - 1, $this->y); + } + + /** + * Not validated + */ + public function getNorthWest(): self + { + return new self($this->x - 1, $this->y - 1); + } +} diff --git a/php/2024/day_04/part_01.php b/php/2024/day_04/part_01.php new file mode 100644 index 0000000..0faa5b0 --- /dev/null +++ b/php/2024/day_04/part_01.php @@ -0,0 +1,94 @@ +<?php + +declare(strict_types=1); + +spl_autoload_register(fn (string $className) => require "{$className}.php"); + +// Assumes executed from workspace root +$input = new Input('../_input/day_04.txt'); +if ($input->contents === "") { + throw new RuntimeException("File not found"); +} + +$grid = $input->toGrid(); + +$matchCount = 0; +foreach ($grid->data as $y => $row) { + foreach ($row as $x => $char) { + if ($char !== 'X') { + continue; + } + + $start = new Position($x, $y); + + $possibleMatches = []; + + $possibleMatches["north"] = $grid->getStringFromPositions([ + $start, + $start->getNorth(), + $start->getNorth()->getNorth(), + $start->getNorth()->getNorth()->getNorth(), + ]); + + $possibleMatches["east"] = $grid->getStringFromPositions([ + $start, + $start->getEast(), + $start->getEast()->getEast(), + $start->getEast()->getEast()->getEast(), + ]); + + $possibleMatches["south"] = $grid->getStringFromPositions([ + $start, + $start->getSouth(), + $start->getSouth()->getSouth(), + $start->getSouth()->getSouth()->getSouth(), + ]); + + $possibleMatches["west"] = $grid->getStringFromPositions([ + $start, + $start->getWest(), + $start->getWest()->getWest(), + $start->getWest()->getWest()->getWest(), + ]); + + $possibleMatches["north-east"] = $grid->getStringFromPositions([ + $start, + $start->getNorthEast(), + $start->getNorthEast()->getNorthEast(), + $start->getNorthEast()->getNorthEast()->getNorthEast(), + ]); + + $possibleMatches["north-west"] = $grid->getStringFromPositions([ + $start, + $start->getNorthWest(), + $start->getNorthWest()->getNorthWest(), + $start->getNorthWest()->getNorthWest()->getNorthWest(), + ]); + + $possibleMatches["south-east"] = $grid->getStringFromPositions([ + $start, + $start->getSouthEast(), + $start->getSouthEast()->getSouthEast(), + $start->getSouthEast()->getSouthEast()->getSouthEast(), + ]); + + $possibleMatches["south-west"] = $grid->getStringFromPositions([ + $start, + $start->getSouthWest(), + $start->getSouthWest()->getSouthWest(), + $start->getSouthWest()->getSouthWest()->getSouthWest(), + ]); + + $matchCount += array_reduce( + array: $possibleMatches, + callback: fn (int $acc, string $possibleMatch): int => match ($possibleMatch) { + "XMAS" => $acc + 1, + default => $acc, + }, + initial: 0, + ); + } +} + +// ANSWER: 2517 +echo $matchCount; diff --git a/php/2024/flake.lock b/php/2024/flake.lock new file mode 100644 index 0000000..b7695d9 --- /dev/null +++ b/php/2024/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1741010256, + "narHash": "sha256-WZNlK/KX7Sni0RyqLSqLPbK8k08Kq7H7RijPJbq9KHM=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ba487dbc9d04e0634c64e3b1f0d25839a0a68246", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/php/2024/flake.nix b/php/2024/flake.nix new file mode 100644 index 0000000..2be5644 --- /dev/null +++ b/php/2024/flake.nix @@ -0,0 +1,43 @@ +{ + description = "Advent of Code 2024: PHP"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + }; + + outputs = + { nixpkgs, ... }: + let + pkgs = import nixpkgs { + config.allowUnfree = true; + }; + in + { + devShells.x86_64-linux.default = + let + phpVersion = "php84"; + + phpPackage = pkgs.lib.attrByPath [ phpVersion ] null pkgs; + phpPackages = pkgs.lib.attrByPath [ "${phpVersion}Packages" ] null pkgs; + phpExtensions = pkgs.lib.attrByPath [ "${phpVersion}Extensions" ] null pkgs; + in + pkgs.mkShell { + # build tools + nativeBuildInputs = with pkgs; [ + phpPackage + nodejs_18 + ]; + # dependencies + buildInputs = with pkgs; [ + intelephense + phpunit + phpPackages.php-cs-fixer + phpPackages.phpstan + phpExtensions.xdebug + + gh # GitHub CLI + ]; + }; + + }; +} |
