Advertisement
jules0707

pouring

Feb 27th, 2017
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 2.00 KB | None | 0 0
  1. package main
  2.  
  3. class Pouring(capacity: Vector[Int]) {
  4.  
  5.   // States
  6.   type State = Vector[Int]
  7.   val initialState = capacity map (x => 0)
  8.  
  9.   // Moves
  10.   trait Move {
  11.     def change(state: State): State
  12.   }
  13.   case class Empty(glass: Int) extends Move {
  14.     def change(state: State): Vector[Int] = state.updated(glass, 0)
  15.   }
  16.   case class Fill(glass: Int) extends Move {
  17.     def change(state: State): Vector[Int] = state.updated(glass, capacity(glass))
  18.   }
  19.   case class Pour(from: Int, to: Int) extends Move {
  20.     def change(state: State): Vector[Int] = {
  21.       val amount = state(from) min (capacity(to) - state(to))
  22.       state.updated(from, state(from) - amount).updated(to, state(to) + amount)
  23.     }
  24.   }
  25.  
  26.   val glasses = 0 until capacity.length
  27.  
  28.   val moves = (
  29.     for (glass <- glasses) yield Empty(glass)) ++ (
  30.       for (glass <- glasses) yield Fill(glass)) ++ (
  31.         for (from <- glasses; to <- glasses if from != to) yield Pour(from, to))
  32.  
  33.   // Paths
  34.   class Path(history: List[Move]) {
  35.  
  36.     def endState: State = (history foldRight initialState)(_ change _)
  37.     def extend(move: Move) = new Path(move :: history)
  38.     override def toString = (history.reverse mkString " ") + " --> " + endState + "\n"
  39.     // def endState(moves: List[Move]): State = history match {
  40.     //      case Nil         => initialState
  41.     //      case move :: xs1 => move change endState(xs1)
  42.     //    }
  43.   }
  44.  
  45.   val initialPath = new Path(Nil)
  46.  
  47.   def from(paths: Set[Path], explored: Set[State]): Stream[Set[Path]] =
  48.     if (paths.isEmpty) Stream.empty
  49.     else {
  50.       val more = for {
  51.         path <- paths
  52.         next <- moves map path.extend
  53.         if !(explored contains next.endState)
  54.       } yield next
  55.       paths #:: from(more, explored ++ (more map (_.endState)))
  56.     }
  57.  
  58.   val pathSets = from(Set(initialPath), Set(initialState))
  59.  
  60.   def solution(target: Int): Stream[Path] =
  61.     for {
  62.       pathSet <- pathSets
  63.       path <- pathSet
  64.       if path.endState contains target
  65.     } yield path
  66.  
  67. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement