機能プログラミングを使用してScalaにBreadth-first searchを実装する方法を知りたいと思います。私は地元の可変性(var
と可変Queue
)を使用していますが、それは純粋に機能していないのですScalaで幅広いファーストサーチを実装する方法
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
}
:
は、ここで私の最初の、不純な、コードです。私は別のバージョンを考え出す
:
case class State[S](q: Queue[S], cur: S)
def update[S](f: S => Seq[S])(s: State[S]) : State[S] = {
val (i, q2) = s.q.dequeue
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]) => s.q.isEmpty || 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)
は、両方のソリューションのためのより良い方法はありますか? cat/scalazを使用して定型文を削除することはできますか?
'Queue'の代わりに(不変の)' List'を使うだけです。 'State'を取り除く - ' cur'は常に待ち行列の先頭です。ツリーの下降時に 'List'を渡してください。 – Dima
'List'はキューではなくスタックではありませんか? –
まあ、あなたはあなたがそれからデータを引っ張っていくところによって決まります。代わりに不変の 'Queue'を使うことができます。これはもう少し効率的ですが、リストベースでもあります。または、最後の要素に一定時間アクセスするために 'IndexedSeq'のようなものです。 – Dima