I am wondering how to implement a width search in Scala using functional programming.
Here is my first, unclean code:
def bfs[S](init: S, f: S => Seq[S], finalS: S => Boolean): Option[S] = { val queue = collection.mutable.Queue[S]() queue += init var found: Option[S] = None while (!queue.isEmpty && found.isEmpty) { val next = queue.dequeue() if (finalS(next)) { found = Some(next) } else { f(next).foreach { s => queue += s } } } found }
Although I use only local variability (a var
and mutable Queue
), it is not purely functional.
I came up with a different version:
case class State[S](q: Queue[S], cur: S) def update[S](f: S => Seq[S])(s: State[S]) : State[S] = { val (i, q2) = sqdequeue val q3 = f(i).foldLeft(q2) { case (acc, i) => acc.enqueue(i)} State(q3, i) } def bfs2[S](init: S, f: S => Seq[S], finalS: S => Boolean): Option[S] = { val s = loop(State[S](Queue[S]().enqueue(init), init), update(f) _, (s: State[S]) => sqisEmpty || finalS(s.cur)) Some(s.cur) } def loop[A](a: A, f: A => A, cond: A => Boolean) : A = if (cond(a)) a else loop(f(a), f, cond)
Is there a better way for both solutions? Can cats / scalps be used to remove some patterns?
source share