package main import scala.annotation.tailrec object FP extends App { println("test solution") val nums = List(1, -1, 1, 2,-1) def comp(in: List[Int]): Int = { @tailrec def helper(in: List[Int], prev: Int, agg: Int): Int = { if (in.isEmpty) agg else if ((in.head > 0 && prev < 0) || (in.head < 0 && prev > 0)) helper(in.tail, in.head, agg + 1) else helper(in.tail, in.head, agg) } helper(in.tail, in.head, 0) } val res = comp(nums) println(res) def sum(l: List[Int]): Int = { if (l.isEmpty) 0 else l.head + sum(l.tail) } val l = List(1,2,5) println(sum(l)) def foldr[A,B](xs: List[A], e : B, f: (A,B) => B): B = { xs match { case Nil => e case y::ys => f(y, foldr(ys, e, f)) } } def sumF(l: List[Int]): Int = foldr(l, 0, (a: Int, b: Int) => a + b) val res2 = sumF(l) println("res2") println(res2) val lstr = List("a", "b", "x") println(foldr(lstr, "", (a: String, b: String) => a + b)) def product(l: List[Int]): Int = foldr(l, 1, (a: Int, b: Int) => a * b) println("product") println(l) println(product(l)) println("anytrue") def anyTrue(l: List[Boolean]): Boolean = foldr(l, false, (a: Boolean, b: Boolean) => a || b) val bools = List(true, true, true) println(anyTrue(bools)) println("allTrue") def allTrue(l: List[Boolean]): Boolean = foldr(l, true, (a: Boolean, b: Boolean) => a && b) println(allTrue(bools)) println("append") def copy(l: List[Int]): List[Int] = foldr(l, Nil, (a: Int, b: List[Int]) => a :: b) // def append(a: List[Int], b: List[Int]): List[Int] = // foldr(Nil, b, Cons) val cL = copy(nums) println(cL) def append(a: List[Int], b: List[Int]): List[Int] = foldr(b, a, (a: Int, b: List[Int]) => a :: b) val jCll = append(cL, l) println(jCll) def count(n: Int): Int = n + 1 def len[T](l: List[T]): Int = foldr(l, 0, (a: T, b: Int) => count(b)) println((len(jCll), len(bools), len(lstr))) def fcur(a: Int)(b: Int)(c: Int, d: Int): Int = a + b + c + d println(fcur(1)(2)(3,1)) // curried with default init aggregator equal to 0 def foldrC[A,B](l: List[A], e: B = 0)(f: (A, B) =>B):B = { l match { case Nil => e case head::tail => f(head, foldrC(tail, e)(f)) } } def sumCur(l: List[Int]): Int = foldrC(l)(_+_) println(sumCur(nums)) // append with new foldr def appendC[T](a: List[T], b: List[T]): List[T] = foldrC(b, a)(_::_) val lstr2 = List("a","b","c") val lnum2 = List(1,2,3) val lstr3 = List("d","e") val resl = appendC(lstr2, lstr3) println(resl) def doubleAndCons(n: Int, l: List[Int]): List[Int] = 2 * n :: l def double(n: Int): Int = 2 * n def fAndCons(el: Int, l: List[Int])(f: (Int)=>Int): List[Int] = f(el)::l def doubleall(l: List[Int]): List[Int] = l match { case Nil => Nil case x::xs => fAndCons(x, xs)(double(_)) } val leven = List(2,3,4) println(doubleall(leven)) def map[T](l: List[T])(f: T => T): List[T] = foldrC(l, List[T]())((a: T, b: List[T]) => f(a) :: b) def doubleAllWithMap(l: List[Int]): List[Int] = map(l)(double) val l10 = List.range(1,10) println(doubleAllWithMap(l10)) case class Node[T](v: T, chlds: List[Node[T]]) val tree1 = Node( 1, Node(2, Nil) :: List(Node(3, List(Node(4, List(Node(2, Nil))))))) def foldTree[A,B](nodes: List[Node[A]], e: B, g: Node[A] => A, f: (A,B) => B): B = { nodes match { case Nil => e case x :: Nil => f(g(x), foldTree(x.chlds, e, g ,f)) case x :: xs => f(g(x), foldTree(xs, e, g, f)) } } println("foldTree tree1") def plus(a: Int, b: Int): Int = a + b println(foldTree(List(tree1), 0, (n: Node[Int]) => n.v, plus)) def mul(a: Int, b: Int) = a * b println(foldTree(List(tree1), 1, (n: Node[Int]) => n.v, mul)) val labels = foldTree(List(tree1), Nil, (n: Node[Int]) => n.v, (a: Int, l: List[Int]) => a :: l) println(labels) // Newton-Raphson algorithm def next(n: Int)(x: Float): Float = (x + n / x)/2 def repeat[T](f: (T) => T, a0: T): Stream[T]= Stream.cons(a0,repeat(f, f(a0))) def abs(x: Float) = if (x > 0) x else -x def within(eps: Float, vals : Stream[Float]): Float = { val a = vals.head val b = vals.tail.head if (abs(a - b) <= eps) b else within(eps, vals.tail) } def sqrt(n: Int, guess: Float, eps: Float): Float = within(eps, repeat(next(n), guess)) // square root of 2 println(sqrt(2, 1, 0.001f)) // square root of 5 println(sqrt(25, 4, 0.001f)) // square root of 90 println(sqrt(90, 8, 0.001f)) }