Я думаю, что иногда бывает полезно немного обобщить при решении подобных проблем. Рассмотрим функцию ниже:
def pathsFrom[S, A](z: S)(f: S => Stream[(S, A)]): Stream[(S, List[A])] = {
def go(initial: Stream[(S, List[A], Set[S])]): Stream[(S, List[A])] =
initial match {
case (s, as, explored) #:: tail =>
val neighbors = f(s)
val newNeighbors = neighbors
.filter { case (s, _) => !explored.contains(s) }
.map { case (s, a) => (s, a :: as, explored + s) }
((s, as)) #:: go(tail #::: newNeighbors)
case _ => Stream.empty
}
go(Stream((z, Nil, Set(z))))
}
Это воплощение обобщенного алгоритма, который начинается с некоторого начального состояния S
и функции перехода f
, которая при заданном состоянии S
возвращает Stream[(S, A)]
всех состояний S
, непосредственно достижимых из этого состояния, вместе с связанные ходы A
. Затем он возвращает Stream[(S, List[A])]
всех путей из начального состояния и связанных с ним конечных состояний.
В вашем случае начальное состояние будет отправной точкой, и вы можете написать функцию перехода следующим образом:
def next(point: Point)(segments: List[Segment]): Stream[(Point, Segment)] =
segments.filter(_.from == point).map(segment => (segment.to, segment)).toStream
Затем вы можете просто отфильтровать состояния, заканчивающиеся в желаемой конечной точке:
pathsFrom(tl)(next(_)(segments))
.filter(_._1 == br)
.map(_._2.reverse)
.toList
.foreach(println)
Если предположить, что вы описали шесть точек и сегменты, идущие сверху вниз и слева направо между соседними точками, это вернет:
List(Segment(Point(tl,0,-10),Point(t,0,0)), Segment(Point(t,0,0),Point(tr,0,10)), Segment(Point(tr,0,10),Point(br,-10,10)))
List(Segment(Point(tl,0,-10),Point(t,0,0)), Segment(Point(t,0,0),Point(b,-10,0)), Segment(Point(b,-10,0),Point(br,-10,10)))
List(Segment(Point(tl,0,-10),Point(bl,-10,-10)), Segment(Point(bl,-10,-10),Point(b,-10,0)), Segment(Point(b,-10,0),Point(br,-10,10)))
Другими словами, чтобы перейти сверху вниз, вправо, мы можем перейти вправо / вправо / вниз, вправо / вниз / вправо или вниз / вправо / вправо.