用于理解的排列

时间:2017-03-17 15:01:58

标签: scala functional-programming permutation scala-collections for-comprehension

所以我有一个问题,想知道如何使用Scala生成排列以进行理解。问题是我希望通过在棋盘上放置棋子来生成一系列独特的棋盘配置。所以我写的代码是:

case class Piece(x:Int,y:Int)

def positionNotOccupied(piece: Piece,board: Seq[Piece]): Boolean = {
  !board.map(piece => (piece.x,piece.y)).contains((piece.x,piece.y))
}

def placePiece(sizeX:Int, sizeY:Int, numPieces:Int): List[List[Piece]] = numPieces match {
  case 0 => List(Nil)
  case _ => for {
    pieces <- placePiece(sizeX,sizeY,numPieces - 1)
    x <- 1 to sizeX
    y <- 1 to sizeY
    piece =  Piece(x, y)
    if positionNotOccupied(piece,pieces)
  } yield piece :: pieces
}

我想假设所有部分都是相同的,所以我有效地寻找独特的配置。即,P1,P2 == P2,P1。但是,如果我为一块大小为2X1的板子调用它并且我想在其上放置两块,我得到以下输出:

placePiece(2,1,2)
List(List(Piece(2,1), Piece(1,1)), List(Piece(1,1), Piece(2,1)))

我得到两个配置,但它们确实是相同的。我当然可以随时做

placePiece(2,1,2).map(_.toSet).distinct
List(Set(Piece(2,1), Piece(1,1)))

解决了这个问题,但我真的只是在生成它们之后过滤它们并且正在进行额外的循环。有什么聪明的方法可以避免这种情况。任何建议都受到欢迎

1 个答案:

答案 0 :(得分:2)

诀窍是在电路板的位置上定义一个顺序,这样你就不会考虑组合(P1,P2),其中P1&gt; P2。函数def rank(x: Int, y: Int) = x * sizeY + y可以给出二维(sizeX x sizeY)集合的顺序。所以现在你可以计算位置之间的顺序,并按顺序生成板位置,即一旦你放置P1,只考虑进一步移动P2,其中P2> P1。