for in loop with where clause in Swift - 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.

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

Swift - Find number that is a multiple of all numbers 1...20

I am working on Euler problem 5 which is:
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
I am having trouble with my nested loops. I have a for loop within in a while loop. My logic is I
check a number (currentNumber) against 1-20 (i), if currentNumber is not a multiple of i (checked using modular arithmatic)
then it breaks out of that loop and trys the next largest number.
My issue is I cannot figure out how to jump out of only my inner loop and not my outer loop. Here is my code:
class Five {
init() {
var currentNumber = 1
while true {
for i in 1...20 {
if currentNumber % i != 0 {
currentNumber += 1
continue
}
}
break
}
print("the smallest positive number that is evenly divisible " +
"by all of the numbers from 1 to 20 is \(currentNumber)")
}
}
You already got a good and correct answer. Just as an add-on, for the
sake of completeness:
An alternative to labeled continue statements is to move the inner loop into a separate function from which you can “early return”:
func isDivisibleBy1To20(_ number: Int) -> Bool {
for j in 2...20 {
if number % j != 0 {
return false
}
}
return true
}
var currentNumber = 1
while !isDivisibleBy1To20(currentNumber) {
currentNumber += 1
}
print("solution:", currentNumber)
Using functional methods this can be simplified to
func isDivisibleBy1To20(_ number: Int) -> Bool {
return !(2...20).contains(where: { number % $0 != 0 })
}
let solution = (1...).first(where: isDivisibleBy1To20)!
print("solution:", solution)
(Remark: There are other, much faster methods to solve this problem.)

What's wrong with this solution for neighbor cell counting of a matrix? (Swift)

