Skip to content

Instantly share code, notes, and snippets.

@chemacortes
Last active December 17, 2015 10:09
Show Gist options
  • Save chemacortes/5592311 to your computer and use it in GitHub Desktop.
Save chemacortes/5592311 to your computer and use it in GitHub Desktop.
Solución del problema "Pouring Water".
class Pouring(capacity: Vector[Int]) {
// States
type State = Vector[Int]
val initialState = capacity map (x ⇒ 0)
// Moves
trait Move {
def change(state: State): State
}
case class Empty(glass: Int) extends Move {
def change(state: State) = state updated (glass, 0)
}
case class Fill(glass: Int) extends Move {
def change(state: State) = state updated (glass, capacity(glass))
}
case class Pour(from: Int, to: Int) extends Move {
def change(state: State) = {
val amount = state(from) min (capacity(to) - state(to))
state updated (from, state(from) - amount) updated (to, state(to) + amount)
}
}
val glasses = 0 until capacity.length
val moves =
(for (g <- glasses) yield Empty(g)) ++
(for (g <- glasses) yield Fill(g)) ++
(for (from <- glasses; to <- glasses if from != to) yield Pour(from, to))
// Paths
class Path(history: List[Move], val endState: State) {
def extend(move: Move) = new Path(move :: history, move change endState)
override def toString = (history.reverse mkString " ") + "-->" + endState
}
val initialPath = new Path(Nil, initialState)
def from(paths: Set[Path], explored: Set[State]): Stream[Set[Path]] =
if (paths.isEmpty) Stream.empty
else {
val more = for {
path <- paths
next <- moves map path.extend
if !(explored contains next.endState)
} yield next
paths #:: from(more, explored ++ (more map (_.endState)))
}
val pathSets = from(Set(initialPath), Set(initialState))
// Solution (optimal)
def solution(target: Int): Stream[Path] =
for {
pathSet <- pathSets
path <- pathSet
if path.endState contains target
} yield path
}
@chemacortes
Copy link
Author

Interesante forma de utilizar la evaluación perezosa para modelizar los infinitos movimientos posibles para llegar a la meta, para luego dar con la solución óptima tras fitrar los movimientos circulares.

Extraído del final del curso "Functiona Programming Principles in scala" de Martin Ordersky.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment