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