- var_dump: documentation ( source)
- array_merge: documentation ( source)
<?php
/**
* Finds pixels with the lowest geometrical distance from given point (x, y) that match the criteria.
*/
function findGeometricallyClosestPixels(array $grid, int $x, int $y, string $criteria): array
{
// if grid is empty or we're out of bounds
if (empty($grid) || !isset($grid[$y]) || !isset($grid[0][$x])) {
return [];
}
if ($grid[$y][$x] === $criteria) {
return [[$x, $y]];
}
$result = [];
for ($offset = 1; $offset < calculateMaximumOffset($grid, $x, $y); $offset++) {
$result = array_merge($result, getClosestPixels($grid, $x, $y, $offset, $criteria));
if (!empty($result)) {
return $result;
}
for ($d = 1; $d <= $offset; $d++) {
$result = array_merge($result, getPixelsForNegativeYOffsets($grid, $x, $y, $offset, $d, $criteria));
$result = array_merge($result, getPixelsForPositiveYOffsets($grid, $x, $y, $offset, $d, $criteria));
if (!empty($result)) {
return $result;
}
}
}
return $result;
}
function getClosestPixels(array $grid, int $x, int $y, int $offset, string $criteria): array
{
$result = [];
if (isset($grid[$y][$x - $offset]) && $grid[$y][$x - $offset] === $criteria) {
$result[] = [$x - $offset, $y];
}
if (isset($grid[$y][$x + $offset]) && $grid[$y][$x + $offset] === $criteria) {
$result[] = [$x + $offset, $y];
}
if (isset($grid[$y - $offset][$x]) && $grid[$y - $offset][$x] === $criteria) {
$result[] = [$x, $y - $offset];
}
if (isset($grid[$y + $offset][$x]) && $grid[$y + $offset][$x] === $criteria) {
$result[] = [$x, $y + $offset];
}
return $result;
}
function getPixelsForNegativeYOffsets(array $grid, int $x, int $y, int $offset, int $d, string $criteria): array
{
if (!isset($grid[$y - $d])) {
return [];
}
$result = [];
if (isset($grid[$y - $d][$x - $offset]) && $grid[$y - $d][$x - $offset] === $criteria) {
$result[] = [$x - $offset, $y - $d];
}
if (isset($grid[$y - $d][$x + $offset]) && $grid[$y - $d][$x + $offset] === $criteria) {
$result[] = [$x + $offset, $y - $d];
}
if (!isset($grid[$y - $offset])) {
return $result;
}
if (isset($grid[$y - $offset][$x - $d]) && $grid[$y - $offset][$x - $d] === $criteria) {
$result[] = [$x - $d, $y - $offset];
}
if (isset($grid[$y - $offset][$x + $d]) && $grid[$y - $offset][$x + $d] === $criteria) {
$result[] = [$x + $d, $y - $offset];
}
return $result;
}
function getPixelsForPositiveYOffsets(array $grid, int $x, int $y, int $offset, int $d, string $criteria): array
{
if (!isset($grid[$y + $d])) {
return [];
}
$result = [];
if (isset($grid[$y + $d][$x + $offset]) && $grid[$y + $d][$x + $offset] === $criteria) {
$result[] = [$x + $offset, $y + $d];
}
if (isset($grid[$y + $d][$x - $offset]) && $grid[$y + $d][$x - $offset] === $criteria) {
$result[] = [$x - $offset, $y + $d];
}
if (!isset($grid[$y + $offset])) {
return $result;
}
if (isset($grid[$y + $offset][$x - $d]) && $grid[$y + $offset][$x - $d] === $criteria) {
$result[] = [$x - $d, $y + $offset];
}
if (isset($grid[$y + $offset][$x + $d]) && $grid[$y + $offset][$x + $d] === $criteria) {
$result[] = [$x + $d, $y + $offset];
}
return $result;
}
/**
* Calculates maximum offset needed to reach the edge of given grid for given starting point.
*
* Lowest possible offset is right in the middle of the greater grid dimension (width or height). Since grid starts
* at zero, if the point is positioned past the middle, then offset will equal its position. Otherwise, it will equal
* greater dimension minus its position increased by one (to compensate for the fact that dimensions are measured
* starting at 1, but positions start at 0).
*/
function calculateMaximumOffset(array $grid, int $x, int $y): int
{
$gridHeight = count($grid);
$gridWidth = count($grid[0]);
if ($gridHeight >= $gridWidth) {
$relevantDimensionValue = $gridHeight;
$relevantCoordinateValue = $y;
} else {
$relevantDimensionValue = $gridWidth;
$relevantCoordinateValue = $x;
}
$half = floor($relevantDimensionValue / 2);
if ($relevantCoordinateValue >= $half) {
return $relevantCoordinateValue;
}
return $relevantDimensionValue - ($relevantCoordinateValue + 1);
}
$heart = [
['w', 'w', 'w', 'r', 'r', 'w', 'w', 'w', 'w', 'w', 'r', 'r', 'w', 'w', 'w', 'w'],
['w', 'w', 'r', 'r', 'r', 'r', 'w', 'w', 'w', 'r', 'r', 'r', 'r', 'w', 'w', 'w'],
['w', 'r', 'r', 'r', 'r', 'r', 'r', 'w', 'r', 'r', 'r', 'r', 'r', 'r', 'w', 'w'],
['r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'w'],
['r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'w'],
['r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'w'],
['r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'w'],
['r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'w'],
['w', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'w', 'w'],
['w', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'w', 'w'],
['w', 'w', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'w', 'w', 'w'],
['w', 'w', 'w', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'w', 'w', 'w', 'w'],
['w', 'w', 'w', 'w', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'w', 'w', 'w', 'w', 'w'],
['w', 'w', 'w', 'w', 'w', 'r', 'r', 'r', 'r', 'r', 'w', 'w', 'w', 'w', 'w', 'w'],
['w', 'w', 'w', 'w', 'w', 'w', 'r', 'r', 'r', 'w', 'w', 'w', 'w', 'w', 'w', 'w'],
['w', 'w', 'w', 'w', 'w', 'w', 'w', 'r', 'w', 'w', 'w', 'w', 'w', 'w', 'w', 'w'],
];
var_dump(findGeometricallyClosestPixels($heart, 3, 0, 'w'));
This script was stopped while abusing our resources