<?php declare(strict_types=1); use Illuminate\\Support\\Collection; \$input = <<<\'PHP\' ............ ........0... .....0...... .......0.... ....0....... ......A..... ............ ............ ........A... .........A.. ............ ............ PHP; \$city = City::fromNotation(\$input); return \$city->antennaPairs() ->map(static fn (AntennaPair \$antennaPair): array => \$antennaPair->antinodes()) ->flatten(1) ->unique(static fn (Antinode \$antinode): string => \$antinode->toString()) ->filter(static fn (Antinode \$antinode): bool => \$city->withinBoundaries(\$antinode)) ->values() ->count(); final readonly class City \{ /** * @param Collection<array-key, Antenna> \$antennas */ public function __construct( public Collection \$antennas, public int \$width, public int \$height, ) \{\} public static function fromNotation(string \$input): self \{ \$map = array_map( static fn (string \$row) => mb_str_split(\$row), explode(\"\\n\", \$input), ); \$antennas = []; \$width = \\count(\$map[0]); \$height = \\count(\$map); foreach (\$map as \$y => \$row) \{ foreach (\$row as \$x => \$frequency) \{ if (\$frequency !== \'.\') \{ \$antennas[] = new Antenna(\$x, \$y, \$frequency); \} \} \} return new self(Collection::make(\$antennas), \$width, \$height); \} /** * @return Collection<array-key, AntennaPair> */ public function antennaPairs(): Collection \{ \$pairs = Collection::make(); \$frequencies = \$this->antennas->mapToGroups(static fn (Antenna \$antenna) => [\$antenna->frequency => \$antenna]); foreach (\$frequencies as \$frequency) \{ foreach (\$frequency as \$i => \$a) \{ foreach (\$frequency as \$j => \$b) \{ if (\$i < \$j) \{ \$pairs->push(new AntennaPair(\$a, \$b)); \} \} \} \} return \$pairs; \} public function withinBoundaries(Antinode \$antinode): bool \{ return \$antinode->x >= 0 && \$antinode->y >= 0 && \$antinode->x < \$this->width && \$antinode->y < \$this->height; \} \} final readonly class Antenna \{ public function __construct( public int \$x, public int \$y, public string \$frequency, ) \{\} \} final readonly class AntennaPair \{ public function __construct( public Antenna \$a, public Antenna \$b, ) \{ if (\$this->a->frequency !== \$this->b->frequency) \{ throw new InvalidArgumentException(); \} \} /** * @return Antinode[] */ public function antinodes(): array \{ \$ax = \$this->a->x - \$this->b->x; \$ay = \$this->a->y - \$this->b->y; \$bx = \$this->b->x - \$this->a->x; \$by = \$this->b->y - \$this->a->y; return [ new Antinode(\$this->a->x + \$ax, \$this->a->y + \$ay), new Antinode(\$this->b->x + \$bx, \$this->b->y + \$by), ]; \} \} final readonly class Antinode \{ public function __construct( public int \$x, public int \$y, ) \{\} public function toString(): string \{ return \"(\{\$this->x\}, \{\$this->y\})\"; \} \}