├── Chapter03 ├── List.scala └── Readme.txt ├── Chapter04 └── BinTree.scala ├── Chapter05 └── MoreListAlgo.scala ├── Chapter06 └── Graph.scala ├── Chapter07 └── RandAccessList.scala ├── Chapter08 ├── Fifo.scala ├── LeftistHeap.scala └── readme.txt ├── Chapter09 ├── ClojureCode.txt ├── ScalaCode.txt ├── allinfiniteStreamCreation.scala ├── arithmeticProgression.clj ├── arithmeticProgression.scala ├── eagerEvaluation.scala ├── fiboSeries.clj ├── fiboSeries.scala ├── immutableStream.scala ├── lazyEvaluation.clj ├── lazyEvaluation.scala ├── memoization.clj ├── memoization.scala ├── standardBrownianMotion.clj ├── standardBrownianMotion.scala ├── streamCreationAndIndexing.scala └── streamSequence.clj ├── Chapter10 ├── Deque.scala └── LazyQueue.scala ├── Chapter11 ├── RBTree.scala └── readme.txt ├── Chapter12 ├── BinomialHeap.scala └── readme.txt ├── Chapter13 ├── BubbleSort.scala ├── InsertionSort.scala ├── MergeSort.scala ├── QuickSort.scala └── SelectionSort.scala ├── LICENSE └── README.md /Chapter03/List.scala: -------------------------------------------------------------------------------- 1 | package com.fpdatastruct.lists 2 | 3 | import scala.annotation.tailrec 4 | 5 | object List extends App { 6 | 7 | sealed trait List[+A] 8 | case object Nil extends List[Nothing] 9 | case class ::[+A](head: A, tail: List[A]) extends List[A] 10 | 11 | def apply[A](as: A*): List[A] = 12 | if (as.isEmpty) Nil 13 | else ::(as.head, apply(as.tail: _*)) 14 | 15 | def head[A](list: List[A]): A = list match { 16 | case Nil => sys.error("tail of empty list") 17 | case x :: _ => x 18 | } 19 | 20 | def tail[A](list: List[A]): List[A] = list match { 21 | case Nil => sys.error("tail of empty list") 22 | case _ :: xs => xs 23 | } 24 | 25 | def drop[A](l: List[A], n: Int): List[A] = 26 | if (n <= 0) l 27 | else l match { 28 | case Nil => Nil 29 | case _ :: t => drop(t, n - 1) 30 | } 31 | 32 | def dropWhile[A](as: List[A])(f: A => Boolean): List[A] = as match { 33 | case x :: xs if f(x) => dropWhile(xs)(f) 34 | case _ => as 35 | } 36 | 37 | def append[A](a1: List[A], a2: List[A]): List[A] = 38 | a1 match { 39 | case Nil => a2 40 | case h :: t => ::(h, append(t, a2)) 41 | } 42 | 43 | def appendElem[A](l: List[A], elem: A): List[A] = l match { 44 | case Nil => List(elem) 45 | case x :: xs => ::(x, appendElem(xs, elem)) 46 | } 47 | 48 | def prepend[A](list: List[A], v: A) = list match { 49 | case Nil => ::(v, Nil) 50 | case x :: xs => ::(v, list) 51 | } 52 | 53 | @tailrec 54 | def elemAtIndex[A](l: List[A], i: Int): A = (l,i) match { 55 | case (Nil, _) => sys.error(s"index ${i} not valid") 56 | case (x :: xs, 0) => x 57 | case (x :: xs, _) => elemAtIndex(xs, i-1) 58 | } 59 | 60 | def setElem[A](l: List[A], i: Int, elem: A): List[A] = (l, i) match { 61 | case (Nil, _) => sys.error(s"index ${i} not valid") 62 | case (_ :: xs, 0) => ::(elem, xs) 63 | case (x :: xs, _) => ::(x, setElem(xs, i-1, elem)) 64 | } 65 | 66 | val l = List(1, 2, 3) // calls apply 67 | println(tail(l)) 68 | 69 | } 70 | 71 | -------------------------------------------------------------------------------- /Chapter03/Readme.txt: -------------------------------------------------------------------------------- 1 | Compile List.scala 2 | 3 | % scalac List.scala 4 | ... 5 | 6 | % scala 7 | ... 8 | 9 | scala> import com.fpdatastruct.lists._ 10 | import com.fpdatastruct.lists._ 11 | 12 | scala> import com.fpdatastruct.lists.List._ 13 | import com.fpdatastruct.lists.List._ 14 | 15 | scala> val l = List(1, 2, 3) 16 | l: com.fpdatastruct.lists.List.List[Int] = ::(1,::(2,::(3,Nil))) 17 | 18 | scala> println(tail(l)) 19 | ::(2,::(3,Nil)) 20 | 21 | You can play with other list functions now 22 | -------------------------------------------------------------------------------- /Chapter04/BinTree.scala: -------------------------------------------------------------------------------- 1 | package com.fpdatastruct.bintree 2 | 3 | object BinTree extends App { 4 | sealed trait BinTree[+A] 5 | case object Leaf extends BinTree[Nothing] 6 | case class Branch[A](value: A, left: BinTree[A], right: BinTree[A]) extends BinTree[A] 7 | 8 | def size[A](tree: BinTree[A]): Int = tree match { 9 | case Leaf => 0 10 | case Branch(_, l, r) => 1 + size(l) + size(r) 11 | } 12 | 13 | def depth [A](tree: BinTree[A]): Int = tree match { 14 | case Leaf => 0 15 | case Branch(_, l, r) => 1 + ( depth(l) max depth(r) ) 16 | } 17 | 18 | def buildCompleteTree(v: Int, depth: Int): BinTree[Int] = 19 | if (depth == 0) Leaf 20 | else Branch(v, buildCompleteTree(2*v, depth-1), buildCompleteTree(2*v+1, depth-1)) 21 | 22 | def buildTree[A](list: List[A]): BinTree[A] = list match { 23 | case Nil => Leaf 24 | case x :: xs => { 25 | val k = xs.length / 2 26 | Branch(x, buildTree(xs.take(k)), buildTree(xs.drop(k))) 27 | } 28 | } 29 | 30 | def flip[A](tree: BinTree[A]): BinTree[A] = tree match { 31 | case Leaf => Leaf 32 | case Branch(v, l, r) => Branch(v, flip(r), flip(l)) 33 | } 34 | 35 | def equal[A](tree1: BinTree[A], tree2: BinTree[A]): Boolean = (tree1, 36 | tree2) match { 37 | case (Leaf, Leaf) => true 38 | case (Branch(v1, l1, r1), Branch(v2, l2, r2)) if v1 == v2 => 39 | equal(l1, l2) && equal(r1, r2) 40 | case _ => false 41 | } 42 | 43 | def flippedEqual[A](tree1: BinTree[A], tree2: BinTree[A]): Boolean = (tree1, 44 | tree2) match { 45 | case (Leaf, Leaf) => true 46 | case (Branch(v1, l1, r1), Branch(v2, l2, r2)) if v1 == v2 => 47 | flippedEqual(l1, r2) && flippedEqual(l2, r1) 48 | case _ => false 49 | } 50 | 51 | def preorder[A](tree: BinTree[A]): List[A] = tree match { 52 | case Leaf => Nil 53 | case Branch(v, l, r) => v :: (preorder(l) ++ preorder(r)) 54 | } 55 | 56 | def inorder[A](tree: BinTree[A]): List[A] = tree match { 57 | case Leaf => Nil 58 | case Branch(v, l, r) => inorder(l) ++ ( v :: inorder(r)) 59 | } 60 | 61 | def postorder[A](tree: BinTree[A]): List[A] = tree match { 62 | case Leaf => Nil 63 | case Branch(v, l, r) => postorder(l) ++ postorder(r) ++ List(v) 64 | } 65 | 66 | def preorderAcc[A](tree: BinTree[A], acc: List[A]): List[A] = tree match { 67 | case Leaf => acc 68 | case Branch(v, l, r) => { 69 | println(s"When at ${v} - acc = ${acc}") 70 | v :: preorderAcc(l, preorderAcc(r, acc)) 71 | } 72 | } 73 | 74 | 75 | def inorderAcc[A](tree: BinTree[A], acc: List[A]): List[A] = tree match { 76 | case Leaf => acc 77 | case Branch(v, l, r) => inorderAcc(l, v :: inorderAcc(r, acc)) 78 | } 79 | 80 | def postorderAcc[A](tree: BinTree[A], acc: List[A]): List[A] = tree match { 81 | case Leaf => acc 82 | case Branch(v, l, r) => postorderAcc(l, postorderAcc(r, v :: acc)) 83 | } 84 | 85 | val tree = buildCompleteTree(1, 3) 86 | println(preorder(tree)) 87 | println(preorderAcc(tree, List())) 88 | 89 | } 90 | 91 | -------------------------------------------------------------------------------- /Chapter05/MoreListAlgo.scala: -------------------------------------------------------------------------------- 1 | package com.fpdatastruct.morelistalgo 2 | 3 | object MoreListAlgo extends App { 4 | def carry(c: Int, list: List[Int]):List[Int] = (c, list) match { 5 | case (0, xs) => xs 6 | case (1, Nil) => List(1) 7 | case (1, x :: xs) => (1 - x) :: carry(x, xs) 8 | case (_, _) => throw new IllegalArgumentException("Invalid input!!!") 9 | } 10 | 11 | def add(c: Int, ps: List[Int], qs: List[Int]): List[Int] = (ps, qs) match { 12 | case (Nil, Nil) => carry(c, Nil) 13 | case (Nil, _ :: _) => carry(c, qs) 14 | case (_ :: _, Nil) => carry(c, ps) 15 | case (x::xs, y::ys) => ((c+x+y) % 2) :: add((c+x+y)/2, xs, ys) 16 | } 17 | 18 | def addNums(first: List[Int], second: List[Int]): List[Int] = { 19 | val result = add(0, first.reverse, second.reverse) 20 | result.reverse 21 | } 22 | 23 | def mult(first: List[Int], second: List[Int]): List[Int] = { 24 | def multiply(ps: List[Int], qs: List[Int]): List[Int] = (ps) match { 25 | case Nil => Nil 26 | case 0 :: xs => 0 :: multiply(xs, qs) 27 | case 1 :: xs => add(0, qs, 0::multiply(xs, qs)) 28 | } 29 | val result = multiply(first.reverse, second.reverse) 30 | result.reverse 31 | } 32 | 33 | val k = carry(1, List(1, 1, 0, 1)) 34 | 35 | println( addNums(List(1, 0, 1, 1), List(1, 1, 1, 1, 0)) ) 36 | println( addNums(List(1, 0), List(1, 0)) ) 37 | println( addNums(List(1, 0, 1), List(1, 0, 0)) ) 38 | println( addNums(List(1, 0, 0), List(1, 0, 1)) ) 39 | 40 | println( mult(List(1, 1), List(1, 1, 1, 1)) ) 41 | println( mult(List(1, 1, 1), List(1, 0, 1)) ) 42 | } 43 | 44 | -------------------------------------------------------------------------------- /Chapter06/Graph.scala: -------------------------------------------------------------------------------- 1 | package com.fpdatastruct.functionalalgo 2 | 3 | object Graph extends App { 4 | import scala.annotation.tailrec 5 | 6 | def succSet(a: String, g: List[(String, String)]): List[String] = g match { 7 | case Nil => Nil 8 | case x :: xs if (a == x._1) => x._2 :: succSet(a, xs) 9 | case _ :: xs => succSet(a, xs) 10 | } 11 | 12 | def depthFirst(initial: String, g: List[(String, String)]) : List[String] = { 13 | def depthf(nodes: List[String], visited: List[String]): List[String] = nodes match { 14 | case Nil => visited 15 | case x :: xs if visited.contains(x) => depthf(xs, visited) 16 | case x :: xs => depthf(succSet(x, g) ++ xs, x::visited) 17 | } 18 | 19 | val result = depthf(List(initial), List()) 20 | result.reverse 21 | } 22 | 23 | def depthFirst1(initial: String, g: List[(String, String)]) : List[String] = { 24 | 25 | def depthf(nodes: List[String], visited: List[String]): List[String] = nodes match { 26 | case Nil => visited 27 | case x :: xs => depthf(xs, 28 | if (visited.contains(x)) visited 29 | else depthf(succSet(x, g), x::visited)) 30 | } 31 | 32 | val result = depthf(List(initial), List()) 33 | result.reverse 34 | } 35 | 36 | def topsort(g: List[(String, String)]) = { 37 | def sort(nodes: List[String], visited: List[String]): List[String] = nodes match { 38 | case Nil => visited 39 | case x :: xs => sort(xs, 40 | if (visited.contains(x)) visited 41 | else x :: sort(succSet(x, g), visited)) 42 | } 43 | 44 | val (start, _) = g.unzip 45 | val result = sort(start, List()) 46 | result 47 | } 48 | 49 | def topsortWithCycle(g: List[(String, String)]) = { 50 | def sort(nodes: List[String], path: List[String], visited: List[String]): 51 | List[String] = nodes match { 52 | case Nil => visited 53 | case x :: xs if path.contains(x) => 54 | throw new RuntimeException("Cycle detected") 55 | case x :: xs => sort(xs, path, 56 | if (visited.contains(x)) visited 57 | else x :: sort(succSet(x, g), x :: path, visited)) 58 | } 59 | 60 | val (start, _) = g.unzip 61 | val result = sort(start, List(), List()) 62 | result 63 | } 64 | 65 | type VC = (List[String], List[String]) 66 | 67 | def addToVisited(x: String, v: VC) = (x :: v._1, v._2) 68 | 69 | def topsortPrintCycle(g: List[(String, String)]) = { 70 | def sort(nodes: List[String], path: List[String], 71 | visited: VC): VC = nodes match { 72 | case Nil => visited 73 | case x :: xs => 74 | val (v, c) = visited 75 | sort(xs, path, 76 | if (path.contains(x)) (v, x::c) 77 | else if (v.contains(x)) visited 78 | else addToVisited(x, sort(succSet(x, g), x :: path, visited)) 79 | ) 80 | } 81 | 82 | val (start, _) = g.unzip 83 | val result = sort(start, List(), (List(), List())) 84 | result 85 | } 86 | 87 | val graph = List(("m", "n"), ("m", "o"), ("m", "p"), 88 | ("n", "q"), ("o", "r"), ("p", "q"), 89 | ("q", "r"), ("q", "s")) 90 | 91 | val nodes = depthFirst1("m", graph) 92 | println(nodes) 93 | 94 | val grwork = List(("getup","shower"), 95 | ("shower", "breakfast"), 96 | ("breakfast","dress"), 97 | ("dress","office"), 98 | ("office", "dinner"), 99 | 100 | ("breakfast","leisurely_lunch"), 101 | ("leisurely_lunch", "movie"), 102 | ("movie", "dinner")) 103 | 104 | val topsorted = topsortPrintCycle(("dinner", "movie") :: grwork) 105 | println(topsorted) 106 | } 107 | 108 | -------------------------------------------------------------------------------- /Chapter07/RandAccessList.scala: -------------------------------------------------------------------------------- 1 | package com.fpdatastruct.randomaccesslists 2 | 3 | object RandAccessList extends App { 4 | def increment(numList: List[Int]): List[Int] = numList match { 5 | case Nil => List(1) 6 | case 0 :: xs => 1 :: xs 7 | case 1 :: xs => 0 :: increment(xs) 8 | case _ => sys.error("Not a binary number") 9 | } 10 | 11 | def add(one: List[Int], two: List[Int]): List[Int] = (one, two) match { 12 | case (Nil, Nil) => Nil 13 | case (xs, Nil) => xs 14 | case (Nil, xs) => xs 15 | case (x :: xs, 0 :: ys) => x :: add(xs, ys) 16 | case (0 :: xs, y :: ys) => y :: add(xs, ys) 17 | case (1 :: xs, 1 :: ys) => 0 :: increment(add(xs, ys)) 18 | case _ => sys.error("Not a binary number") 19 | } 20 | 21 | def decrement(numList: List[Int]): List[Int] = numList match { 22 | case 1 :: Nil => Nil 23 | case 1 :: xs => 0 :: xs 24 | case 0 :: xs => 1 :: decrement(xs) 25 | case _ => sys.error("Not a binary number") 26 | } 27 | 28 | sealed abstract class Tree { 29 | def size: Int 30 | } 31 | 32 | case class Leaf(n: Int) extends Tree { 33 | override def size = 1 34 | } 35 | 36 | case object Zero extends Tree { 37 | override def size = 0 38 | } 39 | 40 | case class One(t: Tree) extends Tree { 41 | override def size = t.size 42 | } 43 | 44 | case class Node(sz: Int, left: Tree, right: Tree) extends Tree { 45 | override def size = sz 46 | } 47 | 48 | def link(t1: Tree, t2: Tree) = Node(t1.size + t2.size, t1, t2) 49 | 50 | def addTreeToList(t1: Tree, listOfTrees: List[Tree]): List[Tree] = listOfTrees match { 51 | case Nil => List(One(t1)) 52 | case Zero :: ts => One(t1) :: ts 53 | case One(t2) :: ts => Zero :: addTreeToList(link(t1, t2), ts) 54 | case _ => sys.error("how did it reach here?") 55 | } 56 | 57 | def cons(treeList: List[Tree], x: Int) = 58 | addTreeToList(Leaf(x), treeList) 59 | 60 | def searchTree(i: Int, tree: Tree): Int = (i, tree) match { 61 | case (0, Leaf(x)) => x 62 | case (i, Node(sz, t1, t2)) if i < (sz / 2) => searchTree(i, t1) 63 | case (i, Node(sz, t1, t2)) => searchTree(i - sz / 2, t2) 64 | } 65 | 66 | def lookup(i: Int, tree: List[Tree]): Int = tree match { 67 | case Zero :: ts => lookup(i, ts) 68 | case One(t) :: ts if i < t.size => searchTree(i, t) 69 | case One(t) :: ts if i >= t.size => lookup(i - t.size, ts) 70 | } 71 | 72 | def removeTree(tree: List[Tree]): (Tree, List[Tree]) = tree match { 73 | case One(t) :: Nil => (t, Nil) 74 | case One(t) :: ts => (t, Zero :: ts) 75 | case (Zero :: ts) => { 76 | val (Node(_, t1, t2), tss) = removeTree(ts) 77 | (t1, One(t2) :: tss) 78 | } 79 | case _ => sys.error("how did it reach here?") 80 | } 81 | 82 | def head(treeList: List[Tree]) = removeTree(treeList) match { 83 | case (Leaf(x), _) => x 84 | case _ => sys.error("how did it reach here?") 85 | } 86 | 87 | def tail(treeList: List[Tree]) = removeTree(treeList) match { 88 | case (_, ts) => ts 89 | } 90 | 91 | def setValInTree(i: Int, newval: Int, tree: Tree): Tree = (i, tree) match { 92 | case (0, Leaf(x)) => Leaf(newval) 93 | case (_, Node(sz, t1, t2)) if (i < sz / 2) => Node(sz, setValInTree(i, newval, t1), t2) 94 | case (_, Node(sz, t1, t2)) => Node(sz, t1, setValInTree(i - sz / 2, newval, t2)) 95 | } 96 | 97 | def setVal(i: Int, newval: Int, treeList: List[Tree]): List[Tree] = treeList match { 98 | case Zero :: ts => Zero :: setVal(i, newval, ts) 99 | case One(t) :: ts if i < t.size => One(setValInTree(i, newval, t)) :: ts 100 | case One(t) :: ts => One(t) :: setVal(i - t.size, newval, ts) 101 | } 102 | 103 | 104 | println(increment(List(1, 0, 1))) 105 | println(add(List(1, 1), List(1, 1))) 106 | 107 | val tree = List(11, 22, 33, 44, 55, 66, 77).reverse.foldLeft(List[Tree]())((b, a) => 108 | cons(b, a)) 109 | println(lookup(3, tree)) 110 | println(lookup(4, tree)) 111 | println(lookup(0, tree)) 112 | println(head(tree)) 113 | println(tail(tree)) 114 | 115 | } 116 | 117 | -------------------------------------------------------------------------------- /Chapter08/Fifo.scala: -------------------------------------------------------------------------------- 1 | package com.fpdatastruct.queue 2 | 3 | object Fifo extends App { 4 | 5 | case class Fifo(out: List[Int], in: List[Int]) { 6 | def check(): Boolean = (out, in) match { 7 | case (Nil, x :: xs) => false 8 | case _ => true 9 | } 10 | require(check, "Invariant Failed - out.em") 11 | } 12 | 13 | def push(e: Int, queue: Fifo): Fifo = { 14 | val newIn = e :: queue.in 15 | queue.out match { 16 | case Nil => Fifo(newIn.reverse, Nil) 17 | case _ => queue.copy(in = newIn) 18 | } 19 | } 20 | 21 | def pop(queue: Fifo): (Int, Fifo) = { 22 | queue.out match { 23 | case Nil => throw new IllegalArgumentException("Empty queue"); 24 | case x :: Nil => (x, queue.copy(out = queue.in.reverse, Nil)) 25 | case y :: ys => (y, queue.copy(out = ys)) 26 | } 27 | } 28 | 29 | // val q = push(3, push(2, push(1, Fifo(Nil, Nil)))) 30 | val q = List(1,2,3).foldLeft(Fifo(Nil, Nil))((q, e) => push(e, q)) 31 | 32 | val (one, q1) = pop(q) 33 | println(one) 34 | 35 | val (two, q2) = pop(q1) 36 | println(two) 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Chapter08/LeftistHeap.scala: -------------------------------------------------------------------------------- 1 | package com.fpdatastruct.queue 2 | 3 | object LeftistHeap extends App { 4 | sealed abstract class TreeNode { 5 | def rank: Int 6 | } 7 | 8 | case class Node(rank: Int, v: Int, left: TreeNode, right: TreeNode) 9 | extends TreeNode 10 | 11 | case object Leaf extends TreeNode { 12 | override val rank = 0 13 | } 14 | 15 | def makeNode(v: Int, left: TreeNode, right: TreeNode): Node = 16 | if (left.rank >= right.rank) Node(left.rank + 1, v, left, right) 17 | else Node(right.rank + 1, v, right, left) 18 | 19 | def merge(node1: TreeNode, node2: TreeNode): TreeNode = (node1, node2) match { 20 | case (node1, Leaf) => node1 21 | case (Leaf, node2) => node2 22 | case (Node(_, x, a1, b1), Node(_, y, a2, b2)) => { 23 | if (x < y) makeNode(x, a1, merge(b1, node2)) 24 | else makeNode(y, a2, merge(node1, b2)) 25 | } 26 | } 27 | 28 | def insert(v: Int, h: TreeNode): TreeNode = { 29 | val singleTree = makeNode(v, Leaf, Leaf) 30 | merge(singleTree, h) 31 | } 32 | 33 | def min (h:TreeNode): Int = h match { 34 | case Leaf => throw new IllegalArgumentException("Empty tree") 35 | case (Node(_, x, _, _)) => x 36 | } 37 | 38 | def pop(h:TreeNode): (Int, TreeNode) = h match { 39 | case Leaf => throw new IllegalArgumentException("Empty tree") 40 | case (Node(_, x, a, b)) => (x, merge(a, b)) 41 | } 42 | 43 | def empty: TreeNode = Leaf 44 | 45 | val q = List(1, 2, 3, 4, 5).foldLeft(empty)((a, b) => insert(b, a)) 46 | 47 | val (one, q1) = pop(q) 48 | println(one) 49 | 50 | val (two, q2) = pop(q1) 51 | println(two) 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /Chapter08/readme.txt: -------------------------------------------------------------------------------- 1 | Compile the scala file 2 | 3 | % scalac *.scala 4 | 5 | % scala com.fpdatastruct.queue.LeftistHeap 6 | 1 7 | 2 8 | % scala com.fpdatastruct.queue.Fifo 9 | 1 10 | 2 11 | 12 | -------------------------------------------------------------------------------- /Chapter09/ClojureCode.txt: -------------------------------------------------------------------------------- 1 | ; Lazy Evaluation in Clojure 2 | (def lazyVal (delay 10)) 3 | lazyVal 4 | (realized? lazyVal) 5 | (class lazyVal) 6 | (deref lazyVal) 7 | lazyVal 8 | (realized? lazyVal) 9 | (def lazyVal (delay 10)) 10 | (force lazyVal) 11 | (def lazyVal (delay 10)) 12 | @lazyVal 13 | (def fp (promise)) 14 | (realized? fp) 15 | (deliver fp (str "MyString")) 16 | (realized? fp) 17 | fp 18 | (deref fp) 19 | (def lazyDate ( delay (new java.util.Date))) 20 | lazyDate 21 | (def simpleDate (new java.util.Date)) 22 | simpleDate 23 | (count [1,2,3,4,5]) 24 | simpleDate 25 | (deref lazyDate) 26 | 27 | 28 | ;Memoization in Clojure 29 | (defn simpleFactFun [n] 30 | (if (or (= n 1) (= n 0)) 1 31 | ( do 32 | (println "Calculating Factorial") 33 | ( * n (simpleFactFun (dec n)))) 34 | ) 35 | ) 36 | 37 | (simpleFactFun 5) 38 | 39 | (def memoizedFactFun (memoize simpleFactFun)) 40 | 41 | (memoizedFactFun 5) 42 | 43 | (memoizedFactFun 5) 44 | 45 | ;Streams (lazy sequence) in Clojure 46 | 47 | (defn strFun [n] 48 | ( lazy-seq (println "Evaluating next element of Stream") (cons n (strFun (inc n))))) 49 | 50 | (take 3 (strFun 1)) 51 | 52 | ;Creating a memoized function of lazy sequences in Clojure 53 | 54 | (defn strFun [n] 55 | ( lazy-seq (println "Evaluating next element of Stream") (cons n (strFun (inc n))))) 56 | 57 | (def memzstrFun (memoize strFun)) 58 | 59 | (take 3 (memzstrFun 1)) 60 | 61 | (take 3 (memzstrFun 1)) 62 | 63 | ;Arithmetic progression in Clojure 64 | 65 | (defn arithmeticProgression [ft cd] 66 | ( lazy-seq (cons ft (arithmeticProgression (+ ft cd) cd)))) 67 | 68 | (println (take 10 (arithmeticProgression 2 3))) 69 | 70 | ;Standard Brownian Motion in Clojure 71 | 72 | (defn brownianPathGenerator [x] ;; Line One 73 | (def rndm (java.util.Random.)) ;; Line Two 74 | (def y (.nextGaussian rndm)) ;; Line Three 75 | (lazy-seq (cons x (brownianPathGenerator (+ x y))))) ;; Line Four 76 | 77 | (take 10 (brownianPathGenerator 0)) 78 | 79 | ;;;;;;;Fibonacci Series in Clojure 80 | 81 | (defn fiboSeries [x y] 82 | (lazy-seq (cons x (fiboSeries y (+ x y))))) 83 | 84 | (take 5 (fiboSeries 0 1)) 85 | 86 | (take 5 (fiboSeries 1 1)) 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /Chapter09/ScalaCode.txt: -------------------------------------------------------------------------------- 1 | //Eager Evaluation 2 | var fv = 5 3 | 4 | def leftBool(x : Int) : Boolean ={ 5 | println("Left Function") 6 | x > 5 7 | } 8 | 9 | def rightBool(x : Int) : Boolean = { 10 | println(" Right Function") 11 | x < 6 12 | } 13 | 14 | val x = 3 15 | leftBool(x) && rightBool(x) 16 | val x = 6 17 | leftBool(x) && rightBool(x) 18 | 19 | // Lazy Evaluation 20 | var sv = 5 21 | sv = 6 22 | val svc = 5 23 | svc = 6 24 | val sv = 5 25 | lazy val svl = 5 26 | lazy var svl = 5 27 | // Lazy Value date example 28 | import java.util.Calendar //Line One 29 | lazy val lazyDate = Calendar.getInstance.getTime //Line Two 30 | val simpleDate = Calendar.getInstance.getTime // Line Three 31 | val rl = 1 to 20 //Line Four 32 | for(x <- rl) print(x) //Line Five 33 | println("Simple Date Variable Value Is : " + simpleDate) // Line Six 34 | println("Lazy Date Variable Value Is : " + lazyDate) // Line Seven 35 | 36 | //// Memoization 37 | val ab = scala.collection.mutable.ArrayBuffer(1,2,3,4) \\ Line one 38 | print(ab.remove(1)) // Line Two 39 | print(ab.remove(1)) // Line Three 40 | print(ab.remove(1)) // Line Four 41 | 42 | 43 | class Multiply { 44 | def mult(num: Int) : Int = num*2 45 | } 46 | 47 | val myMult = new Multiply() \\Line One 48 | print(myMult.mult(4)) \\Line Two 49 | print(myMult.mult(4)) \\Line three 50 | 51 | //Memoization in Scala 52 | class SimpleFactorial{ 53 | def simpleFactFun(num : Int) : Int ={ 54 | if(num == 0 || num == 1) 55 | 1 56 | else{ 57 | println("Calculating Factorial") 58 | num*simpleFactFun(num-1) 59 | } 60 | } 61 | } 62 | 63 | val simpleFact = new SimpleFactorial() 64 | var factValue = simpleFact.simpleFactFun(5) 65 | 66 | var factValue = simpleFact.simpleFactFun(5) 67 | 68 | class MemoizedFactorial{ 69 | var memoized : Map[Int,Int] = Map() 70 | 71 | def lookupFunction(id : Int) :Int = memoized.getOrElse(id,0) 72 | 73 | def memoizedFactFun(num : Int) : Int ={ 74 | if(num == 0 || num == 1) 75 | 1 76 | else if (lookupFunction(num) > 0) 77 | lookupFunction(num) 78 | else{ 79 | val fact = num*memoizedFactFun(num-1) 80 | println("In memoizing part") 81 | memoized += num -> fact 82 | fact 83 | } 84 | } 85 | 86 | } 87 | 88 | 89 | var memFact = new MemoizedFactorial() 90 | 91 | var factValue = memFact.memoizedFactFun(5) 92 | 93 | var factValue = memFact.memoizedFactFun(5) 94 | 95 | var factValue = memFact.memoizedFactFun(4) 96 | 97 | var factValue = memFact.memoizedFactFun(3) 98 | 99 | //Stream in Scala 100 | 101 | import scala.Stream 102 | var ms = Stream("a","b","c","d","e") 103 | 104 | print(ms) 105 | 106 | 107 | //Indexing the elements of Stream 108 | 109 | ms(0) 110 | 111 | ms(2) 112 | 113 | print(ms) 114 | 115 | //Creation of a infinite length Stream 116 | 117 | var msc = 1 #:: 2 #:: empty 118 | 119 | empty 120 | 121 | var ms = cons(1, empty) 122 | 123 | 124 | def strFun(n : Int) : Stream[Int] = { 125 | println("Evaluating next element of Stream") 126 | cons(n,strFun(n+1)) 127 | } 128 | 129 | var infStr = strFun(1) 130 | 131 | 132 | infStr(0) 133 | 134 | infStr(1) 135 | 136 | infStr(1) 137 | 138 | //Stream is Immutable 139 | 140 | infStr(1) 141 | 142 | infStr(1) = 10 143 | 144 | //Creation of a Stream from another 145 | 146 | var minfStr = infStr.map(x => x*x) 147 | 148 | minfStr(2) 149 | 150 | minfStr(2) 151 | 152 | def mapStr( x : Int) : Int = { 153 | println("Mapping Values") 154 | x*x 155 | } 156 | 157 | var infStr = strFun(1) 158 | 159 | 160 | 161 | var minfStr = infStr.map(x => mapStr(x)) 162 | 163 | 164 | 165 | 166 | minfStr(2) 167 | 168 | 169 | 170 | minfStr(2) 171 | 172 | 173 | //Stream to List 174 | 175 | var ls = infStr.toList 176 | 177 | var strm = Stream(1,2,3,4,5) 178 | 179 | 180 | var ls = strm.toList 181 | 182 | 183 | 184 | //Apending one Stream to another 185 | 186 | var strm = Stream(1,2,3,4,5) 187 | 188 | 189 | var strm1 = Stream(6,7,8) 190 | 191 | var astrm = strm.append(strm1) 192 | 193 | //Length of a Stream 194 | 195 | astrm.length 196 | 197 | //Some mathematical function of Stream class 198 | 199 | astrm.sum 200 | 201 | astrm.max 202 | 203 | astrm.min 204 | 205 | 206 | 207 | //Some more methods of Stream class 208 | 209 | var strm = Stream(1,2,3,4,5) 210 | strm.count(x => x%2==0) 211 | 212 | strm 213 | 214 | strm.find(x => x >3) 215 | 216 | //Arithmetic progression in Scala 217 | 218 | import Stream._ 219 | 220 | def arithmeticProgression(ft : Double, cd: Double ) : Stream[Double] = { 221 | cons(ft, arithmeticProgression(ft+cd, cd )) 222 | } 223 | 224 | 225 | val ap = arithmeticProgression(2,3) 226 | 227 | print(ap.take(5).toList) 228 | 229 | //Standard Brownian Motion in Scala 230 | 231 | import Stream._ 232 | 233 | def brownianPathGenerator( x : Double) : Stream[Double] = { 234 | val y = scala.util.Random.nextGaussian 235 | cons(x, brownianPathGenerator(x+y)) 236 | } 237 | 238 | val brownianPath = brownianPathGenerator( 0 ).take(10) 239 | 240 | brownianPath.toList.foreach(println) 241 | 242 | //Fibonacci Series in Scala 243 | 244 | import Stream._ 245 | 246 | def fiboSeries(x : BigInt, y : BigInt) : Stream[BigInt] = { 247 | cons(x,fiboSeries(y,x+y)) 248 | } 249 | 250 | val fibSeriesWithZero = fiboSeries(0,1) 251 | 252 | fibSeriesWithZero.take(5).foreach(println) 253 | 254 | val fibSeriesWithOne = fiboSeries(1,1) 255 | 256 | fibSeriesWithOne.take(5).foreach(println) 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | -------------------------------------------------------------------------------- /Chapter09/allinfiniteStreamCreation.scala: -------------------------------------------------------------------------------- 1 | // Written by Raju 2 | // Run it using following command 3 | // scala allinfiniteStreamCreation.scala 4 | 5 | 6 | import scala.Stream._ 7 | 8 | 9 | 10 | //Creation of a infinite length Stream 11 | 12 | var msc = 1 #:: 2 #:: empty 13 | 14 | println(empty) 15 | 16 | var ms = cons(1, empty) 17 | 18 | 19 | def strFun(n : Int) : Stream[Int] = { 20 | println("Evaluating next element of Stream") 21 | cons(n,strFun(n+1)) 22 | } 23 | 24 | var infStr = strFun(1) 25 | 26 | println("Printing first element of Stream") 27 | println("--------------------------------") 28 | println(infStr(0)) 29 | println("Printing second element of Stream") 30 | println("--------------------------------") 31 | println(infStr(1)) 32 | println("Printing second element of Stream") 33 | println("--------------------------------") 34 | println(infStr(1)) 35 | 36 | 37 | //Creation of a Stream from another 38 | 39 | var minfStr = infStr.map(x => x*x) 40 | println("Printing third element of Stream") 41 | println("--------------------------------") 42 | println(minfStr(2)) 43 | 44 | println(minfStr(2)) 45 | 46 | def mapStr( x : Int) : Int = { 47 | println("Mapping Values") 48 | x*x 49 | } 50 | 51 | infStr = strFun(1) 52 | 53 | 54 | 55 | minfStr = infStr.map(x => mapStr(x)) 56 | 57 | 58 | 59 | 60 | println(minfStr(2)) 61 | 62 | println(minfStr(2)) 63 | 64 | 65 | //Stream to List 66 | 67 | //var ls = infStr.toList 68 | 69 | var strm = Stream(1,2,3,4,5) 70 | 71 | var ls = strm.toList 72 | 73 | 74 | 75 | //Apending one Stream to another 76 | 77 | strm = Stream(1,2,3,4,5) 78 | 79 | 80 | var strm1 = Stream(6,7,8) 81 | 82 | var astrm = strm.append(strm1) 83 | 84 | 85 | 86 | //Length of a Stream 87 | println("Printing Stream Leangth") 88 | println("-----------------------") 89 | println(astrm.length) 90 | 91 | //Some mathematical function of Stream class 92 | println("Printing Stream Summation") 93 | println("-------------------------") 94 | println(astrm.sum) 95 | println("Printing Stream Maximum") 96 | println("-----------------------") 97 | println(astrm.max) 98 | println("Printing Stream Minimum") 99 | println("-----------------------") 100 | println(astrm.min) 101 | 102 | 103 | 104 | //Some more methods of Stream class 105 | 106 | strm = Stream(1,2,3,4,5) 107 | strm.count(x => x%2==0) 108 | println("Printing Stream After Count") 109 | println("---------------------------") 110 | println(strm) 111 | 112 | println(strm.find(x => x >3)) 113 | 114 | 115 | -------------------------------------------------------------------------------- /Chapter09/arithmeticProgression.clj: -------------------------------------------------------------------------------- 1 | ; Written by Raju 2 | ; Run using following command 3 | ; clojure arithmeticProgression.clj 4 | 5 | ;Arithmetic progression in Clojure 6 | 7 | (defn arithmeticProgression [ft cd] 8 | ( lazy-seq (cons ft (arithmeticProgression (+ ft cd) cd)))) 9 | 10 | (println (take 10 (arithmeticProgression 2 3))) 11 | 12 | -------------------------------------------------------------------------------- /Chapter09/arithmeticProgression.scala: -------------------------------------------------------------------------------- 1 | // Written by Raju 2 | // Run it using following command 3 | // scala arithmeticProgression.scala 4 | 5 | import Stream._ 6 | 7 | def arithmeticProgression(ft : Double, cd: Double ) : Stream[Double] = { 8 | cons(ft, arithmeticProgression(ft+cd, cd )) 9 | } 10 | 11 | 12 | val ap = arithmeticProgression(2,3) 13 | println("Printing Arithmetic Progression with first element 2 and common difference 3") 14 | println("-----------------------------------------------------------------------------") 15 | print(ap.take(5).toList) 16 | -------------------------------------------------------------------------------- /Chapter09/eagerEvaluation.scala: -------------------------------------------------------------------------------- 1 | // Written by Raju 2 | // Run it using following command 3 | //scala eagerEvaluation.scala 4 | //Eager Evaluation 5 | var fv = 5 6 | 7 | def leftBool(x : Int) : Boolean ={ 8 | println("Left Function") 9 | x > 5 10 | } 11 | 12 | def rightBool(x : Int) : Boolean = { 13 | println(" Right Function") 14 | x < 6 15 | } 16 | 17 | var x = 3 18 | println(leftBool(x) && rightBool(x)) 19 | x = 6 20 | println(leftBool(x) && rightBool(x)) 21 | -------------------------------------------------------------------------------- /Chapter09/fiboSeries.clj: -------------------------------------------------------------------------------- 1 | ; Written by Raju 2 | ; Run using following command 3 | ; clojure fiboSeries.clj 4 | ;Fibonacci Series in Clojure 5 | 6 | (defn fiboSeries [x y] 7 | (lazy-seq (cons x (fiboSeries y (+ x y))))) 8 | 9 | (println (take 5 (fiboSeries 0 1))) 10 | 11 | (println (take 5 (fiboSeries 1 1))) 12 | 13 | -------------------------------------------------------------------------------- /Chapter09/fiboSeries.scala: -------------------------------------------------------------------------------- 1 | // Written by Raju 2 | // Run it using following command 3 | // scala fiboSeries.scala 4 | import Stream._ 5 | def fiboSeries(x : BigInt, y : BigInt) : Stream[BigInt] = { 6 | cons(x,fiboSeries(y,x+y)) 7 | } 8 | 9 | val fibSeriesWithZero = fiboSeries(0,1) 10 | println("Printing Fibonacci series with start element 1 and 1") 11 | println("----------------------------------------------------") 12 | fibSeriesWithZero.take(5).foreach(println) 13 | println("Printing Fibonacci series with start element 1 and 1") 14 | println("----------------------------------------------------") 15 | val fibSeriesWithOne = fiboSeries(1,1) 16 | fibSeriesWithOne.take(5).foreach(println) 17 | -------------------------------------------------------------------------------- /Chapter09/immutableStream.scala: -------------------------------------------------------------------------------- 1 | // Written by Raju 2 | // Run it using following command 3 | // scala immutableStream.scala 4 | 5 | 6 | import scala.Stream._ 7 | 8 | 9 | 10 | 11 | def strFun(n : Int) : Stream[Int] = { 12 | println("Evaluating next element of Stream") 13 | cons(n,strFun(n+1)) 14 | } 15 | 16 | var infStr = strFun(1) 17 | 18 | 19 | println("Printing second element of Stream") 20 | println("--------------------------------") 21 | println(infStr(1)) 22 | 23 | //Stream is Immutable 24 | 25 | try{ 26 | infStr(1) = 10 27 | }catch{ 28 | case e:Throwable => println(e) 29 | } 30 | 31 | -------------------------------------------------------------------------------- /Chapter09/lazyEvaluation.clj: -------------------------------------------------------------------------------- 1 | ; Written by Raju 2 | ; Run using following command 3 | ; clojure lazyEvaluation.clj 4 | ; Lazy Evaluation in Clojure 5 | (def lazyVal (delay 10)) 6 | (println lazyVal) 7 | (println (realized? lazyVal)) 8 | (println (class lazyVal)) 9 | (println (deref lazyVal)) 10 | (println lazyVal) 11 | (println (realized? lazyVal)) 12 | (println (def lazyVal (delay 10))) 13 | 14 | (println (force lazyVal)) 15 | (println (def lazyVal (delay 10))) 16 | (println @lazyVal) 17 | (println (def fp (promise))) 18 | (println (realized? fp)) 19 | (println (deliver fp (str "MyString"))) 20 | (println (realized? fp)) 21 | (println fp) 22 | (println (deref fp)) 23 | (println (def lazyDate ( delay (new java.util.Date)))) 24 | (println lazyDate ) 25 | (println (def simpleDate (new java.util.Date))) 26 | (println simpleDate) 27 | (println (count [1,2,3,4,5])) 28 | (println simpleDate) 29 | (println (deref lazyDate)) 30 | -------------------------------------------------------------------------------- /Chapter09/lazyEvaluation.scala: -------------------------------------------------------------------------------- 1 | // Written by Raju 2 | // Run it using following command 3 | // scala lazyEvaluation.scala 4 | var sv = 5 5 | sv = 6 6 | val svc = 5 7 | sv = 5 8 | lazy val svl = 5 9 | // Lazy Value date example 10 | import java.util.Calendar //Line One 11 | lazy val lazyDate = Calendar.getInstance.getTime //Line Two 12 | val simpleDate = Calendar.getInstance.getTime // Line Three 13 | val rl = 1 to 20 //Line Four 14 | for(x <- rl) print(x) //Line Five 15 | println("Simple Date Variable Value Is : " + simpleDate) // Line Six 16 | println("Lazy Date Variable Value Is : " + lazyDate) // Line Seven 17 | 18 | -------------------------------------------------------------------------------- /Chapter09/memoization.clj: -------------------------------------------------------------------------------- 1 | ; Written by Raju 2 | ; Run using following command 3 | ; clojure memoization.clj 4 | ;Memoization in Clojure 5 | (defn simpleFactFun [n] 6 | (if (or (= n 1) (= n 0)) 1 7 | ( do 8 | (println "Calculating Factorial") 9 | ( * n (simpleFactFun (dec n)))) 10 | ) 11 | ) 12 | 13 | (println (simpleFactFun 5)) 14 | 15 | (def memoizedFactFun (memoize simpleFactFun)) 16 | 17 | (println (memoizedFactFun 5)) 18 | 19 | (println (memoizedFactFun 5)) 20 | 21 | 22 | -------------------------------------------------------------------------------- /Chapter09/memoization.scala: -------------------------------------------------------------------------------- 1 | // Written by Raju 2 | // Run it using following command 3 | // scala memoization.scala 4 | 5 | val ab = scala.collection.mutable.ArrayBuffer(1,2,3,4) // Line one 6 | print(ab.remove(1)) // Line Two 7 | print(ab.remove(1)) // Line Three 8 | print(ab.remove(1)) // Line Four 9 | 10 | 11 | class Multiply { 12 | def mult(num: Int) : Int = num*2 13 | } 14 | 15 | val myMult = new Multiply() //Line One 16 | print(myMult.mult(4)) //Line Two 17 | print(myMult.mult(4)) //Line three 18 | 19 | //Memoization in Scala 20 | class SimpleFactorial{ 21 | def simpleFactFun(num : Int) : Int ={ 22 | if(num == 0 || num == 1) 23 | 1 24 | else{ 25 | println("Calculating Factorial") 26 | num*simpleFactFun(num-1) 27 | } 28 | } 29 | } 30 | 31 | val simpleFact = new SimpleFactorial() 32 | var factValue = simpleFact.simpleFactFun(5) 33 | 34 | factValue = simpleFact.simpleFactFun(5) 35 | 36 | class MemoizedFactorial{ 37 | var memoized : Map[Int,Int] = Map() 38 | 39 | def lookupFunction(id : Int) :Int = memoized.getOrElse(id,0) 40 | 41 | def memoizedFactFun(num : Int) : Int ={ 42 | if(num == 0 || num == 1) 43 | 1 44 | else if (lookupFunction(num) > 0) 45 | lookupFunction(num) 46 | else{ 47 | val fact = num*memoizedFactFun(num-1) 48 | println("In memoizing part") 49 | memoized += num -> fact 50 | fact 51 | } 52 | } 53 | 54 | } 55 | 56 | 57 | var memFact = new MemoizedFactorial() 58 | 59 | factValue = memFact.memoizedFactFun(5) 60 | 61 | factValue = memFact.memoizedFactFun(5) 62 | 63 | factValue = memFact.memoizedFactFun(4) 64 | 65 | factValue = memFact.memoizedFactFun(3) 66 | 67 | -------------------------------------------------------------------------------- /Chapter09/standardBrownianMotion.clj: -------------------------------------------------------------------------------- 1 | ; Written by Raju 2 | ; Run using following command 3 | ; clojure standardBrownianMotion.clj 4 | ;Standard Brownian Motion in Clojure 5 | 6 | (defn brownianPathGenerator [x] ;; Line One 7 | (def rndm (java.util.Random.)) ;; Line Two 8 | (def y (.nextGaussian rndm)) ;; Line Three 9 | (lazy-seq (cons x (brownianPathGenerator (+ x y))))) ;; Line Four 10 | 11 | (println (take 10 (brownianPathGenerator 0))) 12 | 13 | -------------------------------------------------------------------------------- /Chapter09/standardBrownianMotion.scala: -------------------------------------------------------------------------------- 1 | // Written by Raju 2 | // Run it using following command 3 | // scala standardBrownianMotion.scala 4 | 5 | import Stream._ 6 | 7 | def brownianPathGenerator( x : Double) : Stream[Double] = { 8 | val y = scala.util.Random.nextGaussian 9 | cons(x, brownianPathGenerator(x+y)) 10 | } 11 | 12 | val brownianPath = brownianPathGenerator( 0 ).take(10) 13 | println("Printing 10 elements of a Standard Brownian Path") 14 | println("------------------------------------------------") 15 | brownianPath.toList.foreach(println) 16 | -------------------------------------------------------------------------------- /Chapter09/streamCreationAndIndexing.scala: -------------------------------------------------------------------------------- 1 | // Written by Raju 2 | // Run it using following command 3 | // scala streamCreationAndIndexing.scala 4 | 5 | import scala.Stream 6 | var ms = Stream("a","b","c","d","e") 7 | println("Printing created Stream") 8 | println("-----------------------") 9 | println(ms) 10 | println("-----------------------") 11 | 12 | //Indexing the elements of Stream 13 | println("Printing first element of Stream") 14 | println("--------------------------------") 15 | println(ms(0)) 16 | println("Printing third element of Stream") 17 | println("--------------------------------") 18 | println(ms(2)) 19 | 20 | println(ms) 21 | -------------------------------------------------------------------------------- /Chapter09/streamSequence.clj: -------------------------------------------------------------------------------- 1 | ; Written by Raju 2 | ; Run using following command 3 | ; clojure streamSequence.clj 4 | ;Streams (lazy sequence) in Clojure 5 | 6 | (defn strFun [n] 7 | ( lazy-seq (println "Evaluating next element of Stream") (cons n (strFun (inc n))))) 8 | 9 | (println (take 3 (strFun 1))) 10 | 11 | ;Creating a memoized function of lazy sequences in Clojure 12 | 13 | (defn strFun [n] 14 | ( lazy-seq (println "Evaluating next element of Stream") (cons n (strFun (inc n))))) 15 | 16 | (def memzstrFun (memoize strFun)) 17 | 18 | (println (take 3 (memzstrFun 1))) 19 | 20 | (println (take 3 (memzstrFun 1))) 21 | 22 | -------------------------------------------------------------------------------- /Chapter10/Deque.scala: -------------------------------------------------------------------------------- 1 | package com.fpdatastruct.deque 2 | 3 | object Deque extends App { 4 | 5 | case class Deque(outLen: Int, out: Stream[Int], inLen: Int, in: Stream[Int], c: Int = 2) { 6 | def pushFront(elem: Int): Deque = { 7 | adjustStreams(outLen + 1, Stream.cons(elem, out), inLen, in, c) 8 | } 9 | 10 | def popFront(): (Int, Deque) = { 11 | out match { 12 | case Stream.Empty => throw new IllegalArgumentException("Empty queue") 13 | case x #:: newOut => (x, adjustStreams(outLen - 1, newOut, inLen, in, c)) 14 | } 15 | } 16 | } 17 | 18 | def adjustStreams(outLen: Int, out: Stream[Int], inLen: Int, in: Stream[Int], c: Int): Deque = { 19 | if (outLen > c*inLen+1) { 20 | val newOutLen = (outLen+inLen)/2 21 | val newInLen = outLen + inLen - newOutLen 22 | 23 | val newOut = out.take(newOutLen) 24 | val newIn = in append out.drop(newInLen).reverse 25 | 26 | Deque(newOutLen, newOut, newInLen, newIn, c) 27 | } else if (inLen > c*outLen+1) { 28 | val newInLen = (outLen+inLen)/2 29 | val newOutLen = outLen + inLen - newInLen 30 | 31 | val newIn = in.take(newInLen) 32 | val newOut = out append in.drop(newOutLen).reverse 33 | 34 | Deque(newOutLen, newOut, newInLen, newIn, c) 35 | } else 36 | Deque(outLen, out, inLen, in, c) 37 | } 38 | 39 | val dq = Deque(0, Stream.Empty, 0, Stream.Empty) 40 | val dq1 = dq.pushFront(1) 41 | val dq2 = dq1.pushFront(2) 42 | val dq3 = dq2.pushFront(3) 43 | 44 | val (x,p) = dq3.popFront() 45 | println(x) 46 | 47 | val (y,p1) = p.popFront() 48 | println(y) 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /Chapter10/LazyQueue.scala: -------------------------------------------------------------------------------- 1 | package com.fpdatastruct.deque 2 | 3 | import scala.collection.SeqView 4 | 5 | object LazyQueue extends App { 6 | 7 | case class LazyQueue(out: Stream[Int], outLen: Int, in: List[Int], inLen: 8 | Int) { 9 | 10 | def push(elem: Int) = { 11 | makeLazyQueue(out, outLen, elem :: in, inLen + 1) 12 | } 13 | 14 | def pop: (Int, LazyQueue) = { 15 | (out.head, makeLazyQueue(out.tail, outLen - 1, in, inLen)) 16 | } 17 | 18 | def empty = out.isEmpty && in.isEmpty 19 | } 20 | 21 | def makeLazyQueue(out: Stream[Int], outLen: Int, in: List[Int], inLen: Int): LazyQueue 22 | = if (inLen <= outLen) { 23 | LazyQueue(out, outLen, in, inLen) 24 | } else { 25 | val newOutStream = copyInToOut(out, in, Stream.empty) 26 | val newOutSize = outLen + inLen 27 | val newInList = Nil 28 | val newInSize = 0 29 | 30 | LazyQueue(newOutStream, newOutSize, newInList, newInSize) 31 | } 32 | 33 | def copyInToOut(out: Stream[Int], in: List[Int], revIn: Stream[Int]): Stream[Int] = { 34 | in match { 35 | case Nil => Stream.empty 36 | case x :: xs if out.isEmpty => Stream.cons(x, revIn) 37 | case x :: xs => 38 | Stream.cons(out.head, copyInToOut(out.tail, in.tail, 39 | Stream.cons(x, 40 | revIn))) 41 | 42 | } 43 | } 44 | 45 | val emptyQ = makeLazyQueue(Stream.empty, 0, Nil, 0) 46 | val q = List(10, 20, 30).foldLeft(emptyQ)((acc, x) => acc.push(x)) 47 | 48 | val (a1, q1) = q.pop 49 | println(s"a1 = ${a1}, q1 = ${q1}") 50 | 51 | val (a2, q2) = q1.pop 52 | println(s"a2 = ${a2}, q1 = ${q2}") 53 | 54 | val (a3, q3) = q2.pop 55 | println(s"a3 = ${a3}, q1 = ${q3}") 56 | 57 | } 58 | 59 | -------------------------------------------------------------------------------- /Chapter11/RBTree.scala: -------------------------------------------------------------------------------- 1 | package com.fpdatastruct.rbtrees 2 | 3 | object RBTree extends App { 4 | 5 | sealed trait Color 6 | 7 | case object Red extends Color 8 | 9 | case object Black extends Color 10 | 11 | sealed abstract class Tree { 12 | def color: Color 13 | } 14 | 15 | case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree { 16 | override def toString = left.toString + " " + value.toString + " " + right.toString 17 | } 18 | 19 | case object End extends Tree { 20 | override def toString = "." 21 | 22 | override val color: Color = Black 23 | } 24 | 25 | def insert(v: Int, t: Tree): Tree = { 26 | def ins(s: Tree): Tree = s match { 27 | case End => Node(Red, End, v, End) 28 | case node@Node(_, left, value, right) => 29 | val root = if (v < value) balance(node.copy(left = ins(left))) 30 | else if (v > value) balance(node.copy(right = ins(right))) 31 | else node 32 | root match { 33 | case node@Node(Red, _, _, _) => node.copy(color = Black) 34 | case _ => root 35 | } 36 | } 37 | ins(t) 38 | } 39 | 40 | def balance(ggParent: Node): Tree = 41 | ggParent match { 42 | case Node(Black, gParent@Node(Red, parent@Node(Red, ggChild1, _, ggChild2), _, gChild), _, child) => 43 | gParent.copy(color = Red, 44 | left = parent.copy(color = Black), 45 | right = ggParent.copy(color = Black, left = gChild, right = child)) 46 | case Node(Black, gParent@Node(Red, gChild, _, parent@Node(Red, ggChild1, _, ggChild2)), _, child) => 47 | parent.copy(color = Red, 48 | left = gParent.copy(color = Black, right = ggChild1), 49 | right = ggParent.copy(color = Black, left = ggChild2, right = child)) 50 | case Node(Black, child, _, gParent@Node(Red, gChild, _, parent@Node(Red, ggChild1, 51 | _, ggChild2))) => gParent.copy(color = Red, 52 | left = ggParent.copy(color = Black, left = child, 53 | right = parent.copy(color = Black))) 54 | case Node(Black, child, _, gParent@Node(Red, parent@Node(Red, ggChild1, _, 55 | ggChild2), _, gChild)) => 56 | parent.copy(color = Red, left = ggParent.copy(color = Black, ggChild1), 57 | right = gParent.copy(color = Black, left = ggChild2)) 58 | case _ => ggParent 59 | } 60 | 61 | def end: Tree = End 62 | 63 | val t = List(10, 20, 30, 40).foldLeft(end)((tree, elem) => insert(elem, tree)) 64 | 65 | println(t) 66 | } 67 | 68 | -------------------------------------------------------------------------------- /Chapter11/readme.txt: -------------------------------------------------------------------------------- 1 | Compile the scala file 2 | 3 | % scalac RBTree.scala 4 | 5 | % scala 6 | ... 7 | 8 | scala> import com.fpdatastruct.rbtrees.RBTree._ 9 | import com.fpdatastruct.rbtrees.RBTree._ 10 | 11 | scala> val t = List(10, 20, 30, 40).foldLeft(end)((tree, elem) => insert(elem, tree)) 12 | t: com.fpdatastruct.rbtrees.RBTree.Tree = . 10 . 20 . 30 . 40 . 13 | 14 | scala> println(t) 15 | . 10 . 20 . 30 . 40 . 16 | 17 | -------------------------------------------------------------------------------- /Chapter12/BinomialHeap.scala: -------------------------------------------------------------------------------- 1 | package com.fpdatastruct.binomealheaps 2 | 3 | import com.fpdatastruct.binomealheaps.BinomialHeap.Node 4 | 5 | 6 | object BinomialHeap extends App { 7 | case class Node(rank: Int, v: Int, children: List[Node]) 8 | 9 | def linkUp(t1: Node, t2: Node) = 10 | if (t1.v <= t2.v) 11 | Node(t1.rank+1, t1.v, t2 :: t1.children) 12 | else 13 | Node(t1.rank+1, t2.v, t1 :: t2.children) 14 | 15 | def insert(t: Node, rootList: List[Node]): List[Node] = rootList match { 16 | case Nil => List(t) 17 | case x :: xs if (t.rank < x.rank) => t :: rootList 18 | case x :: xs => insert(linkUp(t, x), xs) 19 | } 20 | 21 | def insertElem(rtList: List[Node], elem: Int) = { 22 | insert(Node(0, elem, Nil), rtList) 23 | } 24 | 25 | def merge(ts1: List[Node], ts2: List[Node]): List[Node] = (ts1, ts2) match { 26 | case (ts1, Nil) => ts1 27 | case (Nil, ts2) => ts2 28 | case (t1 :: ts11, t2 :: ts22) if (t1.rank < t2.rank) => t1 :: merge(ts11, ts2) 29 | case (t1 :: ts11, t2 :: ts22) if (t2.rank < t1.rank) => t2 :: merge(ts1, ts22) 30 | case (t1 :: ts11, t2 :: ts22) => insert(linkUp(t1, t2), merge(ts11, ts22)) 31 | } 32 | 33 | def findMin(rootList: List[Node]): Node = rootList min (Ordering.by((p: Node) => p.v)) 34 | 35 | def removeMin(rootList: List[Node]): List[Node] = { 36 | val min = findMin(rootList) 37 | val listExceptMin = rootList filterNot(_ == min) 38 | merge(listExceptMin, min.children) 39 | } 40 | 41 | val list = List(13, 12, 24, 4, 15, 28, 21, 9, 11, 17, 32, 14, 20, 41, 30) 42 | 43 | val v = list.foldLeft[List[Node]](List[Node]())(insertElem) 44 | 45 | val min = findMin(v) 46 | 47 | println(min.v) 48 | 49 | val v1 = removeMin(v) 50 | 51 | val min1 = findMin(v1) 52 | 53 | println(min1.v) 54 | 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /Chapter12/readme.txt: -------------------------------------------------------------------------------- 1 | % scalac BinomialHeap.scala 2 | % scala com.fpdatastruct.binomealheaps.BinomialHeap 3 | 4 4 | 9 5 | -------------------------------------------------------------------------------- /Chapter13/BubbleSort.scala: -------------------------------------------------------------------------------- 1 | 2 | 3 | package bubbleSort 4 | 5 | object BubbleSort { 6 | 7 | def getLargest[T <% Ordered[T]](data : List[T]): (T,List[T]) = { 8 | 9 | val fv = data.head 10 | val fl = data.tail 11 | if(fl == Nil) 12 | return (fv,Nil) 13 | val (fd, lso) = getLargest(fl) 14 | if(fd >= fv) 15 | (fd ,fv::lso) 16 | else 17 | (fv, fd :: lso) 18 | } 19 | 20 | def bubbleSort[T <% Ordered[T]](data : List[T]) : List[T] = data match { 21 | case Nil => Nil 22 | case _ => 23 | val (fv, sl) = getLargest(data) 24 | bubbleSort(sl):::List(fv) 25 | } 26 | 27 | def main(args: Array[String]) { 28 | 29 | val intData:List[Integer] = List(1,3,5,2,6) 30 | val largestInteger = getLargest(intData) 31 | println(largestInteger) 32 | 33 | val sortedIntegers = bubbleSort(intData) 34 | println(sortedIntegers) 35 | 36 | 37 | val charData: List[String] = List("a","c","b","d") 38 | val largestCharacter = getLargest(charData) 39 | println(largestCharacter) 40 | 41 | val sortedString = bubbleSort(charData) 42 | println(sortedString) 43 | 44 | } 45 | } -------------------------------------------------------------------------------- /Chapter13/InsertionSort.scala: -------------------------------------------------------------------------------- 1 | package insertionSort 2 | 3 | object InsertionSort { 4 | //Function to insert element in sorted List part 5 | def insertElement[T <% Ordered[T]](elm : T , sorted : List[T]): List[T]= { 6 | if(sorted == Nil){ 7 | return elm::sorted 8 | } 9 | val firstElement :: tailElement = sorted 10 | if (firstElement < elm) 11 | firstElement :: insertElement(elm,tailElement) 12 | else 13 | elm :: sorted 14 | } 15 | // Method for Insertion Sorting 16 | def insertionSort[T <% Ordered[T]](data : List[T]) : List[T] = { 17 | if(data == Nil) 18 | data 19 | else{ 20 | val firstElement = data.head 21 | val tailElement = data.tail 22 | val temp = insertionSort(tailElement) 23 | insertElement(firstElement, temp) 24 | } 25 | } 26 | 27 | def main(args: Array[String]) { 28 | val ls : List[Integer] = List(1,4,5) 29 | val v : Integer= 3 30 | val insertedList = insertElement(v,ls) 31 | println(insertedList) 32 | val intData:List[Integer] = List(1,3,5,2,6) 33 | val sortedIntegers = insertionSort(intData) 34 | println(sortedIntegers) 35 | 36 | 37 | val charData: List[String] = List("a","c","b","d") 38 | val sortedString = insertionSort(charData) 39 | println(sortedString) 40 | } 41 | } -------------------------------------------------------------------------------- /Chapter13/MergeSort.scala: -------------------------------------------------------------------------------- 1 | 2 | 3 | package mergeSort 4 | 5 | object MergeSort { 6 | 7 | def split[T <% Ordered[T]](fl : List[T]) :(List[T], List[T]) = { 8 | if(fl == Nil){ 9 | return(Nil,Nil) 10 | } 11 | val fv = fl.head 12 | val ls1 = fl.tail 13 | if (ls1 == Nil) { 14 | return(fv::Nil , Nil) 15 | } 16 | val sv = ls1.head 17 | val ls2 = ls1.tail 18 | val(tl1, tl2) = split(ls1.tail) 19 | return(fv::tl1, sv::tl2) 20 | } 21 | 22 | def merge [T <% Ordered[T]]( x: List[T], y : List[T]) : List[T] = (x,y) match { 23 | 24 | case (x, Nil) => x 25 | case (Nil,y) => y 26 | case( fm::fl, sm::sl) => if (fm > sm) sm::merge(x,sl) 27 | else fm::merge(fl,y) 28 | } 29 | def mergeSort [T <% Ordered[T]] (ls :List[T]): List[T] = { 30 | if( ls == Nil || ls.tail == Nil) 31 | return ls 32 | 33 | val (fl,sl) = split(ls) 34 | val lsm1 = mergeSort(fl) 35 | val lsm2 = mergeSort(sl) 36 | merge(lsm1, lsm2) 37 | } 38 | 39 | 40 | def main(args: Array[String]) { 41 | 42 | val intData:List[Integer] = List(1,3,5,2,6) 43 | val (firstList, secondList) = split(intData) 44 | println(firstList) 45 | println(secondList) 46 | 47 | val firstSortedList: List[Integer] = List(1,3,5) 48 | val secondSortedList : List[Integer] = List(2,6) 49 | val mergedList :List[Integer] = merge(firstSortedList,secondSortedList) 50 | 51 | val sortedIntegers = mergeSort(intData) 52 | println(sortedIntegers) 53 | 54 | val charData: List[String] = List("a","c","b","d") 55 | val (firstListChar, secondListChar) = split(charData) 56 | println(firstListChar) 57 | println(secondListChar) 58 | 59 | val firstSortedListChar: List[String] = List("a","c") 60 | val secondSortedListChar : List[String] = List("b","d") 61 | val mergedListChar :List[String] = merge(firstSortedListChar,secondSortedListChar) 62 | println(mergedListChar) 63 | 64 | val sortedInteger = mergeSort(intData) 65 | println(sortedInteger) 66 | 67 | val sortedString = mergeSort(charData) 68 | println(sortedString) 69 | } 70 | } -------------------------------------------------------------------------------- /Chapter13/QuickSort.scala: -------------------------------------------------------------------------------- 1 | 2 | 3 | package quickSort 4 | 5 | object QuickSort { 6 | //Method to get partition of a List at pivot location 7 | def partition[T <% Ordered[T]](elm : T, seq : List[T], fp :List[T], sp: List[T]): (List[T], List[T]) = seq match { 8 | case fe::fl => if (fe < elm) partition(elm, fl, fe::fp,sp) 9 | else 10 | partition(elm,fl,fp,fe::sp) 11 | case Nil => (fp,sp) 12 | 13 | } 14 | 15 | def quickSort[T <% Ordered[T]](data : List[T]): List[T] = data match { 16 | case Nil => Nil 17 | case fv:: Nil => List(fv) 18 | case fv::fl => { 19 | val (l1, l2) = partition( fv,fl, Nil,Nil) 20 | val lfl = quickSort(l1) 21 | val rhl = quickSort(l2) 22 | val tmp = fv :: rhl 23 | return lfl ++ tmp 24 | } 25 | } 26 | 27 | // Main Function 28 | def main(args: Array[String]) { 29 | val intData1:List[Integer] = List(3,5,2,6) 30 | val elm : Integer= 4 31 | val (firstList, secondList) = partition(elm,intData1,Nil, Nil) 32 | println(firstList) 33 | println(secondList) 34 | 35 | val intData:List[Integer] = List(1,3,5,2,6) 36 | val sortedIntegers = quickSort(intData) 37 | println(sortedIntegers) 38 | 39 | val charData: List[String] = List("a","c","b","d") 40 | val sortedString = quickSort(charData) 41 | println(sortedString) 42 | } 43 | } -------------------------------------------------------------------------------- /Chapter13/SelectionSort.scala: -------------------------------------------------------------------------------- 1 | 2 | 3 | package selectionSort 4 | 5 | object SelectionSort { 6 | def selectionSort[T <% Ordered[T]](data : List[T]): List[T] = data match { 7 | case Nil => Nil 8 | case fv::Nil => List(fv) 9 | case fv::fl => 10 | val minData = fl.min 11 | val minIndex = fl.indexOf(minData) 12 | if(fv <= minData) 13 | fv::selectionSort(fl) 14 | else{ 15 | val (fp,sp)= fl.splitAt(minIndex) 16 | sp.head::selectionSort(fp:::fv::sp.tail) 17 | } 18 | 19 | } 20 | def main(args: Array[String]) { 21 | val intData:List[Integer] = List(1,3,5,2,6) 22 | val sortedIntegers = selectionSort(intData) 23 | println(sortedIntegers) 24 | 25 | val charData: List[String] = List("a","c","b","d") 26 | val sortedString = selectionSort(charData) 27 | println(sortedString) 28 | } 29 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #Learning Functional Data Structures and Algorithms 5 | This is the code repository for [Learning Functional Data Structures and Algorithms](https://www.packtpub.com/application-development/learning-functional-data-structures-and-algorithms?utm_source=github&utm_medium=repository&utm_campaign=9781785888731), published by [Packt](https://www.packtpub.com/?utm_source=github). It contains all the supporting project files necessary to work through the book from start to finish. 6 | ## About the Book 7 | This book is about functional algorithms and data structures. Algorithms and data structures are fundamentals of computer programming. 8 | 9 | ##Instructions and Navigation 10 | All of the code is organized into folders. Each folder starts with a number followed by the application name. For example, Chapter02. 11 | 12 | 13 | 14 | The code will look like the following: 15 | ``` 16 | user=> (def v [7 11 19 52 42 72]) 17 | #'user/v 18 | user=> (def v1 (conj v 52)) 19 | #'user/v1 20 | ``` 21 | 22 | You need to install Scala and Clojure. All the examples were tested with Scala version 2.11.7. The Clojure examples were tested with Clojure version 1.6.0. You don’t need any IDE as most of the examples are small enough, so you can key them in the REPL (Read/Eval/Print Loop). 23 | 24 | You also need a text editor. Use whichever you are comfortable with. 25 | 26 | ##Related Data Structure and Algorithms Products 27 | * [Learning F# Functional Data Structures and Algorithms](https://www.packtpub.com/application-development/learning-f-functional-data-structures-and-algorithms?utm_source=github&utm_medium=repository&utm_campaign=9781783558476) 28 | 29 | * [Clojure Data Structures and Algorithms Cookbook](https://www.packtpub.com/application-development/clojure-data-structures-and-algorithms-cookbook?utm_source=github&utm_medium=repository&utm_campaign=9781785281457) 30 | 31 | * [R Data Structures and Algorithms](https://www.packtpub.com/application-development/r-data-structures-and-algorithms?utm_source=github&utm_medium=repository&utm_campaign=9781786465153) 32 | 33 | ###Suggestions and Feedback 34 | [Click here](https://docs.google.com/forms/d/e/1FAIpQLSe5qwunkGf6PUvzPirPDtuy1Du5Rlzew23UBp2S-P3wB-GcwQ/viewform) if you have any feedback or suggestions. 35 | ### Download a free PDF 36 | 37 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to claim your free PDF.
38 |

https://packt.link/free-ebook/9781785888731

--------------------------------------------------------------------------------