[sf-perl] Farmer Puzzle

Shlomi Fish shlomif at shlomifish.org
Wed Aug 26 05:05:03 PDT 2026


hi David.


On Wed, 26 Aug 2026 00:50:28 -0700
David Christensen <dpchrist at holgerdanske.com> wrote:

> On 8/25/26 22:41, Shlomi Fish wrote:
> > Hi David,  
> 
> 
> Hi, Shlomi.  Thank you for your insights.
> 

you are welcome.

> 
> > "my $a" and "my $b" are discouraged:
> > https://perl-begin.org/tutorials/bad-elements/#vars-a-and-b  
> 
> 
> Thank you for the warning.  It has been a while since I fell into that 
> trap.  Avoiding lexical $a and $b sounds like a good habit.
> 
> 
> Is there a way for an inner scope/block to undeclare/forget lexical 
> variables declared in an enclosing scope/block?
> 

I suggest avoiding using this feature , if it existed.

> 
> > On a different note: why aren't you working fully with integers? Products of
> > cents or 50 cents.  
> 
> 
> The program uses floating point numbers because the problem statement 
> gave animal prices in dollars.
> 
> 
> Adding "use integer" and doing the monetary math in cents both improves 
> performance and prevents floating point representation errors:
> 
> 2026-08-26 00:36:26 dpchrist at laalaa ~/sandbox/perl/farmer-puzzle
> $ expand dpchrist-integer-benchmark
> #!/usr/bin/env perl
> # $Id: dpchrist-integer-benchmark,v 1.2 2026/08/26 07:32:32 dpchrist Exp $
> #
> # A farmer goes to the fair.  Cows cost $10.00 each, pigs cost $3.00
> # each, and sheep cost $0.50 each.  If the farmer wants to buy
> # at least one cow, at least one pig, at least one sheep, and exactly
> # 100 animals total, and wants to spend exactly $100.00, how many cows,
> # pigs, and sheep should the farmer buy?  Find all solutions.
> #
> # Perl program by David Paul Christensen <dpchrist at holgerdanske.com>
> #
> # Public Domain
> 
> use strict;
> use warnings;
> 
> use integer;
> 
> use constant animals            => 100;
> 
> use constant cow_cost           =>  1000;
> use constant pig_cost           =>   300;
> use constant sheep_cost         =>    50;
> use constant budget             => 10000;
> 
> sub buy_fair_animals
> {
>      my @r;
>      my $max_cows = (budget - pig_cost - sheep_cost)/cow_cost;
>      foreach my $c (1 .. $max_cows) {
>          my $max_pigs = (budget - $c * cow_cost - sheep_cost)
>                         / pig_cost;
>          foreach my $p (1 .. $max_pigs) {
>              my $s = (budget - $c * cow_cost - $p * pig_cost)
>                      / sheep_cost;
>              my $total_animals = $c + $p + $s;
>              last if $total_animals  > animals;
>              next if $total_animals != animals;
>              my $total_cost = $c * cow_cost
>                               + $p * pig_cost
>                               + $s * sheep_cost;
>              last if $total_cost  > budget;
>              next if $total_cost != budget;
>              push @r, [$c, $p, $s];
>          }
>      }
>      return @r;
> }
> 
> my $n = @ARGV ? shift : 100_000;
> buy_fair_animals() for 1 .. $n - 1;
> 
> my @r = buy_fair_animals();
> foreach (@r) {
>      my ($c, $p, $s) = @$_;
>      my $total_animals = $c + $p + $s;
>      my $total_cost = ($c * cow_cost + $p * pig_cost + $s * sheep_cost)
>                       / 100;
>      print "cows $c pigs $p sheep $s " .
>             "animals $total_animals cost $total_cost\n";
> }
> 
> 2026-08-26 00:36:34 dpchrist at laalaa ~/sandbox/perl/farmer-puzzle
> $ time perl dpchrist-integer-benchmark
> cows 5 pigs 1 sheep 94 animals 100 cost 100
> 
> real	0m0.957s
> user	0m0.953s
> sys	0m0.004s
> 
> 2026-08-26 00:36:42 dpchrist at laalaa ~/sandbox/perl/farmer-puzzle
> $ time perl dpchrist-integer-benchmark
> cows 5 pigs 1 sheep 94 animals 100 cost 100
> 
> real	0m0.941s
> user	0m0.937s
> sys	0m0.004s
> 
> 2026-08-26 00:36:43 dpchrist at laalaa ~/sandbox/perl/farmer-puzzle
> $ time perl dpchrist-integer-benchmark
> cows 5 pigs 1 sheep 94 animals 100 cost 100
> 
> real	0m0.978s
> user	0m0.974s
> sys	0m0.004s
> 
> 
> But, integer variables impose a cost upon the programmer --I must 
> understand the minutia of every calculation to keep the term and 
> expression values within the range of integers.
> 
> 
> Unfortunately, "use bigint" is not a good solution -- 100_000/200 = 500 
> times slower:
> 
> 2026-08-26 00:42:58 dpchrist at laalaa ~/sandbox/perl/farmer-puzzle
> $ time perl dpchrist-bigint-benchmark 200
> cows 5 pigs 1 sheep 94 animals 100 cost 100
> 
> real	0m0.948s
> user	0m0.947s
> sys	0m0.001s
> 
> 2026-08-26 00:43:02 dpchrist at laalaa ~/sandbox/perl/farmer-puzzle
> $ time perl dpchrist-bigint-benchmark 200
> cows 5 pigs 1 sheep 94 animals 100 cost 100
> 
> real	0m0.969s
> user	0m0.960s
> sys	0m0.009s
> 
> 2026-08-26 00:43:06 dpchrist at laalaa ~/sandbox/perl/farmer-puzzle
> $ time perl dpchrist-bigint-benchmark 200
> cows 5 pigs 1 sheep 94 animals 100 cost 100
> 
> real	0m0.974s
> user	0m0.970s
> sys	0m0.005s
>

I see. 128bits integer might help here: 

https://www.nu42.com/2016/01/excellent-optimization-story.html

[via perl weekly]
 
> 
> David
> 



-- 

Shlomi Fish       https://www.shlomifish.org/
https://shlomifishswiki.branchable.com/Encourage_criticism_and_try_to_get_offended/

Programming today is a race between software engineers striving to build
bigger and better idiot-proof programs, and the universe trying to produce
bigger and better idiots. So far, the universe is winning.
    — https://en.wikiquote.org/wiki/Rick_Cook  (via Oron Peled)

Please reply to list if it's a mailing list post - https://shlom.in/reply .


More information about the SanFrancisco-pm mailing list