Swift BackTracking N-queen - swift

I am trying to solve the N-queen problem.
You can find the problem in https://leetcode.com/problems/n-queens/.
For Backtracking, I have learned that we can solve the problem with three keys:
Make Choices
Constraints
Goal
So I came up with this solution:
func solveNQueens(_ n: Int) -> [[String]] {
typealias ChessBoard = [[Int]]
var result = Set<ChessBoard>()
func getIndexsOfDiagonal(row:Int,column:Int) -> [(row:Int,col:Int)] {
var indexs = [(Int,Int)]()
var rowIndex = row
var colIndex = column
while rowIndex < n && colIndex < n {
indexs.append((rowIndex,colIndex))
rowIndex += 1
colIndex += 1
}
rowIndex = row
colIndex = column
while rowIndex >= 0 && colIndex >= 0 {
indexs.append((rowIndex,colIndex))
rowIndex -= 1
colIndex -= 1
}
rowIndex = row
colIndex = column
while rowIndex >= 0 && colIndex < n {
indexs.append((rowIndex,colIndex))
rowIndex -= 1
colIndex += 1
}
rowIndex = row
colIndex = column
while rowIndex < n && colIndex >= 0 {
indexs.append((rowIndex,colIndex))
rowIndex += 1
colIndex -= 1
}
return indexs
}
func placeQuees(chessboard:ChessBoard,row:Int,column:Int) ->ChessBoard {
var newChessBorad = chessboard
//set row
for index in 0..<n {
newChessBorad[row][index] = -1
}
//set column
for index in 0..<n {
newChessBorad[index][column] = -1
}
//set diagonal
for index in getIndexsOfDiagonal(row:row,column:column) {
newChessBorad[index.row][index.col] = -1
}
newChessBorad[row][column] = 1
return newChessBorad
}
func solve(chessboard:ChessBoard, queens: Int) {
if queens == 0 {
//Goal
result.insert(chessboard)
}
for row in 0..<n {
for col in 0..<n {
//Choices
if chessboard[row][col] == 0 {
//Constraints
let new = placeQuees(chessboard: chessboard, row: row, column: col)
solve(chessboard: new, queens: queens - 1)
}
}
}
}
solve(chessboard: Array(repeating: Array(repeating: 0, count: n), count: n), queens: n)
return result.map {
//chessboard
$0.map {
//row to string
$0.reduce("") { string,value in
if value == 1 {
return string + "Q"
} else {
return string + "."
}
}
}
}
}
But it hits time limited. So I am wondering whether my solution is using Backtracking? What goes wrong, How can I improve the solution, How can we Solve the Backtracking problem? What defines Backtracking?
Thanks a lot.

Your solution is backtracking. It backtracks when it can no longer find an available space (chessboard[row][col] == 0) to place a queen. Since it is finding all possible solutions, it also backtracks after it finds a solution and inserts it into the result.
Your solution is merely trying too many trial positions in each call to solve. Note that there can only ever be one queen on any given row. Because of this, solve can work more efficiently by only trying to place queens on a single row in each call to solve. In the first call to solve, try placing the queen on row 0. Then, you'll only be considering n possible placements instead of n * n. On the second call to solve, try placing the queen on row 1. The current row can be computed as n minus the number of queens remaining or n - queens.
With this slight modification, your code runs much faster and successfully passes when submitted to LeetCode:
func solve(chessboard:ChessBoard, queens: Int) {
if queens == 0 {
//Goal
result.insert(chessboard)
}
else {
let row = n - queens
for col in 0..<n {
//Choices
if chessboard[row][col] == 0 {
//Constraints
let new = placeQuees(chessboard: chessboard, row: row, column: col)
solve(chessboard: new, queens: queens - 1)
}
}
}
}

Related

Unique Paths II - DFS approach

