#!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; }