所以我有一个问题,想知道如何使用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)))
解决了这个问题,但我真的只是在生成它们之后过滤它们并且正在进行额外的循环。有什么聪明的方法可以避免这种情况。任何建议都受到欢迎
答案 0 :(得分:2)
诀窍是在电路板的位置上定义一个顺序,这样你就不会考虑组合(P1,P2),其中P1&gt; P2。函数def rank(x: Int, y: Int) = x * sizeY + y
可以给出二维(sizeX x sizeY)集合的顺序。所以现在你可以计算位置之间的顺序,并按顺序生成板位置,即一旦你放置P1,只考虑进一步移动P2,其中P2> P1。