#!/usr/bin/perl
# fib1.pl
use warnings;
use strict;
#Subroutine/Function Section
# Note this function is called recusively between
# 2 and 74 times to create the Fibonacci series.
# The input consists of
# 1. An $number_of_iterations counter,stating how far
# you want to calculate the Fibonacci Series and
# 2. The given $arev array for the Fibonacci series calculated so far.
#
# The output is the Fibonacci Series to the desired number
# of places as an array ($arev).
#
# To make sense of this start by caluculating the Fibonacci
# series for the first two elements.
# The Fibonacci series for element [1 through 2] is: 0 1
# The 2nd element of the Fibonacci series is: 1
# Note, initially we are not passing in the initial Fibonacci
# array so it is created as [0, 1]
#
sub fibonacci1 {
my ($number_of_iterations, $aref) = @_;
# if the $aref array does not exist create it with
# the block of code around the "unless".
# i.e. if $aref = NULL then create $aref = [0, 1]
unless ($aref) {
# first call - initialize
$aref = [0, 1];
# Decrement the number of iterations by the length of
# the intial array after creating
# the intial array. You have done the first two iterations.
$number_of_iterations -= scalar(@{$aref});
# print " this is initial number_of_iterations left after ";
# print " initialization: <$number_of_iterations> \n";
}
# End of intialization block for first iteration. This part of the
# code will not be touched again.
if ($number_of_iterations < 1) {
return @{$aref}; # You are done, leave function.
}
# Otherwise continue iterations of series.
# Decrement the number_of_iterations by 1 and as long
# as you are not at 0 calculate the next Fibonacci value.
# Fib(n) = Fib(n-1) + Fib (n-2)
# i.e. Fib(7) = Fib(6) + Fib(5)
# Then "push" that is stick this value at the end of the
# array. You can now recursively call the function again.
# You will stay in this "push and decrement" loop until
# the $number_of_iterations counter hits zero. Then
# you will return the array and exit this function.
#
if ($number_of_iterations--) {
my $next = $aref->[-1] + $aref->[-2];
# print "\nFib(n-1): <$aref->[-1]> ";
# print "Fib(n-2): <$aref->[-2]> \n";
push @{$aref}, $next;
return fibonacci1($number_of_iterations, $aref);
}
}
# End Subroutine Section
# calculate desired element of standard Fibonacci sequence
# Main Section
#
# usage ./perlfib integer
#
# i.e. ./perlfib 10
#
# Will print out the First 10 elements of the Fibonacci Series,
# i.e. 0 1 1 2 3 5 8 13 21 34
#
# Note $indexvalue must be at least 2 because
# the nth value of the Fibonacci series is always the sum
# of the two previous terminals. The series starts with
# Fib(2) = Fib(1) - Fib(0), the array can not have a negative index
# Fib(n) = Fib(n-1) + Fib(n-2)
my $indexvalue = shift(@ARGV);
unless($indexvalue) {
print " Sorry, you forgot to enter an iteration number for the ";
print " Fibonacci series. \n\n usage: perlfib i \n\n";
print " where i is an integer between 2 and 74 \n";
exit;
}
if ($indexvalue < 2) {
print "Sorry, Fibonacci element must be two or higher \n";
exit;
}
if ($indexvalue > 74) {
print "Sorry, Fibonacci element must be less than 75. ";
print " Otherwise, deep recursion and rounding errors can";
print " occur due to limits of size of double long integers. \n";
exit;
}
# return first $indexvalue elements of standard Fibonacci sequence
my @sequence = fibonacci1($indexvalue);
#Note, we are intentionally leaving out the second parameter in this
# function, i.e. the $arev array.
# However if we wanted to know what the next $indexvalue
# elements in the Fibonacci series were after [0, 1, 1]
# We could make this call
# my @sequence = fibonacci1($indexvalue, [0,1,1]);
#
print "The Fibonacci series for element [1 through $indexvalue] is: ";
print " @sequence \n";
print "The $indexvalue element of the Fibonacci series is: ";
# Note, pop will give you the last element of the array.
print pop(@sequence), "\n";
exit;
# End Main Section