Skip to content

Commit

Permalink
Merge pull request wangzheng0822#243 from email2liyang/master
Browse files Browse the repository at this point in the history
scala backtracking and topology sort
  • Loading branch information
wangzheng0822 authored Feb 1, 2019
2 parents d93f978 + f6f6d53 commit 5c03956
Show file tree
Hide file tree
Showing 10 changed files with 637 additions and 0 deletions.
25 changes: 25 additions & 0 deletions scala/src/main/scala/ch39_back_tracking/BagWeight.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ch39_back_tracking

class BagWeight(maxBagItemCount: Int, maxBagWeight: Int) {

def calculateMaxWeight(items: Array[Int]): Int = {
var maxWeight = 0

def _calcMaxWeight(itemIndex: Int, currentWeight: Int): Unit = {
if (currentWeight == maxBagWeight || itemIndex == items.length) {
if (currentWeight > maxWeight) {
maxWeight = currentWeight
}
} else {
//check next item
_calcMaxWeight(itemIndex + 1, currentWeight)
if (currentWeight + items(itemIndex) <= maxBagWeight) {
_calcMaxWeight(itemIndex + 1, currentWeight + items(itemIndex))
}
}
}

_calcMaxWeight(0, 0)
maxWeight
}
}
78 changes: 78 additions & 0 deletions scala/src/main/scala/ch39_back_tracking/EightQueens.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package ch39_back_tracking

import scala.util.control.Breaks._

class EightQueens {

//use array index to identify the row,the value of the row to identify the column
val result = new Array[Int](8)
var count = 0

def calc8Queues(row: Int): Unit = {
if (row == 8) {
//everything is done
print8Queens()
return
}

for (column <- Range(0, 8)) {
if (isOkOnColumn(row, column)) {
result(row) = column //place the column value into the array
calc8Queues(row + 1) //calculate next row
}
}

}

def isOkOnColumn(row: Int, column: Int): Boolean = {
var ok = true
var leftUp = column - 1
var rightUp = column + 1

breakable {
//will compare all the rows above current row
for (i <- row - 1 to 0 by -1) {
//check current column
if (result(i) == column) {
ok = false
break
}
//check left up
if (leftUp >= 0) {
if (result(i) == leftUp) {
ok = false
break
}
}
//check right up
if (rightUp < 8) {
if (result(i) == rightUp) {
ok = false
break
}
}
//move leftUp and rightUp
leftUp -= 1
rightUp += 1
}
}

ok
}

def print8Queens(): Unit = {
count +=1
for (row <- Range(0, 8)) {
for (column <- Range(0, 8)) {
if (result(row) == column) {
print("Q ")
} else {
print("* ")
}
}
//new line for next row
println("")
}
println(count+"==============")
}
}
77 changes: 77 additions & 0 deletions scala/src/main/scala/ch39_back_tracking/NQueens.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package ch39_back_tracking

import scala.util.control.Breaks.{break, breakable}

class NQueens(numberOfQueens:Int) {
//use array index to identify the row,the value of the row to identify the column
val result = new Array[Int](numberOfQueens)
var count = 0

def calcNQueues(row: Int): Unit = {
if (row == numberOfQueens) {
//everything is done
printNQueens()
return
}

for (column <- Range(0, numberOfQueens)) {
if (isOkOnColumn(row, column)) {
result(row) = column //place the column value into the array
calcNQueues(row + 1) //calculate next row
}
}

}

def isOkOnColumn(row: Int, column: Int): Boolean = {
var ok = true
var leftUp = column - 1
var rightUp = column + 1

breakable {
//will compare all the rows above current row
for (i <- row - 1 to 0 by -1) {
//check current column
if (result(i) == column) {
ok = false
break
}
//check left up
if (leftUp >= 0) {
if (result(i) == leftUp) {
ok = false
break
}
}
//check right up
if (rightUp < numberOfQueens) {
if (result(i) == rightUp) {
ok = false
break
}
}
//move leftUp and rightUp
leftUp -= 1
rightUp += 1
}
}

ok
}

def printNQueens(): Unit = {
count +=1
for (row <- Range(0, numberOfQueens)) {
for (column <- Range(0, numberOfQueens)) {
if (result(row) == column) {
print("Q ")
} else {
print("* ")
}
}
//new line for next row
println("")
}
println(count+"==============")
}
}
113 changes: 113 additions & 0 deletions scala/src/main/scala/ch39_back_tracking/Sudoku.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package ch39_back_tracking

import scala.util.control.Breaks._

