checkpoint logic programming post

1 parent 21ef0f6 commit 177891c7d0dfce14498b781c4c50e064909808fb committed Apr 5, 2011
57 _code/scala-logic/Bridge.scala
 @@ -0,0 +1,57 @@ +class Bridge1(Logic: Logic) { + import Logic._ + + object Person extends Enumeration { + type Person = Value + val Alice, Bob, Candace, Dave = Value + val all = List(Alice, Bob, Candace, Dave) // values is broken + } + import Person._ + + val times = Map(Alice -> 5, Bob -> 10, Candace -> 20, Dave -> 25) + + case class State(left: List[Person], + lightOnLeft: Boolean, + timeRemaining: Int) + + private def chooseTwo(list: List[Person]): T[(Person,Person)] = + for { p1 <- or(list); p2 <- or(list); if p1 < p2 } + yield (p1, p2) + + private def next(state: State): T[State] = { + if (state.lightOnLeft) { + for { + (p1, p2) <- chooseTwo(state.left) + timeRemaining = + state.timeRemaining - math.max(times(p1), times(p2)) + if timeRemaining >= 0 + } yield { + val left = + state.left.filterNot { p => p == p1 || p == p2 } + State(left, false, timeRemaining) + } + } else { + val right = Person.all.filterNot(state.left.contains) + for { + p <- or(right) + timeRemaining = state.timeRemaining - times(p) + if timeRemaining >= 0 + } yield State(p :: state.left, true, timeRemaining) + } + } + + private def tree(path: List[State]): T[List[State]] = + unit(path) | + (for { + state <- next(path.head) + path <- tree(state :: path) + } yield path) + + def search(n: Int): List[List[State]] = { + val start = List(State(Person.all, true, 60)) + val t = + for { path <- tree(start); if path.head.left == Nil } + yield path + run(t, n) + } +}
61 _code/scala-logic/Bridge0.scala
 @@ -0,0 +1,61 @@ +object Bridge0 { + object Person extends Enumeration { + type Person = Value + val Alice, Bob, Candace, Dave = Value + val all = List(Alice, Bob, Candace, Dave) // values is broken + } + import Person._ + + val times = Map(Alice -> 5, Bob -> 10, Candace -> 20, Dave -> 25) + + case class State(left: List[Person], + lightOnLeft: Boolean, + timeRemaining: Int) + + def chooseTwo(list: List[Person]): List[(Person,Person)] = { + val init: List[(Person, Person)] = Nil + list.foldLeft(init) { (pairs, p1) => + list.foldLeft(pairs) { (pairs, p2) => + if (p1 < p2) (p1, p2) :: pairs else pairs + } + } + } + + def next(state: State): List[State] = { + if (state.lightOnLeft) { + val init: List[State] = Nil + chooseTwo(state.left).foldLeft(init) { + case (states, (p1, p2)) => + val timeRemaining = + state.timeRemaining - math.max(times(p1), times(p2)) + if (timeRemaining >= 0) { + val left = + state.left.filterNot { p => p == p1 || p == p2 } + State(left, false, timeRemaining) :: states + } + else + states + } + } else { + val right = Person.all.filterNot(state.left.contains) + val init: List[State] = Nil + right.foldLeft(init) { (states, p) => + val timeRemaining = state.timeRemaining - times(p) + if (timeRemaining >= 0) + State(p :: state.left, true, timeRemaining) :: states + else + states + } + } + } + + def tree(path: List[State]): List[List[State]] = + next(path.head). + map(s => tree(s :: path)). + foldLeft(List(path)) { _ ++ _ } + + def search: List[List[State]] = { + val start = List(State(Person.all, true, 60)) + tree(start).filter { _.head.left == Nil } + } +}
103 _code/scala-logic/Logic.scala
 @@ -0,0 +1,103 @@ +trait Logic { L => + type T[A] + + def fail[A]: T[A] + def unit[A](a: A): T[A] + def or[A](t1: T[A], t2: => T[A]): T[A] + def apply[A,B](t: T[A], f: A => B): T[B] + def bind[A,B](t: T[A], f: A => T[B]): T[B] + def filter[A](t: T[A], p: A => Boolean): T[A] + def split[A](t: T[A]): Option[(A,T[A])] + + def or[A](as: List[A]): T[A] = + as.foldRight(fail[A])((a, t) => or(unit(a), t)) + + def run[A](t: T[A], n: Int): List[A] = + if (n <= 0) Nil else + split(t) match { + case None => Nil + case Some((a, t)) => a :: run(t, n - 1) + } + + case class Syntax[A](t: T[A]) { + def map[B](f: A => B): T[B] = L.apply(t, f) + def filter(p: A => Boolean): T[A] = L.filter(t, p) + def flatMap[B](f: A => T[B]): T[B] = L.bind(t, f) + def withFilter(p: A => Boolean): T[A] = L.filter(t, p) + + def |(t2: => T[A]): T[A] = L.or(t, t2) + } + + implicit def syntax[A](t: T[A]) = Syntax(t) +} + +object LogicList extends Logic { + type T[A] = List[A] + + def fail[A] = Nil + def unit[A](a: A) = a :: Nil + def or[A](t1: List[A], t2: => List[A]) = t1 ::: t2 + def apply[A,B](t: List[A], f: A => B) = t.map(f) + def bind[A,B](t: List[A], f: A => List[B]) = t.flatMap(f) + def filter[A](t: List[A], p: A => Boolean) = t.filter(p) + def split[A](t: List[A]) = + t match { + case Nil => None + case h :: t => Some(h, t) + } +} + +object LogicSFK extends Logic { + // type FK[R] = => R + type SK[A,R] = (A, => R) => R + + trait T[A] { def apply[R](sk: SK[A,R], fk: => R): R } + + def fail[A] = + new T[A] { + def apply[R](sk: SK[A,R], fk: => R) = fk + } + + def unit[A](a: A) = + new T[A] { + def apply[R](sk: SK[A,R], fk: => R) = sk(a, fk) + } + + def or[A](t1: T[A], t2: => T[A]) = + new T[A] { + def apply[R](sk: SK[A,R], fk: => R) = t1(sk, t2(sk, fk)) + } + + def bind[A,B](t: T[A], f: A => T[B]) = + new T[B] { + def apply[R](sk: SK[B,R], fk: => R) = + t(({ (a, fk) => f(a)(sk, fk) }: SK[A,R]), fk) + } + + def apply[A,B](t: T[A], f: A => B) = + new T[B] { + def apply[R](sk: SK[B,R], fk: => R) = + t(({ (a, fk) => sk(f(a), fk) }: SK[A,R]), fk) + } + + def filter[A](t: T[A], p: A => Boolean) = + new T[A] { + def apply[R](sk: SK[A,R], fk: => R) = + t(({ (a, fk) => if (p(a)) sk(a, fk) else fk }: SK[A,R]), fk) + } + + def split[A](t: T[A]) = { + def unsplit(r: Option[(A,T[A])]): T[A] = + r match { + case None => fail + case Some((a, t)) => or(unit(a), t) + } + def unit[A](a: => A) = + new T[A] { + def apply[R](sk: SK[A,R], fk: => R) = sk(a, fk) + } + def sk : SK[A,Option[(A,T[A])]] = + { (a, fk) => Some(a, bind(unit(fk), unsplit)) } + t(sk, None) + } +}
439 _posts/2011-04-07-logic-programming-in-scala.markdown