forked from wangzheng0822/algo
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request wangzheng0822#243 from email2liyang/master
scala backtracking and topology sort
- Loading branch information
Showing
10 changed files
with
637 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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+"==============") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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+"==============") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
100
scala/src/main/scala/ch43_topology_sort/GraphTopology.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} | ||
|
||
|
Oops, something went wrong.