progs/lecture3.scala
author Christian Urban <urbanc@in.tum.de>
Thu, 24 Nov 2016 09:42:49 +0000
changeset 68 8da9e0c16194
parent 67 ca5884c2e3bd
child 71 19dff7218b0d
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
     1
// Scala Lecture 3
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
     2
//=================
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
     3
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
     4
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
     5
// One of only two places where I conceded to mutable
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
     6
// data structures: The following function generates 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
     7
// new labels
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
     8
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
     9
var counter = -1
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    10
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    11
def fresh(x: String) = {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    12
  counter += 1
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    13
  x ++ "_" ++ counter.toString()
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    14
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    15
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    16
fresh("x")
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    17
fresh("x")
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    18
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    19
// this can be avoided, but would have made my code more
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    20
// complicated
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    21
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    22
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    23
// Tail recursion
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    24
//================
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    25
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    26
def my_contains(elem: Int, lst: List[Int]) : Boolean = lst match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    27
  case Nil => false
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    28
  case x::xs => 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    29
    if (x == elem) true else my_contains(elem, xs)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    30
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    31
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    32
my_contains(4, List(1,2,3))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    33
my_contains(2, List(1,2,3))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    34
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    35
my_contains(1000000, (1 to 1000000).toList)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    36
my_contains(1000001, (1 to 1000000).toList)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    37
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    38
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    39
//factorial 0.1
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    40
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    41
def fact(n: Long): Long = 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    42
  if (n == 0) 1 else n * fact(n - 1)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    43
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    44
fact(10000)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    45
53
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
    46
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    47
def factT(n: BigInt, acc: BigInt): BigInt =
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    48
  if (n == 0) acc else factT(n - 1, n * acc)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    49
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    50
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    51
factT(10000, 1)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    52
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    53
// my_contains and factT are tail recursive 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    54
// you can check this with 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    55
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    56
import scala.annotation.tailrec
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    57
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    58
// and the annotation @tailrec
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    59
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    60
// for tail-recursive functions the compiler
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    61
// generates a loop-like code, which does not
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    62
// to allocate stack-space in each recursive
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    63
// call; scala can do this only for tail-recursive
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    64
// functions
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    65
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    66
// consider the following "stupid" version of the
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    67
// coin exchange problem: given some coins and a,
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    68
// total, what is the change can you get
53
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
    69
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    70
val coins = List(4,5,6,8,10,13,19,20,21,24,38,39, 40)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    71
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    72
def first_positive[B](lst: List[Int], f: Int => Option[B]): Option[B] = lst match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    73
  case Nil => None
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    74
  case x::xs => 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    75
    if (x <= 0) first_positive(xs, f)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    76
    else {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    77
      val fx = f(x)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    78
      if (fx.isDefined) fx else first_positive(xs, f)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    79
  }
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    80
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    81
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    82
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    83
def search(total: Int, coins: List[Int], cs: List[Int]): Option[List[Int]] = {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    84
  if (total < cs.sum) None 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    85
  else if (cs.sum == total) Some(cs) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    86
  else first_positive(coins, (c: Int) => search(total, coins, c::cs))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    87
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    88
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    89
search(11, coins, Nil)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    90
search(111, coins, Nil)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    91
search(111111, coins, Nil)
53
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
    92
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    93
val junk_coins = List(4,-2,5,6,8,0,10,13,19,20,-3,21,24,38,39, 40)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    94
search(11, junk_coins, Nil)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    95
search(111, junk_coins, Nil)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    96
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    97
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    98
import scala.annotation.tailrec
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    99
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   100
@tailrec
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   101
def asearch(total: Int, coins: List[Int], acc_cs: List[List[Int]]): Option[List[Int]] = acc_cs match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   102
  case Nil => None
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   103
  case x::xs => 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   104
    if (total < x.sum) asearch(total, coins, xs)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   105
    else if (x.sum == total) Some(x) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   106
    else asearch(total, coins, coins.filter(_ > 0).map(_::x) ::: xs)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   107
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   108
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   109
val start_acc = coins.filter(_ > 0).map(List(_))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   110
asearch(11, junk_coins, start_acc)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   111
asearch(111, junk_coins, start_acc)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   112
asearch(111111, junk_coins, start_acc)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   113
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   114
// moral: whenever a recursive function is resource-critical
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   115
// (i.e. works on large recursion depth), then you need to
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   116
// write it in tail-recursive fashion
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   117
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   118
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   119
// Polymorphism
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   120
//==============
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   121
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   122
def length_int_list(lst: List[Int]): Int = lst match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   123
  case Nil => 0
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   124
  case x::xs => 1 + length_int_list(xs)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   125
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   126
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   127
length_int_list(List(1, 2, 3, 4))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   128
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   129
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   130
def length[A](lst: List[A]): Int = lst match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   131
  case Nil => 0
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   132
  case x::xs => 1 + length(xs)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   133
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   134
53
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   135
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   136
def map_int_list(lst: List[Int], f: Int => Int): List[Int] = lst match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   137
  case Nil => Nil
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   138
  case x::xs => f(x)::map_int_list(xs, f) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   139
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   140
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   141
map_int_list(List(1, 2, 3, 4), square)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   142
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   143
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   144
// Remember?
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   145
def first[A, B](xs: List[A], f: A => Option[B]): Option[B] = ...
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   146
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   147
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   148
// polymorphic classes
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   149
//(trees with some content)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   150
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   151
abstract class Tree[+A]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   152
case class Node[A](elem: A, left: Tree[A], right: Tree[A]) extends Tree[A]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   153
case object Leaf extends Tree[Nothing]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   154
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   155
def insert[A](tr: Tree[A], n: A): Tree[A] = tr match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   156
  case Leaf => Node(n, Leaf, Leaf)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   157
  case Node(m, left, right) => 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   158
    if (n == m) Node(m, left, right) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   159
    else if (n < m) Node(m, insert(left, n), right)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   160
    else Node(m, left, insert(right, n))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   161
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   162
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   163
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   164
// the A-type needs to be ordered
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   165
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   166
abstract class Tree[+A <% Ordered[A]]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   167
case class Node[A <% Ordered[A]](elem: A, left: Tree[A], right: Tree[A]) extends Tree[A]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   168
case object Leaf extends Tree[Nothing]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   169
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   170
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   171
def insert[A <% Ordered[A]](tr: Tree[A], n: A): Tree[A] = tr match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   172
  case Leaf => Node(n, Leaf, Leaf)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   173
  case Node(m, left, right) => 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   174
    if (n == m) Node(m, left, right) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   175
    else if (n < m) Node(m, insert(left, n), right)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   176
    else Node(m, left, insert(right, n))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   177
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   178
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   179
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   180
val t1 = Node(4, Node(2, Leaf, Leaf), Node(7, Leaf, Leaf))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   181
insert(t1, 3)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   182
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   183
val t2 = Node('b', Node('a', Leaf, Leaf), Node('f', Leaf, Leaf))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   184
insert(t2, 'e')
53
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   185
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   186
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   187
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   188
// Regular expressions - the power of DSLs
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   189
//=========================================
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   190
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   191
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   192
abstract class Rexp
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   193
case object ZERO extends Rexp
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   194
case object ONE extends Rexp
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   195
case class CHAR(c: Char) extends Rexp
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   196
case class ALT(r1: Rexp, r2: Rexp) extends Rexp 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   197
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   198
case class STAR(r: Rexp) extends Rexp 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   199
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   200
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   201
// (ab)*
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   202
val r0 = ??
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   203
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   204
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   205
// some convenience for typing in regular expressions
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   206
import scala.language.implicitConversions    
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   207
import scala.language.reflectiveCalls 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   208
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   209
def charlist2rexp(s: List[Char]): Rexp = s match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   210
  case Nil => ONE
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   211
  case c::Nil => CHAR(c)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   212
  case c::s => SEQ(CHAR(c), charlist2rexp(s))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   213
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   214
implicit def string2rexp(s: String): Rexp = charlist2rexp(s.toList)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   215
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   216
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   217
val r1 = STAR("ab")
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   218
val r2 = STAR("")
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   219
val r3 = STAR(ALT("ab", "ba"))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   220
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   221
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   222
implicit def RexpOps (r: Rexp) = new {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   223
  def | (s: Rexp) = ALT(r, s)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   224
  def % = STAR(r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   225
  def ~ (s: Rexp) = SEQ(r, s)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   226
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   227
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   228
implicit def stringOps (s: String) = new {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   229
  def | (r: Rexp) = ALT(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   230
  def | (r: String) = ALT(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   231
  def % = STAR(s)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   232
  def ~ (r: Rexp) = SEQ(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   233
  def ~ (r: String) = SEQ(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   234
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   235
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   236
val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   237
val sign = "+" | "-" | ""
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   238
val number = sign ~ digit ~ digit.% 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   239
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   240
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   241
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   242
// Lazyness with style
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   243
//=====================
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   244
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   245
// The concept of lazy evaluation doesn’t really exist in 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   246
// non-functional languages, but it is pretty easy to grasp. 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   247
// Consider first 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   248
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   249
def square(x: Int) = x * x
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   250
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   251
square(42 + 8)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   252
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   253
// this is called strict evaluation
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   254
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   255
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   256
def expensiveOperation(n: BigInt): Boolean = expensiveOperation(n + 1) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   257
val a = "foo"
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   258
val b = "foo"
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   259
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   260
val test = if ((a == b) || expensiveOperation(0)) true else false
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   261
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   262
// this is called lazy evaluation
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   263
// you delay compuation until it is really 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   264
// needed; once calculated though, does not 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   265
// need to be re-calculated
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   266
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   267
// a useful example is
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   268
def time_needed[T](i: Int, code: => T) = {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   269
  val start = System.nanoTime()
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   270
  for (j <- 1 to i) code
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   271
  val end = System.nanoTime()
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   272
  ((end - start) / i / 1.0e9) + " secs"
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   273
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   274
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   275
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   276
// streams (I do not care how many)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   277
// primes: 2, 3, 5, 7, 9, 11, 13 ....
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   278
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   279
def generatePrimes (s: Stream[Int]): Stream[Int] =
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   280
  s.head #:: generatePrimes(s.tail filter (_ % s.head != 0))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   281
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   282
val primes: Stream[Int] = generatePrimes(Stream.from(2))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   283
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   284
primes.filter(_ > 100).take(2000).toList
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   285
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   286
time_needed(1, primes.filter(_ > 100).take(2000).toList)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   287
time_needed(1, primes.filter(_ > 100).take(2000).toList)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   288
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   289
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   290
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   291
// streams are useful for implementing search problems ;o)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   292
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   293
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   294
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   295
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   296
// The End
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   297
//=========
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   298
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   299
// A function should do one thing, and only one thing.
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   300
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   301
// Make your variables immutable, unless there's a good 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   302
// reason not to.
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   303
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   304
// You can be productive on Day 1, but the language is deep.
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   305
68
8da9e0c16194 updated
Christian Urban <urbanc@in.tum.de>
parents: 67
diff changeset
   306
// I like best about Scala that it lets me write
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   307
// concise, readable code
68
8da9e0c16194 updated
Christian Urban <urbanc@in.tum.de>
parents: 67
diff changeset
   308