#
# $Id: Factor.pm,v 0.01 2004/01/06 12:19:58 sts Exp $

package Math::Factor;

our $VERSION = '0.01';

use integer;
use strict;
use warnings;

use Exporter;
use base qw(Exporter);

our (@EXPORT_OK, %EXPORT_TAGS, @subs_factor, @subs_match, @subs);

@subs_factor = qw(factor show_factor);
@subs_match = qw(match show_match);
@subs = (@subs_factor, @subs_match);

@EXPORT_OK = @subs;
%EXPORT_TAGS = (  all     =>    [ @subs ],
                  factor  =>    [ @subs_factor ],
                  match   =>    [ @subs_match ],
);

sub croak {
    require Carp;
    &Carp::croak;
}

=head1 NAME

Math::Factor - factorises integers and calculates matching multiplications.

=head1 SYNOPSIS

    use Math::Factor q/:all/;

=head1 DESCRIPTION

C<Math::Factor> factorises integers and calculates matching multiplications.

=head1 FUNCTIONS

=head2 factor

=cut

#
# factor (\@numbers)
#
# Number factorisation.
#

sub factor {
    my $number_ref = $_[0];
    croak q~usage: factor (\@numbers)~
      unless ref $number_ref eq 'ARRAY' && @$number_ref;

    my %factor;
    foreach (@$number_ref) {
        for (my $i = 1; $i <= $_; $i++) {
            if ($_ % $i == 0)  {
                push @{$factor{$_}}, $i;
            }
        }
    }

    return %factor;
}

=head2 match

=cut

#
# match (\%factors)
#
# Evaluates matching multiplications.
#

sub match {
    my $number_ref = $_[0];
    croak q~usage: match (\%factors)~
      unless ref $number_ref eq 'HASH' && %$number_ref;

    my ($i, %match);
    foreach (keys %$number_ref) {
        $i = 0;
        my @cmp = my @base = @{$$number_ref{$_}};
        foreach my $base (@base) {
            foreach my $cmp (@cmp) {
                if ($cmp >= $base) {
                    if ($base * $cmp == $_) {
                        $match{$_}[$i][0] = $base;
                        $match{$_}[$i][1] = $cmp;
                        $i++;
                    }
                }
            }
        }
    }

    return %match;
}

=head2 show_factor

=cut

#
# show_factor (\%factors)
#
# Outputs factors.
#

sub show_factor {
    my $number_ref = $_[0];
    croak q~usage: show_factors (\%factors)~
      unless ref $number_ref eq 'HASH' && %$number_ref;

    print <<'EOT';
-------
FACTORS
-------

EOT
    local $" = "\t";
    foreach (sort {$a <=> $b} keys %$number_ref) {
        my $ul = '-' x length;
        print <<"EOT";
$_
$ul
@{$$number_ref{$_}}


EOT
    }
}

=head2 show_match

=cut

#
# show_match (\%match)
#
# Outputs matching multplications.
#

sub show_match {
    my $number_ref = $_[0];
    croak q~usage: show_match (\%match)~
      unless ref $number_ref eq 'HASH' && %$number_ref;

    print <<'EOT';
-------
MATCHES
-------

EOT
    foreach (sort {$a <=> $b} keys %$number_ref) {
        my $ul = '-' x length;
        print <<"EOT";
$_
$ul
EOT
    for (my $i = 0; $$number_ref{$_}[$i]; $i++) {
        print "$$number_ref{$_}[$i][0] * $$number_ref{$_}[$i][1]\n";
    }
    print <<'EOT';


EOT
    }
}

1;
__END__

=head2 EXPORT

C<factor(), match(), show_factor(), show_match()> upon request.

=head2 TAGS

C<:all - *()>

C<:factor - factor(), show_factor()>

C<:match - match(), show_match()>

=head1 SEE ALSO

perl(1)

=head1 LICENSE

This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself.

=head1 AUTHOR

Steven Schubiger

=cut
