progs/lecture3.scala
author Christian Urban <urbanc@in.tum.de>
Fri, 24 Nov 2017 01:26:01 +0000
changeset 154 39c6b93718f0
parent 153 4383809c176a
child 155 371acb50643d
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
152
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
     4
// adding two binary strings very, very lazy manner
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
     5
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
     6
def badd(s1: String, s2: String) : String = 
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
     7
  (BigInt(s1, 2) + BigInt(s2, 2)).toString(2)
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
     8
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
     9
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    10
// collatz function on binary numbers
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    11
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    12
def bcollatz(s: String) : Long = (s.dropRight(1), s.last) match {
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    13
  case ("", '1') => 1                                  // we reached 1
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    14
  case (rest, '0') => 1 + bcollatz(rest)               // even number => divide by two
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    15
  case (rest, '1') => 1 + bcollatz(badd(s + '1', s))   // odd number => s + '1' is 2 * s + 1
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    16
                                                       //               add another s gives 3 * s + 1  
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    17
} 
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    18
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    19
bcollatz(9.toBinaryString)
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    20
bcollatz(837799.toBinaryString)
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    21
bcollatz(100000000000000000L.toBinaryString)
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    22
bcollatz(BigInt("1000000000000000000000000000000000000000000000000000000000000000000000000000").toString(2))
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    23
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    24
def conv(c: Char) : Int = c match {
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    25
  case '0' => 0
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    26
  case '1' => 1
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    27
}
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    28
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    29
def badds(s1: String, s2: String, carry: Int) : String = (s1, s2, carry) match {
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    30
  case ("", "", 1) => "1"
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    31
  case ("", "", 0) => ""
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    32
  case (cs1, cs2, carry) => (conv(cs1.last) + conv(cs2.last) + carry) match {
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    33
    case 3 => badds(cs1.dropRight(1), cs2.dropRight(1), 1) + '1'
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    34
    case 2 => badds(cs1.dropRight(1), cs2.dropRight(1), 1) + '0'
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    35
    case 1 => badds(cs1.dropRight(1), cs2.dropRight(1), 0) + '1'
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    36
    case 0 => badds(cs1.dropRight(1), cs2.dropRight(1), 0) + '0'
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    37
  }
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    38
} 
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    39
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    40
def bcollatz2(s: String) : Long = (s.dropRight(1), s.last) match {
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    41
  case ("", '1') => 1                                          // we reached 1
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    42
  case (rest, '0') => 1 + bcollatz2(rest)                      // even number => divide by two
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    43
  case (rest, '1') => 1 + bcollatz2(badds(s + '1', '0' + s, 0))   // odd number => s + '1' is 2 * s + 1
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    44
                                                                  //         add another s gives 3 * s + 1  
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    45
} 
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    46
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    47
bcollatz2(9.toBinaryString)
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    48
bcollatz2(837799.toBinaryString)
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    49
bcollatz2(100000000000000000L.toBinaryString)
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    50
bcollatz2(BigInt("1000000000000000000000000000000000000000000000000000000000000000000000000000").toString(2))
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    51
114a89518aea updated
Christian Urban <urbanc@in.tum.de>
parents: 77
diff changeset
    52
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    53
153
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    54
// Roman Numerals
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    55
abstract class RomanDigit 
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    56
case object I extends RomanDigit 
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    57
case object V extends RomanDigit 
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    58
case object X extends RomanDigit 
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    59
case object L extends RomanDigit 
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    60
case object C extends RomanDigit 
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    61
case object D extends RomanDigit 
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    62
case object M extends RomanDigit 
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    63
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    64
type RomanNumeral = List[RomanDigit] 
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    65
153
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    66
def RomanNumeral2Int(rs: RomanNumeral): Int = rs match { 
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    67
  case Nil => 0
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    68
  case M::r    => 1000 + RomanNumeral2Int(r)  
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    69
  case C::M::r => 900 + RomanNumeral2Int(r)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    70
  case D::r    => 500 + RomanNumeral2Int(r)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    71
  case C::D::r => 400 + RomanNumeral2Int(r)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    72
  case C::r    => 100 + RomanNumeral2Int(r)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    73
  case X::C::r => 90 + RomanNumeral2Int(r)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    74
  case L::r    => 50 + RomanNumeral2Int(r)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    75
  case X::L::r => 40 + RomanNumeral2Int(r)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    76
  case X::r    => 10 + RomanNumeral2Int(r)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    77
  case I::X::r => 9 + RomanNumeral2Int(r)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    78
  case V::r    => 5 + RomanNumeral2Int(r)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    79
  case I::V::r => 4 + RomanNumeral2Int(r)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    80
  case I::r    => 1 + RomanNumeral2Int(r)
67
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
153
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    83
RomanNumeral2Int(List(I,I,I,I))         // 4 (invalid roman number)
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    84
RomanNumeral2Int(List(I,V))             // 4
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    85
RomanNumeral2Int(List(V,I))             // 6
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    86
RomanNumeral2Int(List(I,X))             // 9
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    87
RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
    88
RomanNumeral2Int(List(M,M,X,V,I,I))     // 2017
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    89
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    90
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    91
// Tail recursion
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    92
//================
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    93
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
    94
def my_contains(elem: Int, lst: List[Int]): Boolean = lst match {
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    95
  case Nil => false
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    96
  case x::xs => 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    97
    if (x == elem) true else my_contains(elem, xs)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
    98
}
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
my_contains(4, List(1,2,3))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   101
my_contains(2, List(1,2,3))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   102
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   103
my_contains(1000000, (1 to 1000000).toList)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   104
my_contains(1000001, (1 to 1000000).toList)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   105
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   106
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   107
//factorial V0.1
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   108
import scala.annotation.tailrec
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   109
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   110
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   111
def fact(n: Long): Long = 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   112
  if (n == 0) 1 else n * fact(n - 1)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   113
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   114
fact(10000)                        // produces a stackoverflow
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   115
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   116
@tailrec
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   117
def factT(n: BigInt, acc: BigInt): BigInt =
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   118
  if (n == 0) acc else factT(n - 1, n * acc)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   119
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   120
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   121
println(factT(10000, 1))
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   122
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   123
// the functions my_contains and factT are tail-recursive 
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   124
// you can check this with 
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
import scala.annotation.tailrec
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   127
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   128
// and the annotation @tailrec
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   129
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   130
// for tail-recursive functions the scala compiler
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   131
// generates loop-like code, which does not need
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   132
// to allocate stack-space in each recursive
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   133
// call; scala can do this only for tail-recursive
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   134
// functions
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   135
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   136
// consider the following "stupid" version of the
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   137
// coin exchange problem: given some coins and a
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   138
// total, what is the change can you get?
53
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   139
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   140
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
   141
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   142
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
   143
  case Nil => None
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   144
  case x::xs => 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   145
    if (x <= 0) first_positive(xs, f)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   146
    else {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   147
      val fx = f(x)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   148
      if (fx.isDefined) fx else first_positive(xs, f)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   149
  }
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
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   153
import scala.annotation.tailrec
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   154
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   155
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
   156
  if (total < cs.sum) None 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   157
  else if (cs.sum == total) Some(cs) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   158
  else first_positive(coins, (c: Int) => search(total, coins, c::cs))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   159
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   160
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   161
search(11, coins, Nil)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   162
search(111, coins, Nil)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   163
search(111111, coins, Nil)
53
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   164
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   165
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
   166
search(11, junk_coins, Nil)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   167
search(111, junk_coins, Nil)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   168
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
import scala.annotation.tailrec
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   171
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   172
@tailrec
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   173
def searchT(total: Int, coins: List[Int], 
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   174
            acc_cs: List[List[Int]]): Option[List[Int]] = acc_cs match {
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   175
  case Nil => None
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   176
  case x::xs => 
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   177
    if (total < x.sum) searchT(total, coins, xs)
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   178
    else if (x.sum == total) Some(x) 
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   179
    else searchT(total, coins, coins.filter(_ > 0).map(_::x) ::: xs)
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   180
}
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
val start_acc = coins.filter(_ > 0).map(List(_))
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   183
searchT(11, junk_coins, start_acc)
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   184
searchT(111, junk_coins, start_acc)
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   185
searchT(111111, junk_coins, start_acc)
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   186
77
3cbe3d90b77f updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 73
diff changeset
   187
// Moral: Whenever a recursive function is resource-critical
3cbe3d90b77f updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 73
diff changeset
   188
// (i.e. works with large recursion depths), then you need to
3cbe3d90b77f updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 73
diff changeset
   189
// write it in tail-recursive fashion.
3cbe3d90b77f updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 73
diff changeset
   190
// 
3cbe3d90b77f updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 73
diff changeset
   191
// Unfortuantely, the Scala is because of current limitations in 
3cbe3d90b77f updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 73
diff changeset
   192
// the JVM not as clever as other functional languages. It can 
3cbe3d90b77f updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 73
diff changeset
   193
// only optimise "self-tail calls". This excludes the cases of 
3cbe3d90b77f updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 73
diff changeset
   194
// multiple functions making tail calls to each other. Well,
3cbe3d90b77f updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 73
diff changeset
   195
// nothing is perfect. 
3cbe3d90b77f updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 73
diff changeset
   196
3cbe3d90b77f updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 73
diff changeset
   197
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   198
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   199
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   200
// Polymorphic Types
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   201
//===================
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   202
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   203
// You do not want to write functions like contains, first 
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   204
// and so on for every type of lists.
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   205
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   206
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   207
def length_string_list(lst: List[String]): Int = lst match {
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   208
  case Nil => 0
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   209
  case x::xs => 1 + length_string_list(xs)
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   210
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   211
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   212
length_string_list(List("1", "2", "3", "4"))
67
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   215
def length[A](lst: List[A]): Int = lst match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   216
  case Nil => 0
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   217
  case x::xs => 1 + length(xs)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   218
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   219
53
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   220
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   221
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
   222
  case Nil => Nil
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   223
  case x::xs => f(x)::map_int_list(xs, f) 
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
map_int_list(List(1, 2, 3, 4), square)
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   229
// Remember?
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   230
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
   231
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   232
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   233
// polymorphic classes
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   234
//(trees with some content)
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
abstract class Tree[+A]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   237
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
   238
case object Leaf extends Tree[Nothing]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   239
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   240
val t0 = Node('4', Node('2', Leaf, Leaf), Node('7', Leaf, Leaf))
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   241
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   242
def insert[A](tr: Tree[A], n: A): Tree[A] = tr match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   243
  case Leaf => Node(n, Leaf, Leaf)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   244
  case Node(m, left, right) => 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   245
    if (n == m) Node(m, left, right) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   246
    else if (n < m) Node(m, insert(left, n), right)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   247
    else Node(m, left, insert(right, n))
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
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
// the A-type needs to be ordered
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
abstract class Tree[+A <% Ordered[A]]
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   254
case class Node[A <% Ordered[A]](elem: A, left: Tree[A], 
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   255
                                 right: Tree[A]) extends Tree[A]
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   256
case object Leaf extends Tree[Nothing]
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   257
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
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
   260
  case Leaf => Node(n, Leaf, Leaf)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   261
  case Node(m, left, right) => 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   262
    if (n == m) Node(m, left, right) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   263
    else if (n < m) Node(m, insert(left, n), right)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   264
    else Node(m, left, insert(right, n))
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   267
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   268
val t1 = Node(4, Node(2, Leaf, Leaf), Node(7, Leaf, Leaf))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   269
insert(t1, 3)
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
val t2 = Node('b', Node('a', Leaf, Leaf), Node('f', Leaf, Leaf))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   272
insert(t2, 'e')
53
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   273
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   274
9f8751912560 updated
Christian Urban <urbanc@in.tum.de>
parents: 8
diff changeset
   275
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   276
// Regular expressions - the power of DSLs in Scala
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   277
//==================================================
67
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
abstract class Rexp
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   281
case object ZERO extends Rexp
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   282
case object ONE extends Rexp
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   283
case class CHAR(c: Char) extends Rexp
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   284
case class ALT(r1: Rexp, r2: Rexp) extends Rexp     // alternative  r1 + r2
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   285
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp     // sequence     r1 r2  
71
19dff7218b0d updated
Christian Urban <urbanc@in.tum.de>
parents: 68
diff changeset
   286
case class STAR(r: Rexp) extends Rexp               // star         r*
67
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   289
// (ab)*
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   290
val r0 = STAR(SEQ(CHAR('a'), CHAR('b')))
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   291
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
// some convenience for typing in regular expressions
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   294
import scala.language.implicitConversions    
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   295
import scala.language.reflectiveCalls 
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
def charlist2rexp(s: List[Char]): Rexp = s match {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   298
  case Nil => ONE
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   299
  case c::Nil => CHAR(c)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   300
  case c::s => SEQ(CHAR(c), charlist2rexp(s))
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
implicit def string2rexp(s: String): Rexp = charlist2rexp(s.toList)
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
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   305
val r1 = STAR("ab")
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   306
val r2 = STAR("")
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   307
val r3 = STAR(ALT("ab", "baa baa black sheep"))
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   308
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   309
implicit def RexpOps (r: Rexp) = new {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   310
  def | (s: Rexp) = ALT(r, s)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   311
  def % = STAR(r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   312
  def ~ (s: Rexp) = SEQ(r, s)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   313
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   314
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   315
implicit def stringOps (s: String) = new {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   316
  def | (r: Rexp) = ALT(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   317
  def | (r: String) = ALT(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   318
  def % = STAR(s)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   319
  def ~ (r: Rexp) = SEQ(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   320
  def ~ (r: String) = SEQ(s, r)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   321
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   322
153
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
   323
//example regular expressions
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   324
val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   325
val sign = "+" | "-" | ""
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   326
val number = sign ~ digit ~ digit.% 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   327
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   328
153
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
   329
//implement print_re
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
   330
4383809c176a updated
Christian Urban <urbanc@in.tum.de>
parents: 152
diff changeset
   331
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   332
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   333
// Lazyness with style
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   334
//=====================
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   335
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   336
// The concept of lazy evaluation doesn’t really exist in 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   337
// non-functional languages, but it is pretty easy to grasp. 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   338
// Consider first 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   339
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   340
def square(x: Int) = x * x
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   341
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   342
square(42 + 8)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   343
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   344
// this is called strict evaluation
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   345
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   346
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   347
def expensiveOperation(n: BigInt): Boolean = expensiveOperation(n + 1) 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   348
val a = "foo"
72
9d8b172f5337 updated
Christian Urban <urbanc@in.tum.de>
parents: 71
diff changeset
   349
val b = "bar"
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   350
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   351
val test = if ((a == b) || expensiveOperation(0)) true else false
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   352
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   353
// this is called lazy evaluation
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   354
// you delay compuation until it is really 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   355
// needed; once calculated though, does not 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   356
// need to be re-calculated
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   357
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   358
// a useful example is
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   359
def time_needed[T](i: Int, code: => T) = {
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   360
  val start = System.nanoTime()
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   361
  for (j <- 1 to i) code
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   362
  val end = System.nanoTime()
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   363
  ((end - start) / i / 1.0e9) + " secs"
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   364
}
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   365
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   366
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   367
// streams (I do not care how many)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   368
// primes: 2, 3, 5, 7, 9, 11, 13 ....
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   369
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   370
def generatePrimes (s: Stream[Int]): Stream[Int] =
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   371
  s.head #:: generatePrimes(s.tail filter (_ % s.head != 0))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   372
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   373
val primes: Stream[Int] = generatePrimes(Stream.from(2))
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   374
73
5e4696ebd8dc updated
Christian Urban <urbanc@in.tum.de>
parents: 72
diff changeset
   375
primes.take(10).toList
5e4696ebd8dc updated
Christian Urban <urbanc@in.tum.de>
parents: 72
diff changeset
   376
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   377
primes.filter(_ > 100).take(2000).toList
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   378
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   379
time_needed(1, primes.filter(_ > 100).take(2000).toList)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   380
time_needed(1, primes.filter(_ > 100).take(2000).toList)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   381
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   382
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   383
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   384
// streams are useful for implementing search problems ;o)
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   385
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   386
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   387
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   388
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   389
// The End
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   390
//=========
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   391
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   392
// A function should do one thing, and only one thing.
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   393
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   394
// Make your variables immutable, unless there's a good 
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   395
// reason not to.
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   396
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   397
// You can be productive on Day 1, but the language is deep.
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   398
68
8da9e0c16194 updated
Christian Urban <urbanc@in.tum.de>
parents: 67
diff changeset
   399
// I like best about Scala that it lets me write
67
ca5884c2e3bd updated
Christian Urban <urbanc@in.tum.de>
parents: 53
diff changeset
   400
// concise, readable code
68
8da9e0c16194 updated
Christian Urban <urbanc@in.tum.de>
parents: 67
diff changeset
   401