Index out of range - error in function - arrays

I have a function with 2 parameters - arrays of Int called Numbers and Numbers1. I want to multiply each element in Numbers on index "i" with each element in Numbers2 on the same index. Then I want to get a total sum of the results from the multiplying. When I call the function, it displays error - Index out of range. Code bellow:
var sum = Int()
var Array = [Int]()
var totalsum = Int()
func prumerdanehopredmetu(Numbers:[Int], Numbers2:[Int]) -> Int {
for i in Numbers {
sum = Numbers[i] * Numbers2[i]
Array.insert(sum, at: 0)
}
totalsum = Array.reduce(0,+)
return totalsum
}
prumerdanehopredmetu(Numbers: [1,2,3], Numbers2: [1,2,3]) //error
update:
for i in Numbers.indices
This worked.

You're iterating the numbers ([1, 2, 3]), not their indices (0, 1, 2). Try this instead:
var sum = Int()
var sums = [Int]()
var totalsum = Int()
func prumerdanehopredmetu(_ numbers: [Int], _ numbers2: [Int]) -> Int {
for i in numbers.indices {
sum = numbers[i] * numbers[i]
sums.append(sum)
}
totalsum = Array.reduce(0,+)
return totalsum
}
prumerdanehopredmetu([1,2,3], [1,2,3])
There is a much easier/simpler way though. You can just use zip, and map
let products = zip([1, 2, 3], [1, 2, 3]).map(*) // results in [1, 4, 9]
let sumOfProducts = products.reduce(0, +) // 14

In your loop, "i" is equal to the values in "Numbers", not the indices of "Numbers". Here's an example of how such a "for" loop works in Swift:
let myArray = ["John", "Timothy", "James", "Tanmay"]
for i in myArray {
print(i) // "John", "Timothy" ...
}
Whereas, your code expects "i" to be 0, 1, 2 ...
In Swift, you can also have a for loop iterate through the indices and values of an array, by enumerating the array:
let myArray = ["John", "Timothy", "James", "Tanmay"]
for (index, value) in myArray.enumerated() {
print(index) // 0, 1 ...
print(value) // "John", "Timothy" ...
}
Of course, in Swift, you can also loop through just the indices, by finding the indices of the array:
let myArray = ["John", "Timothy", "James", "Tanmay"]
for i in myArray.indices {
print(i) // 0, 1 ...
}
So, in order for your code to work, you must loop through the indices of "Numbers", and not the values:
func prumerdanehopredmetu(Numbers:[Int], Numbers2:[Int]) -> Int {
for i in Numbers.indices {
sum = Numbers[i] * Numbers2[i]
Array.insert(sum, at: 0)
}
totalsum = Array.reduce(0,+)
return totalsum
}

func multiply(array1: [Int], array2: [Int]) -> Int {
if array1.count != array2.count {
//error handler
return 0
} else {
var i = 0
var sum = 0
while i < array1.count {
sum = sum + array1[i]*array2[i]
i = i + 1
}
return sum
}
}
you should consider your array have different number of values.

Related

How to split an Odd array