I was given this problem to solve inside a Swift playground. I was told my answer is correct but not good enough (that's right, pretty vague).
/*
Write a Swift playground that takes an n x n grid of integers. Each integer can be either 1 or 0.
The playground then outputs an n x n grid where each block indicates the number of 1's around that block, (excluding the block itself) . For Block 0 on row 0, surrounding blocks are (0,1) (1,0) and (1,1). Similary for block (1,1) all the blocks around it are to be counted as surrounding blocks.
Requirements:
Make sure your solution works for any size grid.
Spend an hour and a half coding the logic and another hour cleaning your code (adding comments, cleaning variable and function names).
Optimize your functions to be O(n^2).
Your output lines should not have any trailing or leading whitespaces.
Please use hard coded example input constants below.
Examples:
Input Grid:
let sampleGrid = [[0,1,0], [0,0,0], [1,0,0]]
Console Output:
1 0 1
2 2 1
0 1 0
/////////////////
Input Grid:
let sampleGrid = [[0,1,0,0], [0,0,0,1], [1,0,0,1],[0,1,0,1]]
Console Output:
1 0 2 1
2 2 3 1
1 2 4 2
2 1 3 1
*/
/// An *Error* type
struct ComputationError : Error {
/// The message of the error
let message : String
}
/// This function computes a matrix result from the input *matrix*
/// where an integer value represents the number of adjacent cells
/// in the input *matrix* having a 1.
///
/// The algorithm is O(n^2), if n is the side length of the matrix:
///
/// for each row in rows of matrix
/// for each column in columns of matrix
/// for each matrix[row][column] cell if equal to 1
/// add a 1 to adjacent (valid) cell in result matrix
///
/// - Parameter matrix: input square matrix with values of 0 or 1 only
/// - Returns: a matrix of equal size to input matrix with computed adjacency values
/// - Throws: throws a ComputationError is the matrix is of invalid size or has invalid values (something other than 1 or 0)
func compute(matrix:[[Int]]) throws -> [[Int]] {
// The number of rows in matrix, which should equal the number of columns, ie side length, or n
let side = matrix.count
// The resulting matrix to return
var result:[[Int]] = []
// Initialize the result matrix
for _ in 0..<side {
result.append(Array<Int>(repeating: 0, count: side))
}
// A convenience constant to refer to the last element in a row or column
let last = side-1
// Iterate over rows in matrix
for row in 0..<side {
if matrix[row].count < side {
throw ComputationError(message:"Invalid number of columns (\(matrix[row].count)), should match number of rows (\(side))")
}
// Iterate over columns in matrix
for column in 0..<side {
// Consider this cell if it is 1, otherwise skip
// If it is 1, then add a 1 to all valid adjacent cells
// in result matrix.
if matrix[row][column] == 1 {
if 0 < row {
if 0 < column {
result[row-1][column-1] += 1
}
result[row-1][column] += 1
if column < last {
result[row-1][column+1] += 1
}
}
if 0 < column {
result[row][column-1] += 1
}
if column < last {
result[row][column+1] += 1
}
if row < last {
if 0 < column {
result[row+1][column-1] += 1
}
result[row+1][column] += 1
if column < last {
result[row+1][column+1] += 1
}
}
}
else if matrix[row][column] == 0 {
// ok
}
// If value is neither 0 or 1 throw an error
else {
throw ComputationError(message:"Invalid value (\(matrix[row][column])) encountered at row \(row) and column \(column)")
}
}
}
return result
}
/// Print *matrix* to console by iterating over each row in the
/// matrix and each column in the row, regardless of the count
/// of columns in the row. The output is row-wise and a single
/// space delimits columns, with no leading or trailing whitespace.
///
/// - Parameter matrix: an array of array of Int
func print(matrix:[[Int]]) {
let rows = matrix.count
for row in 0..<rows {
let columns = matrix[row].count
var line = ""
for column in 0..<columns {
if 0 < column {
line += " "
}
line += "\(matrix[row][column])"
}
print(line)
}
}
do {
print(matrix:try compute(matrix: [[0,1,0], [0,0,0], [1,0,0]]))
}
catch let error {
print(error)
}
do {
print()
print(matrix:try compute(matrix: [[0,1,0,0], [0,0,0,1], [1,0,0,1],[0,1,0,1]]))
}
catch let error {
print(error)
}
// test for exception
do {
print()
print(matrix:try compute(matrix: [[0,1], [0,0,0], [1,0,0]]))
}
catch let error {
print(error)
}
// test for exception
do {
print()
print(matrix:try compute(matrix: [[0,1,0], [3,0,0], [1,0,0]]))
}
catch let error {
print(error)
}
They were likely looking for something in a functional programming style and you probably needed to demonstrate that your solution is O(n^2).
for example:
// let sampleGrid = [[0,1,0], [0,0,0], [1,0,0]]
let sampleGrid = [[0,1,0,0], [0,0,0,1], [1,0,0,1],[0,1,0,1]]
func printMatrix(_ m:[[Any]])
{
print( m.map{ $0.map{"\($0)"}.joined(separator:" ")}.joined(separator:"\n") )
}
let emptyLine = [Array(repeating:0, count:sampleGrid.first!.count)]
let left = sampleGrid.map{ [0] + $0.dropLast() } // O(n)
let right = sampleGrid.map{ $0.dropFirst() + [0] } // O(n)
let up = emptyLine + sampleGrid.dropLast() // O(n)
let down = sampleGrid.dropFirst() + emptyLine // O(n)
let leftRight = zip(left,right).map{zip($0,$1).map{$0+$1}} // O(n^2)
let upDown = zip(up,down).map{zip($0,$1).map{$0+$1}} // O(n^2)
let cornersUp = emptyLine + leftRight.dropLast() // O(n)
let cornersDown = leftRight.dropFirst() + emptyLine // O(n)
let sides = zip(leftRight,upDown).map{zip($0,$1).map{$0+$1}} // O(n^2)
let corners = zip(cornersUp,cornersDown).map{zip($0,$1).map{$0+$1}} // O(n^2)
// 6 x O(n) + 5 x O(n^2) ==> O(n^2)
let neighbourCounts = zip(sides,corners).map{zip($0,$1).map{$0+$1}} // O(n^2)
print("SampleGrid:")
printMatrix(sampleGrid)
print("\nNeighbour counts:")
printMatrix(neighbourCounts)
...
SampleGrid:
0 1 0 0
0 0 0 1
1 0 0 1
0 1 0 1
Neighbour counts:
1 0 2 1
2 2 3 1
1 2 4 2
2 1 3 1

for loop over odd numbers in swift

I am trying to solve the task
Using a standard for-in loop add all odd numbers less than or equal to 100 to the oddNumbers array
I tried the following:
var oddNumbers = [Int]()
var numbt = 0
for newNumt in 0..<100 {
var newNumt = numbt + 1; numbt += 2; oddNumbers.append(newNumt)
}
print(oddNumbers)
This results in:
1,3,5,7,9,...199
My question is: Why does it print numbers above 100 although I specify the range between 0 and <100?
You're doing a mistake:
for newNumt in 0..<100 {
var newNumt = numbt + 1; numbt += 2; oddNumbers.append(newNumt)
}
The variable newNumt defined inside the loop does not affect the variable newNumt declared in the for statement. So the for loop prints out the first 100 odd numbers, not the odd numbers between 0 and 100.
If you need to use a for loop:
var odds = [Int]()
for number in 0...100 where number % 2 == 1 {
odds.append(number)
}
Alternatively:
let odds = (0...100).filter { $0 % 2 == 1 }
will filter the odd numbers from an array with items from 0 to 100. For an even better implementation use the stride operator:
let odds = Array(stride(from: 1, to: 100, by: 2))
If you want all the odd numbers between 0 and 100 you can write
let oddNums = (0...100).filter { $0 % 2 == 1 }
or
let oddNums = Array(stride(from: 1, to: 100, by: 2))
Why does it print numbers above 100 although I specify the range between 0 and <100?
Look again at your code:
for newNumt in 0..<100 {
var newNumt = numbt + 1; numbt += 2; oddNumbers.append(newNumt)
}
The newNumt used inside the loop is different from the loop variable; the var newNumt declares a new variable whose scope is the body of the loop, so it gets created and destroyed each time through the loop. Meanwhile, numbt is declared outside the loop, so it keeps being incremented by 2 each time through the loop.
I see that this is an old question, but none of the answers specifically address looping over odd numbers, so I'll add another. The stride() function that Luca Angeletti pointed to is the right way to go, but you can use it directly in a for loop like this:
for oddNumber in stride(from:1, to:100, by:2) {
// your code here
}
stride(from:,to:,by:) creates a list of any strideable type up to but not including the from: parameter, in increments of the by: parameter, so in this case oddNumber starts at 1 and includes 3, 5, 7, 9...99. If you want to include the upper limit, there's a stride(from:,through:,by:) form where the through: parameter is included.
If you want all the odd numbers between 0 and 100 you can write
for i in 1...100 {
if i % 2 == 1 {
continue
}
print(i - 1)
}
For Swift 4.2
extension Collection {
func everyOther(_ body: (Element) -> Void) {
let start = self.startIndex
let end = self.endIndex
var iter = start
while iter != end {
body(self[iter])
let next = index(after: iter)
if next == end { break }
iter = index(after: next)
}
}
}
And then you can use it like this:
class OddsEvent: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
(1...900000).everyOther{ print($0) } //Even
(0...100000).everyOther{ print($0) } //Odds
}
}
This is more efficient than:
let oddNums = (0...100).filter { $0 % 2 == 1 } or
let oddNums = Array(stride(from: 1, to: 100, by: 2))
because supports larger Collections
Source: https://developer.apple.com/videos/play/wwdc2018/229/

How to calculate the 21! (21 factorial) in swift?

I am making fuction that calculate factorial in swift. like this
func factorial(factorialNumber: UInt64) -> UInt64 {
if factorialNumber == 0 {
return 1
} else {
return factorialNumber * factorial(factorialNumber - 1)
}
}
let x = factorial(20)
this fuction can calculate untill 20.
I think factorial(21) value bigger than UINT64_MAX.
then How to calculate the 21! (21 factorial) in swift?
func factorial(_ n: Int) -> Double {
return (1...n).map(Double.init).reduce(1.0, *)
}
(1...n): We create an array of all the numbers that are involved in the operation (i.e: [1, 2, 3, ...]).
map(Double.init): We change from Int to Double because we can represent bigger numbers with Doubles than with Ints (https://en.wikipedia.org/wiki/Double-precision_floating-point_format). So, we now have the array of all the numbers that are involved in the operation as Doubles (i.e: [1.0, 2.0, 3.0, ...]).
reduce(1.0, *): We start multiplying 1.0 with the first element in the array (1.0*1.0 = 1.0), then the result of that with the next one (1.0*2.0 = 2.0), then the result of that with the next one (2.0*3.0 = 6.0), and so on.
Step 2 is to avoid the overflow issue.
Step 3 is to save us from explicitly defining a variable for keeping track of the partial results.
Unsigned 64 bit integer has a maximum value of 18,446,744,073,709,551,615. While 21! = 51,090,942,171,709,440,000. For this kind of case, you need a Big Integer type. I found a question about Big Integer in Swift. There's a library for Big Integer in that link.
BigInteger equivalent in Swift?
Did you think about using a double perhaps? Or NSDecimalNumber?
Also calling the same function recursively is really bad performance wise.
How about using a loop:
let value = number.intValue - 1
var product = NSDecimalNumber(value: number.intValue)
for i in (1...value).reversed() {
product = product.multiplying(by: NSDecimalNumber(value: i))
}
Here's a function that accepts any type that conforms to the Numeric protocol, which are all builtin number types.
func factorial<N: Numeric>(_ x: N) -> N {
x == 0 ? 1 : x * factorial(x - 1)
}
First we need to declare temp variable of type double so it can hold size of number.
Then we create a function that takes a parameter of type double.
Then we check, if the number equal 0 we can return or do nothing. We have an if condition so we can break the recursion of the function. Finally we return temp, which holds the factorial of given number.
var temp:Double = 1.0
func factorial(x:Double) -> Double{
if(x==0){
//do nothing
}else{
factorial(x: x-1)
temp *= x
}
return temp
}
factorial(x: 21.0)
I make function calculate factorial like this:
func factorialNumber( namber : Int ) -> Int {
var x = 1
for i in 1...namber {
x *= i
}
return x
}
print ( factorialNumber (namber : 5 ))
If you are willing to give up precision you can use a Double to roughly calculate factorials up to 170:
func factorial(_ n: Int) -> Double {
if n == 0 {
return 1
}
var a: Double = 1
for i in 1...n {
a *= Double(i)
}
return a
}
If not, use a big integer library.
func factoruial(_ num:Int) -> Int{
if num == 0 || num == 1{
return 1
}else{
return(num*factoruial(num - 1))
}
}
Using recursion to solve this problem:
func factorial(_ n: UInt) -> UInt {
return n < 2 ? 1 : n*factorial(n - 1)
}
func factorial(a: Int) -> Int {
return a == 1 ? a : a * factorial(a: a - 1)
}
print(factorial(a : 5))
print(factorial(a: 9))