How Others Do It #1

Subscribe to How Others Do It #1 16 posts

avatar for Senekis93 Senekis93 4090 posts
Flag Post

Each programmer has an unique style and aims for different things: readability, reusability, speed, length, etc.

A How Others Do It thread features a problem that participants will solve in their own way.

Note that this is not a contest, the main point of the thread is that we can learn from others and discover different ways to solve the same problem.

If you want to take part, please make sure to include your code (at least all the relevant parts) that solves the presented problem.


Suggested by: Draco18s

Topic: Sorting a collection of objects based on distance from a known point.

Instructions:

1) Assume that a point p is constant (i.e. does not change during code execution)
2) Assume that the array of objects objectArray contains objects with an x and y property
3) Assume you have an O(1) sort function available to operate on any list or array type passed

The goal of the exercise is not to optimize the sort itself, but rather to see how you lay out the structure prior to sorting.

 
avatar for BobTheCoolGuy BobTheCoolGuy 3757 posts
Flag Post

Assume you have an O(1) sort function available to operate on any list or array type passed

Wow – pretty sick sort function. :D


Reserved for my answer later.

 
avatar for TheAwsomeOpossum TheAwsomeOpo... 1219 posts
Flag Post

I’ll answer this when I get time… but I am wondering, what exactly do you want? Do you want us to just find the distance from the point, and then sort the data in our own way? Is that it basically?

 
avatar for Senekis93 Senekis93 4090 posts
Flag Post

Another question: Can the objects inside of objectArray include an extra property (d)?
Mostly to see if we can simply sort on that or we’d need to create an extra list / figure out another way.


E:

public static function sortByDistance(p:Point,o:Array):void{
	const
		x:Number=p.x,
		y:Number=p.y,
		e:int=o.length,
		d:Vector.<Pair>=new Vector.<Pair>(e);
	var
		v:DisplayObject,
		i:int=e;
	while(--i>-1)
		v=o[i],
		d[i]=new Pair(((x-v.x)*(x-v.x))+((y-v.y)*(y-v.y)),v);
	magicallySort(d,"d");
	i=e;
	while(--i>-1)
		o[i]=d[i].v;
}
  • v type can be changed to whatever the contents of objectArray are.
  • Pair is a class with property d and v (the object).
 
avatar for MoonlaughMaster MoonlaughMaster 6660 posts
Flag Post
public static function sortByDist(p:Point, a:Array):Array {
	var temp:Array = new Array(a.length); // Create a new areay
	for (var i:int = 0; i < a.length; i++ ) {
		temp[i] = { d:Math.sqrt(((p.x - a[i].x) * (p.x - a[i].x)) + ((p.y - a[i].y) * (p.y - a[i].y))), obj:a[i]}; // Populate the array with Objects containing the object and the distance
	}
	
	sort(temp, "d"); // Sort array using our fancy sort function
	
	for (i = 0; i < temp.length; i++) {
		temp[i] = temp[i].obj; //reassign the indexes to be the original objects
	}
	
	return temp;
}

Amidoinitrite?

Whipped this up in a couple minutes. Probably nowhere near as efficient as it could be.

 
avatar for RTL_Shadow RTL_Shadow 1023 posts
Flag Post

Interesting- I’ll definitely do this.


E: There we go.

import flash.geom.Point;
public static const MAIN_POINT:Point = new Point( 300, 400 ); // Point
private var pointList:Vector.<Point> = new Vector.<Point> // Points in here.

for ( var i:int = 0; i < pointList.length; ++i )
{
	var distList:Vector.<Number> = new Vector.<Number>();
	var dist:Number = Math.pow( pointList[ i ].x - MAIN_POINT.x, 2 ) + Math.pow( pointList[ i ].y - MAIN_POINT.y, 2 );
	
	distList.push(dist);
}
sort(distList);
 
avatar for qwerberberber qwerberberber 508 posts
Flag Post

Originally posted by MoonlaughMaster:

public static function sortByDist(p:Point, a:Array):Array {
	var temp:Array = new Array(a.length); // Create a new areay
	for (var i:int = 0; i &lt; a.length; i++ ) {
		temp[i] = { d:Math.sqrt(((p.x - a[i].x) * (p.x - a[i].x)) + ((p.y - a[i].y) * (p.y - a[i].y))), obj:a[i]}; // Populate the array with Objects containing the object and the distance
	}
	
	sort(temp, "d"); // Sort array using our fancy sort function
	
	for (i = 0; i &lt; temp.length; i++) {
		temp[i] = temp[i].obj; //reassign the indexes to be the original objects
	}
	
	return temp;
}

Amidoinitrite?

Whipped this up in a couple minutes. Probably nowhere near as efficient as it could be.

i was expecting someone to make such a mistake; you don’t have to sqrt it :)

 
avatar for TheAwsomeOpossum TheAwsomeOpo... 1219 posts
Flag Post

