Last active
October 29, 2017 03:45
-
-
Save ykon/fb7916822dcc08a232dc4f5ec9b807d2 to your computer and use it in GitHub Desktop.
Basic FP in Scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2017 Yuki Ono | |
* Licensed under the MIT License. | |
*/ | |
package func_basic | |
import scala.annotation.tailrec | |
object Main extends App { | |
def proceduralSum(ns: List[Int]): Int = { | |
var sum = 0 | |
for (n <- ns) | |
sum += n | |
sum | |
} | |
def recSum(ns: List[Int]): Int = ns match { | |
case Nil => 0 | |
case n :: rest => n + recSum(rest) | |
} | |
def tailRecSum(ns: List[Int]): Int = { | |
@tailrec | |
def loop(l: List[Int], acc: Int): Int = l match { | |
case Nil => acc | |
case n :: rest => loop(rest, n + acc) | |
} | |
loop(ns, 0) | |
} | |
def foldLeftSum(ns: List[Int]): Int = { | |
ns.foldLeft(0)((acc, n) => acc + n) | |
//ns.foldLeft(0)(_ + _) | |
} | |
def foldRightSum(ns: List[Int]): Int = { | |
ns.foldRight(0)((n, acc) => acc + n) | |
// ns.foldRight(0)(_ + _) | |
} | |
def reduceLeftSum(ns: List[Int]): Int = { | |
ns.reduceLeft((acc, n) => acc + n) | |
//ns.reduceLeft(_ + _) | |
} | |
def reduceRightSum(ns: List[Int]): Int = { | |
ns.reduceRight((n, acc) => acc + n) | |
//ns.reduceRight(_ + _) | |
} | |
def sumSum(ns: List[Int]): Int = { | |
ns.sum | |
} | |
val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) | |
//val numbers = (1 to 10).toList | |
println("*** Sum ***") | |
println(proceduralSum(numbers)) | |
println(recSum(numbers)) | |
println(tailRecSum(numbers)) | |
println(foldLeftSum(numbers)) | |
println(foldRightSum(numbers)) | |
println(reduceLeftSum(numbers)) | |
println(reduceRightSum(numbers)) | |
println(sumSum(numbers)) | |
println("\n*** foldLeft ***") | |
val lRes = numbers.foldLeft(0)((acc, n) => { | |
println(s"acc: $acc, n: $n") | |
acc + n | |
}) | |
println(s"leftRes: $lRes") | |
println("\n*** foldRight ***") | |
val rRes = numbers.foldRight(0)((n, acc) => { | |
println(s"n: $n, acc: $acc") | |
n + acc | |
}) | |
println(s"rightRes: $rRes") | |
def proceduralFactorial(num: Int): BigInt = { | |
require(num >= 0) | |
var fn = BigInt(1) | |
var i = 1 | |
while (i <= num) { | |
fn *= i | |
i += 1 | |
} | |
fn | |
} | |
def recFactorial(num: Int): BigInt = { | |
require(num >= 0) | |
num match { | |
case 0 => 1 | |
case n => recFactorial(n - 1) * n | |
} | |
} | |
def tailRecFactorial(num: Int): BigInt = { | |
require(num >= 0) | |
@tailrec | |
def loop(n: Int, acc: BigInt): BigInt = n match { | |
case 0 => acc | |
case _ => loop(n - 1, acc * n) | |
} | |
loop(num, 1) | |
} | |
def foldLeftFactorial(num: Int): BigInt = { | |
require(num >= 0) | |
(1 to num).foldLeft(BigInt(1))((acc, n) => acc * n) | |
//(1 to num).foldLeft(BigInt(1))(_ * _) | |
} | |
def foldRightFactorial(num: Int): BigInt = { | |
require(num >= 0) | |
(1 to num).foldRight(BigInt(1))((n, acc) => acc * n) | |
//(1 to num).foldRight(BigInt(1))(_ * _) | |
} | |
println() | |
println("*** Factorial ***") | |
println(proceduralFactorial(10)) | |
println(recFactorial(10)) | |
println(tailRecFactorial(10)) | |
println(foldLeftFactorial(10)) | |
println(foldRightFactorial(10)) | |
def proceduralFib(num: Int): Int = { | |
if (num < 2) | |
return num | |
var a = 0; | |
var b = 1; | |
var i = 2 | |
while (i <= num) { | |
val temp = a | |
a = b | |
b = temp + b | |
i += 1 | |
} | |
return b | |
} | |
def recFib(num: Int): Int = num match { | |
case n if n < 2 => n | |
case n => recFib(n - 1) + recFib(n - 2) | |
} | |
def tailRecFib(num: Int): Int = { | |
@tailrec | |
def loop(n: Int, a: Int, b: Int): Int = n match { | |
case 0 => a | |
case _ => loop(n - 1, b, (a + b)) | |
} | |
loop(num, 0, 1) | |
} | |
def memoFib(num: Int): Int = { | |
val memo = collection.mutable.Map[Int, Int]() | |
def fib(n: Int) = n match { | |
case n if n < 2 => n | |
case _ => memoFib(n - 1) + memoFib(n - 2) | |
} | |
memo.get(num) match { | |
case Some(res) => res | |
case None => { | |
val res = fib(num) | |
memo(num) = res | |
res | |
} | |
} | |
} | |
println() | |
println("*** Fibonacci ***") | |
println(proceduralFib(10)) | |
println(recFib(10)) | |
println(tailRecFib(10)) | |
println(memoFib(10)) | |
def proceduralX2(ns: List[Int]): List[Int] = { | |
val buf = collection.mutable.ListBuffer.empty[Int] | |
for (n <- ns) | |
buf += n * 2 | |
return buf.toList | |
} | |
def recX2(ns: List[Int]): List[Int] = ns match { | |
case Nil => Nil | |
case n :: rest => n * 2 :: recX2(rest) | |
} | |
def tailRecX2(ns: List[Int]): List[Int] = { | |
@tailrec | |
def loop(l: List[Int], acc: List[Int]): List[Int] = l match { | |
case Nil => acc | |
case n :: rest => loop(rest, n * 2 :: acc) | |
} | |
loop(ns, Nil).reverse | |
} | |
def foldLeftX2(ns: List[Int]): List[Int] = { | |
ns.foldLeft(List[Int]())((acc, n) => n * 2 :: acc).reverse | |
} | |
def foldRightX2(ns: List[Int]): List[Int] = { | |
ns.foldRight(List[Int]())((n, acc) => n * 2 :: acc) | |
} | |
def mapX2(ns: List[Int]): List[Int] = { | |
def x2(n: Int) = n * 2 | |
ns.map(x2) | |
//ns.map(n => n * 2) | |
//ns.map(_ * 2) | |
} | |
println() | |
println("*** X2 ***") | |
println(proceduralX2(numbers)) | |
println(recX2(numbers)) | |
println(tailRecX2(numbers)) | |
println(foldLeftX2(numbers)) | |
println(foldRightX2(numbers)) | |
println(mapX2(numbers)) | |
def proceduralEven(ns: List[Int]): List[Int] = { | |
val buf = collection.mutable.ListBuffer.empty[Int] | |
for (n <- ns) { | |
if (n % 2 == 0) | |
buf += n | |
} | |
return buf.toList | |
} | |
def recEven(ns: List[Int]): List[Int] = ns match { | |
case Nil => Nil | |
case n :: rest => if (n % 2 == 0) n :: recEven(rest) else recEven(rest) | |
} | |
def tailRecEven(ns: List[Int]): List[Int] = { | |
@tailrec | |
def loop(l: List[Int], acc: List[Int]): List[Int] = l match { | |
case Nil => acc | |
case n :: rest => loop(rest, if (n % 2 == 0) n :: acc else acc) | |
} | |
loop(ns, Nil).reverse | |
} | |
def filterEven(ns: List[Int]): List[Int] = { | |
def isEven(n: Int) = n % 2 == 0 | |
ns.filter(isEven) | |
//ns.filter(n => n % 2 == 0) | |
//ns.filter(_ % 2 == 0) | |
} | |
println() | |
println("*** Even ***") | |
println(proceduralEven(numbers)) | |
println(recEven(numbers)) | |
println(tailRecEven(numbers)) | |
println(filterEven(numbers)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment