progs/lecture3.scala
changeset 71 19dff7218b0d
parent 68 8da9e0c16194
child 72 9d8b172f5337
equal deleted inserted replaced
70:6024381415cb 71:19dff7218b0d
    21 
    21 
    22 
    22 
    23 // Tail recursion
    23 // Tail recursion
    24 //================
    24 //================
    25 
    25 
    26 def my_contains(elem: Int, lst: List[Int]) : Boolean = lst match {
    26 def my_contains(elem: Int, lst: List[Int]): Boolean = lst match {
    27   case Nil => false
    27   case Nil => false
    28   case x::xs => 
    28   case x::xs => 
    29     if (x == elem) true else my_contains(elem, xs)
    29     if (x == elem) true else my_contains(elem, xs)
    30 }
    30 }
    31 
    31 
    34 
    34 
    35 my_contains(1000000, (1 to 1000000).toList)
    35 my_contains(1000000, (1 to 1000000).toList)
    36 my_contains(1000001, (1 to 1000000).toList)
    36 my_contains(1000001, (1 to 1000000).toList)
    37 
    37 
    38 
    38 
    39 //factorial 0.1
    39 //factorial V0.1
    40 
    40 
    41 def fact(n: Long): Long = 
    41 def fact(n: Long): Long = 
    42   if (n == 0) 1 else n * fact(n - 1)
    42   if (n == 0) 1 else n * fact(n - 1)
    43 
    43 
    44 fact(10000)
    44 fact(10000)                        // produces a stackoverflow
    45 
    45 
    46 
    46 
    47 def factT(n: BigInt, acc: BigInt): BigInt =
    47 def factT(n: BigInt, acc: BigInt): BigInt =
    48   if (n == 0) acc else factT(n - 1, n * acc)
    48   if (n == 0) acc else factT(n - 1, n * acc)
    49 
    49 
    50 
    50 
    51 factT(10000, 1)
    51 factT(10000, 1)
    52 
    52 
    53 // my_contains and factT are tail recursive 
    53 // the functions my_contains and factT are tail-recursive 
    54 // you can check this with 
    54 // you can check this with 
    55 
    55 
    56 import scala.annotation.tailrec
    56 import scala.annotation.tailrec
    57 
    57 
    58 // and the annotation @tailrec
    58 // and the annotation @tailrec
    59 
    59 
    60 // for tail-recursive functions the compiler
    60 // for tail-recursive functions the scala compiler
    61 // generates a loop-like code, which does not
    61 // generates loop-like code, which does not need
    62 // to allocate stack-space in each recursive
    62 // to allocate stack-space in each recursive
    63 // call; scala can do this only for tail-recursive
    63 // call; scala can do this only for tail-recursive
    64 // functions
    64 // functions
    65 
    65 
    66 // consider the following "stupid" version of the
    66 // consider the following "stupid" version of the
    67 // coin exchange problem: given some coins and a,
    67 // coin exchange problem: given some coins and a
    68 // total, what is the change can you get
    68 // total, what is the change can you get?
    69 
    69 
    70 val coins = List(4,5,6,8,10,13,19,20,21,24,38,39, 40)
    70 val coins = List(4,5,6,8,10,13,19,20,21,24,38,39,40)
    71 
    71 
    72 def first_positive[B](lst: List[Int], f: Int => Option[B]): Option[B] = lst match {
    72 def first_positive[B](lst: List[Int], f: Int => Option[B]): Option[B] = lst match {
    73   case Nil => None
    73   case Nil => None
    74   case x::xs => 
    74   case x::xs => 
    75     if (x <= 0) first_positive(xs, f)
    75     if (x <= 0) first_positive(xs, f)
    96 
    96 
    97 
    97 
    98 import scala.annotation.tailrec
    98 import scala.annotation.tailrec
    99 
    99 
   100 @tailrec
   100 @tailrec
   101 def asearch(total: Int, coins: List[Int], acc_cs: List[List[Int]]): Option[List[Int]] = acc_cs match {
   101 def searchT(total: Int, coins: List[Int], acc_cs: List[List[Int]]): Option[List[Int]] = acc_cs match {
   102   case Nil => None
   102   case Nil => None
   103   case x::xs => 
   103   case x::xs => 
   104     if (total < x.sum) asearch(total, coins, xs)
   104     if (total < x.sum) searchT(total, coins, xs)
   105     else if (x.sum == total) Some(x) 
   105     else if (x.sum == total) Some(x) 
   106     else asearch(total, coins, coins.filter(_ > 0).map(_::x) ::: xs)
   106     else searchT(total, coins, coins.filter(_ > 0).map(_::x) ::: xs)
   107 }
   107 }
   108 
   108 
   109 val start_acc = coins.filter(_ > 0).map(List(_))
   109 val start_acc = coins.filter(_ > 0).map(List(_))
   110 asearch(11, junk_coins, start_acc)
   110 searchT(11, junk_coins, start_acc)
   111 asearch(111, junk_coins, start_acc)
   111 searchT(111, junk_coins, start_acc)
   112 asearch(111111, junk_coins, start_acc)
   112 searchT(111111, junk_coins, start_acc)
   113 
   113 
   114 // moral: whenever a recursive function is resource-critical
   114 // moral: whenever a recursive function is resource-critical
   115 // (i.e. works on large recursion depth), then you need to
   115 // (i.e. works on large recursion depth), then you need to
   116 // write it in tail-recursive fashion
   116 // write it in tail-recursive fashion
   117 
   117 
   118 
   118 
   119 // Polymorphism
   119 // Polymorphic Types
   120 //==============
   120 //===================
       
   121 
       
   122 // You do not want to frite functions like contains, first 
       
   123 // and so on for every type of lists.
       
   124 
   121 
   125 
   122 def length_int_list(lst: List[Int]): Int = lst match {
   126 def length_int_list(lst: List[Int]): Int = lst match {
   123   case Nil => 0
   127   case Nil => 0
   124   case x::xs => 1 + length_int_list(xs)
   128   case x::xs => 1 + length_int_list(xs)
   125 }
   129 }
   183 val t2 = Node('b', Node('a', Leaf, Leaf), Node('f', Leaf, Leaf))
   187 val t2 = Node('b', Node('a', Leaf, Leaf), Node('f', Leaf, Leaf))
   184 insert(t2, 'e')
   188 insert(t2, 'e')
   185 
   189 
   186 
   190 
   187 
   191 
   188 // Regular expressions - the power of DSLs
   192 // Regular expressions - the power of DSLs in Scala
   189 //=========================================
   193 //==================================================
   190 
   194 
   191 
   195 
   192 abstract class Rexp
   196 abstract class Rexp
   193 case object ZERO extends Rexp
   197 case object ZERO extends Rexp
   194 case object ONE extends Rexp
   198 case object ONE extends Rexp
   195 case class CHAR(c: Char) extends Rexp
   199 case class CHAR(c: Char) extends Rexp
   196 case class ALT(r1: Rexp, r2: Rexp) extends Rexp 
   200 case class ALT(r1: Rexp, r2: Rexp) extends Rexp     // alternative  r1 + r2
   197 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp 
   201 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp     // sequence     r1 r2    
   198 case class STAR(r: Rexp) extends Rexp 
   202 case class STAR(r: Rexp) extends Rexp               // star         r*
   199 
   203 
   200 
   204 
   201 // (ab)*
   205 // (ab)*
   202 val r0 = ??
   206 val r0 = ??
   203 
   207