Skip to content

Instantly share code, notes, and snippets.

@maartenpaauw
Created December 10, 2023 22:06
Show Gist options
  • Save maartenpaauw/75b5bef0a134f75f3df7b837fde1b809 to your computer and use it in GitHub Desktop.
Save maartenpaauw/75b5bef0a134f75f3df7b837fde1b809 to your computer and use it in GitHub Desktop.
Advent of Code 2023 - Day 10 - Part 1
<?php
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
$input = "..F7.
.FJ|.
SJ.L7
|F--J
LJ...";
enum Type: string
{
case Start = 'S';
case Vertical = '|';
case Horizontal = '-';
case NorthEast = 'L';
case NorthWest = 'J';
case SouthWest = '7';
case SouthEast = 'F';
case None = '.';
public function directions(): array
{
return match ($this) {
Type::Start => [Direction::North, Direction::East, Direction::South, Direction::West],
Type::Vertical => [Direction::North, Direction::South],
Type::Horizontal => [Direction::East, Direction::West],
Type::NorthEast => [Direction::North, Direction::East],
Type::NorthWest => [Direction::North, Direction::West],
Type::SouthWest => [Direction::South, Direction::West],
Type::SouthEast => [Direction::South, Direction::East],
};
}
}
enum Direction
{
case North;
case East;
case South;
case West;
}
final readonly class Coordinate
{
public function __construct(
public int $x,
public int $y,
) {
}
public function neighbors(Collection $directions): Collection
{
return $directions->map(fn (Direction $direction) => match ($direction) {
Direction::North => new Coordinate($this->x, $this->y - 1),
Direction::East => new Coordinate($this->x + 1, $this->y),
Direction::South => new Coordinate($this->x, $this->y + 1),
Direction::West => new Coordinate($this->x - 1, $this->y),
});
}
public function toString(): string
{
return "$this->x, $this->y";
}
}
final readonly class Pipe
{
public function __construct(
public Coordinate $coordinate,
public Type $type,
) {
}
public function neighbors(Collection $pipes): Collection
{
return $this->coordinate
->neighbors(Collection::make($this->type->directions()))
->map(static fn (Coordinate $coordinate) => $pipes->get($coordinate->toString()))
->filter()
->filter(static fn (Pipe $pipe): bool => $pipe->type !== Type::None)
->values();
}
}
/** @var Collection<string, Pipe> $pipes */
$pipes = Str::of($input)
->explode(PHP_EOL)
->map(static function (string $line, int $y): array {
preg_match_all('/[SLJ7F|\-.]/', $line, $matches, PREG_OFFSET_CAPTURE);
return Arr::map($matches[0], static function (array $pipe) use ($y) {
[$type, $x] = $pipe;
return new Pipe(new Coordinate($x, $y), Type::from($type));
});
})
->flatten(1)
->keyBy(static fn (Pipe $pipe): string => $pipe->coordinate->toString());
$start = $pipes->first(static fn (Pipe $pipe): bool => $pipe->type === Type::Start);
/** @var Collection<string, Pipe> $queue */
$queue = new Collection();
$visited = new Collection();
$queue->put($start->coordinate->toString(), $start);
$visited->put($start->coordinate->toString(), $start);
while ($queue->isNotEmpty()) {
$current = $queue->shift();
$neighbors = $current->neighbors($pipes);
$neighbors->each(function (Pipe $pipe) use ($queue, $visited) {
$key = $pipe->coordinate->toString();
if (! $visited->has($key)) {
$queue->put($key, $pipe);
$visited->put($key, $pipe);
}
});
}
$part1 = $visited->count() / 2;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment