patternMinor
How idiomatic is this Scala 36 Cube Solver?
Viewed 0 times
thisidiomaticscalacubehowsolver
Problem
I've written a short program to find solutions to the 36 Cube puzzle.
I'm trying to break away from my normal Java / imperative style, and would like some feedback on how I'm doing.
Puzzle.scala
Board.scala
```
package cube36
case class Board(val placedPieces: IndexedSeq[IndexedSeq[Option[Piece]]] /rows of cols/ ) {
val row1Heights = ListInt
val row2Heights = ListInt
val row3Heights = ListInt
val row4Heights = ListInt
val row5Heights = ListInt
val row6Heights = ListInt
val contours = List[List[Int]](row1Height
I'm trying to break away from my normal Java / imperative style, and would like some feedback on how I'm doing.
Puzzle.scala
package cube36
/**
* An immutable class representing the state of a 36 Cube puzzle
*/
case class CubePuzzle(val board: Board, val availablePieces: List[Piece]) {
/**
* Add a piece to this puzzle, to create new instance of the puzzle
* @param rowNum row to add piece to
* @param colNum column to add piece to
* @param piece piece to add
* @param checkSuitable check if the position will accept this piece (default true if omitted)
* @return a new puzzle instance, with the specified piece added
*/
def addPiece(rowNum: Int, colNum: Int, piece: Piece, checkSuitable: Boolean = true): CubePuzzle = {
val newBoard = board.addPiece(rowNum, colNum, piece,checkSuitable)
CubePuzzle(newBoard, availablePieces.filterNot(_ == piece))
}
/**
* Find solutions to the puzzle which satisfy the rules
* @param solutionsSoFar
* @return a list of all valid solutions
*/
def solve(solutionsSoFar: List[Board]=List[Board]()): List[Board] = {
if (this.availablePieces.size == 0) this.board :: solutionsSoFar
else {
val nextPiece = availablePieces.head
val availableSpots = board.spaces.filter(space => board.suitable(space, nextPiece))
val sols = for (spot = 1,"Piece size out of range")
override def toString: String = colour.toString().head.toString + size.toString
}Board.scala
```
package cube36
case class Board(val placedPieces: IndexedSeq[IndexedSeq[Option[Piece]]] /rows of cols/ ) {
val row1Heights = ListInt
val row2Heights = ListInt
val row3Heights = ListInt
val row4Heights = ListInt
val row5Heights = ListInt
val row6Heights = ListInt
val contours = List[List[Int]](row1Height
Solution
Puzzle.scala
Case classes don't need "val" before field names.
More idiomatic is
Instead, how about
Also, I suspect the for loop in solve() can be rewritten so that you do not need to call flatten.
Board.scala
This seems backward, why not just return
case class CubePuzzle(val board: Board, val availablePieces: List[Piece])Case classes don't need "val" before field names.
def solve(solutionsSoFar: List[Board]=List[Board]()): List[Board] =More idiomatic is
Nil instead of List[Board](). Although sometimes I use List.empty[Board] in case I change the collection type (Nil is only available on List)if (this.availablePieces.size == 0) this.board :: solutionsSoFarInstead, how about
availablePieces match {
case Nil => board :: solutionsSoFar
case nextPiece :: tail => ...Also, I suspect the for loop in solve() can be rewritten so that you do not need to call flatten.
Board.scala
val unsuitable = ...This seems backward, why not just return
spaceEmpty && rightHeight && !colourAlreadyInCol && !colourAlreadyInRowCode Snippets
case class CubePuzzle(val board: Board, val availablePieces: List[Piece])def solve(solutionsSoFar: List[Board]=List[Board]()): List[Board] =if (this.availablePieces.size == 0) this.board :: solutionsSoFaravailablePieces match {
case Nil => board :: solutionsSoFar
case nextPiece :: tail => ...val unsuitable = ...Context
StackExchange Code Review Q#22865, answer score: 3
Revisions (0)
No revisions yet.