[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