Erk… gotta reformat this sometime…
private var inList:Vector<Points>;

inList = new Vector<Points>;

public function sort(inX:Number, inY:Number)

{
var tempList:Vector.<Number> = new Vector.<Number>();

for (var a:int = 0; a < inList.length; a++)
{
tempList.push(((inX - inList[a].x)(inX - inList[a].x)) + ((inY - inList[a].y)(inY - inList[a].y)));
}

//Do sorting after this point. Make sure to move points in both lists with the swapping methods.
//Also remember the tempList contains squares, not real values.
}

 
avatar for MoonlaughMaster MoonlaughMaster 6660 posts
Flag Post
Originally posted by qwerberberber:

Originally posted by MoonlaughMaster:

public static function sortByDist(p:Point, a:Array):Array {
	var temp:Array = new Array(a.length); // Create a new areay
	for (var i:int = 0; i &amp;lt; a.length; i++ ) {
		temp[i] = { d:Math.sqrt(((p.x - a[i].x) * (p.x - a[i].x)) + ((p.y - a[i].y) * (p.y - a[i].y))), obj:a[i]}; // Populate the array with Objects containing the object and the distance
	}
	
	sort(temp, "d"); // Sort array using our fancy sort function
	
	for (i = 0; i &amp;lt; temp.length; i++) {
		temp[i] = temp[i].obj; //reassign the indexes to be the original objects
	}
	
	return temp;
}

Amidoinitrite?

Whipped this up in a couple minutes. Probably nowhere near as efficient as it could be.

i was expecting someone to make such a mistake; you don’t have to sqrt it :)

That’s very true. I pulled it directly from my utils class in which it does have to be a pretty number, so that’s why it’s there.

 
avatar for RTL_Shadow RTL_Shadow 1023 posts
Flag Post

Sorry- Why is no square root needed?

 
avatar for Ace_Blue Ace_Blue 1091 posts
Flag Post

Because for a and b two real, positive numbers, if a > b then sqrt(a) > sqrt(b). Since you’re not interested in the value of the distance but only in the ordering of distances, you don’t need to compute the actual distance, its square is enough.

		public function orderAround(center:Point, dots:Array):void
		{
			var dist:Array = new Array(dots.length);
			var i:int = 0;
			var dx:Number;
			var dy:Number;
			while (i < dist.length)
			{
				dx = dots[i].x - center.x;
				dy = dots[i].y - center.y;
				dist[i] = [i, dx * dx + dy * dy];
				i++;
			}
			GodSort(dist, 1); // Magically sort the Array of Arrays dist 
					// based on the value at index 1 of each of its elements.
			i = 0;
			while (i < dist.length)
			{
				dist[i] = dots[dist[i, 0]];
				i++;
			}
			dots = dist;
		}
 
avatar for feartehstickman feartehstickman 521 posts
Flag Post

I’m not sure what else there is to add, I’d have done it roughly the same way.

But in terms of the sorting, what are the faster ways it could be done?
The simplest I could come up with on the spot would need 1/2 (list.length)^2 interactions:
search list, find lowest distance, push to array
search list -1, find lowest distance, push to array
search list -2 ……

 
avatar for NineFiveThree NineFiveThree 1370 posts
Flag Post
Originally posted by feartehstickman:


The simplest I could come up with on the spot would need 1/2 (list.length)^2 interactions:
search list, find lowest distance, push to array
search list -1, find lowest distance, push to array
search list -2 ……

There are plenty of sorting algorithms. Many are better than n².
This is not topic of this thread.

 
avatar for Draco18s Draco18s 6860 posts
Flag Post
Originally posted by BobTheCoolGuy:

Assume you have an O(1) sort function available to operate on any list or array type passed

Wow – pretty sick sort function. :D

The point is to assume a perfectly optimized sort function. The goal is to set up the datastructure to sort, not actually write a sort function. So I have people assume that a super-optimal sort function exists.

Originally posted by Senekis93:

Another question: Can the objects inside of objectArray include an extra property (d)?
Mostly to see if we can simply sort on that or we’d need to create an extra list / figure out another way.

The original objects on stage cannot, but any temporary object you set up to pass to the sort function can.
MoonlaughMaster appears to have done it that way, as have I in the past.

 
avatar for Jabor Jabor 11355 posts
Flag Post
sortByDistance :: Point -> [Point] -> [Point]
sortByDistance (x0,y0) = sortBy (compare `on` \(x,y) -> (x-x0)^2 * (y-y0)^2)

Haskell I know, but I do think the functional style is clearer here.

 
avatar for Senekis93 Senekis93 4090 posts
Flag Post
Originally posted by Draco18s:

The original objects on stage cannot, but any temporary object you set up to pass to the sort function can.

Ok. Edited my previous post.