Python Translator Hole ExampleMoved from PythonTranslator
In Perl:
package hole;
use strict;
use Exporter;
use vars qw ($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT = ();
@EXPORT_OK = qw( &new );
%EXPORT_TAGS = ( DEFAULT => [qw ( &new )] );
#
# new - hole constructor
# peg ) By convention, contains a fill color
# black implies there is a peg in the hole and
# white impleis there is no peg in the hole.
#
# index) holes must be indexed 0 through 14
#
# links) is a ref to an array of adjacent holes.
# This isn't typical passed to the new constructor.
# It is easier to call setLinks ( see below )
#
sub new {
my ($pkg, $peg, $index, $level, $links ) = @_;
my $obj = bless {
peg => $peg,
holeIndex => $index,
level => $level,
links => $links # ref to array of holes
}, $pkg;
return $obj;
}
#
# takes a ref to an array of adjacent holes
# and sets this hole's links attribute
#
sub setLinks {
my $obj = shift;
my $links = shift;
$obj->{'links'} = $links;
}
#
# takes a fill color of the peg.
# black => has peg
# white => does not have peg
#
sub setPeg {
my $obj = shift;
my $peg = shift;
$obj->{'peg'} = $peg;
}
#
# returns the links attribute
#
sub getLinks {
my $obj = shift;
return $obj->{'links'};
}
#
# returns the peg attribute
#
sub getPeg {
my $obj = shift;
return $obj->{'peg'};
}
#
# jumpingOver determines if another peg from the hole
# having index of $jumperIndex is allowed to jump the
# peg in this hole.
#
sub jumpingOver {
my $obj = shift;
my $jumperIndex = shift;
#
# You have no peg to jump with
#
if ( $obj->{'peg'} eq 'white' ) { return -1; }
#
# You can't jump yourself
#
if ( $jumperIndex == $obj->{'holeIndex'} ) { return -1; }
#
# find jumper in links array
#
my $jumper = $obj->getHoleWithIndex ( $jumperIndex );
if ( $jumper ) {
if ( !$jumper->hasPeg() ) { return -1; }
my $objIndex = $obj->{'holeIndex'};
my $jumperLevel = $jumper->{'level'};
my $objLevel = $obj->{'level'};
my $levelDiff = abs($objLevel - $jumperLevel);
my $targetIndex = 2 * $objIndex + $levelDiff - $jumperIndex;
my $targetHole = $obj->getHoleWithIndex( $targetIndex );
if ( $targetHole ) {
#
# we can jump to hole with index of $targetIndex
#
return $targetIndex if $targetHole->{'peg'} eq 'white';
#
# we can jump because there is a peg is blocking
#
return -1;
} else {
#
# no hole
#
return -1;
}
} else {
#
# The jumper is not adjacent to this hole
#
return -1;
}
#
# we should NOT get here.
#
return -1;
}
#
# If peg is black then there is a peg there
#
sub hasPeg {
my $obj = shift;
return ( $obj->{'peg'} eq 'black' );
}
#
# return the hole that has index, i
#
sub getHoleWithIndex {
my $obj = shift;
my $i = shift;
foreach my $link ( @{$obj->{'links'}} ) {
if ( $link->{'holeIndex'} == $i ) {
return $link;
}
}
return undef;
}
1;
Direct Python Translation:
class Hole: # # _init_ - hole constructor # peg ) By convention, contains a fill color # black implies there is a peg in the hole and # white impleis there is no peg in the hole. # #index) holes must be indexed 0 through 14 # #links) is a ref to an array of adjacent holes. # This isn't typical passed to the new constructor. # It is easier to call setLinks ( see below ) # def __init__ ( self, peg, index, level, links ): self.peg= peg self.holeIndex= index self.level= level self.links= links # ref to array of holes # # takes a ref to an array of adjacent holes # and sets this hole's links attribute # def setLinks ( self, links ): self.links = links # # takes a fill color of the peg. # black => has peg # white => does not have peg # def setPeg ( self, peg ): self.peg = peg # # returns the links attribute # def getLinks (self): return self.links # # returns the peg attribute # def getPeg (self): return self.peg # # jumpingOver determines if another peg from the hole # having index of jumperIndex is allowed to jump the # peg in this hole. # def jumpingOver ( self, jumperIndex ): # # You have no peg to jump with # if self.peg == 'white': return -1 # # You can't jump yourself # if jumperIndex == self.holeIndex: return -1 # # find jumper in links array # jumper = self.getHoleWithIndex ( jumperIndex ) if jumper: # # you have to use a peg to jump # if not jumper.hasPeg(): return -1 objIndex = self.holeIndex jumperLevel = jumper.level objLevel = self.level levelDiff = abs(objLevel - jumperLevel) targetIndex = 2 * objIndex + levelDiff - jumperIndex targetHole = self.getHoleWithIndex( targetIndex ) if targetHole: # # we can jump to hole with index of targetIndex # if targetHole.peg == 'white': return targetIndex # # we can't jump because there is a # peg is blocking # return -1 else: # # no hole # return -1 else: # # The jumper is not adjacent to this hole # return -1 # # we should NOT get here. # return -1 # # If peg is black then there is a peg there # def hasPeg (self): return self.peg == 'black' # # return the hole that has index, i # def getHoleWithIndex (self, i): for link in self.links: if link.holeIndex == i: return link return NULL # # print out the hole object # def dump (self): print "Hole:\n\tpeg => [" + self.peg + "]" for l in self.links: print "\tlink => [" + l.peg + "]" print "\tlevel => [" + str(self.level) + "]"
Be aware that the preious translation is _really_ not idiomatic:
class Hole(object):
def __init__(self, has_peg, index, level, links):
'''
_init_ - hole constructor
has_peg ) Flag set to True if hole contains a peg or False if not
index) holes must be indexed 0 through 14
links) is a ref to an array of adjacent holes.
This isn't typical passed to the new constructor.
It is easier to just set the links directly
'''
self.has_peg = has_peg
assert 0 <= index <= 14
self.index = index
self.level = level
self.links = links # ref to array of holes
def jumping_over(self, jumper_index):
'''
Determines if another peg from the hole having index of jumper_index
is allowed to jump the peg in this hole.
'''
try:
assert self.has_peg # Must have a peg to jump
assert jumper_index != self.index # You can't jump yourself
# find jumper in adjacent links array
jumper = self.get_hole_with_index(jumper_index)
assert jumper # There must be a hole to jump from
assert jumper.has_peg # it must contain a peg
# find target in adjacent links array
level_diff = abs(self.level - jumper.level)
target_index = 2 * self.index - jumper.index + level_diff
target_hole = self.get_hole_with_index(target_index)
assert target_hole # There must be a hole to jump to
assert not target_hole.has_peg # it mustn't contain a peg
except AssertionError?:
return -1 # retained for compatibility
return target_index # All tests passed
def get_hole_with_index(self, i):
'''
Returns the hole that has index equal to i
'''
for link in self.links:
if link.holeIndex == i:
return link
return None
def __str__(self):
'''
Allows "print <hole>"
'''
out = ["Hole %s:"%self.index,
"\thas_peg => [%s]"%self.has_peg]
out.extend(["\tlink => [%s]"%l.peg for l in self.links])
out.append("\tlevel => [%s]"% self.level)
return "\n".join(out)
Of course this still isn't fully idiomatic - links should be a dictionary, with its keys as each hole's index. This makes lookup trivial (though even this version still doesn't feel fully idiomatic ;-):
class Hole(object):
def __init__(self, has_peg, index, level, links):
'''
Constructor for hole instances
has_peg: Flag set to True if hole contains a peg or False if not
index: holes must be indexed 0 through 14
links: This is a property, allowing self._links to be accessed as:
self.links # call self._get_links()
self.links = [h1, h2, h3] # call self._set_links([h1, h2, h3])
_links: This is a dictionary (associative array/mapping) with
key equal to hole.index, and value equal to a ref to the hole.
'''
self.has_peg = has_peg
assert 0 <= index <= 14
self.index = index
self.level = level
self._links = {}
self.links = links
def _set_links(self, links):
'''
Accessor function for links property()
'''
for link in links:
self._links[link.index] = link
def _get_links(self):
'''
Accessor function for links property()
'''
return self._links
links = property(_get_links, _set_links)
def jumping_over(self, jumper_index):
'''
Determines if another peg from the hole having index of jumper_index
is allowed to jump the peg in this hole.
'''
try:
assert self.has_peg # Must have a peg to jump
assert jumper_index != self.index # Can't jump yourself
# find jumper in links dict. Raises KeyError? if not found
jumper = self.links[jumper_index]
assert jumper.has_peg # hole must contain a peg
level_diff = abs(self.level - jumper.level)
target_index = 2 * self.index - jumper.index + level_diff
# find target in links dict. Raises KeyError? if not found
target_hole = self.links[target_index]
assert not target_hole.has_peg # hole mustn't contain a peg
except (AssertionError?, KeyError?):
return -1 # retained for compatibility
return target_index # All tests passed
def __str__(self):
'''
Allows "print <hole>"
'''
out = ["Hole %s:"%self.index,
"\thas_peg => [%s]"%self.has_peg]
out.extend(["\tlink => [%s]"%l.peg for l in self.links.values()])
out.append("\tlevel => [%s]"% self.level)
return "\n".join(out)
EditText of this page
(last edited June 27, 2004)
or FindPage with title or text search