rendered paste body#!perl -w
use strict;
my $INITIAL_SEED_COUNT = 100;
my ($T_SEED, $T_SEEDLING, $T_MATURE) = (0, 1, 2);
my $PCT_GERMINATE = .04;
my $PCT_MATURE = .25;
my $SEEDS_PRODUCED = 1000;
my $MAX_SEED_AGE = 8;
my $MAX_PLANT_AGE = 5;
my $END_YEAR = 10;
my $population =
{
'seeds' => InitArray($INITIAL_SEED_COUNT, $MAX_SEED_AGE),
'germinated' => InitArray(0, $MAX_PLANT_AGE),
'mature' => InitArray(0, $MAX_PLANT_AGE)
};
for (my $year = 0; $year < $END_YEAR; ++$year)
{
GrowPopulation($population);
print "At the end of year $year:\n";
PrintPopulation($population);
}
sub PrintPopulation
{
PrintAge($population->{'seeds'}, 'Seeds');
print "\n";
PrintAge($population->{'germinated'}, 'Germinated');
print "\n";
PrintAge($population->{'mature'}, 'Mature');
print '-' x 40 . "\n";
}
sub PrintAge
{
my $array = shift;
my $heading = shift;
print "$heading\n";
for my $i (0 .. $#{$array})
{
my $amt = $array->[$i];
print "Age $i:" . ' ' x (12 - length($amt)) . "$amt\n";
}
print 'Total: ' . Sum($array) . "\n";
}
sub GrowPopulation
{
my $population = shift;
# everyone ages, dead items are removed
UpdateAge($population->{'seeds'});
UpdateAge($population->{'germinated'});
UpdateAge($population->{'mature'});
# things that sprout/produce do so
my $newSeeds = ProduceSeeds($population->{'mature'}, $SEEDS_PRODUCED);
my $newSprouts = Grow($population->{'seeds'}, InitArray(0, $MAX_PLANT_AGE), $PCT_GERMINATE, 1);
my $newPlants = Grow($population->{'germinated'}, InitArray(0, $MAX_PLANT_AGE), $PCT_MATURE, 0);
# add newly grown things to their proper age positions
$population->{'seeds'}->[0] += $newSeeds;
Combine($population->{'germinated'}, $newSprouts);
Combine($population->{'mature'}, $newPlants);
}
sub ProduceSeeds
{
my $mature = shift;
my $toProduce = shift;
return Sum($mature) * $toProduce;
}
sub Grow
{
my $items = shift;
my $grown = shift;
my $pctToGrow = shift;
my $resetAge = shift;
my $total = Sum($items);
my $numToGrow = int($total * $pctToGrow);
for my $i (0 .. $#{$items})
{
if ($items->[$i] < $numToGrow)
{
$grown->[$resetAge ? 0 : $i] = $items->[$i];
$items->[$i] = 0;
$numToGrow -= $items->[$i];
}
else
{
$grown->[$resetAge ? 0 : $i] = $numToGrow;
$items->[$i] -= $numToGrow;
last;
}
}
return $grown;
}
sub Sum
{
my $array = shift;
my $sum = 0;
for my $x (@$array)
{
$sum += $x;
}
return $sum;
}
sub Combine
{
my $destination = shift;
my $other = shift;
for my $i (0 .. $#{$destination})
{
$destination->[$i] += $other->[$i];
}
}
sub UpdateAge
{
my $array = shift;
# everyone ages (shifts over 1 'aging column' to the right)
unshift(@$array, 0);
# these ones died
pop(@$array);
}
sub InitArray
{
my $init = shift;
my $length = shift;
my $array = [ $init ];
for my $i (1 .. $length - 1)
{
$array->[$i] = 0;
}
return $array;
}