Friday, March 25, 2011

How to use Perl, PHP, Python, R, and Ruby to find Euclidean distance between two points

According to Wikipedia:
In the Euclidean plane, if p = (p1, p2) and q = (q1, q2) then the distance is given by:

Assuming you are using the Cartesian coordinate system, your two coordinates must both be of length n, where n can be any non-zero positive integer. So if the two points in question, p and q, each had 3 values:

p = (p1, p2, p3), q = (q1, q2, q3)

Then n would equal 3, and the distance formula would be:



The hardest part for me, when putting this all together, was figuring out, for each scripting language, how to iterate over, i.e., step through, the respective elements of both coordinates, simultaneously:

Perl 5 (5.12.2):
use List::Util qw(sum);
use List::MoreUtils qw{ any pairwise };

sub get_distance_between
{
if (scalar(@_) != 2)
{
die "You must supply 2, and only 2, coordinates, no more, no less. Stopped";
}

my $a_ref = shift;
my $b_ref = shift;

if (@$a_ref != @$b_ref)
{
die "Coordinates do not have the same number of elements, stopped";
}
else
{
@x = pairwise { ($a - $b)**2 } @a, @b;
return sqrt(sum(@x));
}
}

# Usage:
@a = (1008, 2243, 976), @b = (1005, 2249, 974);
$ad = get_distance_between(\@a, \@b);
print "\$ad == $ad";

PHP 5.3.6:
function subtract_and_square($n, $m)
{
return(pow($n - $m, 2));
}

function find_distance_between($p, $q)
{
$numargs = func_num_args();
if ($numargs != 2)
{
die("You must supply 2, and only 2, coordinates, no more, no less.\n");
}
else if (sizeof($p) != sizeof($q))
{
die("Coordinates do not have the same number of elements.\n");
}
else
{
$c = array_map("subtract_and_square", $p, $q);
return pow(array_sum($c), .5);
}
}

Python 2 (2.5.4):
def get_distance_between(p, q):
if len(p) != len(q):
raise Exception
else:
sum = 0
for pval, qval in zip(p, q):
sum += (pval - qval)**2
return sum**(.5)

R (2.12.1):
get_distance_between = function(p, q)
{
if (length(p) != length(q))
{
stop("\nCoordinates do not have the same number of elements.")
}
else
{
element_products = mapply(function(a,b) (a - b)**2, p, q)
sqrt(sum(element_products))
}
}

Ruby 1.9.2:
require 'generator'

def get_distance_between(p, q)
if p.length != q.length
raise Exception
else
sum = 0
syen = SyncEnumerator.new(p, q)
for pval, qval in syen
sum += (pval - qval)**2
end
end
return Math.sqrt(sum)
end

In the Perl example, thanks to Miller Hall and Jon Bjornstad for their review and suggestions on how to improve my Perl code to make it more readable.
In the R example, thanks to Spencer Graves and Nicholas Lewin-Koh for pointing me to mapply and plyr (which I did not have time to research and use).

Update: On October 31, 2011, my friend Nikita Borisov, assistant professor in Computer Science, offered the following suggestion on facebook re the R and Python code:
This person clearly hasn't used these languages very much. In R, you can say sqrt(sum((p-q)**2)). Similarly, in Python you can write sqrt(sum([(x-y)**2 for (x,y) in zip(p,q)]))
Thanks, Nikita!

Monday, March 21, 2011

The 3 Most Important Things a Programmer Must Know

Write code, run code, fix code is essentially what a programmer does, said the speaker at an intriguing talk I recently attended, hosted by the Perl Mongers group. Zed Shaw is the author of Learning Python the Hard Way and in review, I have to agree with this user-generated comment:
Very knowledgeable not just with Python, but he has a deep understanding of programming. He inspired me to be a better thinker and programmer.
I was interested in this talk because Zed Shaw made a name for himself by coding the Mongrel web server, as well as Mongrel2, both of which were and are integral parts of Ruby on Rails. I looked forward to the rather unique confluence of a core Ruby on Rails programmer giving a talk about Python at a Perl meetup. I had a prior discussion with a female attendee at a Ruby on Rails Workshop for Women on why religious wars in technology were so prevalent; some people get worked-up over a particular choice of scripting language (Perl vs Python vs Ruby) or text editor, and soon flame wars ensue on the internet about which technology is best. Rodney King asked us after the Los Angeles riots, and Zed is living proof that we can all get along, at least when it comes to scripting languages.

Zed took a year off to learn jazz guitar. He realized, when learning music, you have the concept of a trainer, who tells you to play individual chords multiple times until you get better at it. Then the trainer tells you to play another chord, and then play a song in both chords, in a progression, until you have some experience under your belt. Whenever you want to learn something difficult, it's hard to explain the ideas unless you have some experience under your belt. Using this same principle, Zed decided to introduce the beginner to simple coding exercises, until you get better at writing computer programs, and then he slowly introduces the concepts to you.

The fact that Zed was able to use an analogy from music learning in explaining hard-to-grasp concepts in computer programming makes his experience valuable and his book a must-read for me. Zed strikes me as hard-working, dedicated to his craft, and he knows something about how to get beginner programmers engaged in a new, complex, but rewarding venture. One last thing he said that really hit home for me: Zed recommends learning parsing and lexing, the two most important things, other than algorithms, that a programmer must know. Right now, Zed is doing C and Lua, and he mentioned software called Corona that enables the Lua programmer to write iPhone games.