Monday, 25 February 2008

scales balancing puzzle check weights40.pl

see perl script weight40.pl


#!/usr/bin/perl

=head1 NAME

weights40.pl - check you can make each weight from 1 to 40 balance

=head1 DESCRIPTION

This doesn't solve the puzzle but does prove that the solution works.

The puzzle is you have a balance (bilancia in Italian).
And you can choose some unit weights to help weigh things.
If you get any unit weight from 1 to 40 you need to be able to determine the weight.
(You have to make the scales balance, you're not allowed to measure
it as lighter than w+1 and heavier than w-1 hence is w.)
What is the minimum number of weights you can do this in ?

If the puzzle is told properly then you probably have to bring the
balance and weights up a big mountain with dragons on top so you wish to use the absolute minimum
number of weights (or possibly minimum weight of weights - is it the same answer I wonder?)

=cut

my @weights = ( 1, 3, 9, 27 );

for(my $w=-1; $w<=41; $w++) {

# brute force, try balance all permutations, weights on both sizes

# try position of not there, left, right for each weight
my @weight_pos = ( 0, 0, 0, 0 );
my $wi = 0;

# print terrible message if not found otherwise might miss one
my $terribleness = "BAH! :( not good, no match for $w\n";
my $found = 0;

for($weight_pos[0]=0; $weight_pos[0]<3 && $found==0; $weight_pos[0]++) {
for($weight_pos[1]=0; $weight_pos[1]<3 && $found==0; $weight_pos[1]++) {
for($weight_pos[2]=0; $weight_pos[2]<3 && $found==0; $weight_pos[2]++) {
for($weight_pos[3]=0; $weight_pos[3]<3 && $found==0; $weight_pos[3]++) {

# start with $w always on left
my $left_tot = $w;
my $right_tot = 0;
my @leftside = ( $w );
my @rightside = ();

# print '$#weights is ' . $#weights . " (number of elements in weights array)\n";

# put weights on balance
for($wi=0;$wi<=$#weights;$wi++) {

#print "dbg w=$w wi=$wi pos=$weight_pos[$wi]\n";

if ($weight_pos[$wi] == 1) {
#printf "L";
push @leftside, $weights[$wi];
$left_tot += $weights[$wi];
} elsif ($weight_pos[$wi] == 2) {
#printf "R";
push @rightside, $weights[$wi];
$right_tot += $weights[$wi];
}
#$ls += "(".$weights[$wi].) ";
#$rs += "(".$weights[$wi].) ";
}


#print "dbg w: $w, balance $left_tot = $right_tot, left: @leftside - right: @rightside\n";

if ($left_tot == $right_tot) {
print "w: $w, balance $left_tot = $right_tot, left: @leftside - right: @rightside\n";
$terribleness = "";
$found = 1;
break;
}

}
}
}
}

print $terribleness;
}



perldoc is a good reference, (command-line interface to perl docs)
not on all machines but is on slaine
same stuff as is on web in lots of places of course:
http://perldoc.perl.org/perl.html

e.g. perldoc perl, perldoc perldoc (for table of contents)
perldoc perlsyn
perldoc perlre

-f or -q to get function documentation or search faq:

perldoc -f printf
perldoc -q while

After you know all that perldoc then you can start thinking about using perl modules! :D


To read perl documentation _inside_ perl scripts or modules just do e.g.:

perldoc weight40.pl

No comments: