我正在写算法,该算法必须在此图中计算平方:
在数据库中,我具有以下各列的所有要点:x-coordinate
,y-coordinate
,toRight
,toLeft
,up
和down
。 toRight
,toLeft
等都是布尔值,表示您可以从该点向那个方向移动。
但是,我不清楚如何利用方向信息。我现在拥有的是以下代码:
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作为平方数。
答案 0 :(得分:1)
您可以使用属性来判断某个点是有效的JsonInclude
,upperLeft
,upperRight
还是lowerLeft
点。
以下是使用该信息的可能算法:
创建lowerRight
,upperLeft
,upperRight
或lowerLeft
点的列表。
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个列表
现在,通过从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点: