progs/lecture5.scala
author Christian Urban <christian.urban@kcl.ac.uk>
Mon, 21 Jul 2025 16:38:07 +0100
changeset 491 2a30c7dfe3ed
parent 479 78cb5cdda3c3
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
238
25d896ada26c updated
updated
parents: 226
diff changeset
     1
// Scala Lecture 5
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     2
//=================
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     3
491
2a30c7dfe3ed updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 479
diff changeset
     4
def foo(n: Int) = ???
478
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
     5
491
2a30c7dfe3ed updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 479
diff changeset
     6
fop(10)
478
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
     7
491
2a30c7dfe3ed updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 479
diff changeset
     8
List.fill(1)(100)
2a30c7dfe3ed updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 479
diff changeset
     9
// (Immutable) OOP
478
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    10
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    11
// Object Oriented Programming in Scala
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    12
// =====================================
238
25d896ada26c updated
updated
parents: 226
diff changeset
    13
329
828326d1b3b2 updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
    14
828326d1b3b2 updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
    15
abstract class Animal 
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    16
case class Bird(name: String) extends Animal {
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    17
   override def toString = name
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    18
}
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    19
case class Mammal(name: String) extends Animal
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    20
case class Reptile(name: String) extends Animal
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    21
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    22
Mammal("Zebra")
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    23
println(Mammal("Zebra"))
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    24
println(Mammal("Zebra").toString)
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    25
238
25d896ada26c updated
updated
parents: 226
diff changeset
    26
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    27
Bird("Sparrow")
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    28
println(Bird("Sparrow"))
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    29
println(Bird("Sparrow").toString)
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    30
383
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
    31
Bird("Sparrow").copy(name = "House Sparrow")
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
    32
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
    33
def group(a : Animal) = a match {
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
    34
  case Bird(_) => "It's a bird"
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
    35
  case Mammal(_) => "It's a mammal"
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
    36
}
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
    37
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    38
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    39
// There is a very convenient short-hand notation
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    40
// for constructors:
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    41
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    42
class Fraction(x: Int, y: Int) {
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    43
  def numer = x
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    44
  def denom = y
238
25d896ada26c updated
updated
parents: 226
diff changeset
    45
}
25d896ada26c updated
updated
parents: 226
diff changeset
    46
478
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    47
val half = Fraction(1, 2)
383
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
    48
half.numer
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    49
478
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    50
// does not work with "vanilla" classes
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    51
half match {
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    52
  case Fraction(x, y) => x / y
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    53
}
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    54
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    55
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    56
case class Fraction(numer: Int, denom: Int)
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    57
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    58
val half = Fraction(1, 2)
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    59
383
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
    60
half.numer
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    61
half.denom
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    62
478
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    63
// works with case classes
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    64
half match {
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    65
  case Fraction(x, y) => x / y
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    66
}
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
    67
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    68
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    69
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    70
// All is public by default....so no public is needed.
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    71
// You can have the usual restrictions about private 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    72
// values and methods, if you are MUTABLE !!!
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    73
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    74
case class BankAccount(init: Int) {
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    75
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    76
  private var balance = init
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    77
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    78
  def deposit(amount: Int): Unit = {
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    79
    if (amount > 0) balance = balance + amount
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    80
  }
238
25d896ada26c updated
updated
parents: 226
diff changeset
    81
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    82
  def withdraw(amount: Int): Int =
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    83
    if (0 < amount && amount <= balance) {
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    84
      balance = balance - amount
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    85
      balance
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    86
    } else throw new Error("insufficient funds")
238
25d896ada26c updated
updated
parents: 226
diff changeset
    87
}
25d896ada26c updated
updated
parents: 226
diff changeset
    88
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    89
// BUT since we are completely IMMUTABLE, this is 
383
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
    90
// virtually of no concern to us.
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    91
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    92
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    93
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    94
// another example about Fractions
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    95
import scala.language.implicitConversions
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    96
import scala.language.reflectiveCalls
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    97
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    98
case class Fraction(numer: Int, denom: Int) {
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
    99
  override def toString = numer.toString + "/" + denom.toString
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   100
383
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   101
  def +(other: Fraction) = 
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   102
    Fraction(numer * other.denom + other.numer * denom, 
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   103
             denom * other.denom)
478
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
   104
  def *(other: Fraction) = 
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
   105
    Fraction(numer * other.numer, denom * other.denom)
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   106
 }
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   107
478
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
   108
given Conversion[Int, Fraction] = (x => Fraction(x, 1))
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   109
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   110
val half = Fraction(1, 2)
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   111
val third = Fraction (1, 3)
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   112
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   113
half + third
383
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   114
half * third
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   115
383
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   116
1 + half
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   117
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   118
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   119
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   120
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   121
// DFAs in Scala  
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   122
//===============
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   123
import scala.util.Try
238
25d896ada26c updated
updated
parents: 226
diff changeset
   124
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   125
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   126
// A is the state type
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   127
// C is the input (usually characters)
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   128
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   129
case class DFA[A, C](start: A,              // starting state
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   130
                     delta: (A, C) => A,    // transition function
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   131
                     fins:  A => Boolean) { // final states (Set)
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   132
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   133
  def deltas(q: A, s: List[C]) : A = s match {
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   134
    case Nil => q
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   135
    case c::cs => deltas(delta(q, c), cs)
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   136
  }
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   137
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   138
  def accepts(s: List[C]) : Boolean = 
383
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   139
    Try(fins(deltas(start, s))).getOrElse(false)
238
25d896ada26c updated
updated
parents: 226
diff changeset
   140
}
25d896ada26c updated
updated
parents: 226
diff changeset
   141
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   142
// the example shown in the handout 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   143
abstract class State
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   144
case object Q0 extends State
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   145
case object Q1 extends State
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   146
case object Q2 extends State
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   147
case object Q3 extends State
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   148
case object Q4 extends State
238
25d896ada26c updated
updated
parents: 226
diff changeset
   149
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   150
val delta : (State, Char) => State = 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   151
  { case (Q0, 'a') => Q1
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   152
    case (Q0, 'b') => Q2
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   153
    case (Q1, 'a') => Q4
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   154
    case (Q1, 'b') => Q2
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   155
    case (Q2, 'a') => Q3
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   156
    case (Q2, 'b') => Q2
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   157
    case (Q3, 'a') => Q4
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   158
    case (Q3, 'b') => Q0
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   159
    case (Q4, 'a') => Q4
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   160
    case (Q4, 'b') => Q4 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   161
    case _ => throw new Exception("Undefined") }
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   162
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   163
val dfa = DFA(Q0, delta, Set[State](Q4))
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   164
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   165
dfa.accepts("abaaa".toList)     // true
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   166
dfa.accepts("bbabaab".toList)   // true
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   167
dfa.accepts("baba".toList)      // false
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   168
dfa.accepts("abc".toList)       // false
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   169
238
25d896ada26c updated
updated
parents: 226
diff changeset
   170
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   171
// NFAs (Nondeterministic Finite Automata)
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   172
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   173
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   174
case class NFA[A, C](starts: Set[A],          // starting states
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   175
                     delta: (A, C) => Set[A], // transition function
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   176
                     fins:  A => Boolean) {   // final states 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   177
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   178
  // given a state and a character, what is the set of 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   179
  // next states? if there is none => empty set
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   180
  def next(q: A, c: C) : Set[A] = 
383
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   181
    Try(delta(q, c)).getOrElse(Set[A]()) 
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   182
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   183
  def nexts(qs: Set[A], c: C) : Set[A] =
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   184
    qs.flatMap(next(_, c))
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   185
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   186
  // depth-first version of accepts
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   187
  def search(q: A, s: List[C]) : Boolean = s match {
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   188
    case Nil => fins(q)
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   189
    case c::cs => next(q, c).exists(search(_, cs))
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   190
  }
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   191
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   192
  def accepts(s: List[C]) : Boolean =
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   193
    starts.exists(search(_, s))
238
25d896ada26c updated
updated
parents: 226
diff changeset
   194
}
25d896ada26c updated
updated
parents: 226
diff changeset
   195
25d896ada26c updated
updated
parents: 226
diff changeset
   196
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   197
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   198
// NFA examples
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   199
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   200
val nfa_trans1 : (State, Char) => Set[State] = 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   201
  { case (Q0, 'a') => Set(Q0, Q1) 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   202
    case (Q0, 'b') => Set(Q2) 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   203
    case (Q1, 'a') => Set(Q1) 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   204
    case (Q2, 'b') => Set(Q2) }
238
25d896ada26c updated
updated
parents: 226
diff changeset
   205
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   206
val nfa = NFA(Set[State](Q0), nfa_trans1, Set[State](Q2))
238
25d896ada26c updated
updated
parents: 226
diff changeset
   207
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   208
nfa.accepts("aa".toList)             // false
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   209
nfa.accepts("aaaaa".toList)          // false
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   210
nfa.accepts("aaaaab".toList)         // true
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   211
nfa.accepts("aaaaabbb".toList)       // true
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   212
nfa.accepts("aaaaabbbaaa".toList)    // false
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   213
nfa.accepts("ac".toList)             // false
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   214
238
25d896ada26c updated
updated
parents: 226
diff changeset
   215
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   216
// Q: Why the kerfuffle about the polymorphic types in DFAs/NFAs?
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   217
// A: Subset construction. Here the state type for the DFA is
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   218
//    sets of states.
238
25d896ada26c updated
updated
parents: 226
diff changeset
   219
383
72d6a4af4b4a updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   220
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   221
def subset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = {
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   222
  DFA(nfa.starts, 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   223
      { case (qs, c) => nfa.nexts(qs, c) }, 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   224
      _.exists(nfa.fins))
238
25d896ada26c updated
updated
parents: 226
diff changeset
   225
}
25d896ada26c updated
updated
parents: 226
diff changeset
   226
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   227
subset(nfa).accepts("aa".toList)             // false
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   228
subset(nfa).accepts("aaaaa".toList)          // false
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   229
subset(nfa).accepts("aaaaab".toList)         // true
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   230
subset(nfa).accepts("aaaaabbb".toList)       // true
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   231
subset(nfa).accepts("aaaaabbbaaa".toList)    // false
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   232
subset(nfa).accepts("ac".toList)             // false
238
25d896ada26c updated
updated
parents: 226
diff changeset
   233
384
627a944c744b updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   234
452
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   235
// Laziness with style
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   236
//=====================
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   237
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   238
// The concept of lazy evaluation doesn’t really 
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   239
// exist in non-functional languages. C-like languages
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   240
// are (sort of) strict. To see the difference, consider
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   241
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   242
def square(x: Int) = x * x
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   243
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   244
square(42 + 8)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   245
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   246
// This is called "strict evaluation".
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   247
467
1b879b3e704e updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 452
diff changeset
   248
