Leonardo numbers
The Leonardo numbers are a sequence of numbers defined by:
L(0) = 1 L(1) = 1 L(n) = L(n-1) + L(n-2) + 1 also L(n) = 2 * Fib(n+1) - 1
- where the + 1 (herein) will be known as the add number.
- where the FIB is the Fibonacci numbers.
The task will be using the 3rd equation (above) to calculate the Leonardo numbers.
Edsger W. Dijkstra used them as an integral part of
his smoothsort algorithm.
The first few Leonardo numbers are:
1 1 3 5 9 15 25 41 67 109 177 287 465 753 1219 1973 3193 5167 8361 ···
- Task
-
- show the 1st 25 Leonardo numbers, starting at L(0).
- allow the first two Leonardo numbers to be specified [for L(0) and L(1)].
- allow the add number to be specified (1 is the default).
- show the 1st 25 Leonardo numbers, specifying 0 and 1 for L(0) and L(1), and 0 for the add number.
(The last task requirement will produce the Fibonacci numbers.)
Show all output here.
- Related tasks
- See also
ALGOL 68
<lang algol68>BEGIN
# leonardo number parameters # MODE LEONARDO = STRUCT( INT l0, l1, add number ); # default leonardo number parameters # LEONARDO leonardo numbers = LEONARDO( 1, 1, 1 ); # operators to allow us to specify non-default parameters # PRIO WITHLZERO = 9, WITHLONE = 9, WITHADDNUMBER = 9; OP WITHLZERO = ( LEONARDO parameters, INT l0 )LEONARDO: LEONARDO( l0, l1 OF parameters, add number OF parameters ); OP WITHLONE = ( LEONARDO parameters, INT l1 )LEONARDO: LEONARDO( l0 OF parameters, l1, add number OF parameters ); OP WITHADDNUMBER = ( LEONARDO parameters, INT add number )LEONARDO: LEONARDO( l0 OF parameters, l1 OF parameters, add number ); # show the first n Leonardo numbers with the specified parameters # PROC show = ( INT n, LEONARDO parameters )VOID: IF n > 0 THEN INT l0 = l0 OF parameters; INT l1 = l1 OF parameters; INT add number = add number OF parameters; print( ( whole( l0, 0 ), " " ) ); IF n > 1 THEN print( ( whole( l1, 0 ), " " ) ); INT lp := l0; INT ln := l1; FROM 2 TO n - 1 DO INT next = ln + lp + add number; lp := ln; ln := next; print( ( whole( ln, 0 ), " " ) ) OD FI FI # show # ;
# first series # print( ( "First 25 Leonardo numbers", newline ) ); show( 25, leonardo numbers ); print( ( newline ) ); # second series # print( ( "First 25 Leonardo numbers from 0, 1 with add number = 0", newline ) ); show( 25, leonardo numbers WITHLZERO 0 WITHADDNUMBER 0 ); print( ( newline ) )
END</lang>
- Output:
First 25 Leonardo numbers 1 1 3 5 9 15 25 41 67 109 177 287 465 753 1219 1973 3193 5167 8361 13529 21891 35421 57313 92735 150049 First 25 Leonardo numbers from 0, 1 with add number = 0 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368
Fortran
Happily, no monster values result for the trial run, so ordinary 32-bit integers suffice. The source style uses the F90 facilities only to name the subroutine being ended (i.e. END SUBROUTINE LEONARDO
rather than just END
) and the I0 format code that shows an integer without a fixed space allowance, convenient in produced well-formed messages. The "$" format code signifies that the end of output from its WRITE statement should not trigger the starting of a new line for the next WRITE statement, convenient when rolling a sequence of values to a line of output one-by-one as they are concocted. Otherwise, the values would have to be accumulated in a suitable array and then written in one go.
Many versions of Fortran have enabled parameters to be optionally supplied and F90 has standardised a protocol, also introducing a declaration syntax that can specify multiple attributes in one statement which in this case would be INTEGER, OPTIONAL:: AF
rather than two statements concerning AF. However, in a test run with CALL LEONARDO(25,1,1)
the Compaq F90/95 compiler rejected this attempt because there was another invocation with four parameters, not three, in the same program unit. By adding the rigmarole for declaring a MODULE containing the subroutine LEONARDO, its worries were assuaged.
The method relies on producing a sequence of values, rather than calculating L(n) from the start each time a value from the sequence is required. <lang Fortran> SUBROUTINE LEONARDO(LAST,L0,L1,AF) !Show the first LAST values of the sequence.
INTEGER LAST !Limit to show. INTEGER L0,L1 !Starting values. INTEGER AF !The "Add factor" to deviate from Fibonacci numbers. OPTIONAL AF !Indicate that this parameter may be omitted. INTEGER EMBOLISM !The bloat to employ. INTEGER N,LN,LNL1,LNL2 !Assistants to the calculation. IF (PRESENT(AF)) THEN !Perhaps the last parameter has not been given. EMBOLISM = AF !It has. Take its value. ELSE !But if not, EMBOLISM = 1 !This is the specified default. END IF !Perhaps there should be some report on this? WRITE (6,1) LAST,L0,L1,EMBOLISM !Announce. 1 FORMAT ("The first ",I0, !The I0 format code avoids excessive spacing. 1 " numbers in the Leonardo sequence defined by L(0) = ",I0, 2 " and L(1) = ",I0," with L(n) = L(n - 1) + L(n - 2) + ",I0) IF (LAST .GE. 1) WRITE (6,2) L0 !In principle, LAST may be small. IF (LAST .GE. 2) WRITE (6,2) L1 !!So, suspicion rules. 2 FORMAT (I0,", ",$) !Obviously, the $ sez "don't finish the line". LNL1 = L0 !Syncopation for the sequence's initial values. LN = L1 !Since the parameters ought not be damaged. DO N = 3,LAST !Step away. LNL2 = LNL1 !Advance the two state variables one step. LNL1 = LN !Ready to make a step forward. LN = LNL1 + LNL2 + EMBOLISM !Thus. WRITE (6,2) LN !Reveal the value. Overflow is distant... END DO !On to the next step. WRITE (6,*) !Finish the line. END SUBROUTINE LEONARDO !Only speedy for the sequential production of values.
PROGRAM POKE
CALL LEONARDO(25,1,1,1) !The first 25 Leonardo numbers. CALL LEONARDO(25,0,1,0) !Deviates to give the Fibonacci sequence. END </lang>
Output:
The first 25 numbers in the Leonardo sequence defined by L(0) = 1 and L(1) = 1 with L(n) = L(n - 1) + L(n - 2) + 1 1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219, 1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735, 150049, The first 25 numbers in the Leonardo sequence defined by L(0) = 0 and L(1) = 1 with L(n) = L(n - 1) + L(n - 2) + 0 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368,
Perl 6
<lang perl6>sub 𝑳 ( $𝑳0 = 1, $𝑳1 = 1, $𝑳add = 1 ) { $𝑳0, $𝑳1, { $^n2 + $^n1 + $𝑳add } ... * }
- Part 1
say "The first 25 Leonardo numbers:"; put 𝑳()[^25];
- Part 2
say "\nThe first 25 numbers using 𝑳0 of 0, 𝑳1 of 1, and adder of 0:"; put 𝑳( 0, 1, 0 )[^25];</lang>
- Output:
The first 25 Leonardo numbers: 1 1 3 5 9 15 25 41 67 109 177 287 465 753 1219 1973 3193 5167 8361 13529 21891 35421 57313 92735 150049 The first 25 numbers using 𝑳0 of 0, 𝑳1 of 1, and adder of 0: 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368
REXX
<lang rexx>/*REXX pgm computes Leonardo numbers, allowing the specification of L(0), L(1), and ADD#*/ numeric digits 500 /*just in case the user gets ka-razy. */ @.=1 /*define the default for the @. array.*/ parse arg N L0 L1 a# . /*obtain optional arguments from the CL*/ if N == | N =="," then N= 25 /*Not specified? Then use the default.*/ if L0\== & L0\=="," then @.0= L0 /*Was " " " " value. */ if L1\== & L1\=="," then @.1= L1 /* " " " " " " */ if a#\== & a#\=="," then @.a= a# /* " " " " " " */ say 'The first ' N " Leonardo numbers are:" /*display a title for the output series*/ if @.0\==1 | @.1\==1 then say 'using ' @.0 " for L(0)" if @.0\==1 | @.1\==1 then say 'using ' @.1 " for L(1)" if @.a\==1 then say 'using ' @.a " for the add number" say /*display blank line before the output.*/ $= /*initialize the output line to "null".*/
do j=0 for N /*construct a list of Leonardo numbers.*/ if j<2 then z=@.j /*for the 1st two numbers, use the fiat*/ else do /*··· otherwise, compute the Leonardo #*/ _=@.0 /*save the old primary Leonardo number.*/ @.0=@.1 /*store the new primary number in old. */ @.1=@.0 + _ + @.a /*compute the next Leonardo number. */ z=@.1 /*store the next Leonardo number in Z. */ end /* [↑] only 2 Leonardo #s are stored. */ $=$ z /*append the just computed # to $ list.*/ end /*j*/ /* [↓] elide the leading blank in $. */
say strip($) /*stick a fork in it, we're all done. */</lang>
- output when using the default input:
The first 25 Leonardo numbers are: 1 1 3 5 9 15 25 41 67 109 177 287 465 753 1219 1973 3193 5167 8361 13529 21891 35421 57313 92735 150049
- output when using the input of: 12 0 1 0
The first 25 Leonardo numbers are: using 0 for L(0) using 1 for L(1) using 0 for the add number 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368
Scala
<lang scala>def leo( n:Int, n1:Int=1, n2:Int=1, addnum:Int=1 ) : BigInt = n match {
case 0 => n1 case 1 => n2 case n => leo(n - 1, n1, n2, addnum) + leo(n - 2, n1, n2, addnum) + addnum
}
{ println( "The first 25 Leonardo Numbers:") (0 until 25) foreach { n => print( leo(n) + " " ) }
println( "\n\nThe first 25 Fibonacci Numbers:") (0 until 25) foreach { n => print( leo(n, n1=0, n2=1, addnum=0) + " " ) } } </lang>
- Output:
The first 25 Leonardo Numbers: 1 1 3 5 9 15 25 41 67 109 177 287 465 753 1219 1973 3193 5167 8361 13529 21891 35421 57313 92735 150049 The first 25 Fibonacci Numbers: 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368
Sidef
<lang ruby>func 𝑳(n, 𝑳0 = 1, 𝑳1 = 1, 𝑳add = 1) {
{ (𝑳0, 𝑳1) = (𝑳1, 𝑳0 + 𝑳1 + 𝑳add) } * n return 𝑳0
}
say "The first 25 Leonardo numbers:" say 25.of { 𝑳(_) }
say "\nThe first 25 numbers using 𝑳0 of 0, 𝑳1 of 1, and adder of 0:" say 25.of { 𝑳(_, 0, 1, 0) }</lang>
- Output:
The first 25 Leonardo numbers: [1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219, 1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735, 150049] The first 25 numbers using 𝑳0 of 0, 𝑳1 of 1, and adder of 0: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368]
zkl
<lang zkl>fcn leonardoNumber(n, n1=1,n2=1,addnum=1){
if(n==0) return(n1); if(n==1) return(n2); self.fcn(n-1,n1,n2,addnum) + self.fcn(n-2,n1,n2,addnum) + addnum
}</lang> <lang zkl>println("The first 25 Leonardo Numbers:"); foreach n in (25){ print(leonardoNumber(n)," ") } println("\n");
println("The first 25 Fibonacci Numbers:"); foreach n in (25){ print(leonardoNumber(n, 0,1,0)," ") } println();</lang>
- Output:
The first 25 Leonardo Numbers: 1 1 3 5 9 15 25 41 67 109 177 287 465 753 1219 1973 3193 5167 8361 13529 21891 35421 57313 92735 150049 The first 25 Fibonacci Numbers: 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368