Unique Paths II - DFS approach - swift

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.

Related

Swift BackTracking N-queen

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)
}
}
}
}

How to check if a number is a power of 2 in SWIFT

I find out a lot of example to solve it, but nothing in SWIFT. Please help
smthng like this
Input : n = 4
Output : Yes
2^2 = 4
Input : n = 7
Output : No
Input : n = 32
Output : Yes
2^5 = 32
I needed algorithm for checking if a number is a power of 2. like 4, 8, 16 , 32 , 64 .... is number power of two
Determining if an integer is a power of 2
from the Bit Twiddling Hacks
is almost verbatim translated to Swift:
func isPowerOfTwo(_ n: Int) -> Bool {
return (n > 0) && (n & (n - 1) == 0)
}
Example:
print(isPowerOfTwo(4)) // true
print(isPowerOfTwo(5)) // false
Or as a generic function, so that it can be used with all binary
integer types:
func isPowerOfTwo<T: BinaryInteger> (_ n: T) -> Bool {
return (n > 0) && (n & (n - 1) == 0)
}
Example:
print(isPowerOfTwo(Int16(4))) // true
print(isPowerOfTwo(UInt8(5))) // false
Or as a protocol extension:
extension BinaryInteger {
var isPowerOfTwo: Bool {
return (self > 0) && (self & (self - 1) == 0)
}
}
Example:
print(1048576.isPowerOfTwo) // true
print(Int(50).isPowerOfTwo) // false
Partial answer:
If it's a FixedWidthInteger and it's positive and its non zero bit count is 1, then it is a power of 2.
let x = 128
if x > 0 && x.nonzeroBitCount == 1
{
// power of 2
}
For a floating point number, I think you can just test the significand. If it is exactly 1, the number is a power of 2.
let x: Double = 4
if x > 0 && x.significand == 1
{
// Power of 2
}
I haven't checked that in a Playground yet, so it might be wrong.
let numberToBeChecked = 4
result = numberToBeChecked.squareRoot()
If result%1 == 0 {
print(“4 is a power of 2”) } else {
print(“4 is not a power of 2”)
}
//note: result%1== 0 checks if result is a whole number.
Hope this works.

DP Coin Change Algorithm - Retrieve coin combinations from table

To find how many ways we have of making change for the amount 4 given the coins [1,2,3], we can create a DP algorithm that produces the following table:
table[amount][coins.count]
0 1 2 3 4
-----------
(0) 1 | 1 1 1 1 1
(1) 2 | 1 1 2 2 3
(2) 3 | 1 1 2 3 4
The last position being our answer. The answer is 4 because we have the following combinations: [1,1,1,1],[2,1],[2,2],[3,1].
My question is, is it possible to retrieve these combinations from the table I just generated? How?
For completeness, here's my algorithm
func coinChange(coins: [Int], amount: Int) -> Int {
// int[amount+1][coins]
var table = Array<Array<Int>>(repeating: Array<Int>(repeating: 0, count: coins.count), count: amount + 1)
for i in 0..<coins.count {
table[0][i] = 1
}
for i in 1...amount {
for j in 0..<coins.count {
//solutions that include coins[j]
let x = i - coins[j] >= 0 ? table[i - coins[j]][j] : 0
//solutions that don't include coins[j]
let y = j >= 1 ? table[i][j-1] : 0
table[i][j] = x + y
}
}
return table[amount][coins.count - 1];
}
Thanks!
--
Solution
Here's an ugly function that retrieves the combinations, based on #Sayakiss 's explanation:
func getSolution(_ i: Int, _ j: Int) -> [[Int]] {
if j < 0 || i < 0 {
//not a solution
return []
}
if i == 0 && j == 0 {
//valid solution. return an empty array where the coins will be appended
return [[]]
}
return getSolution(i - coins[j], j).map{var a = $0; a.append(coins[j]);return a} + getSolution(i, j - 1)
}
getSolution(amount, coins.count-1)
Output:
[[1, 3], [2, 2], [1, 1, 2], [1, 1, 1, 1]]
Sure you can. We define a new function get_solution(i,j) which means all solution for your table[i][j].
You can think it returns an array of array, for example, the output of get_solution(4,3) is [[1,1,1,1],[2,1],[2,2],[3,1]]. Then:
Case 1. Any solution from get_solution(i - coins[j], j) plus coins[j] is a solution for table[i][j].
Case 2. Any solution from get_solution(i, j - 1) is a solution for table[i][j].
You can prove Case 1 + Case 2 is all possible solution for table[i][j](note you get table[i][j] by this way).
The only problem remains is to implement get_solution(i,j) and I think it's good for you to do it by yourself.
If you still got any question, please don't hesitate to leave a comment here.

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.

How to "link" two ranges together in swift

I have a function that produces a random number output (see below). I'd like for it to choose that output from either 0-50 or 150-400, but not in between. I couldn't find much about it on my own... so if any of you could post either resources or an answer that would be awesome! Thanks so much in advance!
The three question marks are where I assume some operator would go.
func random() -> UInt32 {
var range = UInt32(0)...UInt32(50) ??? UInt32(150)...UInt32(400)
return range.startIndex + arc4random_uniform(range.endIndex - range.startIndex + 1)
}
I tried using the + operator and the | operator, but no luck.
You cannot pass a union of ranges to arc4random_uniform().
What you can do is to create a random number in a single interval and then "adjust" all numbers which are not in the first range to the second range:
func random() -> UInt32 {
var x = arc4random_uniform(302) // 0 .. 301
if (x > 50) {
// map 51 .. 301 to 150 .. 400:
x += 99
}
return x
}
This can be generalized to multiple ranges (now updated for Swift 3):
func randomNumber(fromRanges ranges: Range<UInt32>...) -> UInt32 {
let totalLength = ranges.reduce(0) { $0 + ($1.upperBound - $1.lowerBound)}
var rnd = arc4random_uniform(totalLength)
for range in ranges {
if rnd < range.upperBound - range.lowerBound {
return rnd + range.lowerBound
}
rnd -= range.upperBound - range.lowerBound
}
fatalError("this should never be reached")
}
let x = randomNumber(fromRanges: 0 ..< 51, 150 ..< 401)
An alternative to ranges is to just use a while loop to make sure you get a value in the range you want.
func randomFunc() -> UInt32 {
var rand: UInt32 = 401
while rand < 0 || rand > 400 || (rand > 50 && rand < 150){
rand = arc4random_uniform(400)
}
return rand;
}