// In contrast say we have a pretty expensive operation:
452
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   249
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   250
def peop(n: BigInt): Boolean = peop(n + 1) 
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   251
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   252
val a = "foo"
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   253
val b = "foo"
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   254
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   255
if (a == b || peop(0)) println("true") else println("false")
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   256
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   257
// This is called "lazy evaluation":
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   258
// you delay compuation until it is really 
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   259
// needed. Once calculated though, the result
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   260
// does not need to be re-calculated.
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   261
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   262
// A useful example is
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   263
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   264
def time_needed[T](i: Int, code: => T) = {
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   265
  val start = System.nanoTime()
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   266
  for (j <- 1 to i) code
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   267
  val end = System.nanoTime()
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   268
  f"${(end - start) / (i * 1.0e9)}%.6f secs"
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   269
}
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   270
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   271
// A slightly less obvious example: Prime Numbers.
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   272
// (I do not care how many) primes: 2, 3, 5, 7, 9, 11, 13 ....
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   273
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   274
def generatePrimes (s: LazyList[Int]): LazyList[Int] =
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   275
  s.head #:: generatePrimes(s.tail.filter(_ % s.head != 0))
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   276
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   277
val primes = generatePrimes(LazyList.from(2))
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   278
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   279
// the first 10 primes
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   280
primes.take(100).toList
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   281
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   282
time_needed(1, primes.filter(_ > 100).take(3000).toList)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   283
time_needed(1, primes.filter(_ > 100).take(3000).toList)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   284
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   285
// A Stream (LazyList) of successive numbers:
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   286
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   287
LazyList.from(2).take(10)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   288
LazyList.from(2).take(10).force
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   289
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   290
// An Iterative version of the Fibonacci numbers
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   291
def fibIter(a: BigInt, b: BigInt): LazyList[BigInt] =
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   292
  a #:: fibIter(b, a + b)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   293
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   294
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   295
fibIter(1, 1).take(10).force
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   296
fibIter(8, 13).take(10).force
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   297
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   298
fibIter(1, 1).drop(10000).take(1)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   299
fibIter(1, 1).drop(10000).take(1).force
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   300
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   301
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   302
// LazyLists are good for testing
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   303
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   304
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   305
// Regular expressions - the power of DSLs in Scala
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   306
//                                     and Laziness
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   307
//==================================================
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   308
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   309
abstract class Rexp
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   310
case object ZERO extends Rexp                     // nothing
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   311
case object ONE extends Rexp                      // the empty string
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   312
case class CHAR(c: Char) extends Rexp             // a character c
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   313
case class ALT(r1: Rexp, r2: Rexp) extends Rexp   // alternative  r1 + r2
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   314
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence     r1 . r2  
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   315
case class STAR(r: Rexp) extends Rexp             // star         r*
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   316
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   317
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   318
// some convenience for typing in regular expressions
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   319
import scala.language.implicitConversions    
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   320
import scala.language.reflectiveCalls 
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   321
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   322
def charlist2rexp(s: List[Char]): Rexp = s match {
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   323
  case Nil => ONE
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   324
  case c::Nil => CHAR(c)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   325
  case c::s => SEQ(CHAR(c), charlist2rexp(s))
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   326
}
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   327
478
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
   328
given Conversion[String, Rexp] = (s => charlist2rexp(s.toList))
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
   329
0e6ca70496c1 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 467
diff changeset
   330
extension (r: Rexp) {
452
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   331
  def | (s: Rexp) = ALT(r, s)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   332
  def % = STAR(r)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   333
  def ~ (s: Rexp) = SEQ(r, s)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   334
}
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   335
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   336
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   337
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   338
//example regular expressions
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   339
val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   340
val sign = "+" | "-" | ""
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   341
val number = sign ~ digit ~ digit.% 
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   342
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   343
// Task: enumerate exhaustively regular expressions
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   344
// starting from small ones towards bigger ones.
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   345
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   346
// 1st idea: enumerate them all in a Set
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   347
// up to a level
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   348
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   349
def enuml(l: Int, s: String) : Set[Rexp] = l match {
491
2a30c7dfe3ed updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 479
diff changeset
   350
  case 0 => Set(ZERO, ONE) ++ s.map(CHAR(_)).toSet
452
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   351
  case n =>  
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   352
    val rs = enuml(n - 1, s)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   353
    rs ++
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   354
    (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) ++
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   355
    (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) ++
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   356
    (for (r1 <- rs) yield STAR(r1))
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   357
}
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   358
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   359
enuml(1, "a")
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   360
enuml(1, "a").size
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   361
enuml(2, "a").size
467
1b879b3e704e updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 452
diff changeset
   362
enuml(3, "a").size 
1b879b3e704e updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 452
diff changeset
   363
enuml(4, "a").size // out of heap space
452
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   364
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   365
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   366
def enum(rs: LazyList[Rexp]) : LazyList[Rexp] = 
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   367
  rs #::: enum( (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) #:::
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   368
                (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) #:::
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   369
                (for (r1 <- rs) yield STAR(r1)) )
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   370
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   371
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   372
enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(200).force
467
1b879b3e704e updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 452
diff changeset
   373
enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(5_000_000).force // out of memory
452
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   374
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   375
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   376
def depth(r: Rexp) : Int = r match {
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   377
  case ZERO => 0
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   378
  case ONE => 0
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   379
  case CHAR(_) => 0
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   380
  case ALT(r1, r2) => Math.max(depth(r1), depth(r2)) + 1
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   381
  case SEQ(r1, r2) => Math.max(depth(r1), depth(r2)) + 1 
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   382
  case STAR(r1) => depth(r1) + 1
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   383
}
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   384
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   385
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   386
val is = 
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   387
  (enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b')))
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   388
    .dropWhile(depth(_) < 3)
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   389
    .take(10).foreach(println))
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   390
ee348feb4c37 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 415
diff changeset
   391
