turing.scala
author Christian Urban <christian dot urban at kcl dot ac dot uk>
Fri, 15 Feb 2013 18:24:00 +0000
changeset 176 d2c85556d290
child 177 1c2e639d4e54
permissions -rw-r--r--
added scala file

abstract class Cell
case object Bk extends Cell { override def toString = "0" }
case object Oc extends Cell { override def toString = "1" }

abstract class Action
case object WBk extends Action
case object WOc extends Action
case object R extends Action
case object L extends Action
case object Nop extends Action

type State = Int
type Prog = List[(Action, State)]

//some list functions
def tl[A](xs: List[A]) : List[A] = xs match {
  case Nil => Nil
  case x::xs => xs
}

def hd[A](xs: List[A]) : A = xs.head

def nth_of[A](xs: List[A], n: Int) = 
  if (n <= xs.length) Some(xs(n)) else None 


//tapes
case class Tape(l: List[Cell], r: List[Cell]) {
  def update(a: Action) = a match {
    case WBk => Tape(l, Bk::tl(r))
    case WOc => Tape(l, Oc::tl(r))
    case L => if (l == Nil) Tape(Nil, Bk::r) else Tape (tl(l), hd(l)::r)
    case R => if (r == Nil) Tape(Bk::l, Nil) else Tape(hd(r)::l, tl(r))
    case Nop => Tape(l, r)
  }

  def read = r match {
    case Nil => Bk
    case x::_ => x
  }

  override def toString = 
    l.reverse.map(_.toString).foldLeft("")(_+_) + 
    ">" + r.map(_.toString).foldLeft("")(_+_)
}

// standard tapes
def std(n: Int) : List[Cell] = n match {
  case 0 => List(Oc)
  case n => Oc::std(n - 1)
}

class STape(ns: Int*) extends Tape(Nil, ns.map(std).reduceLeft(_ ::: List(Bk) ::: _))
  
// configurations
case class Config(s: State, tp: Tape) {
  def is_final = s == 0

  override def toString = tp.toString
}


// Turing Machines
case class TM(p: Prog, tp: Tape) {
  
  def fetch(s: State, a: Cell) = (s, a) match {
    case (0, _) => (Nop, 0)
      case (s, Bk) => nth_of(p, 2 * (s - 1)) match {
        case None => (Nop, 0)
        case Some(i) => i
      }
    case (s, Oc) => nth_of(p, 2 * (s - 1) + 1) match {
      case None => (Nop, 0)
      case Some(i) => i
    }
  } 

  def step(cf: Config) : Config = fetch (cf.s, cf.tp.read) match {
    case (a, s_next) => Config(s_next, cf.tp.update(a))
  }

  def steps(cf: Config, n: Int) : Config = n match {
    case 0 => cf
    case n => steps(step(cf), n - 1)
  } 

  def steps(n: Int) : Config = steps(Config(1, tp), n)

  def run(cf: Config) : Config = {
    if (cf.is_final) cf else run(step(cf))
  }
 
  def run : Tape = run(Config(1, tp)).tp
}



// examples
class TMCopy(n: Int) extends 
  TM(List((WBk, 5), (R, 2), (R, 3), (R, 2), (WOc, 3), 
          (L, 4), (L, 4), (L, 5), (R, 11), (R, 6), 
          (R, 7), (WBk, 6), (R, 7), (R, 8), (WOc, 9), 
          (R, 8), (L, 10), (L, 9), (L, 10), (L, 5), 
          (L, 0), (R, 12), (WOc, 13), (L, 14), (R, 12), 
          (R, 12), (L, 15), (WBk, 14), (R, 0), (L, 15)), new STape(n))

println((new TMCopy(0)).run)