This question already has an answer here:
Swift - fatal error: Array index out of range
(1 answer)
Closed 3 years ago.
Below is the small code snippet written in swift,gives below error, although looking at code nothing seems wrong.
Fatal error: Index out of range
Illegal instruction: 4
Not clear to me what is the exact cause of problem ? Would be really helpful if someone can share insights on it.
func getBinary(ValueInDecimal:Int) -> [Int]
{
var valueToPlayWith = ValueInDecimal
var aryBinary = [Int]()
var i:Int = 0
while valueToPlayWith != 0 {
aryBinary[i] = valueToPlayWith % 2
valueToPlayWith = valueToPlayWith / 2
i = i + 1
}
return aryBinary
}
// calling of function
let aryBin = getBinary(ValueInDecimal:10)
print(aryBin)
Expected answer is binary value of passed decimal number in array of 0s and 1s.
So I think if I will use it like this then syntax array[i] = value will work.
func getBinary(ValueInDecimal:Int) -> [Int:Int]
{
var valueToPlayWith = ValueInDecimal
var aryBinary = [Int:Int]()
var i:Int = 0
while valueToPlayWith != 0 {
aryBinary[i] = valueToPlayWith % 2
valueToPlayWith = valueToPlayWith / 2
i = i + 1
}
return aryBinary
}
let aryBin = getBinary(ValueInDecimal:10)
print(aryBin)
This is an empty array
var aryBinary = [Int]()
so this will crash as index 0 doesn't exist
aryBinary[i] = valueToPlayWith % 2
Fatal error: Index out of range
You may need
func getBinary(_ valueInDecimal:Int) -> [Int] {
var valueToPlayWith = valueInDecimal
var aryBinary = [Int]()
while valueToPlayWith != 0 {
aryBinary.append(valueToPlayWith % 2)
valueToPlayWith = valueToPlayWith / 2
}
return aryBinary
}
let aryBin = getBinary(10)
print(aryBin) /// [0, 1, 0, 1]
Related
I want to add the numbers together and print every 4 elements, however i cannot wrap my head around using the stride function, if i am using the wrong approach please explain a better method
var numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13]
func addNumbersByStride(){
var output = Stride...
//first output = 1+2+3+4 = 10
//second output = 5+6+7+8 = 26 and so on
print(output)
}
It seems you would like to use stride ...
let arr = [1,2,3,4,5,6,7,8,9,10,11,12,13]
let by = 4
let i = stride(from: arr.startIndex, to: arr.endIndex, by: by)
var j = i.makeIterator()
while let n = j.next() {
let e = min(n.advanced(by: by), arr.endIndex)
let sum = arr[n..<e].reduce(0, +)
print("summ of arr[\(n)..<\(e)]", sum)
}
prints
summ of arr[0..<4] 10
summ of arr[4..<8] 26
summ of arr[8..<12] 42
summ of arr[12..<13] 13
You can first split the array into chunks, and then add the chunks up:
extension Array {
// split array into chunks of n
func chunked(into size: Int) -> [[Element]] {
return stride(from: 0, to: count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, count)])
}
}
}
// add each chunk up:
let results = numbers.chunked(into: 4).map { $0.reduce(0, +) }
If you would like to discard the last sum if the length of the original array is not divisible by 4, you can add an if statement like this:
let results: [Int]
if numbers.count % 4 != 0 {
results = Array(numbers.chunked(into: 4).map { $0.reduce(0, +) }.dropLast())
} else {
results = numbers.chunked(into: 4).map { $0.reduce(0, +) }
}
This is quite a basic solution and maybe not so elegant. First calculate and print sum of every group of 4 elements
var sum = 0
var count = 0
for n in stride(from: 4, to: numbers.count, by: 4) {
sum = 0
for i in n-4..<n {
sum += numbers[i]
}
count = n
print(sum)
}
Then calculate the sum of the remaining elements
sum = 0
for n in count..<numbers.count {
sum += numbers[n]
}
print(sum)
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))
I'm new at programming and started with Swift. The first issue I came along with is the following:
I have 4 variables
var a = "345"
var b = "30.6"
var c = "74hf2"
var d = "5"
I need to count the sum of Integers (if not integer, it will turn to nil)
if Int(a) != nil {
var aNum = Int(ar)!
}
if Int (b) != nil {
var bNum = Int (b)!
}
and so on..
As far as I understand, the Int() should convert each element into an Optional Integer.
Then I should use forced unwrapping by convertin the Int? to Int and only then I can use it for my purposes. But instead, when I count the sum of my variables, the compiler sums them as Strings.
var sum = aNum + bNum + cNum + dNum
Output:
34530.674hf25
Why my variables, which are declared as strings and then converted into optional integers with Int(), didn't work?
Your code has typos that make it hard to tell what you are actually trying to do:
Assuming your 2nd variable should be b, as below:
var a = "345"
var b = "30.6"
var c = "74hf2"
var d = "5"
///Then you can use code like this:
var sum = 0
if let aVal = Int(a) { sum += aVal }
if let bVal = Int(b) { sum += bVal }
if let cVal = Int(c) { sum += cVal }
if let dVal = Int(d) { sum += dVal }
print(sum)
That prints 350 since only 345 and 5 are valid Int values.
Hello I'm trying to do pagination for array of contacts, some how i the code crashed on paged 2
here is my code :
// Initialize
let limit : Int = 10
var page : Int = self.defaults.integer(forKey: "ConPage") == 0 ? 1 : self.defaults.integer(forKey: "ConPage")
var start : Int = page == 0 || page == 1 ? 0 : limit * ( page-1)
var increment : Int = 1
var data = (contacts)?[start...limit]
print("[CONTACTS SYNC][LoadUpContacts] Success \(success) , Data : \(data?.count) , start : \(start) , Limit : \(limit) , Page : \(page), Total : \(contacts?.count) ")
for contact in data!
{
print("\(increment) : \(contact.name) ")
increment = increment + 1
}
//go Next
self.defaults.set(page+1, forKey: "ConPage")
self.LoadUpContacts()
and here is the crash log :
fatal error: Can't form Range with upperBound < lowerBound
2017-07-10 11:32:01.758790+0300 muzeit[6085:2216770] fatal error: Can't form Range with upperBound < lowerBound
What is the best way to paginate an array in swift 3 ?
the problem was in array range , so i fixed it and i hope it solve someone else issue , below is the correct code for array pagination in Swift 3
let total : Int = (contacts?.count)!
let limit : Int = 20
let page : Int = self.defaults.integer(forKey: "ConPage") == 0 ? 1 : self.defaults.integer(forKey: "ConPage")
let start : Int = page == 0 || page == 1 ? 0 : (limit * page) - limit
var end : Int = start + limit
end = end >= total ? total : end
end = end - 1
let data = start >= total ? [] : (contacts)?[start...(end)]
To respond to your question in the comment. In fact, the subArrayWithRange is only available in Objective-c. So you can create a subarray from an index, with length by:
let arr = [1, 3, 4, 5, 10, 2, 100, 40, 1244, 23]
let startIndex = 3
let length = 4
let arr2 = arr[startIndex..<(startIndex + length)] //print [5, 10, 2, 100]
And to get the contents of a page from your items, you have to calculate the right startIndex and the endIndex of your subarray. Be attention that, the subcript returns a ArraySlice, not Array. You may to cast it to Array.
//page start from 0
func getPageItems(page: UInt, allItems: [Int], maxItemsPerPage: UInt) -> [Int] {
let startIndex = Int(page * maxItemsPerPage)
var length = max(0, allItems.count - startIndex)
length = min(Int(maxItemsPerPage), length)
guard length > 0 else { return [] }
return Array(allItems[startIndex..<(startIndex + length)])
}
the call:
let arr3 = getPageItems(page: 3, allItems: arr, maxItemsPerPage: 4)
will return [1244, 23]
Looking at the error it seems like there is an issue with the array range.
If you look at the line:
var data = (contacts)?[start...limit]
of your code, you can see that the limit is always equal to 10. And the range upper...lower represents the start and the end of the range. So you should properly calculate the lower bound also in the way you calculate the upper bound.
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/