├── 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 |