Saturday, October 15, 2011

Factorial and Fibonacci in Scala



Update 1: Porting code examples to Scala 2.10.1 - support for String Interpolation.

WARNING! I know that Scala is intended to be use in a very Functional way, however, my goal is to show its Imperative and OO language features, so it can be compared with other 19 OO languages. Said that, if you know how to do something on the examples below in a more Functional style you can add it in a comment :)

Here below a little program in Scala that implements 2 classes (in fact, they are 3). There is the main class, called Fiborial (Fibo(nnacci)+(Facto)rial) that implements the Fibonacci and the Factorial algorithms in two ways, one Recursive (using recursion) and the other Imperative (using loops and states). The second class is just an instance class that does the same thing, but its there just to show the difference between static and instance classes, and finally the third one (which will not appear in other languages) is the Program class which has the static execution method "Main".

You can also find 3 more little examples at the bottom. One prints out the Factorial's Series and Fibonacci's Series, the second one just shows a class that mixes both: static and instance members, and finally the third one that uses different return types (including System.Numerics.BigInteger) for the Factorial method to compare the timing and result.

As with the previous posts, you can copy and paste the code below in your favorite IDE/Editor and start playing and learning with it. This little "working" program will teach you some more basics of the Programming Language.

There are some "comments" on the code added just to tell you what are or how are some features called. In case you want to review the theory, you can read my previous post, where I give a definition of each of the concepts mentioned on the code. You can find it here: http://carlosqt.blogspot.com/2011/01/new-series-factorial-and-fibonacci.html 

I'm using the same Stopwatch java class that I used in the Java version of this post. I just added the .java file in the same scala-eclipse project. http://carlosqt.blogspot.com/2011/05/stopwatch-class-for-java.html

The Fiborial Program

package com.series
import scala.math.BigInt._  
import java.util.Scanner
import blog.series.lib.Stopwatch

// Instance (Singleton) Class that works as a Module/Utils class             
// static is not a class modifier in Scala    
object StaticFiborial  
{  
    // 'Static' Field  
    // 'Static' Constructor/Initializer  
    private var _message:String = "'Static' Constructor"  
    println(_message)  
    // 'Static' Method - Factorial Recursive    
    def factorialR(n:Int):BigInt = {  
        if(n==1)  
            BigInt(1)  
        else  
            BigInt(n) * factorialR(n - 1)  
    }  
    // 'Static' Method - Factorial Imperative  
    def factorialI(n:Int):BigInt = {  
        var res:BigInt = 1        
        for (i <- n until 1 by -1) {  
            res = res * i  
        }        
        res  
    }  
    // 'Static' Method - Fibonacci Recursive   
    def fibonacciR(n:Int):Long = {  
        if(n<2)  
            1  
        else  
            fibonacciR(n - 1) + fibonacciR(n - 2)  
    }  
    // 'Static' Method - Fibonacci Imperative  
    def fibonacciI(n:Int):Long = {  
        var pre:Long = 1  
        var cur:Long = 1  
        var tmp:Long = 0  
        for(i <- 2 to n) {  
            tmp = cur + pre  
            pre = cur  
            cur = tmp  
        }  
        cur  
    }  
    // Static Method - Benchmarking Algorithms   
    def benchmarkAlgorithm(algorithm:Int, values:List[Int]) = {        
        val timer = new Stopwatch  
        var (i:Int, testValue:Int) = (0, 0)  
        var facTimeResult:BigInt = 0  
        var fibTimeResult:Long = 0  
        
        algorithm match {    
            case 1 =>   
                println("\nFactorial Imperative:")  
                // "For" Loop Statement  
                for (i <- 0 to values.size - 1) {  
                    testValue = values(i)  
                    // Taking Time      
                    timer.start()      
                    facTimeResult = factorialI(testValue)      
                    timer.stop()  
                    // Getting Time  
                    println(s" ($testValue) = ${timer.getElapsed}")  
                }  
            case 2 =>   
                println("\nFactorial Recursive:")  
                // "While" Loop Statement  
                while (i < values.size) {  
                    testValue = values(i)  
                    // Taking Time      
                    timer.start()      
                    facTimeResult = factorialR(testValue)      
                    timer.stop()  
                    // Getting Time  
                    println(s" ($testValue) = ${timer.getElapsed}")  
                    i += 1  
                }  
            case 3 =>  
                println("\nFibonacci Imperative:")  
                // "For" Loop Statement  
                for (i <- 0 to values.size - 1) {  
                    testValue = values(i)  
                    // Taking Time      
                    timer.start()      
                    fibTimeResult = fibonacciI(testValue)  
                    timer.stop()  
                    // Getting Time  
                    println(s" ($testValue) = ${timer.getElapsed}")  
                }  
            case 4 =>   
                println("\nFibonacci Recursive:")  
                // "For" Loop Statement  
                for (i <- 0 to values.size - 1) {  
                    testValue = values(i)  
                    // Taking Time      
                    timer.start()      
                    fibTimeResult = fibonacciR(testValue)  
                    timer.stop()  
                    // Getting Time  
                    println(s" ($testValue) = ${timer.getElapsed}")  
                }  
            case _ =>   
                println("DONG!")  
        }    
    }      
}  
  
