progs/lecture3.scala
author Christian Urban <urbanc@in.tum.de>
Thu, 24 Nov 2016 11:43:07 +0000
changeset 71 19dff7218b0d
parent 68 8da9e0c16194
child 72 9d8b172f5337
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
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
    26
def my_contains(elem: Int, lst: List[Int]): Boolean = lst match {
67
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
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
    39
//factorial V0.1
67
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
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
    44
fact(10000)                        // produces a stackoverflow
67
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
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
    53
// the functions my_contains and factT are tail-recursive 
67
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
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
    60
// for tail-recursive functions the scala compiler
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
    61
// generates loop-like code, which does not need
67
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
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
    67
// coin exchange problem: given some coins and a
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
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
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
    70
val coins = List(4,5,6,8,10,13,19,20,21,24,38,39,40)
67
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
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   101
def searchT(total: Int, coins: List[Int], acc_cs: List[List[Int]]): Option[List[Int]] = acc_cs match {
67
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 => 
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   104
    if (total < x.sum) searchT(total, coins, xs)
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   105
    else if (x.sum == total) Some(x) 
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   106
    else searchT(total, coins, coins.filter(_ > 0).map(_::x) ::: xs)
67
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(_))
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   110
searchT(11, junk_coins, start_acc)
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   111
searchT(111, junk_coins, start_acc)
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   112
searchT(111111, junk_coins, start_acc)
67
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
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   119
// Polymorphic Types
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   120
//===================
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   121
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   122
// You do not want to frite functions like contains, first 
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   123
// and so on for every type of lists.
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   124
67
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
def length_int_list(lst: List[Int]): Int = lst match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   127
  case Nil => 0
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   128
  case x::xs => 1 + length_int_list(xs)
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   131
length_int_list(List(1, 2, 3, 4))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   132
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
def length[A](lst: List[A]): Int = lst match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   135
  case Nil => 0
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   136
  case x::xs => 1 + length(xs)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   137
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   138
53
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   139
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   140
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
   141
  case Nil => Nil
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   142
  case x::xs => f(x)::map_int_list(xs, f) 
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   145
map_int_list(List(1, 2, 3, 4), square)
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
// Remember?
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   149
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
   150
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   151
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   152
// polymorphic classes
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   153
//(trees with some content)
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
abstract class Tree[+A]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   156
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
   157
case object Leaf extends Tree[Nothing]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   158
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   159
def insert[A](tr: Tree[A], n: A): Tree[A] = tr match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   160
  case Leaf => Node(n, Leaf, Leaf)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   161
  case Node(m, left, right) => 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   162
    if (n == m) Node(m, left, right) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   163
    else if (n < m) Node(m, insert(left, n), right)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   164
    else Node(m, left, insert(right, n))
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   167
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   168
// the A-type needs to be ordered
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
abstract class Tree[+A <% Ordered[A]]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   171
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
   172
case object Leaf extends Tree[Nothing]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   173
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   174
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   175
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
   176
  case Leaf => Node(n, Leaf, Leaf)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   177
  case Node(m, left, right) => 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   178
    if (n == m) Node(m, left, right) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   179
    else if (n < m) Node(m, insert(left, n), right)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   180
    else Node(m, left, insert(right, n))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   181
}
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   184
val t1 = Node(4, Node(2, Leaf, Leaf), Node(7, Leaf, Leaf))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   185
insert(t1, 3)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   186
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   187
val t2 = Node('b', Node('a', Leaf, Leaf), Node('f', Leaf, Leaf))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   188
insert(t2, 'e')
53
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   189
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   190
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   191
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   192
// Regular expressions - the power of DSLs in Scala
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   193
//==================================================
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   194
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   195
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   196
abstract class Rexp
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   197
case object ZERO extends Rexp
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   198
case object ONE extends Rexp
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   199
case class CHAR(c: Char) extends Rexp
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   200
case class ALT(r1: Rexp, r2: Rexp) extends Rexp     // alternative  r1 + r2
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   201
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp     // sequence     r1 r2    
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   202
case class STAR(r: Rexp) extends Rexp               // star         r*
67
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
// (ab)*
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   206
val r0 = ??
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   207
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
// some convenience for typing in regular expressions
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   210
import scala.language.implicitConversions    
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   211
import scala.language.reflectiveCalls 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   212
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   213
def charlist2rexp(s: List[Char]): Rexp = s match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   214
  case Nil => ONE
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   215
  case c::Nil => CHAR(c)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   216
  case c::s => SEQ(CHAR(c), charlist2rexp(s))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   217
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   218
implicit def string2rexp(s: String): Rexp = charlist2rexp(s.toList)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   219
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
val r1 = STAR("ab")
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   222
val r2 = STAR("")
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   223
val r3 = STAR(ALT("ab", "ba"))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   224
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   225
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   226
implicit def RexpOps (r: Rexp) = new {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   227
  def | (s: Rexp) = ALT(r, s)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   228
  def % = STAR(r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   229
  def ~ (s: Rexp) = SEQ(r, s)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   230
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   231
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   232
implicit def stringOps (s: String) = new {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   233
  def | (r: Rexp) = ALT(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   234
  def | (r: String) = ALT(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   235
  def % = STAR(s)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   236
  def ~ (r: Rexp) = SEQ(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   237
  def ~ (r: String) = SEQ(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   238
}
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
val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   241
val sign = "+" | "-" | ""
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   242
val number = sign ~ digit ~ digit.% 
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   246
// Lazyness with style
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   247
//=====================
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
// The concept of lazy evaluation doesn’t really exist in 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   250
// non-functional languages, but it is pretty easy to grasp. 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   251
// Consider first 
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
def square(x: Int) = x * x
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
square(42 + 8)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   256
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   257
// this is called strict evaluation
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   258
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
def expensiveOperation(n: BigInt): Boolean = expensiveOperation(n + 1) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   261
val a = "foo"
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   262
val b = "foo"
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   263
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   264
val test = if ((a == b) || expensiveOperation(0)) true else false
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   265
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   266
// this is called lazy evaluation
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   267
// you delay compuation until it is really 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   268
// needed; once calculated though, does not 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   269
// need to be re-calculated
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   270
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   271
// a useful example is
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   272
def time_needed[T](i: Int, code: => T) = {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   273
  val start = System.nanoTime()
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   274
  for (j <- 1 to i) code
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   275
  val end = System.nanoTime()
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   276
  ((end - start) / i / 1.0e9) + " secs"
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   277
}
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   280
// streams (I do not care how many)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   281
// primes: 2, 3, 5, 7, 9, 11, 13 ....
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   282
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   283
def generatePrimes (s: Stream[Int]): Stream[Int] =
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   284
  s.head #:: generatePrimes(s.tail filter (_ % s.head != 0))
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
val primes: Stream[Int] = generatePrimes(Stream.from(2))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   287
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   288
primes.filter(_ > 100).take(2000).toList
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
time_needed(1, primes.filter(_ > 100).take(2000).toList)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   291
time_needed(1, primes.filter(_ > 100).take(2000).toList)
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
// streams are useful for implementing search problems ;o)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   296
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   300
// The End
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   301
//=========
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   302
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   303
// A function should do one thing, and only one thing.
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   304
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   305
// Make your variables immutable, unless there's a good 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   306
// reason not to.
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   307
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   308
// You can be productive on Day 1, but the language is deep.
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   309
68
8da9e0c16194 updated
Christian Urban <urbanc@in.tum.de>
parents: 67
diff changeset
   310
// I like best about Scala that it lets me write
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   311
// concise, readable code
68
8da9e0c16194 updated
Christian Urban <urbanc@in.tum.de>
parents: 67
diff changeset
   312