I am trying to solve the following question
https://leetcode.com/problems/unique-paths-ii/
Question is as follows:
An obstacle and space is marked as 1 and 0 respectively in the grid.
Input: obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
Output: 2
Explanation:
There is one obstacle in the middle of the 3x3 grid above. There are
two ways to reach the bottom-right corner:
Right -> Right -> Down -> Down
Down -> Down -> Right -> Right
My DFS Solution is as follows, but it returns 1 instead of 2. I am wondering what I am missing in the following approach?
class Solution {
func uniquePathsWithObstacles(_ obstacleGrid: [[Int]]) -> Int {
var column = obstacleGrid[0].count
var row = obstacleGrid.count
var visited = Array(repeating: Array(repeating: false, count:column), count: row)
return dfs(obstacleGrid, 0, 0, &visited)
}
func dfs(_ obstacleGrid: [[Int]], _ i: Int, _ j: Int, _ visited: inout [[Bool]]) -> Int {
if i < 0 || i >= obstacleGrid.count || j < 0 || j >= obstacleGrid[0].count || obstacleGrid[i][j] == 1 || visited[i][j] == true {
return 0
}
visited[i][j] = true
if i == obstacleGrid.count - 1 && j == obstacleGrid[0].count - 1 {
return 1
}
return dfs(obstacleGrid, i+1, 0, &visited) +
dfs(obstacleGrid, i-1, 0, &visited) +
dfs(obstacleGrid, i, j+1, &visited) +
dfs(obstacleGrid, i, j-1, &visited)
}
}
Returning 0 if visited[i][j] doesn't look correct. You should memorize the return value for visited cells, and return it again for the later calls on that cell. The reason is that you can reach that cell following different paths, and each of those should contribute to the result.
The fact that your code returns 1 makes sense, because the second time you reach the bottom-right cell, you will return 0 since that cell was 'visited' during the discovery of previous path.

looping through a 2D Array diagonally

I'm writing a function thats supposed to loop though a 2D array diagonally(top left to bottom right). However, the code does not add to the outer while loop(i), it keeps it at 0. arr is 9X9
var i = 0
var j = 0
while(i < arr.count-1){
while (j < arr.count-1) {
print("i = \(i) --- j = \(j)")
if(i == j){
sumDiagonalLeft += arr[j][i]
print(sumDiagonalLeft)
if(arr[j][i] == 1){
informationUsed += 1
arr[i][j] = 2
}
}
j += 1
}
i += 1
}
Thank you for your time :)
try this,
var array:[[Int]] = []
array.append([1,2,3,4,5,6,7,8,9])
....
array.append([1,2,3,4,5,6,7,8,9])
for (index, element) in array.enumerated(){
for (innerIndex,innerElement) in element.enumerated(){
print(innerElement) // you can do your logics here
}
}

How can I write the code of Bessel function with 10 term in swift?

I hope you guys can check. when I use 5 as x it should be showing me -0.17749282815107623 but it returns -0.2792375. I couldn't where I have been doing the mistake.
var evenNumbers = [Int]()
for i in 2...10 {
if i % 2 == 0 {
evenNumbers.append(i)
}
}
func power(val: Float, power: Int)->Float{
var c:Float = 1
for i in 1...power {
c *= val
}
return c
}
func bessel(x: Float)->Float{
var j0:Float = 0
var counter = 1
var lastDetermVal:Float = 1
for eNumber in evenNumbers {
print(lastDetermVal)
if counter == 1 {
lastDetermVal *= power(val: Float(eNumber), power: 2)
j0 += (power(val: x, power: eNumber))/lastDetermVal
counter = -1
}else if counter == -1{
lastDetermVal *= power(val: Float(eNumber), power: 2)
j0 -= (power(val: x, power: eNumber))/lastDetermVal
counter = 1
}
}
return 1-j0
}
bessel(x: 5)
Function 1:
Your mistake seems to be that you didn't have enough even numbers.
var evenNumbers = [Int]()
for i in 2...10 {
if i % 2 == 0 {
evenNumbers.append(i)
}
}
After the above is run, evenNumbers will be populated with [2,4,6,8,10]. But to evaluate 10 terms, you need even numbers up to 18 or 20, depending on whether you count 1 as a "term". Therefore, you should loop up to 18 or 20:
var evenNumbers = [Int]()
for i in 2...18 { // I think the 1 at the beginning should count as a "term"
if i % 2 == 0 {
evenNumbers.append(i)
}
}
Alternatively, you can create this array like this:
let evenNumbers = (1..<10).map { $0 * 2 }
This means "for each number between 1 (inclusive) and 10 (exclusive), multiply each by 2".
Now your solution will give you an answer of -0.1776034.
Here's my (rather slow) solution:
func productOfFirstNEvenNumbers(_ n: Int) -> Float {
if n == 0 {
return 1
}
let firstNEvenNumbers = (1...n).map { Float($0) * 2.0 }
// ".reduce(1.0, *)" means "multiply everything"
return firstNEvenNumbers.reduce(1.0, *)
}
func nthTerm(_ n: Int, x: Float) -> Float {
let numerator = pow(x, Float(n) * 2)
// yes, this does recalculate the product of even numbers every time...
let product = productOfFirstNEvenNumbers(n)
let denominator = product * product
return numerator / (denominator) * pow(-1, Float(n))
}
func bessel10Terms(x: Float) -> Float {
// for each number n in the range 0..<10, get the nth term, add them together
(0..<10).map { nthTerm($0, x: x) }.reduce(0, +)
}
print(bessel10Terms(x: 5))
You code is a bit unreadable, however, I have written a simple solution so try to compare your intermediate results:
var terms: [Float] = []
let x: Float = 5
for index in 0 ..< 10 {
guard index > 0 else {
terms.append(1)
continue
}
// calculate only the multiplier for the previous term
// - (minus) to change the sign
// x * x to multiply nominator
// (Float(index * 2) * Float(index * 2) to multiply denominator
let termFactor = -(x * x) / (Float(index * 2) * Float(index * 2))
terms.append(terms[index - 1] * termFactor)
}
print(terms)
// sum the terms
let result = terms.reduce(0, +)
print(result)
One of the errors I see is the fact that you are actually calculating only 5 terms, not 10 (you iterate 1 to 10, but only even numbers).

