├── Chapter12
├── readme.txt
└── BinomialHeap.scala
├── Chapter08
├── readme.txt
├── Fifo.scala
└── LeftistHeap.scala
├── Chapter09
├── fiboSeries.clj
├── arithmeticProgression.clj
├── standardBrownianMotion.clj
├── eagerEvaluation.scala
├── memoization.clj
├── standardBrownianMotion.scala
├── arithmeticProgression.scala
├── lazyEvaluation.scala
├── immutableStream.scala
├── streamSequence.clj
├── streamCreationAndIndexing.scala
├── fiboSeries.scala
├── lazyEvaluation.clj
├── memoization.scala
├── ClojureCode.txt
├── allinfiniteStreamCreation.scala
└── ScalaCode.txt
├── Chapter11
├── readme.txt
└── RBTree.scala
├── Chapter03
├── Readme.txt
└── List.scala
├── Chapter13
├── SelectionSort.scala
├── BubbleSort.scala
├── InsertionSort.scala
├── QuickSort.scala
└── MergeSort.scala
├── LICENSE
├── Chapter05
└── MoreListAlgo.scala
├── Chapter10
├── Deque.scala
└── LazyQueue.scala
├── README.md
├── Chapter04
└── BinTree.scala
├── Chapter06
└── Graph.scala
└── Chapter07
└── RandAccessList.scala
/Chapter12/readme.txt:
--------------------------------------------------------------------------------
1 | % scalac BinomialHeap.scala
2 | % scala com.fpdatastruct.binomealheaps.BinomialHeap
3 | 4
4 | 9
5 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |