main_templates3/re.scala
changeset 428 cdfa6a293453
parent 424 daf561a83ba6
child 477 a4e1f63157d8
--- a/main_templates3/re.scala	Sat Oct 08 00:30:51 2022 +0100
+++ b/main_templates3/re.scala	Tue Nov 01 15:03:48 2022 +0000
@@ -1,23 +1,24 @@
 // Main Part 3 about Regular Expression Matching
-//=============================================
+//==============================================
 
 object M3 {
 
-// Regular Expressions
 abstract class Rexp
 case object ZERO extends Rexp
 case object ONE extends Rexp
 case class CHAR(c: Char) extends Rexp
-case class ALTs(rs: List[Rexp]) extends Rexp      // alternatives 
-case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence
-case class STAR(r: Rexp) extends Rexp             // star
+case class ALTs(rs: List[Rexp]) extends Rexp  // alternatives 
+case class SEQs(rs: List[Rexp]) extends Rexp  // sequences
+case class STAR(r: Rexp) extends Rexp         // star
+
 
-//the usual binary choice can be defined in terms of ALTs
+//the usual binary choice and binary sequence can be defined 
+//in terms of ALTs and SEQs
 def ALT(r1: Rexp, r2: Rexp) = ALTs(List(r1, r2))
+def SEQ(r1: Rexp, r2: Rexp) = SEQs(List(r1, r2))
 
 
 // some convenience for typing regular expressions
-
 import scala.language.implicitConversions    
 import scala.language.reflectiveCalls 
 
@@ -42,92 +43,77 @@
   def ~ (r: String) = SEQ(s, r)
 }
 
-
+// examples for the implicits:
 // ALT(CHAR('a'), CHAR('b'))
-// val reg : Rexp = "a" | "b" 
-
+// val areg : Rexp = "a" | "b"
 
-// (1) Complete the function nullable according to
-// the definition given in the coursework; this 
-// function checks whether a regular expression
-// can match the empty string and Returns a boolean
-// accordingly.
-
-def nullable (r: Rexp) : Boolean = ???
-
-
-// (2) Complete the function der according to
-// the definition given in the coursework; this
-// function calculates the derivative of a 
-// regular expression w.r.t. a character.
-
-def der (c: Char, r: Rexp) : Rexp = ???
+// SEQ(CHAR('a'), CHAR('b')) 
+// val sreg : Rexp = "a" ~ "b"
 
 
-// (3) Implement the flatten function flts. It
-// deletes 0s from a list of regular expressions
-// and also 'spills out', or flattens, nested 
-// ALTernativeS.
+// ADD YOUR CODE BELOW
+//======================
 
-def flts(rs: List[Rexp]) : List[Rexp] = ???
+// (1)
+def nullable (r: Rexp) : Boolean = ???
 
-
+// (2) 
+def der (c: Char, r: Rexp) : Rexp = ???
 
-// (4) Complete the simp function according to
-// the specification given in the coursework description; 
-// this function simplifies a regular expression from
-// the inside out, like you would simplify arithmetic 
-// expressions; however it does not simplify inside 
-// STAR-regular expressions. Use the _.distinct and 
-// flts functions.
+// (3) 
+def denest(rs: List[Rexp]) : List[Rexp] = ???
+
+// (4)
+def flts(rs: List[Rexp], acc: List[Rexp] = Nil) : List[Rexp] = ???
 
+// (5)
+def ALTs_smart(rs: List[Rexp]) : Rexp = ???
+def SEQs_smart(rs: List[Rexp]) : Rexp = ???
+
+// (6)
 def simp(r: Rexp) : Rexp = ???
 
-
-// (5) Complete the two functions below; the first 
-// calculates the derivative w.r.t. a string; the second
-// is the regular expression matcher taking a regular
-// expression and a string and checks whether the
-// string matches the regular expression
-
+// (7)
 def ders (s: List[Char], r: Rexp) : Rexp = ???
-
 def matcher(r: Rexp, s: String): Boolean = ???
 
-
-// (6) Complete the size function for regular
-// expressions according to the specification 
-// given in the coursework.
-
+// (8) 
 def size(r: Rexp): Int = ???
 
 
-// some testing data
-
+// Some testing data
+//===================
 /*
+
+simp(ALT(ONE | CHAR('a'), CHAR('a') | ONE))   // => ALTs(List(ONE, CHAR(a)))
+simp(((CHAR('a') | ZERO) ~ ONE) | 
+     (((ONE | CHAR('b')) | CHAR('c')) ~ (CHAR('d') ~ ZERO)))   // => CHAR(a)
+
+matcher(("a" ~ "b") ~ "c", "ab")   // => false
 matcher(("a" ~ "b") ~ "c", "abc")  // => true
-matcher(("a" ~ "b") ~ "c", "ab")   // => false
+
 
 // the supposedly 'evil' regular expression (a*)* b
 val EVIL = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
 
+matcher(EVIL, "a" * 1000)          // => false
 matcher(EVIL, "a" * 1000 ++ "b")   // => true
-matcher(EVIL, "a" * 1000)          // => false
+
 
 // size without simplifications
-size(der('a', der('a', EVIL)))             // => 28
-size(der('a', der('a', der('a', EVIL))))   // => 58
+size(der('a', der('a', EVIL)))             // => 36
+size(der('a', der('a', der('a', EVIL))))   // => 83
 
 // size with simplification
-size(simp(der('a', der('a', EVIL))))           // => 8
-size(simp(der('a', der('a', der('a', EVIL))))) // => 8
+size(simp(der('a', der('a', EVIL))))           // => 7
+size(simp(der('a', der('a', der('a', EVIL))))) // => 7
 
 // Python needs around 30 seconds for matching 28 a's with EVIL. 
 // Java 9 and later increase this to an "astonishing" 40000 a's in
 // 30 seconds.
 //
 // Lets see how long it really takes to match strings with 
-// 5 Million a's...it should be in the range of a couple
+// 5 Million a's...it should be in the range of a few
 // of seconds.
 
 def time_needed[T](i: Int, code: => T) = {