Skip to content

Instantly share code, notes, and snippets.

@ykon
Last active October 29, 2017 03:45
Show Gist options
  • Save ykon/fb7916822dcc08a232dc4f5ec9b807d2 to your computer and use it in GitHub Desktop.
Save ykon/fb7916822dcc08a232dc4f5ec9b807d2 to your computer and use it in GitHub Desktop.
Basic FP in Scala
/*
* 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