... красные циклы от руки к спасению.
Вот два разных цикла в тех же четырех вершинах , что показывает, что сортировка Недостаточно :
В эскизе предполагается, что все точки являются вершинами полностью связного графа (ребра опущены), и должно отображатьсячто циклы [0, 1, 2, 3, 0]
и [0, 2, 1, 3, 0]
не совпадают, несмотря на то, что при сортировке наборов вы получаете [0, 1, 2, 3]
в обоих случаях.
Вот что может работать вместо:
- Удалите все пути, которые проходят через одну и ту же вершину более одного раза, отфильтровав все пути, которые не состоят из четырех отдельных элементов.
- Поверните путьпредставление в канонической форме (например, начиная с вершины с минимальной позицией).
- Вычисляет набор канонических представлений, сохраняя только уникальные пути.
Вот как может выглядеть реализациякак:
def canonicalize(cycle: List[Int]) = {
val t = cycle.tail
val (b, a) = t.splitAt(t.zipWithIndex.minBy(_._1)._2)
val ab = (a ++ b)
ab :+ (ab.head)
}
val cycles = List(
List(4, 0, 1, 2, 4),
List(4, 0, 1, 3, 4),
List(4, 0, 2, 3, 4),
List(4, 3, 2, 3, 4),
List(4, 3, 4, 3, 4),
List(0, 1, 2, 4, 0),
List(0, 1, 3, 4, 0),
List(0, 2, 3, 4, 0),
List(1, 2, 4, 0, 1),
List(1, 3, 4, 0, 1),
List(3, 4, 0, 1, 3),
List(3, 4, 0, 2, 3),
List(3, 2, 3, 2, 3),
List(3, 4, 3, 2, 3),
List(3, 2, 3, 4, 3),
List(3, 4, 3, 4, 3),
List(2, 3, 4, 0, 2),
List(2, 4, 0, 1, 2),
List(2, 3, 2, 3, 2),
List(2, 3, 4, 3, 2)
)
val unique = cycles.filter(_.toSet.size == 4).map(canonicalize).toSet
unique foreach println
Вывод:
List(0, 1, 2, 4, 0)
List(0, 1, 3, 4, 0)
List(0, 2, 3, 4, 0)
Строчный пример того, что canonicalize
делает:
tail
удаляет дублирующую вершину: [2, 1, 0, 4, 2] -> [1, 0, 4, 2]
splitAt
находит минимальную вершину и сокращает список: [1, 0, 4, 2] -> ([1], [0, 4, 2])
a ++ b
перестраивает повернутый список: [0, 4, 2, 1]
:+
добавляет минимальную вершину к концу: [0, 4, 2, 1, 0]