Tricky Median Question

1

Given n points, choose a point in the given list such that the sum of distances to this point is minimum ,compared to all others.

Distance is measured in the following manner.

For a point (x,y) all 8 adjacent points have distance 1.

(x+1,y)(x+1,y+1),(x+1,y-1),(x,y+1),(x,y-1),(x-1,y)(x-1,y+1),(x-1,y-1)

EDIT

More clearer explanation.

A function foo is defined as

foo(point_a,point_b) = max(abs(point_a.x - point_b.x),abs(point_a.y - point_b.y))

Find a point x such that sum([foo(x,y) for y in list_of_points]) is minimum.

Example

Input:

0 1
2 5
3 1
4 0

Output

3 1

Eg: Distance between (4,5) and 6,7) is 2.

This can be done in O(n^2) time, by checking the sum of each pair. Is there any better algorithm to do it?

Greyhound

Posted 2011-08-14T19:37:26.363

Reputation: 35

I don't understand how the diagonal distances are the same as the perpendicular distances. Also, I'm not sure I understand: are you you asking for the average of the n points? – Griffin – 2011-08-14T20:12:37.037

Edited the question – Greyhound – 2011-08-14T20:20:39.307

@griffin he means chessboard distance

– ratchet freak – 2011-08-14T21:57:13.347

Can we assume the points are distinct? Having two points in the same place would give it more weight. – Joey Adams – 2011-08-15T01:17:41.613

1This isn't really a puzzle - wouldn't it belong to SO? – user unknown – 2011-08-15T04:03:21.510

1

Crossposting: http://stackoverflow.com/q/7059500/312172 (with python-tag, there)

– user unknown – 2011-08-15T04:06:58.320

1@user unknown: How do you define "puzzle"? For me, the puzzle is finding the more efficient algorithm, and I'm having fun working it out. – Joey Adams – 2011-08-15T10:11:07.813

@Greyhound: Welcome to StackExchange! Please don't cross-post; pick one site and post it there. If it's deemed off-topic, it will hopefully be migrated. See "Is cross-posting a question on multiple Stack Exchange sites permitted if the question is on-topic for each site?"

– Joey Adams – 2011-08-15T10:14:16.637

Which one should I pick? For example, which site should I pick,if its Algorithm or Combinatorics related problem. – Greyhound – 2011-08-15T12:03:58.190

@Greyhound: If it is language agnostic, and you do the work to make a competition out of it: PPCG. To post it here, you need to have a metric, by which you decide which solution is best. In most cases: shortest solution. But you would need to clarify, whether to solve an specific example, or take input from a file/system in/program parameters. – user unknown – 2011-08-15T16:19:46.073

Btw.: I somehow overseen your 'is there a better algo than O(n^2)'. Now I deleted my answer, which was 0(n^2). – user unknown – 2011-08-15T16:23:19.950

Answers

2

I can imagine a scheme better than O(n^2), at least in the common case.

Build a quadtree out of your input points. For each node in the tree, compute the number and average position of the points within that node. Then for each point, you can use the quadtree to compute its distance to all other points in less than O(n) time. If you're computing the distance from a point p to a distant quadtree node v, and v doesn't overlap the 45 degree diagonals from p, then the total distance from p to all the points in v is easy to compute (for v which are more horizontally than vertically separated from p, it is just v.num_points * |p.x - v.average.x|, and similarly using y coordinates if v is predominately vertically seperated). If v overlaps one of the 45 degree diagonals, recurse on its components.

That should beat O(n^2), at least when you can find a balanced quadtree to represent your points.

Keith Randall

Posted 2011-08-14T19:37:26.363

Reputation: 19 865

nice. this should be on the stackoverflow page. – Neil G – 2011-08-17T20:41:52.670

0

Scala

object Median extends App
{
    var(xMin,yMin,xMax,yMax,a,x)=(100000000,100000000,-100000000,-100000000,"",Array.fill(2)(""))
    var points=Array((100000000,100000000))
    a=readLine
    while(a!=null)
    {
        x=a.split(" ")
        if(x(0).toInt<xMin)xMin=x(0).toInt
        if(x(1).toInt<yMin)yMin=x(1).toInt
        if(x(0).toInt>xMax)xMax=x(0).toInt
        if(x(1).toInt>yMax)yMax=x(1).toInt
        points=points:+((x(0).toInt,x(1).toInt))
        a=readLine
    }
    var middlex=(xMax-xMin)/2
    var middley=(yMax-yMin)/2

    var meanPoint=(100000000,100000000)
    var shortestDistance=100000000

    points.map(x=>
        {
            var s=(math.abs(x._1-middlex).max(math.abs(x._2-middley)))
            if(s<shortestDistance)
            {
                shortestDistance=s
                meanPoint=x
            }
        })

    println(meanPoint)
}

Takes in the points, keeping track of the highest and lowest values of x and y.
Uses those values to find the midpoint of the square defined by xMin,yMin,xMax,yMax.
Finds the point with the shortest distance to that midpoint.

Never was very good with that Big O business, so I couldn't tell you what it is for this algorithm.

Gareth

Posted 2011-08-14T19:37:26.363

Reputation: 11 678

1I don't think that will give you the correct answer, especially if the points are clustered. For example, if the points are (0,0) (0,1) (0,2) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2) (10,10), the correct answer should be (1,1) - total distance of 17. Yours would return (2,2) - total distance of 21. – migimaru – 2011-08-15T00:03:05.270

@migimaru Hmmm...I'll have to rethink. – Gareth – 2011-08-15T07:05:23.737

0

Haskell, 136 characters

main=interact$show.n.q.map read.words
n x=snd$minimum$map(\p@(a,b)->(sum$map(\(x,y)->max(abs$a-x)$abs$b-y)x,p))x
q[]=[]
q(x:y:z)=(x,y):q z

Thomas Eding

Posted 2011-08-14T19:37:26.363

Reputation: 796

Is it less than than O(2^n)? – user unknown – 2011-08-15T22:37:44.063

No. The OP didn't require it to be less than O(n^2). – Thomas Eding – 2011-08-15T23:21:57.283

1Last two sentences. I provided an O(n²)-solution myself before realizing it. And it isn't a golf-question, so avoiding whitespace and meaningful variable names isn't requiered. – user unknown – 2011-08-16T00:40:18.417

I didn't realize that posting non-golf puzzles was a part of this site. Eh, I'll keep my solution here. – Thomas Eding – 2011-08-16T18:05:54.040

0

Python

def median(lst):
    """ sort of median of a list """
    return sorted(lst)[len(lst) / 2]

def median_point(points):
    xs = [point[0] for point in points]
    ys = [point[1] for point in points]
    return (median(xs), median(ys))

points = [
    (0, 1),
    (2, 5),
    (3, 1),
    (4, 0),
]

print median_point(points) # (3, 1)

It calculates the median of the x and y coordinates separately. I'm not positive that that's correct in all cases, but it kind of seems like it might be. It's O(n log n).

recursive

Posted 2011-08-14T19:37:26.363

Reputation: 8 616

Calculating the medians separately means you may get a result that isn't one of the original points. In your example, if you replace (3,1) and (4,0) with (3,0) and (4,1), it will still print out (3,1). – migimaru – 2011-08-17T23:38:21.887

Ah yes, I didn't notice that was a requirement. – recursive – 2011-08-18T01:45:50.013