检查坐标是否创建循环

时间:2016-11-21 13:23:56

标签: scala

我为数组ArrayBuffet((Int, Int))中的walker存储x / y坐标的元组。

代表(0,0)(2,1)之间旅程的步骤可以是((0,0), (0,1), (1,1), (2,1))((0,0), (1,1), (2,1))等。

麻烦的是,我需要一种方法来测试步行者是否在圈子里旅行。

E.g。考虑从(0,0)(0,1)的步行路线,其中步行者的路径为((0,0), (1,0), (1,-1), (0,0), (0,1))。步行者将走了一圈。

方法

def hasLoop(path: ArrayBuffer[(Int,Int)]): Boolean = {
    if (path.length < 3) return false
    else {
      for i <- 0 to path.length - 1 {
        val temp = path
        temp.remove(i)
        if (temp.contains(i)) return true
        }
      return false
    }
  }

如果步行者在一次旅行中多次访问坐标。但是,如果助行器从(0,0)移动到(0,1)或甚至到(0,2),但随后通过(0,1)返回相同的路径,则不应将其视为循环。

任何人都可以为我的isLoop方法提供解决方案吗?

2 个答案:

答案 0 :(得分:0)

如果我理解正确,您只是想确定一个集合是否具有2次或更多次的相同值。

@annotation.tailrec
def hasLoop(path: Seq[(Int, Int)]): Boolean =
  if (path.size < 2) false
  else if (path.tail.contains(path.head)) true
  else hasLoop(path.tail)

println(hasLoop(Array((0, 0), (0, 1))))
println(hasLoop(Array((0, 0), (1, 0), (1, -1), (0, 0), (0, 1))))

答案 1 :(得分:0)

不确定这是最优雅的解决方案,但我认为它能满足您的需求:

// some type aliases to make this more readable, can do without them too
type Vertex = (Int,Int)
type Edge = (Vertex, Vertex)

def hasLoop(path: Array[Vertex]): Boolean = {
  // create all edges - connections between one vertex and the next one in path
  val edges: Array[Edge] = path.zip(path.drop(1))

  // fold right searching for PREVIOUS edges for which SRC equals current edge's DESTINATION,
  // but DESTINATION does not equal current edge's SOURCE
  val foldResult: (Seq[Edge], Boolean) = edges.foldLeft((Seq[Edge](), false)) {
    case ((visited, found), e) => 
      (visited :+ e, found || visited.exists(oldE => oldE._1 == e._2 && oldE._2 != e._1) )
  }

  foldResult._2 // return the boolean result
}

println(hasLoop(Array((0,0), (1,0), (1,-1), (0,0), (0,1)))) // true
println(hasLoop(Array((0,0), (1,0), (1,-1), (0,0)))) // true
println(hasLoop(Array((0,0), (1,0), (1,-1), (1,0), (0,0)))) // false
println(hasLoop(Array((0,0), (1,0), (1,-1)))) // false