4

Here I have written simple program but I have little issue in managing it.

I have 6 points, for each point I want to calculate distance to other points.

DEmo - http://ideone.com/mYl30O

code:

<?php
$a_points = array(
    array(0, -1),
    array(-2, 3),
    array(4, 0),
    array(3, 1),
    array(5, 2),
    array(0, 1),
);
$k = 0;
$a_sum_dists = array();
$sum = array();
foreach ($a_points as $i => $pt1) {
    list($x1, $y1) = $pt1;
    //$sum = 0;
    foreach ($a_points as $j => $pt2) {
        if ($j == $i) continue;
        list($x2, $y2) = $pt2;
        $sum[$k] = pow($x2- $x1, 2) + pow($y2- $y1, 2);
        $k++;
    }
    //$a_sum_dists[$i] = $sum;
}

?>

What I want:

  1. for each point, get distance to all other points. Then print point which is at min distance. If more then one such points, print all

  2. Now we have min distance points for each point. So now prints points which appears most frequently as a min distance. If more then one such points, print all

3
  • To get the distance, you also need to take square root there. sqrt(pow($x2- $x1, 2) + pow($y2- $y1, 2)), also I believe if you want to know the points used for specific sums a counter is not the best way. Commented Feb 24, 2014 at 7:53
  • 1
    display your required output gives more clarity Commented Feb 24, 2014 at 8:01
  • @Pietu1998: thanks but if I skip using sqrt, even purpose of getting closest points can be preserved. If i am not wrong Commented Feb 24, 2014 at 9:50

2 Answers 2

3

Now when you've specified algorithm in detail, I can suggest implementation for it:

$a_all_ids = array_keys($a_points);
$a_neibor_ids = array();
foreach ($a_points as $i => $pt1) {
    list($x1, $y1) = $pt1;
    $a_dists = array();
    foreach ($a_points as $j => $pt2) {
        if ($j == $i) continue;
        list($x2, $y2) = $pt2;
        $a_dists[$j] = pow($x2- $x1, 2) + pow($y2- $y1, 2);
    }
    $min_dist = min($a_dists);
    $a_neibor_ids = array_merge(
        $a_neibor_ids,
        array_keys(array_filter($a_dists, function ($v) use ($min_dist) {
            return $v == $min_dist;
        }))
        );
}

$a_counts = array_count_values($a_neibor_ids);
$max_count = max($a_counts);

$a_result_points = array_intersect_key(
    $a_points, 
    array_filter($a_counts, function ($v) use ($max_count) {
        return $v == $max_count;
    })
);

Notations:

  • $a_dists - distances from the current point to the rest points.
  • $a_neibor_ids - for each point we find its nearest point(s). $a_neibor_ids is union of all such points (including duplicates).
  • $a_counts - numbers of occurences of each value from $a_neibor_ids.

Demo

Sign up to request clarification or add additional context in comments.

4 Comments

thanks a ton. Can you please add comments in code?? in ideone? little complex php DS.
Added some explanation
can you please suggest name for this algo? want your opinion
Something like "most frequent neighbor" or "most frequent nearest point" algo
1

A straightforward implementation of what you have described is:

$points = [
    [0, -1],
    [-2, 3],
    [4, 0],
    [3, 1],
    [5, 2],
    [0, 1],
];

$max_closest = [];

foreach ($points as $i => list($ax, $ay)) {
        $min_dist = INF;
        $dists = [];

        foreach ($points as $j => list($bx, $by)) {
                if ($i == $j) {
                        continue;
                }
                $dists[$j] = $sq_dist = ($bx - $ax) * ($bx - $ax) + ($by - $ay) * ($by - $ay);

                if ($sq_dist < $min_dist) {
                        $min_dist = $sq_dist;
                }
        }

        // select closest points
        foreach (array_keys($dists, $min_dist, true) as $key) {
                print_r($points[$key]); // print point

                // keep track of points that were closest
                if (isset($max_closest[$key])) {
                        ++$max_closest[$key];
                } else {
                        $max_closest[$key] = 1;
                }
        }
}

rsort($max_closest);

foreach (array_keys($max_closest, $max_closest[0], true) as $key) {
        print_r($points[$key]); // print point
}

1 Comment

@Programming_crazy Oh, you need 5.5 to use foreach($array as list($foo, $bar) :) see 3v4l.org/2Z7cj

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.