Scala algorithm: Check Sudoku board
Published
Algorithm goal
The game of Sudoku is composed of a 9x9 grid that is valid when each of the rows, columns, and every of the 9 3-by-3 squares contains only a unique combination of numbers 1 to 9 (or no number). The game is complete when all the squares are filled. In this challenge, create a function to check whether a given board is valid, as it is easy for the players to miss something.
Test cases in Scala
assert(SudokuBoard.blank.isValid)
assert(SudokuBoard.fromStrings("1").isValid)
assert(SudokuBoard.fromStrings("12").isValid)
assert(SudokuBoard.fromStrings("1", "2").isValid)
assert(SudokuBoard.fromStrings("1", " 2").isValid)
assert(!SudokuBoard.fromStrings("1", "1").isValid)
assert(!SudokuBoard.fromStrings("11").isValid)
assert(!SudokuBoard.fromStrings("1", " 1").isValid)
assert(!SudokuBoard.fromStrings("1 1").isValid)
assert(
!SudokuBoard.fromStrings("1", " ", " ", " ", " ", " ", " ", " ", "1").isValid
)
assert(
SudokuBoard.fromStrings("1", " ", " ", " ", " ", " ", " ", " ", "9").isValid
)
Algorithm in Scala
45 lines of Scala (compatible versions 2.13 & 3.0).
Explanation
The trickiest part of this challenge is actually the representation of the grid. While it may be tempting to go for an Array/Vector-based solution, such a board is actually far simpler to represent as a Map, and its 'PositionGroup's as Sets of positions sa well.
Initially, we generate SudokuBoard.Groups by: (this is © from www.scala-algorithms.com)
- Taking a row, then shifting it down by 1 8 times
- Taking a row, turning it into a column, then shifting it right by 1 for 8 times
- Taking a 3x3 box, then doing a combination of shifting it by 1 and 2 times in both x and y directions.
This then gives us a set of Groups that we can validate the SudokuBoard with.
Scala concepts & Hints
For-comprehension
The for-comprehension is highly important syntatic enhancement in functional programming languages.
Option Type
The 'Option' type is used to describe a computation that either has a result or does not. In Scala, you can 'chain' Option processing, combine with lists and other data structures. For example, you can also turn a pattern-match into a function that return an Option, and vice-versa!
Pattern Matching
Pattern matching in Scala lets you quickly identify what you are looking for in a data, and also extract it.
Range
The
(1 to n)
syntax produces a "Range" which is a representation of a sequence of numbers.