Created
December 10, 2023 22:06
-
-
Save maartenpaauw/75b5bef0a134f75f3df7b837fde1b809 to your computer and use it in GitHub Desktop.
Advent of Code 2023 - Day 10 - Part 1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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