384
627a944c744b updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   392
627a944c744b updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   393
627a944c744b updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   394
627a944c744b updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   395
627a944c744b updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   396
627a944c744b updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   397
627a944c744b updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   398
627a944c744b updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   399
627a944c744b updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   400
238
25d896ada26c updated
updated
parents: 226
diff changeset
   401
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   402
240
2d8d198360c8 updated
Christian Urban <urbanc@in.tum.de>
parents: 238
diff changeset
   403
// The End ... Almost Christmas
238
25d896ada26c updated
updated
parents: 226
diff changeset
   404
//===============================
25d896ada26c updated
updated
parents: 226
diff changeset
   405
25d896ada26c updated
updated
parents: 226
diff changeset
   406
// I hope you had fun!
25d896ada26c updated
updated
parents: 226
diff changeset
   407
25d896ada26c updated
updated
parents: 226
diff changeset
   408
// A function should do one thing, and only one thing.
25d896ada26c updated
updated
parents: 226
diff changeset
   409
25d896ada26c updated
updated
parents: 226
diff changeset
   410
// Make your variables immutable, unless there's a good 
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   411
// reason not to. Usually there is not.
238
25d896ada26c updated
updated
parents: 226
diff changeset
   412
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   413
// I did it once, but this is actually not a good reason:
240
2d8d198360c8 updated
Christian Urban <urbanc@in.tum.de>
parents: 238
diff changeset
   414
// generating new labels:
2d8d198360c8 updated
Christian Urban <urbanc@in.tum.de>
parents: 238
diff changeset
   415
238
25d896ada26c updated
updated
parents: 226
diff changeset
   416
var counter = -1
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   417
238
25d896ada26c updated
updated
parents: 226
diff changeset
   418
def Fresh(x: String) = {
25d896ada26c updated
updated
parents: 226
diff changeset
   419
  counter += 1
25d896ada26c updated
updated
parents: 226
diff changeset
   420
  x ++ "_" ++ counter.toString()
25d896ada26c updated
updated
parents: 226
diff changeset
   421
}
25d896ada26c updated
updated
parents: 226
diff changeset
   422
25d896ada26c updated
updated
parents: 226
diff changeset
   423
Fresh("x")
25d896ada26c updated
updated
parents: 226
diff changeset
   424
Fresh("x")
25d896ada26c updated
updated
parents: 226
diff changeset
   425
25d896ada26c updated
updated
parents: 226
diff changeset
   426
25d896ada26c updated
updated
parents: 226
diff changeset
   427
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   428
// I think you can be productive on Day 1, but the 
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   429
// language is deep.
238
25d896ada26c updated
updated
parents: 226
diff changeset
   430
//
25d896ada26c updated
updated
parents: 226
diff changeset
   431
// http://scalapuzzlers.com
25d896ada26c updated
updated
parents: 226
diff changeset
   432
//
25d896ada26c updated
updated
parents: 226
diff changeset
   433
// http://www.latkin.org/blog/2017/05/02/when-the-scala-compiler-doesnt-help/
25d896ada26c updated
updated
parents: 226
diff changeset
   434
328
b217232e9246 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   435
val two   = 0.2
b217232e9246 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   436
val one   = 0.1
b217232e9246 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   437
val eight = 0.8
b217232e9246 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   438
val six   = 0.6
b217232e9246 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   439
b217232e9246 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   440
two - one == one
b217232e9246 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   441
eight - six == two
329
828326d1b3b2 updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   442
eight - six
328
b217232e9246 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   443
b217232e9246 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   444
329
828326d1b3b2 updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   445
// problems about equality and type-errors
328
b217232e9246 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   446
329
828326d1b3b2 updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   447
List(1, 2, 3).contains("your cup")   // should not compile, but retruns false
828326d1b3b2 updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   448
828326d1b3b2 updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   449
List(1, 2, 3) == Vector(1, 2, 3)     // again should not compile, but returns true
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   450
238
25d896ada26c updated
updated
parents: 226
diff changeset
   451
326
7d983ee99fcc updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   452