How to write a non-C-like for-loop in Swift 2.2+?

I have updated Xcode (7.3) and there are a lot of changes; C-like for expressions will be deprecated. For a simple example,
for var i = 0; i <= array.count - 1; i++
{
//something with array[i]
}
How do I write this clear and simple C-like for-loop to be compliant with the new changes?
for var i = 0, j = 1; i <= array.count - 2 && j <= array.count - 1; i++, j++
{
//something with array[i] and array[j]
}
Update.
One more variant
for var i = 0; i <= <array.count - 1; i++
{
for var j = i + 1; j <= array.count - 1; j++
{
//something with array[i] and array[j]
}
}
And more ...
for var i = 0, j = 1, g = 2; i <= array.count - 3 && j <= array.count - 2 && g <= array.count - 1; i++, j++, g++
{
//something with array[i] and array[j] and array[g]
}
Update2 After several suggestions for me while loop is preferable universal substitution for all cases more complicated than the simple example of C-like for-loop (suitable for for in expression). No need every time to search for new approach.
For instance: Instead of
for var i = 0; i <= <array.count - 1; i++
{
for var j = i + 1; j <= array.count - 1; j++
{
//something with array[i] and array[j]
}
}
I can use
var i = 0
while i < array.count
{
var j = i + 1
while j < array.count
{
//something with array[i] and array[j]
j += 1
}
i += 1
}
charl's (old) answer will crash. You want 0..<array.count:
for index in 0..<array.count {
// ...
}
If you want something like your i/j loop you can use stride and get i's successor:
for i in 0.stride(through: array.count, by: 1) {
let j = i.successor()
// ...
}
Just make sure to check i.successor() in case you go out of bounds.
for var i = 0; i <= array.count - 1; i++ {
//something with array[i]
}
Here you don't need the element index at all, so you can simply
enumerate the array elements:
for elem in array {
// Do something with elem ...
}
for var i = 0, j = 1; i <= array.count - 2 && j <= array.count - 1; i++, j++ {
//something with array[i] and array[j]
}
To iterate over pairs of adjacent elements, use zip()
and dropFirst():
for (x, y) in zip(array, array.dropFirst()) {
// Do something with x and y ...
print(x, y)
}
Output:
1 2
2 3
3 4
4 5
For other distances, use dropFirst(n):
for (x, y) in zip(array, array.dropFirst(3)) {
// Do something with x and y ...
print(x, y)
}
Output:
1 4
2 5
There are probably many solutions to do
for var i = 0; i <= <array.count - 1; i++ {
for var j = i + 1; j <= array.count - 1; j++ {
//something with array[i] and array[j]
}
}
without a C-style for-loop, here is one:
for (index, x) in array.enumerate() {
for y in array.dropFirst(index + 1) {
print(x, y)
}
}
If you want to do something with subsequent pairs there are many other ways to do it.
Something like this would work...
var previousItem = array.first
for index in 1..<array.count {
let currentItem = array[index]
// do something with current and previous items
previousItem = currentItem
}
for (i, j) in zip(array.dropLast(), array.dropFirst())
{
// something
}
What you're really doing here is enumerating two parallel sequences. So, create those sequences and use zip to turn them into a single sequence.
Do enumeration
let suits = ["♠︎", "♥︎", "♣︎", "♦︎"]
for (i, suite) in suits.enumerate() {
// ...
}
or to compare neighbors
import Foundation
let suits = ["♠︎", "♥︎", "♣︎", "♦︎"]
for (i, suite1) in suits.enumerate() {
let j = i.successor()
if j < suits.count {
let suite2 = suits[j]
// ...
}
}
or zipping and enumerating
let suits = ["♠︎", "♥︎", "♣︎", "♦︎"]
let combination = zip(suits, suits.dropFirst())
for (i, (s1,s2)) in combination.enumerate() {
print("\(i): \(s1) \(s2)")
}
result
0: ♠︎ ♥︎
1: ♥︎ ♣︎
2: ♣︎ ♦︎
Worst case, you can convert it to a while loop.
var i = 0
var j = 1
while i <= array.count -2 && j <= array.count - 1 {
// something
i += 1
j += 1
}
-- EDIT --
Because you said, "while loop is preferable universal substitution for all cases more complicated than the simple example of C-like for-loop"... I feel the need to expand on my answer. I don't want to be responsible for a bunch of bad code...
In most cases, there is a simple for-in loop that can handle the situation:
for item in array {
// do something with item
}
for (item1, item2) in zip(array, array[1 ..< array.count]) {
// do something with item1 and item2
}
for (index, item1) in array.enumerate() {
for item2 in array[index + 1 ..< array.count] {
// do soemthing with item1 and item2
}
}
For your last case, you might be justified using a for look, but that is an extremely rare edge case.
Don't litter your code with for loops.
to compare neighbouring elements from the same array you can use
let arr = [1,2,2,5,2,2,3,3]
arr.reduce(nil) { (i, j)->Int? in
if let i = i {
print(i,"==",j,"is",i == j)
}
return j
}
it prints
1 == 2 is false
2 == 2 is true
2 == 5 is false
5 == 2 is false
2 == 2 is true
2 == 3 is false
3 == 3 is true
more 'generic' approach without using subscript but separate generators
let arr1 = [1,2,3,4,5,6,7,8,9,0]
var g1 = arr1.generate()
var g2 = (arr1.dropFirst(5) as AnySequence).generate()
var g3 = (arr1.dropFirst(6) as AnySequence).generate()
while true {
if let a1 = g1.next(),
let a2 = g2.next(),
let a3 = g3.next() {
print(a1,a2,a3)
} else {
break
}
}
/* prints
1 6 7
2 7 8
3 8 9
4 9 0
*/