class InstanceFiborial(message:String) {  
    // Instance Field  
    private var _message:String = message  
    // Instance Constructor      
    def this() = {  
        this("Instance Constructor")  
        println(_message)  
    }      
    // Instance Method - Factorial Recursive    
    def factorialR(n:Int):BigInt = {  
        // Calling 'Static' Method  
        StaticFiborial.factorialR(n)  
    }  
    // Instance Method - Factorial Imperative  
    def factorialI(n:Int):BigInt = {  
        // Calling 'Static' Method        
        StaticFiborial.factorialI(n)  
    }  
    // Instance Method - Fibonacci Recursive   
    def fibonacciR(n:Int):Long = {  
        // Calling 'Static' Method        
        StaticFiborial.fibonacciR(n)  
    }  
    // Instance Method - Fibonacci Imperative  
    def fibonacciI(n:Int):Long = {  
        // Calling 'Static' Method        
        StaticFiborial.fibonacciI(n)  
    }  
}  
  
object Program {  
    def main(args: Array[String]): Unit = {  
        // Calling 'Static' Class and Methods      
        // No instantiation needed. Calling method directly from the class      
        println(s"FacImp(5) = ${StaticFiborial.factorialI(5)}")      
        println(s"FacRec(5) = ${StaticFiborial.factorialR(5)}")      
        println(s"FibImp(11)= ${StaticFiborial.fibonacciI(11)}")      
        println(s"FibRec(11)= ${StaticFiborial.fibonacciR(11)}")   
          
        println("\nInstance Class")      
        // Calling Instance Class and Methods       
        // Need to instantiate before using. Call method from instantiated object      
        val ff = new InstanceFiborial()      
        println(s"FacImp(5) = ${ff.factorialI(5)}")      
        println(s"FacRec(5) = ${ff.factorialR(5)}")      
        println(s"FibImp(11)= ${ff.fibonacciI(11)}")      
        println(s"FibRec(11)= ${ff.fibonacciR(11)}")  
          
        // Create a (generic) list of integer values to test      
        // From 5 to 50 by 5  
        var values:List[Int] = Nil  
        for(i <- 5 until 55 by 5)  
            values = values ::: List(i)  
  
        // Benchmarking Fibonacci  
        // 1 = Factorial Imperative                  
        StaticFiborial.benchmarkAlgorithm(1, values)      
        // 2 = Factorial Recursive      
        StaticFiborial.benchmarkAlgorithm(2, values)      
    
        // Benchmarking Factorial                  
        // 3 = Fibonacci Imperative      
        StaticFiborial.benchmarkAlgorithm(3, values)      
        // 4 = Fibonacci Recursive      
        StaticFiborial.benchmarkAlgorithm(4, values)  
  
        println("Press any key to exit...")      
        val in = new Scanner(System.in)      
        in.nextLine()      
        in.close()           
    }  
}

And the Output is:





































Printing the Factorial and Fibonacci Series


import scala.math.BigInt._
import scala.collection.mutable.StringBuilder._

object Fiborial {
    // Using a StringBuilder as a list of string elements
    def getFactorialSeries(n:Int):String = {
        // Create the String that will hold the list
        val series:StringBuilder = new StringBuilder
        // We begin by concatenating the number you want to calculate
        // in the following format: "!# ="
        series.append("!")
        series.append(n)
        series.append(" = ")
        // We iterate backwards through the elements of the series
        for (i <- n until 0 by -1) {
            // and append it to the list
            series.append(i)
            if (i > 1)
                series.append(" * ")
            else 
                series.append(" = ")
        }
        // Get the result from the Factorial Method
        // and append it to the end of the list
        series.append(factorial(n))
        // return the list as a string
        series.toString
    }

    // Using a StringBuilder as a list of string elements
    def getFibonnaciSeries(n:Int):String = {
        // Create the String that will hold the list
        val series:StringBuilder = new StringBuilder
        // We begin by concatenating the first 3 values which
        // are always constant
        series.append("0, 1, 1")
        // Then we calculate the Fibonacci of each element
        // and add append it to the list
        for (i <- 2 to n) {
            if (i < n)
                series.append(", ")
            else
                series.append(" = ")
            
            series.append(fibonacci(i))
        }
        // return the list as a string
        series.toString
    }

    def factorial(n:Int):BigInt = {
        if(n==1)
            BigInt(1)
        else
            BigInt(n) * factorial(n - 1)
    }

    def fibonacci(n:Int):Long = {
        if (n < 2)
            1  
        else  
            fibonacci(n - 1) + fibonacci(n - 2)  
    }
}

