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