looping through a 2D Array diagonally - swift

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

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

display the even numbers from 1 to 500 using a while loop and the break keyword in swift

My question is as on the title. I'm trying to print even numbers from 1 to 500 suing a while loop and break keyword. Below is my best possible answer I can think of, but this only print number 2. I've been spending hours but I wasn't able to solve it.
var number = 0
while true{
number += 2
print(number)
if number % 2 == 0 && number <= 500 {
break
}
}
You can use Stride
for evenNumber in stride(from: 0, through: 500, by: 2) {
print(evenNumber)
}
To specifically do this with while and break:
var i = 0
while true {
print(i)
i += 2
if i > 500 {
break
}
}
for i in 0...500 {
if i % 2 == 0 {
print(i)
}
}
Use below code
var numbers = 0...500
for number in numbers {
if number % 2 == 0 {
print(number)
}
}
I think it's easier to use build-in stride
let arr = Array(stride(from: 0, to: 502, by: 2))
print(arr)
//
For manually
var counter = 0
var arr = [Int]()
while counter <= 500 {
if counter % 2 == 0 {
print(counter)
arr.append(counter)
}
counter += 1
}
var number = 0
while true {
number += 2
print(number)
// ↓ Your code goes here ↓
if number > 499 {
break
}
}

Missing return in Swift

Here is my code.
import UIKit
var str = "Hello, playground"
//There are two sorted arrays nums1 and nums2 of size m and n respectively.
//Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
//Example 1:
//nums1 = [1, 3]
//nums2 = [2]
//
//The median is 2.0
//Example 2:
//nums1 = [1, 2]
//nums2 = [3, 4]
//
//The median is (2 + 3)/2 = 2.5
var num1 = [1,2,2,5]
var num2 = [2,3,9,9]
class Solution {
func findMedianSortedArrays(_ nums1: [Int], _ nums2: [Int]) -> Double {
var A = nums1
var B = nums2
var m = nums1.count
var n = nums2.count
var max_of_left : Int = 0
var min_of_right = 0
if n < m {
var temp : [Int]
var tempt : Int
temp = nums1
tempt = m
A = nums2
B = temp
m = n
n = tempt
}
if n == 0{
fatalError("Arrays must be fulfilled")
}
var imin = 0
var imax = m
let half_len = Int((m+n+1)/2)
while imin <= imax {
let i = Int((imin + imax) / 2)
let j = half_len - i
if i > 0 && A[i-1] > B[j]{
imax = i - 1
}
else if i < m && A[i] < B[j-1]{
imin = i + 1
}
else
{
if i == 0{
max_of_left = B[j-1]
}
else if j == 0{
max_of_left = A[i-1]
}
else
{
max_of_left = max(A[i-1], B[j-1])
}
if m+n % 2 == 1{
return Double(max_of_left)
}
if i==m{
min_of_right = B[j]
}
else if j == n{
min_of_right = A[i]
}
else{
min_of_right = min(A[i], B[j])
//editor indicates error here
}
return Double((Double(max_of_left+min_of_right) / 2.0))
}
}
}
}
var a = Solution()
print(a.findMedianSortedArrays(num1, num2))
error: day4_Median_of_Two_Sorted_Arrays.playground:86:13: error: missing return in a function expected to return 'Double'
Since I put my return out of if statement, I think it will be okay because it will stop while looping when it meets return.
But editor says it's not.
I want to know why. Please explain me why.
Every code path through your findMedianSortedArrays() must return a Double.
So you need a return of a Double placed outside of your while loop. Even if you had every code path within the while loop have a return double, if imin > imax you wouldn't even enter the while loop, and so would need a return of a double outside it.
I fixed it by putting another return out of while loop.
//: Playground - noun: a place where people can play
import UIKit
var str = "Hello, playground"
//There are two sorted arrays nums1 and nums2 of size m and n respectively.
//Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
//Example 1:
//nums1 = [1, 3]
//nums2 = [2]
//
//The median is 2.0
//Example 2:
//nums1 = [1, 2]
//nums2 = [3, 4]
//
//The median is (2 + 3)/2 = 2.5
var num1 = [1,2,2,5]
var num2 = [2,3,9,9]
class Solution {
func findMedianSortedArrays(_ nums1: [Int], _ nums2: [Int]) -> Double {
var A = nums1
var B = nums2
var m = nums1.count
var n = nums2.count
var max_of_left : Int = 0
var min_of_right = 0
if n < m {
var temp : [Int]
var tempt : Int
temp = nums1
tempt = m
A = nums2
B = temp
m = n
n = tempt
}
if n == 0{
fatalError("Arrays must be fulfilled")
}
var imin = 0
var imax = m
let half_len = Int((m+n+1)/2)
while imin <= imax {
let i = Int((imin + imax) / 2)
let j = half_len - i
if i > 0 && A[i-1] > B[j]{
imax = i - 1
}
else if i < m && A[i] < B[j-1]{
imin = i + 1
}
else
{
if i == 0{
max_of_left = B[j-1]
}
else if j == 0{
max_of_left = A[i-1]
}
else
{
max_of_left = max(A[i-1], B[j-1])
}
if m+n % 2 == 1{
return Double(max_of_left)
}
if i==m{
min_of_right = B[j]
}
else if j == n{
min_of_right = A[i]
}
else{
min_of_right = min(A[i], B[j])
}
return Double((Double(max_of_left+min_of_right) / 2.0))
}
}
return Double((Double(max_of_left+min_of_right) / 2.0))
}
}
var a = Solution()
print(a.findMedianSortedArrays(num1, num2))

Refactor for-loop statement to swift 3.0

I have following line in my code:
for (i = 0, j = count - 1; i < count; j = i++)
Can anyone help to remove the two compiler warnings, that i++ will be removed in Swift 3.0 and C-style for statement is depreciated?
You could use this:
var j = count-1
for i in 0..<count {
defer { j = i } // This will keep the cycle "logic" all together, similarly to "j = i++"
// Cycle body
}
EDIT
As #t0rst noted, be careful using defer, since it will be executed no matter how its enclosing scope is exited, so it isn't a 100% replacement.
So while the standard for ( forInit ; forTest ; forNext ) { … } will not execute forNext in case of a break statement inside the cycle, a return or an exception, the defer will.
Read here for more
Alternatively, lets go crazy to avoid having to declare j as external to the loop scope!
Snippet 1
let count = 10
for (i, j) in [count-1..<count, 0..<count-1].flatten().enumerate() {
print(i, j)
}
/* 0 9
1 0
2 1
3 2
4 3
5 4
6 5
7 6
8 7
9 8 */
Snippet 2
for (i, j) in (-1..<count-1).map({ $0 < 0 ? count-1 : $0 }).enumerate() {
print(i, j)
}
Trying to win the prize for the craziest solution in this thread
Snippet 1
extension Int {
func j(count:Int) -> Int {
return (self + count - 1) % count
}
}
for i in 0..<count {
print(i, i.j(count))
}
Snippet 2
let count = 10
let iList = 0..<count
let jList = iList.map { ($0 + count - 1) % count }
zip(iList, jList).forEach { (i, j) in
print(i, j)
}
You could use a helper function to abstract away the wrapping of j as:
func go(count: Int, block: (Int, Int) -> ()) {
if count < 1 { return }
block(0, count - 1)
for i in 1 ..< count {
block(i, i - 1)
}
}

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
*/