के साथ स्कैला में चौड़ाई पहली खोज को कैसे कार्यान्वित करें मैं सोच रहा हूं कि कार्यात्मक प्रोग्रामिंग का उपयोग करके स्केल में Breadth-first search को कैसे कार्यान्वित किया जाए।एफपी
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
}
हालांकि मैं केवल स्थानीय अस्थिरता (एक var
और एक परिवर्तनशील Queue
) का उपयोग करें, यह पूरी तरह कार्यात्मक नहीं है:
यहाँ मेरा पहला, अशुद्ध, कोड है।
मैं एक और संस्करण के साथ आते हैं:
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)
वहाँ दोनों के समाधान के लिए एक बेहतर तरीका है? क्या कुछ बॉयलरप्लेट को हटाने के लिए बिल्लियों/स्कालाज़ का उपयोग करना संभव है?
बस 'कतार' के बजाय एक (अपरिवर्तनीय) 'सूची' का उपयोग करें। और 'राज्य' से छुटकारा पाएं - वैसे भी 'cur' चीज़ हमेशा कतार का शीर्ष है - बस पेड़ से उतरने के दौरान काम की' सूची 'को पास करें। – Dima
कोई कतार के बजाय 'सूची' स्टैक नहीं है? –
ठीक है, इस बात पर निर्भर करता है कि आप किस डेटा को खींचते हैं। आप इसके बजाय एक अपरिवर्तनीय 'कतार' का उपयोग कर सकते हैं, जो थोड़ा अधिक कुशल है, लेकिन सूची-आधारित भी है। या पिछले तत्व को निरंतर समय तक पहुंच प्राप्त करने के लिए 'इंडेक्सेडस्क' जैसी कुछ। – Dima