progs/lecture3.scala
changeset 72 9d8b172f5337
parent 71 19dff7218b0d
child 73 5e4696ebd8dc
equal deleted inserted replaced
71:19dff7218b0d 72:9d8b172f5337
    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 V0.1
    39 //factorial V0.1
       
    40 import scala.annotation.tailrec
       
    41 
    40 
    42 
    41 def fact(n: Long): Long = 
    43 def fact(n: Long): Long = 
    42   if (n == 0) 1 else n * fact(n - 1)
    44   if (n == 0) 1 else n * fact(n - 1)
    43 
    45 
    44 fact(10000)                        // produces a stackoverflow
    46 fact(10000)                        // produces a stackoverflow
    45 
    47 
    46 
    48 @tailrec
    47 def factT(n: BigInt, acc: BigInt): BigInt =
    49 def factT(n: BigInt, acc: BigInt): BigInt =
    48   if (n == 0) acc else factT(n - 1, n * acc)
    50   if (n == 0) acc else factT(n - 1, n * acc)
    49 
    51 
    50 
    52 
    51 factT(10000, 1)
    53 println(factT(10000, 1))
    52 
    54 
    53 // the functions my_contains and factT are tail-recursive 
    55 // the functions my_contains and factT are tail-recursive 
    54 // you can check this with 
    56 // you can check this with 
    55 
    57 
    56 import scala.annotation.tailrec
    58 import scala.annotation.tailrec
    78       if (fx.isDefined) fx else first_positive(xs, f)
    80       if (fx.isDefined) fx else first_positive(xs, f)
    79   }
    81   }
    80 }
    82 }
    81 
    83 
    82 
    84 
       
    85 import scala.annotation.tailrec
       
    86 
    83 def search(total: Int, coins: List[Int], cs: List[Int]): Option[List[Int]] = {
    87 def search(total: Int, coins: List[Int], cs: List[Int]): Option[List[Int]] = {
    84   if (total < cs.sum) None 
    88   if (total < cs.sum) None 
    85   else if (cs.sum == total) Some(cs) 
    89   else if (cs.sum == total) Some(cs) 
    86   else first_positive(coins, (c: Int) => search(total, coins, c::cs))
    90   else first_positive(coins, (c: Int) => search(total, coins, c::cs))
    87 }
    91 }
    96 
   100 
    97 
   101 
    98 import scala.annotation.tailrec
   102 import scala.annotation.tailrec
    99 
   103 
   100 @tailrec
   104 @tailrec
   101 def searchT(total: Int, coins: List[Int], acc_cs: List[List[Int]]): Option[List[Int]] = acc_cs match {
   105 def searchT(total: Int, coins: List[Int], 
       
   106             acc_cs: List[List[Int]]): Option[List[Int]] = acc_cs match {
   102   case Nil => None
   107   case Nil => None
   103   case x::xs => 
   108   case x::xs => 
   104     if (total < x.sum) searchT(total, coins, xs)
   109     if (total < x.sum) searchT(total, coins, xs)
   105     else if (x.sum == total) Some(x) 
   110     else if (x.sum == total) Some(x) 
   106     else searchT(total, coins, coins.filter(_ > 0).map(_::x) ::: xs)
   111     else searchT(total, coins, coins.filter(_ > 0).map(_::x) ::: xs)
   117 
   122 
   118 
   123 
   119 // Polymorphic Types
   124 // Polymorphic Types
   120 //===================
   125 //===================
   121 
   126 
   122 // You do not want to frite functions like contains, first 
   127 // You do not want to write functions like contains, first 
   123 // and so on for every type of lists.
   128 // and so on for every type of lists.
   124 
   129 
   125 
   130 
   126 def length_int_list(lst: List[Int]): Int = lst match {
   131 def length_string_list(lst: List[String]): Int = lst match {
   127   case Nil => 0
   132   case Nil => 0
   128   case x::xs => 1 + length_int_list(xs)
   133   case x::xs => 1 + length_string_list(xs)
   129 }
   134 }
   130 
   135 
   131 length_int_list(List(1, 2, 3, 4))
   136 length_string_list(List("1", "2", "3", "4"))
   132 
   137 
   133 
   138 
   134 def length[A](lst: List[A]): Int = lst match {
   139 def length[A](lst: List[A]): Int = lst match {
   135   case Nil => 0
   140   case Nil => 0
   136   case x::xs => 1 + length(xs)
   141   case x::xs => 1 + length(xs)
   153 //(trees with some content)
   158 //(trees with some content)
   154 
   159 
   155 abstract class Tree[+A]
   160 abstract class Tree[+A]
   156 case class Node[A](elem: A, left: Tree[A], right: Tree[A]) extends Tree[A]
   161 case class Node[A](elem: A, left: Tree[A], right: Tree[A]) extends Tree[A]
   157 case object Leaf extends Tree[Nothing]
   162 case object Leaf extends Tree[Nothing]
       
   163 
       
   164 val t0 = Node('4', Node('2', Leaf, Leaf), Node('7', Leaf, Leaf))
   158 
   165 
   159 def insert[A](tr: Tree[A], n: A): Tree[A] = tr match {
   166 def insert[A](tr: Tree[A], n: A): Tree[A] = tr match {
   160   case Leaf => Node(n, Leaf, Leaf)
   167   case Leaf => Node(n, Leaf, Leaf)
   161   case Node(m, left, right) => 
   168   case Node(m, left, right) => 
   162     if (n == m) Node(m, left, right) 
   169     if (n == m) Node(m, left, right) 
   166 
   173 
   167 
   174 
   168 // the A-type needs to be ordered
   175 // the A-type needs to be ordered
   169 
   176 
   170 abstract class Tree[+A <% Ordered[A]]
   177 abstract class Tree[+A <% Ordered[A]]
   171 case class Node[A <% Ordered[A]](elem: A, left: Tree[A], right: Tree[A]) extends Tree[A]
   178 case class Node[A <% Ordered[A]](elem: A, left: Tree[A], 
       
   179                                  right: Tree[A]) extends Tree[A]
   172 case object Leaf extends Tree[Nothing]
   180 case object Leaf extends Tree[Nothing]
   173 
   181 
   174 
   182 
   175 def insert[A <% Ordered[A]](tr: Tree[A], n: A): Tree[A] = tr match {
   183 def insert[A <% Ordered[A]](tr: Tree[A], n: A): Tree[A] = tr match {
   176   case Leaf => Node(n, Leaf, Leaf)
   184   case Leaf => Node(n, Leaf, Leaf)
   196 abstract class Rexp
   204 abstract class Rexp
   197 case object ZERO extends Rexp
   205 case object ZERO extends Rexp
   198 case object ONE extends Rexp
   206 case object ONE extends Rexp
   199 case class CHAR(c: Char) extends Rexp
   207 case class CHAR(c: Char) extends Rexp
   200 case class ALT(r1: Rexp, r2: Rexp) extends Rexp     // alternative  r1 + r2
   208 case class ALT(r1: Rexp, r2: Rexp) extends Rexp     // alternative  r1 + r2
   201 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp     // sequence     r1 r2    
   209 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp     // sequence     r1 r2  
   202 case class STAR(r: Rexp) extends Rexp               // star         r*
   210 case class STAR(r: Rexp) extends Rexp               // star         r*
   203 
   211 
   204 
   212 
   205 // (ab)*
   213 // (ab)*
   206 val r0 = ??
   214 val r0 = STAR(SEQ(CHAR('a'), CHAR('b')))
   207 
   215 
   208 
   216 
   209 // some convenience for typing in regular expressions
   217 // some convenience for typing in regular expressions
   210 import scala.language.implicitConversions    
   218 import scala.language.implicitConversions    
   211 import scala.language.reflectiveCalls 
   219 import scala.language.reflectiveCalls 
   218 implicit def string2rexp(s: String): Rexp = charlist2rexp(s.toList)
   226 implicit def string2rexp(s: String): Rexp = charlist2rexp(s.toList)
   219 
   227 
   220 
   228 
   221 val r1 = STAR("ab")
   229 val r1 = STAR("ab")
   222 val r2 = STAR("")
   230 val r2 = STAR("")
   223 val r3 = STAR(ALT("ab", "ba"))
   231 val r3 = STAR(ALT("ab", "baa baa black sheep"))
   224 
       
   225 
   232 
   226 implicit def RexpOps (r: Rexp) = new {
   233 implicit def RexpOps (r: Rexp) = new {
   227   def | (s: Rexp) = ALT(r, s)
   234   def | (s: Rexp) = ALT(r, s)
   228   def % = STAR(r)
   235   def % = STAR(r)
   229   def ~ (s: Rexp) = SEQ(r, s)
   236   def ~ (s: Rexp) = SEQ(r, s)
   257 // this is called strict evaluation
   264 // this is called strict evaluation
   258 
   265 
   259 
   266 
   260 def expensiveOperation(n: BigInt): Boolean = expensiveOperation(n + 1) 
   267 def expensiveOperation(n: BigInt): Boolean = expensiveOperation(n + 1) 
   261 val a = "foo"
   268 val a = "foo"
   262 val b = "foo"
   269 val b = "bar"
   263 
   270 
   264 val test = if ((a == b) || expensiveOperation(0)) true else false
   271 val test = if ((a == b) || expensiveOperation(0)) true else false
   265 
   272 
   266 // this is called lazy evaluation
   273 // this is called lazy evaluation
   267 // you delay compuation until it is really 
   274 // you delay compuation until it is really