class Sudoku {

def resolve(grid: Array[Array[Int]]): Unit = {
printGrid(grid)
println("")
if (resolve(grid, 0, 0)) {
printGrid(grid)
} else {
println("no result")
printGrid(grid)
}
}

private[this] def resolve(grid: Array[Array[Int]], row: Int, column: Int): Boolean = {
if (row == 8 && column == 9) {
//find the result
return true
}

if (column == 9) {
//move to next line
return resolve(grid, row + 1, 0)
}

if (grid(row)(column) != 0) {
//given number, resolve next one
return resolve(grid, row, column + 1)
}

//start the real resolve
for (num <- 1 to 9) {
if (isOk(grid, row, column, num)) {
grid(row)(column) = num
if (resolve(grid, row, column + 1)) {
return true
}
}
}

//do not find anything, reset given row and column
grid(row)(column) = 0
false
}

def isOk(grid: Array[Array[Int]], row: Int, column: Int, num: Int): Boolean = {
isRowOk(grid, row, num) && isColumnOk(grid, column, num) && isSmallBoxOk(grid, row, column, num)
}

def isRowOk(grid: Array[Array[Int]], row: Int, num: Int): Boolean = {
var isOk = true
breakable {
for (column <- Range(0, 9)) {
if (grid(row)(column) == num) {
isOk = false
break
}
}
}
isOk
}

def isColumnOk(grid: Array[Array[Int]], column: Int, num: Int): Boolean = {
var isOk = true
breakable {
for (row <- Range(0, 9)) {
if (grid(row)(column) == num) {
isOk = false
break
}
}
}
isOk
}

def isSmallBoxOk(grid: Array[Array[Int]], row: Int, column: Int, num: Int): Boolean = {
val rowOffSet = (row / 3) * 3
val columnOffSet = (column / 3) * 3
var isOk = true
breakable {
for (i <- Range(0, 3)) {
for (j <- Range(0, 3)) {
if (grid(i + rowOffSet)(j + columnOffSet) == num) {
isOk = false
break
}
}
}
}
isOk
}

def printGrid(grid: Array[Array[Int]]): Unit = {
for (i <- Range(0, 9)) {
if (i % 3 == 0) {
println("-------------------------")
}
for (j <- Range(0, 9)) {
if (j % 3 == 0) {
print("| ")
}
print(grid(i)(j) + " ")
}
println("| ")

}
println("-------------------------")
}

}
100 changes: 100 additions & 0 deletions scala/src/main/scala/ch43_topology_sort/GraphTopology.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package ch43_topology_sort

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

class GraphTopology(vertex: Int) {

//define the graph
val adjacency = new Array[mutable.MutableList[Int]](vertex)
for (i <- Range(0, vertex)) {
adjacency(i) = new mutable.MutableList[Int]()
}

def addEdge(startIndex: Int, targetIndex: Int) = {
adjacency(startIndex) += targetIndex
}

def topologySortByKahn(): Array[Int] = {
val seq = new mutable.ArrayBuffer[Int]()
//inDegrees contains all the inDegree for a given node
val inDegrees = new Array[Int](vertex)
for (i <- Range(0, vertex)) {
for (j <- adjacency(i).indices) {
val index = adjacency(i).get(j).get
inDegrees(index) += 1
}
}

val queue = new mutable.Queue[Int]()
for (i <- inDegrees.indices) {
if (inDegrees(i) == 0) {
// means there is no inDegree for this node,
// this could be the starting point of the dependency graph
queue += i
}
}

//start to navigating the graph from the starting point
while (queue.nonEmpty) {
val index = queue.dequeue()

//push to the result
seq += index

for (i <- adjacency(index).indices) {
val inDegreeIndex = adjacency(index).get(i).get
inDegrees(inDegreeIndex) -= 1

if (inDegrees(inDegreeIndex) == 0) {
queue += inDegreeIndex
}
}
}

seq.toArray
}

def topologySortByDFS(): Array[Int] = {
val inverseAdj = new Array[mutable.MutableList[Int]](vertex)
for (i <- Range(0, vertex)) {
inverseAdj(i) = new mutable.MutableList[Int]()
}

//build the inverse adj
for (i <- Range(0, vertex)) {
for (j <- adjacency(i).indices) {
val index = adjacency(i).get(j).get
inverseAdj(index) += i
}
}

val visited = new Array[Boolean](vertex)
val seq = new ArrayBuffer[Int]()
for (i <- Range(0, vertex)) {
if (!visited(i)) {
visited(i) = true
//call dfs
seq ++= dfs(i, inverseAdj, visited)
}
}

seq.toArray
}

def dfs(index: Int, inverseAdj: Array[mutable.MutableList[Int]], visited: Array[Boolean]): ArrayBuffer[Int] = {
val seq = new ArrayBuffer[Int]()

for (i <- inverseAdj(index).indices) {
val sourceIndex = inverseAdj(index).get(i).get
if (!visited(sourceIndex)) {
visited(sourceIndex) = true
seq ++= dfs(sourceIndex, inverseAdj, visited)
}
}
seq += index
seq
}
}


Loading

0 comments on commit 5c03956

Please sign in to comment.