in reply to Challenge: Simple algorithm for continuing series of integers
I more or less agree with most of the criticisms of this idea that I've read, but I felt like writing a solution anyway.
sub geometric { my @known = @_; my $prev = shift @known; my $curr = shift @known; return undef if ! $prev; my $factor = $curr / $prev; while ( @known ) { $prev = $curr; $curr = shift @known; return undef if ! $prev; return undef if $factor != $curr / $prev; } return $curr * $factor; } sub arith { my @known = @_; my $prev = shift @known; my $curr = shift @known; my $diff = $curr - $prev; while ( @known ) { $prev = $curr; $curr = shift @known; return undef if $diff != $curr - $prev; } return $curr + $diff; } sub series { my @known = @_; return undef if scalar @known < 2; my @next_gen = ( \&arith, \&geometric ); my @next = grep { defined } map { $_->( @known ) } @next_gen; return undef if scalar @next != 1; return $next[0]; }
Note that this doesn't pass all tests or even some of the ones that look easy. I have series() written to look at a list of sub references and ask each one for a "next in list" for the proposed list. If exactly one of them gets an answer, I return that answer, otherwise undef.
If the list of guessers becomes large or expensive, it would be more efficient to ask each one and fail as soon as two return answers.
It's easy to add other guessers, and it won't ever give an answer if the question is ambiguous. This may be odd. The series "0, 0" has an answer because it won't detect as geometric, but "1, 1" does not have an answer because it could be either one, even though the next in sequence is '1' both ways.
|
|---|