If I have an array [-23,0,43,7,5,2,4], how to do I split the array [odd][even].
I want 4 elements in the first array and 3 elements in the second array.
I tried to do something like this:
let leftArray = Array(mainArray[0..<mainArray.count/2])
let rightArray = Array(mainArray[mainArray.count/2..<mainArray.count])
I keep on getting [-23,0,43] and [7,5,2,4].
I'd create an extension implementing properties that yield the left and right halves of the array. In this implementation left includes the larger half of the array if the array has an odd number of elements.
extension Array {
var left: ArraySlice<Element> {
prefix(count / 2 + count % 2)
}
var right: ArraySlice<Element> {
suffix(count / 2)
}
}
And its usage would be:
let main = [-23, 0, 43, 7, 5, 2, 4]
let left = main.left
let right = main.right
The result of the above is an ArraySlice for efficiency, but if you want an Array you can just use map.
let main = [-23, 0, 43, 7, 5, 2, 4]
let left = main.left.map { $0 }
let right = main.right.map { $0 }
I think you want to split your array in the middle, and for odd counts, have the first part be the larger one. Use a function like this (intentionally spelled our very explicitly):
func splitArray(_ arr: [Int]) -> ([Int], [Int]) {
let count = arr.count
let half = count.isMultiple(of: 2) ? count / 2 : count / 2 + 1
let left = arr[0..<half]
let right = arr[half..<count]
return (Array(left), Array(right))
}
splitArray([-23,0,43,7,5,2,4]) // ([-23, 0, 43, 7], [5, 2, 4])
splitArray([-23,0,43,7,5,2,4,1]) // ([-23, 0, 43, 7], [5, 2, 4, 1])
This can be simplified and be made generic (i.e., work on all kinds of Collections) like so:
extension Collection {
func splitHalf() -> (SubSequence, SubSequence) {
let count = self.count
let left = self.prefix(count / 2 + count % 2)
let right = self.suffix(count / 2)
return (left, right)
}
}
[-23,0,43,7,5,2,4].splitHalf() // ([-23, 0, 43, 7], [5, 2, 4])
[-23,0,43,7,5,2,4,1].splitHalf() // ([-23, 0, 43, 7], [5, 2, 4, 1])
"12345".splitHalf() // (.0 "123", .1 "45")
"123456".splitHalf() // (.0 "123", .1 "456")
Function for split the array
func getSplitArr(arr:[Int])->Void{
let count = arr.count
let secArrCount = abs(count/2)
var firstArray = [Int]()
for i in 0..<secArrCount{
let value = arr[i]
firstArray.append(value)
}
var secondArray = [Int]()
for i in secArrCount..<count{
let value = arr[i]
secondArray.append(value)
}
print("\(firstArray)")
print("\(secondArray)")
}
Use of Functions
self.getSplitArr(arr: [-23,0,43,7,5,2,4])
Your first question wasn't clear. This should return two arrays one where the first array is even and the second is odd every time.
var array = [-23,0,43,7,5,2,4]
func splitArray(in array : [Int]) -> (firstArray :[Int], secondArray: [Int]) {
let firstArray = array.dropLast(array.count / 2).compactMap { item -> Int in
item
}
let secondArray = array.dropFirst((array.count / 2) + 1).compactMap { item -> Int in
item
}
return (firstArray,secondArray)
}
var newArray = splitArray(in: array)
print(newArray)

How to sort array of integer first by value and second by number of repetition using swift in time complexity < O(n^2) and space complexity O(n)

This is the solution I had tried but It was in the order of O(n^2) so didn't passed the test result
func sortArrayByValueAndByFrequency(nums : [Int]) {
var countDict = [Int : Int]()
var count = Int()
var values = Int()
var output = [Int]()
for index in 0 ..< nums.count {
for index2 in 0 ..< nums.count{
if nums[index2] == nums[index] {
values = nums[index2]
count += 1
}
}
countDict[values] = count
count = 0
}
let sortedByKey = countDict.sorted { ($0.key < $1.key)}
let sortedByValue = sortedByKey.sorted { ($0.value < $1.value)}
for (k,v) in sortedByValue {
for _ in 1 ... v {
output.append(k)
}
}
output.forEach { (orderedNumber) in
print(orderedNumber)
}
}
Example input/output:
Example array = [1,1,2,3,4,5,5,6,7,7,7,8,9,9,9,20,25,21,20]
Expected output = [2,3,4,6,8,21,25,1,1,5,5,20,20,7,7,7,9,9,9]
example 2 = [1,2,3,4,4,3,3]
output = [1,2,4,4,3,3,3]
This question was asked to me on HackerRank
First determine the number of occurrences of each value (O(n)),
then sort the values, with the number of occurrences as the
first sort criterion, and the value itself as the second
sort criterion (O(n log(n))). The sorting is conveniently done
with a tuple-comparison (compare Swift - Sort array of objects with multiple criteria):
let array = [1,1,2,3,4,5,5,6,7,7,7,8,9,9,9,20,25,21,20]
let countDict = array.reduce(into: [Int:Int]()) {
$0[$1, default: 0] += 1
}
let sorted = array.sorted(by: {
(countDict[$0]!, $0) < (countDict[$1]!, $1)
})
print(sorted)
// [2, 3, 4, 6, 8, 21, 25, 1, 1, 5, 5, 20, 20, 7, 7, 7, 9, 9, 9]

Custom operation to split sorted array into subarrays in Swift

