summaryrefslogtreecommitdiff
path: root/2024/PHP
diff options
context:
space:
mode:
Diffstat (limited to '2024/PHP')
-rw-r--r--2024/PHP/day_04/Grid.php67
-rw-r--r--2024/PHP/day_04/Input.php25
-rw-r--r--2024/PHP/day_04/Position.php77
-rw-r--r--2024/PHP/day_04/part_01.php94
4 files changed, 263 insertions, 0 deletions
diff --git a/2024/PHP/day_04/Grid.php b/2024/PHP/day_04/Grid.php
new file mode 100644
index 0000000..c0382df
--- /dev/null
+++ b/2024/PHP/day_04/Grid.php
@@ -0,0 +1,67 @@
+<?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/2024/PHP/day_04/Input.php b/2024/PHP/day_04/Input.php
new file mode 100644
index 0000000..f7e03c1
--- /dev/null
+++ b/2024/PHP/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/2024/PHP/day_04/Position.php b/2024/PHP/day_04/Position.php
new file mode 100644
index 0000000..182da7e
--- /dev/null
+++ b/2024/PHP/day_04/Position.php
@@ -0,0 +1,77 @@
+<?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/2024/PHP/day_04/part_01.php b/2024/PHP/day_04/part_01.php
new file mode 100644
index 0000000..250da0c
--- /dev/null
+++ b/2024/PHP/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;