for in loop with where clause in Swift

I have tried to update a little function to Swift 2.1. The original working code was:
import func Darwin.sqrt
func sqrt(x:Int) -> Int { return Int(sqrt(Double(x))) }
func sigma(n: Int) -> Int {
// adding up proper divisors from 1 to sqrt(n) by trial divison
if n == 1 { return 0 } // definition of aliquot sum
var result = 1
let root = sqrt(n)
for var div = 2; div <= root; ++div {
if n % div == 0 {
result += div + n/div
}
}
if root*root == n { result -= root }
return (result)
}
print(sigma(10))
print(sigma(3))
After updating the for loop I get a runtime error for the last line. Any idea why that happens?
import func Darwin.sqrt
func sqrt(x:Int) -> Int { return Int(sqrt(Double(x))) }
func sigma(n: Int) -> Int {
// adding up proper divisors from 1 to sqrt(n) by trial divison
if n == 1 { return 0 } // definition of aliquot sum
var result = 1
let root = sqrt(n)
for div in 2...root where n % div == 0 {
result += div + n/div
}
if root*root == n { result -= root }
return (result)
}
print(sigma(10))
print(sigma(3)) //<- run time error with for in loop
When you pass 3 to sigma, your range 2...root becomes invalid, because the left side, the root, is less than the right side, 2.
The closed range operator (a...b) defines a range that runs from a to b, and includes the values a and b. The value of a must not be greater than b.
root is assigned sqrt(n), which means that in order for the 2...root range to remain valid, n must be above 22.
You can fix by supplying a lower limit for the right side, i.e.
for div in 2...max(root,2) where n % div == 0 {
...
}
However, at this point your solution with the regular for loop is more readable.