I want to write a custom operation on a sorted Array (or Collection or Sequence, whatever) that does the following:
Starting from the beginning, it looks at each adjacent pair of elements. If the condition is met among the two, move on to the next pair, otherwise split it. So in the end, I would have an array of arrays, where the condition is satisfied among the elements within the same subarray, but not between different subarrays. Is the following correct and efficient?
extension Array {
public func splitSorted(by condition: (Element, Element)->(Bool)) -> [[Element]] {
var result = [[Element]]()
var start = 0
var end = 0
while end != self.count - 1 {
while end < self.count && condition(self[start], self[end]) {
end += 1
}
result.append(Array(self[start..<end]))
start = end
}
return result
}
}
Your code does not work correctly because:
You do not compare adjacent elements.
You start by comparing the first element with itself, this can lead
to an never-terminating loop.
An empty array is not handled correctly.
Here is a working variation of your approach:
extension Array {
public func splitSorted(by condition: (Element, Element)->(Bool)) -> [[Element]] {
var result = [[Element]]()
var start = startIndex
while start != endIndex {
var end = start
repeat {
end += 1
} while end != endIndex && condition(self[end - 1], self[end])
result.append(Array(self[start..<end]))
start = end
}
return result
}
}
Example:
let arr = [1, 2, 3, 2, 3, 4, 3, 4, 5]
let split = arr.splitSorted(by: <)
print(split) // [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
A generalization to Sequence would be:
extension Sequence {
public func splitSorted(by condition: (Element, Element)->(Bool)) -> [[Element]] {
var it = makeIterator()
guard var currentElem = it.next() else {
return [] // Input sequence is empty
}
var result = [[Element]]()
var currentSegment = [currentElem]
while let nextElem = it.next() {
if condition(currentElem, nextElem) {
// Append to current segment:
currentSegment.append(nextElem)
} else {
// Start new segment:
result.append(currentSegment)
currentSegment = [nextElem]
}
currentElem = nextElem
}
result.append(currentSegment)
return result
}
}
Example (group Fibonacci numbers by same parity):
// From https://stackoverflow.com/a/40203183/1187415
let fibs = sequence(state: (0, 1),
next: { (pair: inout (Int, Int)) -> Int? in
defer { pair = (pair.1, pair.0 + pair.1) }
return pair.1
})
print(fibs.prefix(12).splitSorted(by: { ($0 - $1) % 2 == 0 }))
// [[1, 1], [2], [3, 5], [8], [13, 21], [34], [55, 89], [144]]

Sum of digits of each elements inside an array of integers (Swift)

In swift 3, how to calculate each integers digits summation inside an array?
Example:
var nums = [111,222,333]
The output should be like this: [3,6,9]
which is the result of calculating: [1+1+1, 2+2+2, 3+3+3]
You could implement it as follows:
let nums = [111,222,333]
func transform(_ element: Int) -> Int {
var intsChars: [Int] = []
for char in "\(element)".characters {
intsChars.append(Int(String(char))!)
}
return intsChars.reduce(0, +)
}
let result = nums.map { transform($0) }
print(result) // [3, 6, 9]
UPDATE:
As mentioned in Martin R's answer:
func digitSum(_ n : Int) -> Int {
var n = n
var sum = 0
while n > 0 {
sum += n % 10 // Add least significant digit ...
n /= 10 // ... and remove it from the number.
}
return sum
}
you could also achieve the same output:
let result = nums.map { digitSum($0) } // [3, 6, 9]

Getting the most frequent value of an array

