#!/usr/bin/perl -w
##################
# oct9.pl
# 
# In class example of a perl program with good form:
# header comments, implementation comments, tests,
# and POD - plain old documentation, data structures, ..
#
# Oh yeah, the program actually looks for "perfect" numbers like these:
# 
#   6 has factors 1,2,3       and is 1+2+3.
#  28 has factors 1,2,4,7,14  and is 1+2+4+7+14
# 
# See the POD at the end of the file for more details.
#
# To do:
#   - tests for find_factors; 
#   - finish implementing find_factors odd cases like 1 and 0 correctly.
#   - tests for is_perfect
#   - implement is_perfect
#   - define sub for appending data to $perfect
#   - flesh out the main loop
#   - decide what to print out
#
##################################################
use strict;

# == file "global" variables ==============================

# For each perfect number found, 
# I'm going to remember the number and the list of factors here, eg
# $perfect[$n] = { number => $n, factors => [ $f1, $f2, $f3, ... ] };
my $perfects = ();

# == main =================================================

run_tests();
exit;

# (only pseudo code in "main" right now...)

# Loop over possible perfect numbers.

#   If number $n is perfect,
#   append $n and its @factors to $perfect data structure.

# Print out some kind of summary report.

# Let the user ask about a given integer, 
# and give some information about it.

# == subs =================================================

#-----------------------------
# ... add comments here ...
sub is_perfect {
}

# ------------------------------------------------------
# Return a list of factors of a given integer $n,
# not including 1 or $n.
# Usage: @list = find_factors($n);
sub find_factors {
  my ($n) = @_;
  my $factor = 2;            # first possible factor to test.
  my $last = int(sqrt($n));  # don't need to look higher than this.
  my @answer = ();
  while (1){
    return @answer         if ($factor > $last);
    push @answer, $factor  if is_factor($factor, $n);
  }
}

# --------------------------------------------------------
# Return true if $factor is a factor of number, else false.
# Usage: if (is_factor($factor,$number)){ ... }
sub is_factor {
  my ($factor, $number) = @_;
  return 0 if $factor == 0;
  if ( $number % $factor == 0 ){
    return 1;
  }
  else {
    return 0;
  }
}


# ---------------------------------
# Tests... Tests for sale... Get your tests here...
# (It's particularly good to put weird cases here.)
sub run_tests {

  ok( is_factor(2,10));
  ok( ! is_factor(2,7));
  ok( is_factor(12.0, 144)       ,  "is_factor(12.0,144) is true" );
  ok( ! is_factor(0,1)           ,  "is_factor(0,1) is false (no 0 divide)" );
  ok( is_factor(1,0)             ,  "is_factor(1,0) is true");
  ok( ! is_factor(4,2)           ,  "is_factor(4,2) is false : 4's bigger");

  ok( find_factors(0) == ()      ,  "0 has no factors");
  ok( find_factors(0) == ()      ,  "0 has no factors");
  
}

# -----------------------------------------------------------
# Print "ok" or "not ok" for each test,
# where each test is an expression which should evaluat to true.
# Second argument is an optional comment describing the test.
# Usage: ok( 1 == is_prime(7), "is_prime(7) is true" );
our $test_number;    # initialized to 1 on first test.
sub ok {
  my ($boolean, $comment) = @_;

  # -- debugging --
  # print "    boolean = '$boolean' \n";
  # print "    comment = '$boolean' \n";

  $test_number = 0 unless defined $test_number;
  $test_number++;
  if ($boolean) {
    print "ok ";
  }
  else {
    print "not ok ";
  }
  print $test_number;
  if ($comment){
    print " "x10, $comment;
  }
  print "\n";
}


__END__

=head1 NAME

  oct9.pl

=head1 SYNOPSIS

  From the command line,
  $ ./oct9.pl

=head1 DESCRIPTION

This is where you should describe what your program
does when it runs - in other words, what a user
needs to know.  What inputs does it take?  What output
does it produce?  And so on.

First let's talk about POD - plain old documentation.
See <a href="http://perldoc.com/perl5.8.0/pod/perlpod.html">perdoc.com on perlpod</a> for more details.

To create the .html file with the documentation, you 
type "pod2html filename.pl > filename.html" at the 
command line.

Here's a bullet list.

=over

=item One

So here's item one.

=item Two

And here's item two.

=back

=head2 Text formatting.

You can also put I<italic> or B<bold> stuff in.

And this is a "head2" section.

 indenting stuff
   keeps the white space
      as you . . . type it.


=head1 HISTORY

 * version 0.1 before class on Oct 9.

=head1 SEE ALSO

The class notes are accessible through
the  http://cs.marlboro.edu/ website.

=head1 AUTHOR

Jim Mahoney, E<lt>mahoney@marlboro.eduE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright 2003 by Jim Mahoney

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

=cut