object FiborialProgram {
    def main(args:Array[String]) {
        // Printing Factorial Series  
        println("")
        println(Fiborial.getFactorialSeries(5))
        println(Fiborial.getFactorialSeries(7))  
        println(Fiborial.getFactorialSeries(9))  
        println(Fiborial.getFactorialSeries(11))  
        println(Fiborial.getFactorialSeries(40))  
        // Printing Fibonacci Series  
        println("")  
        println(Fiborial.getFibonnaciSeries(5))  
        println(Fiborial.getFibonnaciSeries(7))  
        println(Fiborial.getFibonnaciSeries(9))  
        println(Fiborial.getFibonnaciSeries(11))  
        println(Fiborial.getFibonnaciSeries(40))  
    }
}

And the Output is:

















Mixing Instance and Static Members in the same Class

There are no static classes in Scala, instead you can define an object which in fact is an instance singleton class that can be used as a static class. It is possible to mix 'static' and instance members into the same class. You do that by creating a class (instance members) and an object ('static' members)

package com.series
// To mix Instance and 'Static' methods in Scala you define a Class (instance)   
// and and object (static) with the same Name  
  
// Instance Class  
class Fiborial(init:Int) {  
    // Instance Field  
    private var _instanceCount:Int = init  
    // Instance Read-Only Getter  
    def InstanceCount = _instanceCount  
    // Instance Constructor  
    def this() = {  
        this(0)  
        println(s"\nInstance Constructor ${_instanceCount}")  
    }      
    // Instance Method   
    def factorial(n:Int) = {  
        _instanceCount += 1      
        println(s"\nFactorial($n)")  
    }  
}  
// 'Static' Class  
object Fiborial {  
    // 'Static' Field  
    private var _staticCount:Int = 0  
    // Instance Read-Only Getter  
    def StaticCount = _staticCount  
    // 'Static' Constructor/Initializer  
    println(s"\nStatic Constructor ${_staticCount}")  
    // 'Static' Method   
    def fibonacci(n:Int) = {  
        _staticCount += 1      
        println(s"\nFactorial($n)")  
    }  
}  
  
object Program {  
    def main(args: Array[String]) = {  
        // Calling Static Constructor and Methods  
        // No need to instantiate      
        Fiborial.fibonacci(5)                  
    
        // Calling Instance Constructor and Methods      
        // Instance required      
        val fib = new Fiborial      
        fib.factorial(5)    
    
        Fiborial.fibonacci(15)                  
        fib.factorial(5)      
    
        // Calling Instance Constructor and Methods      
        // for a second object      
        val fib2 = new Fiborial      
        fib2.factorial(5)      
              
        println("")  
        // Calling Static Property      
        println(s"Static Count = ${Fiborial.StaticCount}")      
        // Calling Instance Getter of object 1 and 2      
        println(s"Instance 1 Count = ${fib.InstanceCount}")      
        println(s"Instance 2 Count = ${fib2.InstanceCount}")     
    }  
}

And the Output is:























Factorial using scala.Long, scala.Double, scala.math.BigInt

import scala.math.BigInt._
import blog.series.lib.Stopwatch

object Program {

    def main(args: Array[String]): Unit = {
        val timer = new Stopwatch()  
        var facLngResult:Long = 0  
        var facDblResult:Double = 0  
        var facBigResult:BigInt = BigInt(0)  
            
        println("\nFactorial using Long")    
        // Benchmark Factorial using Long  
        for(i <- 5 until 55 by 5) {            
            timer.start   
            facLngResult = factorialLong(i)    
            timer.stop  
            println(s" ($i) = ${timer.getElapsed} : $facLngResult")    
        }  
        println("\nFactorial using Double")  
        // Benchmark Factorial using Double    
        for(i <- 5 until 55 by 5) {            
            timer.start    
            facDblResult = factorialDouble(i)    
            timer.stop    
            println(s" ($i) = ${timer.getElapsed} : $facDblResult")  
        }  
        println("\nFactorial using BigInteger")  
        // Benchmark Factorial using BigInteger  
        for(i <- 5 until 55 by 5) {            
            timer.start    
            facBigResult = factorialBigInt(i)    
            timer.stop    
            println(s" ($i) = ${timer.getElapsed} : $facBigResult")  
        }  
    }  
    // Long Factorial   
    def factorialLong(n:Int):Long = {      
        if(n==1)  
            1.toLong  
        else  
            n.toLong * factorialLong(n - 1)  
    }  
    // Double Factorial   
    def factorialDouble(n:Int):Double = {  
        if(n==1)  
            1.toDouble  
        else  
            n.toDouble * factorialDouble(n - 1)  
    }  
    // BigInteger Factorial     
    def factorialBigInt(n:Int):BigInt = {       
        if(n==1)  
            BigInt(1)  
        else  
            BigInt(n) * factorialBigInt(n - 1)  
    }  

}

And the Output is:



No comments:

Post a Comment