计数平方算法

时间:2019-05-05 11:59:41

标签: php algorithm

我正在写算法,该算法必须在此图中计算平方:

figure containing squares to count

在数据库中,我具有以下各列的所有要点:x-coordinatey-coordinatetoRighttoLeftupdowntoRighttoLeft等都是布尔值,表示您可以从该点向那个方向移动。

但是,我不清楚如何利用方向信息。我现在拥有的是以下代码:

public function count(array $points)
{ 
    $pointsGroupedByX = array();
    $edges = array();

    foreach ($points as $point) {
        $key = $point->getX();

        if (!in_array($key, array_keys($pointsGroupedByX))) {
            $pointsGroupedByX[$key] = array();
        }

        if (!in_array($point, $pointsGroupedByX[$key])) {
            $pointsGroupedByX[$key][] = $point;
        }
    }

    foreach ($pointsGroupedByX as $group) {
        for ($i = 0; $i < count($group) - 1; $i++) {
            for ($j = 0; $j < count($group) - 1; $j++) {

                if ($group[$i] === $group[$j + 1] || $group[$i] > $group[$j + 1]) {
                    continue;
                }

                $edge = array($group[$i], $group[$j + 1]);
                $key = $group[$i]->getX();

                if (!in_array($key, array_keys($edges))) {
                    $edges[$key] = array();
                }

                $edges[$key][] = $edge;
            }
        }   
    }
}

它首先按x-coordinate将点分类,然后返回多维数组,其中包含来自这些分类点的所有可能的垂直边。

想法是使这些边缘的每组循环通过,并检查另一组是否具有相反的边缘。例如,边缘x:0 y:0 - x:0 y:2,则下一组必须具有x:2 y:0 - x:2 y:2,然后:

x:0 y:0 - x:0 y:4的相对边缘必须再看两组:x:4 y:0 - x:4 y:4

x:0 y:0 - x:0 y:6的相对边缘必须进一步看3组:x:6 y:0 - x:6 y:6

以此类推。

但是我不清楚如何编写此代码,这看起来像是错误的方法。

什么是计数平方算法的更好方法?谢谢

编辑

现在从vacawama的答案中遵循算法,我有了以下代码(php):

$upperLeft = array();
$upperRight = array();
$lowerRight = array();
$lowerLeft = array();
$squares = 0;

foreach ($points as $point) {
    if ($point->getToRight()) {
        if ($point->getDown()) {
            $upperLeft[] = $point;
        }

        if ($point->getUp()) {
            $lowerLeft[] = $point;
        }
    }
    if ($point->getToLeft()) {
        if ($point->getDown()) {
            $upperRight[] = $point;
        }

        if ($point->getUp()) {
            $lowerRight[] = $point;
        }
    }
}

foreach ($upperLeft as $ul) {
    foreach ($upperRight as $ur) {
        if ($ur->getY() !== $ul->getY() || $ur->getX() > $ul->getX()) { // ur is not at same vertical as ul or not to the right of ul
            continue;
        }
        foreach ($lowerLeft as $ll) {
            if ($ll->getX() !== $ul->getX() || $ll->getY() < $ul->getY()) { // ll is not at same horizontal as ul or not bellow ul
                continue;
            }
            if ($ll->getY() - $ul->getY() !== $ur->getX() - $ul->getX()) {
                continue;
            }
            foreach ($lowerRight as $lr) {
                if ($lr->getY() !== $ll->getY()) {
                    continue;
                }
                if ($lr->getX() !== $ur->getX()) {
                    continue;
                }
                $squares++;
            }
        }
    }
}
return $squares;

但是它返回错误的答案。

共有4个列表,总共17个点,而不是26个点,因此该代码以某种方式返回17作为平方数。

1 个答案:

答案 0 :(得分:1)

您可以使用属性来判断某个点是有效的JsonIncludeupperLeftupperRight还是lowerLeft点。

以下是使用该信息的可能算法:

  1. 创建lowerRightupperLeftupperRightlowerLeft点的列表。

    lowerRight

    注意事项:a)有些点属于所有4个列表,因此在任何比较中都不要使用// Attributes for inclusion: // upperLeft === (toRight && down) // upperRight === (toLeft && down) // lowerLeft === (toRight && up) // lowerRight === (toLeft && up) for pt in points if pt.toRight if pt.down upperLeft.append(pt) end if pt.up lowerLeft.append(pt) end end if pt.toLeft if pt.down upperRight.append(pt) end if pt.up lowerRight.append(pt) end end end b)在41个点中,每个点仅属于26个列表

  2. 现在,通过从4个列表中选择点来找到正方形。如果等到选择了一个潜在正方形的所有4个角,则需要检查else-if 26*26*26*26个正方形。您可以拒绝不起作用的要点来加快流程。例如,一旦有了左上点,便知道右上点必须具有相同的垂直(y值),并且右上值必须在左上值的右边。选择左下点时,它应位于左上点下方(相同的x值),并且距左上点的距离应与左上点距右上点的距离相同(因为寻找正方形)。选取右下角的点时,它应与左下角的点(相同的y值)和右上角的点(相同的x值)对齐。

    (456,976)

这是我用Swift编写的解决方案:

squares = 0
for ul in upperLeft
  for ur in upperRight
    next if ur is not at same vertical and to the right of ul
    for ll in lowerLeft
      next if ll is not at same horizontal and below ul
      next if dist(ul,ll) != dist(ul,ur)  // looking for squares
      for lr in lowerRight
        next if lr not at same vertical as ll
        next if lr not at same horizontal as ur
        squares += 1
      end
    end
  end
end

以下是符合左上角的26点:

The 26 upperLeft points