Re-published article by Ratul Buragohain.
Original article can be found here : http://rbsomeg.blogspot.gr/2013/03/fun-with-scalas-for-comprehension.html
Interested to learn more about Scala or Akka? Then visit our Selected Books area
S = {2*x; x <- N; x <= 10}
Problem: Given a positive integer n, find all the pairs of integers (i,j) such that 1 <= j < i < n, and i+j is a prime number.
scala> def isPrime(n: Int) = (2 until n).forall(d => n % d != 0)
isPrime: (n: Int)Boolean
Neat, elegant and concise.
Let’s try one more problem before we delve into solving sudoku in less than 11 line!
Let’s try find the numbers x,y,z below n such that x^2 + y^2 == z^2. Let’s call the function rightAngledNumbers!
scala> def rightAngledNumbers(n: Int) =
| for {
| x <- 1 until n
| y <- x+1 until n
| z <- y+1 until n
| if(x*x + y*y == z*z)
| } yield (x,y,z)
rightAngledNumbers: (n: Int)IndexedSeq[(Int, Int, Int)]
val result = rightAngledNumbers(100)
result: = Vector((3,4,5), (5,12,13), (6,8,10), (7,24,25), (8,15,17), (9,12,15), (9,40,41), (10,24,26), (11,60,61), (12,16,20), (12,35,37), (13,84,85), (14,48,50), (15,20,25), (15,36,39), (16,30,34), (16,63,65), (18,24,30), (18,80,82), (20,21,29), (20,48,52), (21,28,35), (21,72,75), (24,32,40), (24,45,51), (24,70,74), (25,60,65), (27,36,45), (28,45,53), (30,40,50), (30,72,78), (32,60,68), (33,44,55), (33,56,65), (35,84,91), (36,48,60), (36,77,85), (39,52,65), (39,80,89), (40,42,58), (40,75,85), (42,56,70), (45,60,75), (48,55,73), (48,64,80), (51,68,85), (54,72,90), (57,76,95), (60,63,87), (65,72,97))
type Cell = (Int,Int,Int)
type Solutions = List[List[Cell]]
def fillCells(emptyCells: List[Cell]): Solutions = {
if(emptyCells == Nil) List(List())
else {
for {
filledCells <- fillCells(emptyCells.init)
cellValue <- 1 to 9
cell = (cellValue,emptyCells.last._2, emptyCells.last._3)
if(isOk(cell, filledCells ::: nonEmpties))
} yield cell :: filledCells
}}
https://github.com/ratulb/sudoku/
Problem 1:
1 9 0 2 0 0 8 0 0
4 0 7 0 9 0 0 0 0
0 3 0 0 0 1 4 0 0
0 0 3 0 0 0 0 0 2
9 8 0 0 0 0 0 7 3
2 0 0 0 0 0 6 0 0
0 0 5 3 0 0 0 1 0
0 0 0 0 4 0 9 0 6
0 0 9 0 0 6 0 5 4
scala> val sol1: Sudoku.Solution = List(List((3,8,6), (8,8,4), (1,8,3), (2,8,1), (7,8,0), (2,7,7), (7,7,5), (5,7,3), (8,7,2), (1,7,1), (3,7,0), (8,6,8), (7,6,6), (9,6,5), (2,6,4), (4,6,1), (6,6,0), (9,5,8), (8,5,7), (5,5,5), (3,5,4), (4,5,3), (1,5,2), (7,5,1), (5,4,6), (2,4,5), (1,4,4), (6,4,3), (4,4,2), (4,3,7), (1,3,6), (8,3,5), (7,3,4), (9,3,3), (6,3,1), (5,3,0), (5,2,8), (9,2,7), (6,2,4), (7,2,3), (2,2,2), (8,2,0), (1,1,8), (6,1,7), (2,1,6), (3,1,5), (8,1,3), (5,1,1), (7,0,8), (3,0,7), (4,0,5), (5,0,4), (6,0,2)))
Problem 2:
0 0 6 9 0 0 3 0 1
0 0 4 0 3 1 0 0 7
2 0 0 0 0 0 0 6 0
1 0 0 0 0 0 0 0 0
0 2 0 7 0 3 0 8 0
0 0 0 0 0 0 0 0 3
0 4 0 0 0 0 0 0 2
3 0 0 1 7 0 9 0 0
8 0 9 0 0 2 1 0 0
scala> val sol2 = Sudoku.solution
sol2: Sudoku.Solution = List(List((6,8,8), (3,8,7), (4,8,4), (5,8,3), (7,8,1), (8,7,8), (4,7,7), (6,7,5), (2,7,2), (5,7,1), (7,6,7), (5,6,6), (9,6,5), (8,6,4), (3,6,3), (1,6,2), (6,6,0), (1,5,7), (7,5,6), (5,5,5), (9,5,4), (2,5,3), (8,5,2), (6,5,1), (4,5,0), (4,4,8), (6,4,6), (1,4,4), (5,4,2), (9,4,0), (5,3,8), (9,3,7), (2,3,6), (8,3,5), (6,3,4), (4,3,3), (7,3,2), (3,3,1), (9,2,8), (4,2,6), (7,2,5), (5,2,4), (8,2,3), (3,2,2), (1,2,1), (2,1,7), (8,1,6), (6,1,3), (9,1,1), (5,1,0), (5,0,7), (4,0,5), (2,0,4), (8,0,1), (7,0,0)))
Following listing shows the complete sudoku code.
import io.Source
object Sudoku {
type Input = List[List[Int]]
type Cell = (Int,Int,Int)
type Solutions = List[List[Cell]]
def readFile = {
val lines = io.Source.fromFile("sudoku1.txt").getLines.toList
lines.map { line => line.split(" ").toList.map(e => e.toInt)
}
}
def solution = {
val in = readFile
val cells = index(in)
val empties = emptyCells(cells)
val nonEmpties = nonEmptyCells(cells)
solve(empties,nonEmpties)
}
def solve(empties: List[Cell], nonEmpties: List[Cell]): Solutions = {
//Actual logic
def fillCells(emptyCells: List[Cell]): Solutions = {
if(emptyCells == Nil) List(List())
else {
for {
filledCells <- fillCells(emptyCells.init)
cellValue <- 1 to 9
cell = (cellValue,emptyCells.last._2, emptyCells.last._3)
if(isOk(cell, filledCells ::: nonEmpties))
} yield cell :: filledCells
}
}
fillCells(empties)
}
def isOk(c:Cell, cells: List[Cell]) = {
(colCells(c,cells) ::: rowCells(c,cells) ::: boxCells(c,cells)).forall(e => e._1 != c._1)
}
def colCells(c: Cell, cells: List[Cell]) = cells.filter(e => e._3 == c._3)
def rowCells(c: Cell, cells: List[Cell]) = cells.filter(e => e._2 == c._2)
def emptyCells(cells: List[Cell]) = cells.filter(e => e._1 == 0)
def nonEmptyCells(cells: List[Cell]) = cells.filterNot(e => e._1 == 0)
def boxCells(c: Cell, cells: List[Cell]) = {
val inBox = cellAt(c)
val filtered = inBox match {
case 1 => cells.filter{e =>(e._2 < 3 && e._3 < 3)}
case 2 => cells.filter{e =>(e._2 < 3 && (e._3 > 2 && e._3 < 6))}
case 3 => cells.filter{e => (e._2 < 3 && e._3 > 5)}
case 4 => cells.filter{e => ((e._2 > 2 && e._2 < 6) && e._3 < 3)}
case 5 => cells.filter{e => ((e._2 > 2 && e._2 < 6) && (e._3 > 2 && e._3 < 6))}
case 6 => cells.filter{e => ((e._2 > 2 && e._2 < 6) && (e._3 > 5))}
case 7 => cells.filter{e => (e._2 > 5 && e._3 < 3)}
case 8 => cells.filter{e => (e._2 > 5 && (e._3 > 2 && e._3 < 6))}
case 9 => cells.filter{e => (e._2 > 5 && e._3 > 5)}
}
filtered
}
def index(in: Input) = in.zipWithIndex.map{r => r._1.zipWithIndex.map { c => (c._1, r._2, c._2) }}.flatMap(l => l)
def cellAt(c: Cell) = c match {
case (_,x,y) if(x < 3 && y < 3) => 1
case (_,x,y) if (x < 3 && ( y > 2 && y < 6)) => 2
case (_,x,y) if (x < 3 && (y > 5 && y < 9)) => 3
case (_,x,y) if ((x > 2 && x < 6) && y < 3) => 4
case (_,x,y) if ((x > 2 && x < 6) && (y > 2 && y < 6)) => 5
case (_,x,y) if ((x > 2 && x < 6) && (y > 5 && y < 9)) => 6
case (_,x,y) if (x > 5 && y < 3) => 7
case (_,x,y) if (x > 5 && (y > 2 && y < 6)) => 8
case _ => 9
}
}
Re-published article by Ratul Buragohain.
Original article can be found here : http://rbsomeg.blogspot.gr/2013/03/fun-with-scalas-for-comprehension.html
Interested to learn more about Scala or Akka? Then visit our Selected Books area

