scala/abacus.scala
changeset 193 317a2532c567
child 194 fc2a5e9fbb97
equal deleted inserted replaced
192:3c1107984b41 193:317a2532c567
       
     1 package object abacus {
       
     2 
       
     3 import lib._
       
     4 
       
     5 // Abacus machines
       
     6 sealed abstract class AInst 
       
     7 case class Inc(n: Int) extends AInst
       
     8 case class Dec(n: Int, l: Int) extends AInst
       
     9 case class Goto(l: Int) extends AInst
       
    10 
       
    11 type AProg = List[AInst]
       
    12 type Regs = Map[Int, Int]
       
    13 
       
    14 case class AConfig(s: Int, regs: Regs)  
       
    15 
       
    16 case class Abacus(p: AProg) {
       
    17 
       
    18   def ++ (that: Abacus) = Abacus(this.p ::: that.p)
       
    19 
       
    20   def shift(offset: Int, jump: Int) = Abacus(p.map(_ match {
       
    21     case Inc(n) => Inc(n)
       
    22     case Dec(n, l) => if (l == jump) Dec(n, l) else Dec(n, l + offset)
       
    23     case Goto(l) => if (l == jump) Goto(l) else Goto(l + offset)
       
    24   }))
       
    25       
       
    26   def adjust(old_jump: Int, jump: Int) = Abacus(p.map(_ match {
       
    27     case Inc(n) => Inc(n)
       
    28     case Dec(n, l) => if (l == old_jump) Dec(n, jump) else Dec(n, l)
       
    29     case Goto(l) => if (l == old_jump) Goto(jump) else Goto(l)
       
    30   }))
       
    31 
       
    32   def step(cf: AConfig) : AConfig = (nth_of(p, cf.s), cf.s) match {
       
    33     case (None, _) => cf
       
    34     case (Some(Inc(n)), s) => AConfig(s + 1, cf.regs + (n -> (dget(cf.regs, n) + 1)))
       
    35     case (Some(Dec(n, l)), s) => {
       
    36       if (dget(cf.regs, n) == 0) AConfig(l, cf.regs)
       
    37       else AConfig(s + 1, cf.regs + (n -> (dget(cf.regs, n) - 1)))
       
    38     }
       
    39     case (Some(Goto(l)), _) => AConfig(l, cf.regs)
       
    40   }  
       
    41 
       
    42   def steps(cf: AConfig, n: Int) : AConfig = n match {
       
    43     case 0 => cf
       
    44     case n => steps(step(cf), n - 1)
       
    45   } 
       
    46 
       
    47   def steps(regs: Regs, n: Int) : AConfig = steps(AConfig(0, regs), n)
       
    48 
       
    49   def run(cf: AConfig) : AConfig = {
       
    50     if (cf.s >= p.length || cf.s < 0) cf else run(step(cf))
       
    51   }
       
    52  
       
    53   def run(regs: Regs): Regs = run(AConfig(0, regs)).regs
       
    54 }
       
    55 
       
    56 }
       
    57