Skip to content

Instantly share code, notes, and snippets.

@jgamble
Last active June 27, 2016 04:15
Show Gist options
  • Select an option

  • Save jgamble/c7b6d31ce633a4669a7c12264b504dc0 to your computer and use it in GitHub Desktop.

Select an option

Save jgamble/c7b6d31ce633a4669a7c12264b504dc0 to your computer and use it in GitHub Desktop.
Find the distance between two points on a hexagonal grid. Problem defined by Pete Stewart in 2002, solved by Tom Ruschak and Tanya Gilham.
#
# For calculating the diagonal distance, it is important to
# know which columns are shifted up (see the diagram below in
# the hexagon_distance() function).
#
# For the purposes of this code snippet we have a simple
# function that defines the odd-numbered columns as 'up'.
#
sub upcolumn
{
my $col = shift;
return ($col & 1);
}
#
# This is like the Manhattan Distance formula (found in Chapter 10 of
# Mastering Algorithms With Perl, by Orwant, Hietaniemi & Macdonald)
# but with an adjustment for the diagonal short cuts of the hexagonal
# movement.
#
# hexagonal mesh square grid with 'hexagonal drift'
#
# 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
# __ __ __ __ ___ ___ ___ ___
# 1 / \__/ \__/ \__/ \__ | |___| |___| |___| |___
# \__/ \__/ \__/ \__/ \ |___| |___| |___| |___| |
# 2 / \__/ \__/- \__/ \__/ | |___| |___|- |___| |___|
# \__/ \__/- \__/ \__/ \ |___| |___|- |___| |___| |
# 3 / \__/- \__/ \__/ \__/ | |___|- |___| |___| |___|
# \__/S \__/ \__/ \__/ \ |___|S |___| |___| |___| |
# 4 / \__/+ \__/ \__/ \__/ | |___|+ |___| |___| |___|
# \__/ \__/+ \__/ \__/ \ |___| |___|+ |___| |___| |
# 5 / \__/ \__/+ \__/ \__/ | |___| |___|+ |___| |___|
# \__/ \__/ \__/ \__/ \ |___| |___| |___| |___| |
# \__/ \__/ \__/ \__/ |___| |___| |___| |___|
#
# 1 2 3 4 5 6 7 8
# _______________________________
# 1 | | | | | | | | | The diagonal moves only occur
# |___|___|___|___|___|___|___|___| when moving from an up column
# 2 | | | |- |- | | | | to a down column in a NorthEast-
# |___|___|___|___|___|___|___|___| SouthWest slope, or when moving
# 3 | |S |- | | | | | | from a down column to an up
# |___|___|___|___|___|___|___|___| column in a SouthEast-NorthWest
# 4 | | |+ |+ | | | | | slope.
# |___|___|___|___|___|___|___|___|
# 5 | | | | |+ | | | |
# |___|___|___|___|___|___|___|___|
#
sub hexagon_distance
{
my($x0, $y0, $x1, $y1) = @_;
#
# Find the pre-adjusted Manhattan distance.
#
my $dx = abs($x1 - $x0);
my $dy = abs($y1 - $y0);
my $diag = 0;
#
# Count how many diagonal moves we made.
#
if (upcolumn($x0))
{
$diag = ( $y1 < $y0 )? int(($dx + 1)/2): int($dx/2 );
}
else
{
$diag = ( $y1 < $y0 )? int($dx/2): int(($dx + 1)/2);
}
return $dx + $dy - $diag if ($dy > $diag);
return $dx;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment