NAME

Math::TotalBuilder -- build a whole total out of valued pieces

SYNOPSIS

use Math::TotalBuilder;

my %lsd = ( pound => 240, shilling => 20, penny => 1 );

# units for 952 pence
my %tender = build(\%lsd, 952);

# total value of 3, 21, 98
my $wealth = total(\%lsd, { pound => 3, shilling => 21, penny => 98 });

# best better representation of 18, 6, 40
my %moolah = build(\%lsd,
  total (\%lsd, { pound => 18, shilling => 6, penny => 40 }));

DESCRIPTION

This module provides two subroutines, build and total, which can be used to handle quantities of valued items. These can be used to build the proper tender to represent a quantity of money, to compose a mass from standard weights, to convert a difference of seconds to a set of time units, or other similar calculations.

Subroutines

build(\%pieces, $total, \@code)
my %nicetime = build (
  { days => 86400, hours => 3600, minutes => 60, seconds => 1 },
  39102
);

This routine takes a hash of valued units and a total, and it returns the quantity of each unit required to build that total. If the total can't be cleanly built, the routine will return a set that builds the nearest total it can, without going over. A special value, _remainder will indicate by how many units it fell short.

This module does not solve the knapsack problem, and hardly tries. It may fail to provide a solution for solveable instances, like this:

my $difficult = build (
  { kroener => 30, talen => 7 },
  49
); 
# yields { kroener => 1, talen => 2, _remainder => 5 }
# not    { talen => 7 }

The third, optional, argument to build must be either a coderef or a reference to an array of coderefs, each of which accept \%pieces and $total as arguments. build will return the result of building a total using the passed sub. If an arrayref of coderefs was passed, build will construct a total using each sub and return the total with the smallest remainder.

If no third option is passed, &build_basic, a very simple-minded algorithm, is assumed.

total(\%pieces, \%set)
my $total = total(
  { ten => 10, five => 5, one => 1 },
  { ten =>  2, five => 6 }
); # returns 50

This routines returns the total value of the units in %set, valued according to the definition in %pieces.

NOTES

This module is hardly ready for use. It needs much more error-handling. The sub names may be changed in the future to avoid conflict, since they're very simple names, but probably not. (If so, the current names will remain exportable.)

TODO

  • Use subrefs for ever-extending pieces. (e.g., "powers of two")

  • Allow building a total from a given set of source units. ("I have this many units to try and build into this total. Can I?")

  • Allow for useful handling of pieces-sets with multiple pieces of the same value: always use one, randomly distribute, etc.

  • Allow use of bigfloats so that the smallest value need not be the base value.

  • Provide an option to try harder to build totals.

AUTHOR

Ricardo SIGNES, <rjbs@cpan.org>

COPYRIGHT

This is free software, and can be distributed under the same terms as perl itself.