I have an Array of numbers and I want to know which number is most frequent in this array. The array sometimes has 5-6 integers, sometimes it has 10-12, sometimes even more - also the integers in the array can be different. So I need a function which can work with different lengths and values of an array.
One example:
myArray = [0, 0, 0, 1, 1]
Another example:
myArray = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2]
Now I am searching for a function which gives out 0 (in the first example) as Integer, as it is 3 times in this array and the other integer in the array (1) is only 2 times in the array. Or for the second example it would be 4.
It seems pretty simple, but I cannot find a solution for this. Found some examples in the web, where the solution is to work with dictionaries or where the solution is simple - but I cannot use it with Swift 3 it seems...
However, I did not find a solution which works for me. Someone has an idea how to get the most frequent integer in an array of integers?
You can also use the NSCountedSet, here's the code
let nums = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2]
let countedSet = NSCountedSet(array: nums)
let mostFrequent = countedSet.max { countedSet.count(for: $0) < countedSet.count(for: $1) }
Thanks to #Ben Morrow for the smart suggestions in the comments below.
let myArray = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2]
// Create dictionary to map value to count
var counts = [Int: Int]()
// Count the values with using forEach
myArray.forEach { counts[$0] = (counts[$0] ?? 0) + 1 }
// Find the most frequent value and its count with max(by:)
if let (value, count) = counts.max(by: {$0.1 < $1.1}) {
print("\(value) occurs \(count) times")
}
Output:
4 occurs 4 times
Here it is as a function:
func mostFrequent(array: [Int]) -> (value: Int, count: Int)? {
var counts = [Int: Int]()
array.forEach { counts[$0] = (counts[$0] ?? 0) + 1 }
if let (value, count) = counts.max(by: {$0.1 < $1.1}) {
return (value, count)
}
// array was empty
return nil
}
if let result = mostFrequent(array: [1, 3, 2, 1, 1, 4, 5]) {
print("\(result.value) occurs \(result.count) times")
}
1 occurs 3 times
Update for Swift 4:
Swift 4 introduces reduce(into:_:) and default values for array look ups which enable you to generate the frequencies in one efficient line. And we might as well make it generic and have it work for any type that is Hashable:
func mostFrequent<T: Hashable>(array: [T]) -> (value: T, count: Int)? {
let counts = array.reduce(into: [:]) { $0[$1, default: 0] += 1 }
if let (value, count) = counts.max(by: { $0.1 < $1.1 }) {
return (value, count)
}
// array was empty
return nil
}
if let result = mostFrequent(array: ["a", "b", "a", "c", "a", "b"]) {
print("\(result.value) occurs \(result.count) times")
}
a occurs 3 times
The most frequent value is called the "mode". Here's a concise version:
let mode = myArray.reduce([Int: Int]()) {
var counts = $0
counts[$1] = ($0[$1] ?? 0) + 1
return counts
}.max { $0.1 < $1.1 }?.0
Whether that's considered "unreadable" or "elegant" depends on your feelings towards higher order functions. Nonetheless, here it is as a generic method in an extension on Array (so it'll work with any Hashable element type):
extension Array where Element: Hashable {
var mode: Element? {
return self.reduce([Element: Int]()) {
var counts = $0
counts[$1] = ($0[$1] ?? 0) + 1
return counts
}.max { $0.1 < $1.1 }?.0
}
}
Simply remove the .0 if you'd rather have a tuple that includes the count of the mode.
My take on it with Swift 5:
extension Collection {
/**
Returns the most frequent element in the collection.
*/
func mostFrequent() -> Self.Element?
where Self.Element: Hashable {
let counts = self.reduce(into: [:]) {
return $0[$1, default: 0] += 1
}
return counts.max(by: { $0.1 < $1.1 })?.key
}
}
I have tried the following code. It helps especially when the max count is applicable for 2 or more values.
var dictionary = arr.reduce(into: [:]) { counts, number in counts[number, default: 0] += 1}
var max = dictionary.values.max()!
dictionary = dictionary.filter{$0.1 == max}
mode = dictionary.keys.min()!
func mostR(num : [Int]) -> (number : Int , totalRepeated : Int)
{
var numberTofind : Int = 0
var total : Int = 0
var dic : [Int : Int] = [:]
for index in num
{
if let count = dic[index]
{
dic[index] = count + 1
}
else
{
dic[index] = 1
}
}
var high = dic.values.max()
for (index , count) in dic
{
if dic[index] == high
{
numberTofind = index
top.append(count)
total = count
}
}
return (numberTofind , total)
}
var array = [1,22,33,55,4,3,2,0,0,0,0]
var result = mostR(num : [1,22,3,2,43,2,11,0,0,0])
print("the number is (result.number) and its repeated by :(result.totalRepeated)" )
Here is an encapsulated/reusable method.
extension Array where Element: Hashable {
/// The mode will be nil when the array is empty.
var mode: Element? {
var counts: [Element: Int] = [:]
forEach { counts[$0] = (counts[$0] ?? 0) + 1 }
if let (value, count) = counts.max(by: {$0.1 < $1.1}) {
print("\(value) occurs \(count) times")
return value
} else {
return nil
}
}
}
usage:
print([3, 4, 5, 6, 6].mode) // 6
Keep track of each occurrence, counting the value of each key in a dictionary. This case is exclusive for integers. Will update this method using generics.
func mostCommon(of arr: [Int]) -> Int {
var dict = [Int:Int]()
arr.forEach {
if let count = dict[$0] {
dict[$0] = count + 1
} else {
dict[$0] = 1
}
}
let max = dict.values.max()
for (_ , value) in dict {
if value == max {
return value
}
}
return -1
}

Resources