# InferWhatever.pm 20oct08waw package InferWhatever; { # begin package closure use warnings; use strict; our $VERSION = '0.1.0'; our @EXPORT = (); our @EXPORT_OK = qw(series); use Exporter; our @ISA = qw(Exporter); sub Iterator (&) { return $_[0] } sub series { return if @_ < 2; my @s = @_; # at least 2 parameters: 1st difference(s) must exist. my @d1 = map $s[$_] - $s[$_-1], 1 .. $#s; # repeat sequence: 3, 3, ... return Iterator { return $s[-1] } if zeros(@d1); # any 2nd difference(s) (at least 3 parameters)? return unless my @d2 = map $d1[$_] - $d1[$_-1], 1 .. $#d1; # arithmetic sequence: 5, 9, 13, ... return Iterator { return $s[-1] += $d1[-1] } if zeros(@d2); # any 3rd difference(s) (at least 4 parameters)? return unless my @d3 = map $d2[$_] - $d2[$_-1], 1 .. $#d2; # quadratic sequence: 1, 4, 9, 16, ... return Iterator { $s[-1] += $d1[-1] += $d2[-1] } if zeros(@d3); return; # that's all for now ######################## # any 4th difference(s) (at least 5 parameters)? return unless my @d4 = map $d3[$_] - $d3[$_-1], 1 .. $#d3; } sub zeros { return unless @_; $_ and return for @_; return 1 } } # end package InferWhatever closure 1; # inclusion success #### # InferWhatever.t 20oct08waw use warnings; use strict; use Test::More 'no_plan', # tests => ??, ; use InferWhatever qw(series); use constant { NO => 0, YES => 1, }; my @tests = ( # for the given the do we expect # sequence, first n, completion? [ [ 1, 1, 1, 1, ], 1, NO, ], [ [ 1, 1, 1, 1, ], 2, YES, ], [ [ 1, 1, 1, 1, ], 3, YES, ], [ [ 0, 0, 0, 0, ], 1, NO, ], [ [ 0, 0, 0, 0, ], 2, YES, ], [ [ 0, 0, 0, 0, ], 3, YES, ], [ [ 9, 9, 9, 9, 9, 9, 9, ], 3, YES, ], [ [ 1, 2, 3, 4, 5, 6, ], 2, NO, ], [ [ 1, 2, 3, 4, 5, 6, ], 3, YES, ], [ [ 13, 11, 9, 7, 5, 3, ], 3, YES, ], [ [ 1, 0, -1, -2, -3, ], 2, NO, ], [ [ 1, 0, -1, -2, -3, ], 3, YES, ], [ [ 1, 4, 9, 16, 25, 36, 49, 64, ], 2, NO, ], [ [ 1, 4, 9, 16, 25, 36, 49, 64, ], 3, NO, ], [ [ 1, 4, 9, 16, 25, 36, 49, 64, ], 4, YES, ], [ [ 64, 49, 36, 25, 16, 9, 4, 1, ], 4, YES, ], [ [ 34, 19, 6, -5, -14, -21, -26, -29, ], 4, YES, ], [ [ 35, 24, 15, 8, 3, 0, ], 4, YES, ], [ [ 81, 100, 121, 144, 169, 196, ], 2, NO, ], [ [ 81, 100, 121, 144, 169, 196, ], 3, NO, ], [ [ 81, 100, 121, 144, 169, 196, ], 4, YES, ], [ [ 196, 169, 144, 121, 100, 81, ], 2, NO, ], [ [ 196, 169, 144, 121, 100, 81, ], 3, NO, ], [ [ 196, 169, 144, 121, 100, 81, ], 4, YES, ], # [ [1, 2, 3], 4], # [ [1, 2, 4], 8], # powers # [ [2, 4, 8], 16], # [ [1, 3, 9], 27], # [ [1, -1, 1, -1], 1], # alternations # [ [-1, 1, -1, 1], -1], # [ [1, 0, 1, 0], 1], # [ [0, 1, 0, 1], 0], # [ [1, 1, 2, 3, 5], 8], # fibonacci # [ [0, 1, 1, 2, 3], 8], # [ [1, 2, 3, 5, 8], 13], # [ [1, 2, 6, 24, 120], 720], # factorials # [ [1, 0, 0, 1], undef], # [ [1, 2, 3, 1], undef], # [ [], ], ); for my $ar_test (@tests) { my @sequence = @{ $ar_test->[0] }; # full sequence my $given = $ar_test->[1]; # initial stimulus my $finish = $ar_test->[2]; # completion expected? my @hint = @sequence[ 0 .. $given - 1 ]; my $iter = series(@hint); my @generated = @{ $finish ? \@hint : [] }; my @expected = @{ $finish ? \@sequence : [] }; if ($iter) { # check iterator if one was generated push @generated, $iter->() for 0 .. $#sequence - $given; } my $expected = "(@expected)"; my $got = "(@generated)"; my $hint = "(@hint)"; my $desc = "from $hint, expected $expected, got $got"; is ($expected, $got, $desc); }