solutions5/bfc.scala
author Christian Urban <urbanc@in.tum.de>
Thu, 06 Dec 2018 16:08:11 +0000
changeset 232 0855c4478f27
child 233 38ea26f227af
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
232
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     1
// Part 2 about a "Compiler" for the Brainf*** language
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     2
//======================================================
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     3
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     4
//object CW10b {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     5
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     6
// !!! Copy any function you need from file bf.scala !!!
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     7
//
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     8
// If you need any auxiliary function, feel free to 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     9
// implement it, but do not make any changes to the
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    10
// templates below.
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    11
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    12
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    13
def time_needed[T](n: Int, code: => T) = {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    14
  val start = System.nanoTime()
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    15
  for (i <- 0 until n) code
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    16
  val end = System.nanoTime()
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    17
  (end - start)/(n * 1.0e9)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    18
}
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    19
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    20
type Mem = Map[Int, Int]
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    21
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    22
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    23
import io.Source
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    24
import scala.util._
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    25
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    26
def load_bff(name: String) : String = 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    27
  Try(Source.fromFile(name)("ISO-8859-1").mkString).getOrElse("")
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    28
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    29
def sread(mem: Mem, mp: Int) : Int = 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    30
  mem.getOrElse(mp, 0)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    31
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    32
def write(mem: Mem, mp: Int, v: Int) : Mem =
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    33
  mem.updated(mp, v)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    34
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    35
def jumpRight(prog: String, pc: Int, level: Int) : Int = {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    36
  if (prog.length <= pc) pc 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    37
  else (prog(pc), level) match {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    38
    case (']', 0) => pc + 1
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    39
    case (']', l) => jumpRight(prog, pc + 1, l - 1)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    40
    case ('[', l) => jumpRight(prog, pc + 1, l + 1)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    41
    case (_, l) => jumpRight(prog, pc + 1, l)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    42
  }
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    43
}
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    44
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    45
def jumpLeft(prog: String, pc: Int, level: Int) : Int = {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    46
  if (pc < 0) pc 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    47
  else (prog(pc), level) match {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    48
    case ('[', 0) => pc + 1
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    49
    case ('[', l) => jumpLeft(prog, pc - 1, l - 1)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    50
    case (']', l) => jumpLeft(prog, pc - 1, l + 1)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    51
    case (_, l) => jumpLeft(prog, pc - 1, l)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    52
  }
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    53
}
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    54
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    55
def compute(prog: String, pc: Int, mp: Int, mem: Mem) : Mem = {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    56
  if (0 <= pc && pc < prog.length) { 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    57
    val (new_pc, new_mp, new_mem) = prog(pc) match {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    58
      case '>' => (pc + 1, mp + 1, mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    59
      case '<' => (pc + 1, mp - 1, mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    60
      case '+' => (pc + 1, mp, write(mem, mp, sread(mem, mp) + 1))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    61
      case '-' => (pc + 1, mp, write(mem, mp, sread(mem, mp) - 1))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    62
      case '.' => { print(sread(mem, mp).toChar); (pc + 1, mp, mem) }
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    63
      case ',' => (pc + 1, mp, write(mem, mp, Console.in.read().toByte))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    64
      case '['  => 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    65
	if (sread(mem, mp) == 0) (jumpRight(prog, pc + 1, 0), mp, mem) else (pc + 1, mp, mem) 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    66
      case ']'  => 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    67
	if (sread(mem, mp) != 0) (jumpLeft(prog, pc - 1, 0), mp, mem) else (pc + 1, mp, mem) 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    68
      case _ => (pc + 1, mp, mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    69
    }		     
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    70
    compute(prog, new_pc, new_mp, new_mem)	
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    71
  }
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    72
  else mem
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    73
}
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    74
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    75
def run(prog: String, m: Mem = Map()) = compute(prog, 0, 0, m)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    76
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    77
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    78
// The baseline to what we compare our "compiler";
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    79
// it requires something like 60 seconds on my laptop
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    80
//
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    81
//time_needed(1, run(load_bff("benchmark.bf")))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    82
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    83
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    84
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    85
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    86
// (5) Write a function jtable that precomputes the "jump
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    87
//     table" for a bf-program. This function takes a bf-program 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    88
//     as an argument and Returns a Map[Int, Int]. The 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    89
//     purpose of this map is to record the information
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    90
//     that given on the pc-position, say n, is a '[' or a ']',
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    91
//     then to which pc-position do we need to jump?
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    92
// 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    93
//     For example for the program
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    94
//    
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    95
//       "+++++[->++++++++++<]>--<+++[->>++++++++++<<]>>++<<----------[+>.>.<+<]"
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    96
//
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    97
//     we obtain the map
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    98
//
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    99
//       Map(69 -> 61, 5 -> 20, 60 -> 70, 27 -> 44, 43 -> 28, 19 -> 6)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   100
//  
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   101
//     This states that for the '[' on position 5, we need to
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   102
//     jump to position 20, which is just after the corresponding ']'.
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   103
//     Similarly, for the ']' on position 19, we need to jump to
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   104
//     position 6, which is just after the '[' on position 5, and so
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   105
//     on. The idea to not calculate this information each time
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   106
//     we hit a bracket, but just loop uu this information in the 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   107
//     jtable.
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   108
//
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   109
//     Adapt the compute and run functions from Part 1 in order to
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   110
//     take advantage of the information in the jtable. 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   111
 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   112
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   113
def jtable(pg: String) : Map[Int, Int] = 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   114
    (0 until pg.length).collect { pc => pg(pc) match {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   115
      case '[' => (pc -> jumpRight(pg, pc + 1, 0))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   116
      case ']' => (pc -> jumpLeft(pg, pc - 1, 0))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   117
    }}.toMap
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   118
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   119
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   120
// testcase
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   121
// jtable("""+++++[->++++++++++<]>--<+++[->>++++++++++<<]>>++<<----------[+>.>.<+<]""")
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   122
// =>  Map(69 -> 61, 5 -> 20, 60 -> 70, 27 -> 44, 43 -> 28, 19 -> 6)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   123
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   124
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   125
def compute2(pg: String, tb: Map[Int, Int], pc: Int, mp: Int, mem: Mem) : Mem = {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   126
  if (0 <= pc && pc < pg.length) { 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   127
    val (new_pc, new_mp, new_mem) = pg(pc) match {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   128
      case '>' => (pc + 1, mp + 1, mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   129
      case '<' => (pc + 1, mp - 1, mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   130
      case '+' => (pc + 1, mp, write(mem, mp, sread(mem, mp) + 1))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   131
      case '-' => (pc + 1, mp, write(mem, mp, sread(mem, mp) - 1))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   132
      case '.' => { print(sread(mem, mp).toChar); (pc + 1, mp, mem) }
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   133
      case ',' => (pc + 1, mp, write(mem, mp, Console.in.read().toByte))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   134
      case '['  => 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   135
	if (sread(mem, mp) == 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   136
      case ']'  => 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   137
	if (sread(mem, mp) != 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   138
      case _ => (pc + 1, mp, mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   139
    }		     
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   140
    compute2(pg, tb, new_pc, new_mp, new_mem)	
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   141
  }
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   142
  else mem
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   143
}
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   144
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   145
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   146
def run2(pg: String, m: Mem = Map()) = 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   147
  compute2(pg, jtable(pg), 0, 0, m)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   148
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   149
//time_needed(1, run2(load_bff("benchmark.bf")))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   150
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   151
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   152
// (6) Write a function optimise which deletes "dead code" (everything
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   153
// that is not a bf-command) and also replaces substrings of the form
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   154
// [-] by a new command 0. The idea is that the the loop [-] resets the
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   155
// memory at the current location to 0. In the compute3 and run3 functions
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   156
// below we implement this command by writing 0 to mem(mp), then is
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   157
// write(mem, mp, 0). 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   158
//
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   159
// The easiest way to modify a string in this way is to use the regular
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   160
// expression """[^<>+-.,\[\]]""", whcih recognises everything that is 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   161
// not a bf-command and replace it by the empty string. Similarly the
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   162
// regular expression """\[-\]""" finds all occurences of [-] and 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   163
// by using the Scala method .replaceAll you can repplace it with the 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   164
// string "0" standing for the new bf-program.
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   165
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   166
def optimise(s: String) : String = 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   167
  s.replaceAll("""[^<>+-.,\[\]]""","").replaceAll("""\[-\]""", "0")
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   168
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   169
def compute3(pg: String, tb: Map[Int, Int], pc: Int, mp: Int, mem: Mem) : Mem = {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   170
  if (0 <= pc && pc < pg.length) { 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   171
    val (new_pc, new_mp, new_mem) = pg(pc) match {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   172
      case '0' => (pc + 1, mp, write(mem, mp, 0))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   173
      case '>' => (pc + 1, mp + 1, mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   174
      case '<' => (pc + 1, mp - 1, mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   175
      case '+' => (pc + 1, mp, write(mem, mp, sread(mem, mp) + 1))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   176
      case '-' => (pc + 1, mp, write(mem, mp, sread(mem, mp) - 1))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   177
      case '.' => { print(sread(mem, mp).toChar); (pc + 1, mp, mem) }
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   178
      case ',' => (pc + 1, mp, write(mem, mp, Console.in.read().toByte))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   179
      case '['  => 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   180
	if (sread(mem, mp) == 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   181
      case ']'  => 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   182
	if (sread(mem, mp) != 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   183
      case _ => (pc + 1, mp, mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   184
    }		     
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   185
    compute3(pg, tb, new_pc, new_mp, new_mem)	
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   186
  }
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   187
  else mem
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   188
}
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   189
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   190
def run3(pg: String, m: Mem = Map()) = { 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   191
  val pg_opt = optimise(pg)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   192
  compute3(pg_opt, jtable(pg_opt), 0, 0, m)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   193
}
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   194
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   195
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   196
time_needed(1, run3(load_bff("benchmark.bf")))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   197
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   198
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   199
// (7) 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   200
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   201
def splice(cs: List[Char], acc: List[(Char, Int)]) : List[(Char, Int)] = (cs, acc) match {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   202
  case (Nil, acc) => acc  
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   203
  case ('[' :: cs, acc) => splice(cs, ('[', 1) :: acc)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   204
  case (']' :: cs, acc) => splice(cs, (']', 1) :: acc)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   205
  case ('.' :: cs, acc) => splice(cs, ('.', 1) :: acc)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   206
  case (',' :: cs, acc) => splice(cs, (',', 1) :: acc)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   207
  case ('0' :: cs, acc) => splice(cs, ('0', 1) :: acc)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   208
  case (c :: cs, Nil) => splice(cs, List((c, 1)))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   209
  case (c :: cs, (d, n) :: acc) => 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   210
    if (c == d && n < 26) splice(cs, (c, n + 1) :: acc)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   211
    else splice(cs, (c, 1) :: (d, n) :: acc)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   212
}
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   213
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   214
def spl(s: String) = splice(s.toList, Nil).reverse
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   215
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   216
spl(load_bff("benchmark.bf"))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   217
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   218
def combine(cs: List[(Char, Int)]) : String = {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   219
  (for ((c, n) <- cs) yield c match {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   220
    case '>' => List('>', (n + '@').toChar)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   221
    case '<' => List('<', (n + '@').toChar)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   222
    case '+' => List('+', (n + '@').toChar)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   223
    case '-' => List('-', (n + '@').toChar)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   224
    case _ => List(c)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   225
  }).flatten.mkString
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   226
}
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   227
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   228
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   229
combine(spl(load_bff("benchmark.bf")))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   230
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   231
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   232
def compute4(pg: String, tb: Map[Int, Int], pc: Int, mp: Int, mem: Mem) : Mem = {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   233
  if (0 <= pc && pc < pg.length) { 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   234
    val (new_pc, new_mp, new_mem) = pg(pc) match {
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   235
      case '0' => (pc + 1, mp, write(mem, mp, 0))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   236
      case '>' => (pc + 2, mp + (pg(pc + 1) - '@'), mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   237
      case '<' => (pc + 2, mp - (pg(pc + 1) - '@'), mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   238
      case '+' => (pc + 2, mp, write(mem, mp, sread(mem, mp) + (pg(pc + 1) - '@')))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   239
      case '-' => (pc + 2, mp, write(mem, mp, sread(mem, mp) - (pg(pc + 1) - '@')))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   240
      case '.' => { print(sread(mem, mp).toChar); (pc + 1, mp, mem) }
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   241
      case ',' => (pc + 1, mp, write(mem, mp, Console.in.read().toByte))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   242
      case '['  => 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   243
	if (sread(mem, mp) == 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   244
      case ']'  => 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   245
	if (sread(mem, mp) != 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   246
      case _ => (pc + 1, mp, mem)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   247
    }		     
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   248
    compute4(pg, tb, new_pc, new_mp, new_mem)	
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   249
  }
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   250
  else mem
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   251
}
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   252
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   253
def run4(pg: String, m: Mem = Map()) = { 
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   254
  val pg_opt = combine(spl(optimise(pg)))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   255
  compute4(pg_opt, jtable(pg_opt), 0, 0, m)
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   256
}
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   257
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   258
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   259
//time_needed(1, run4(load_bff("benchmark.bf")))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   260
//time_needed(1, run4(load_bff("mandelbrot.bf")))
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   261
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   262
0855c4478f27 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   263
}