Unexpected behavior with simple Swift code - arrays

I'm trying to get a var to get an array's value mirroring its position. Then divide it by another var's value getting it from another array mirroring its position. Then assign the result value to a third var.
Now, in a function I increment the 1st var by 1 and then append the resulting value to a third array.
Or so I thought.
It adds a value that is the simple division of the first two vars without incrementing the first var.
But in the console the result of the 3rd var (holding the division's result), it shows the increment.
It's only in the append part of the function that it doesn't take it into account.
I'm sure it's a syntax problem but I'd be really thankful if anyone could look at my code.
import UIKit
var positionA = 3
var positionB = 1
var arrayA = [0, 1, 2, 3, 4, 5, 6]
var arrayB = [0, 1, 2, 3, 4, 5, 6]
var arrayPosition = arrayA[positionA] / arrayB[positionB]
var arrayOfValues = [ 0 ,1 , 2, 3, 4]
print(arrayOfValues[1])
print(arrayOfValues[arrayPosition])
func increment() {
positionA = positionA + 1
arrayOfValues.append(positionA)
}
increment()
print(positionA)
print(arrayOfValues)
print(" ads a value of 4 to the arrayOfValues ( equal to positionA + 1) ")
func incrementB() {
positionA = positionA + 1
arrayOfValues.append(arrayPosition)
}
incrementB()
print(positionA)
print(arrayOfValues)
print("adds a value of 3 to the arrayOfValues that it still is equal to positionA, WITHOUT adding a +1 in the calculation of arrayPosition, when it SHOULD ADD a value of 5( positionA + 1 from increment(), +1 from incrementB) ")

arrayPosition is never changed after its initial assignment ( with a value of 3 resulting from 3 / 1 ).
Although positionA will indeed be 5 after the 2nd increment, that's not what you're adding to your arrayOfValues so the result is as expected (3).
[EDIT]
You could make it a computed variable like this
var arrayPosition : Int { return arrayA[positionA] / arrayB[positionB] }
It's just like a function but you don't need to use () to call it.

Related

Save previous bar values when using a loop in pine script

In pine script I'm calling a function that sums the previous bar value with an increment:
myFunction(myVar1) =>
var int myVar2 = 0
myVar2 := myVar1 + nz(myVar2[1],1)
The increment value is added using a loop that calls the function and the result is stored in an array:
myArray = array.new_int(0)
var int myVar1 = 1
myVar1 := 1
while myVar1 <= 3
array.push(myArray, myFunction(myVar1))
myVar1 += 1
The result in the first bar was expected. Since there is no previous bar the previous value is replaced by 1 nz(myVar2[1],1)
plot(myArray.get(myArray, 0))
plot(myArray.get(myArray, 1))
plot(myArray.get(myArray, 2))
Result: [2, 3, 4]
But in the second bar:
Result: [5, 6, 7]
My expected result: [3, 5, 7]
Since it runs the loop for the first bar first and then runs the loop again in the second bar it uses for myVar2[1] the last value 4 saved when running the last loop in the first bar.
How can the previous bar values be stored correctly when using a loop so that the expected results can be achieved:
First bar: [2, 3, 4]
Second bar: [3, 5, 7]
Third bar: [4, 7, 10]
Answer to your comment: You could save the current array in another array. That way, you always have access to the array values of the previous bar.
//#version=5
indicator("My Script", overlay=false)
var int myVar1 = na
var int[] myArray = array.new_int(3) // Current array
var int[] prevArray = array.new_int(3) // Previous array
myFunction(myVar1) =>
var int myVar2 = 0
myVar2 := myVar1 + nz(myVar2[1],1)
myVar1 := 1
prevArray := array.copy(myArray) // Save current array
array.clear(myArray) // Clear current array
while myVar1 <= 3
array.push(myArray, myFunction(myVar1))
myVar1 += 1
// Show previous array
plot(array.get(prevArray, 0), 'prevArray[0]')
plot(array.get(prevArray, 1), 'prevArray[1]')
plot(array.get(prevArray, 2), 'prevArray[2]')
// Show current array
plot(array.get(myArray, 0), 'myArray[0]')
plot(array.get(myArray, 1), 'myArray[1]')
plot(array.get(myArray, 2), 'myArray[2]')

Does time complexity become O(n) when return value of myArray.reversed() is assigned to a previously initialized array? Copy-on-write?

Apple docs state Time Complexity is O(1) for the .reversed() method.
In the following code, arr (line 2) is a ReversedCollection<Array<Int>> type.
How come printing arr (line 3) doesn't return the numbers in reversed order?
// 1 - let a = [1, 2, 3, 4, 5]
// 2 - let arr = a.reversed() // <- O(1) is the complexity of this operation.
// 3 - print(arr) // unexpected - prints ReversedCollection<Array<Int>>(_base: [1, 2, 3, 4, 5])
Regarding the following code sample - Converting the ReversedCollection to an Array (line 2) returns values in reversed order as expected in a new array. Additional storage was allocated. I understand a.reversed() operation itself is O(1). There is no question about that. I do not understand how this operation remains O(1) after converting its output to a newly initialized array. Apple's docs show this conversion to an Array & directly below it they mention O(1). https://developer.apple.com/documentation/swift/arrayslice/1688969-reversed
Did Apple fail to state that the time & space complexity both change after line 2 completes execution?
// 1 - let a = [1, 2, 3, 4, 5]
// 2 - let arr = Array(a.reversed()) // arr is type Array<Int>
// 3 - print(arr) // prints [5, 4, 3, 2, 1] as expected
In the following code, (line 3) - a.reversed() return value is type ReversedCollection<Array<Int>>, which is then assigned to arr - type Array<Int>. I am concerned this assignment to arr operation removes the O(1) time complexity; it appears similar to the code above(line 2) - where we converted the ReversedCollection<Array<Int>> to an Array.
Is the code below the same as the code directly above?
Does time complexity remain O(1) after execution of line 3 completes in the code below?
// 1 - let a = [1, 2, 3, 4, 5]
// 2 - var arr = a // arr is type Array<Int>
// 3 - arr = arr.reversed() // assigns a ReversedCollection<Array<Int>> to an Array
// 4 - print(type(of: arr) // prints Array<Int>
// 5 - print(arr) // print [5, 4, 3, 2, 1] as expected
Another scenario is shared below - (line 3) - Error is returned - unable to assign rev to arr. I present it to compare against the code directly above (line 3), which assigns the ReversedCollection type to the Array type in 1 less step than in the code below.
// 1 - let a = [1, 2, 3]
// 2 - let rev = a.reversed() // arr is type Array<Int>
// 3 - let arr = rev // Error - Cannot assign value of type 'ReversedCollection<[Int]>' to type '[Int]'
Regarding the sample code below, (line 3) - This time I'm not assigning arr.reversed() to arr. It results in arr not being reversed, which is not what I expected. I wanted to avoid using .reverse() in line 3 because that runs in O(n).
// 1 - let a = [1, 2, 3, 4, 5]
// 2 - var arr = a // arr is type Array<Int>
// 3 - arr.reversed() // does not reverse arr's items
// 5 - print(arr) // prints [1, 2, 3, 4, 5] - not what I initially expected
Is copy-on-write keeping time complexity O(1) even after ReversedCollection is assigned / converted to an Array?
The result of .reversed() is just a structure that iterates backwards over the collection. It costs a constant time to create. Iterating over it costs O(n) just like any collection.
So let rev = a.reversed() is O(1), but let rev = Array(a.reversed()) is O(n) since it iterates over a to make the copy. There is no implicit conversion. Array and ReversedCollection<Array> are completely different types. You can pass any Sequence to Array.init and it will copy the values into a new Array.
Stdlib is open source, so you can also look at how it's all implemented. You'll see that the initializer is only an assignment:
internal init(_base: Base) {
self._base = _base
}
As you noted, Array.reversed() is an O(1) operation. It just wraps the original Array with logic that automatically adjusts the indexes as you access them for an effective reversal.
If you explicitly create a new Array from a Reversed collection, you are creating a full copy of the data and you are going to pay the O(n) cost. I don't think Swift's copy-on-write optimizations apply here.
Here is a code snippet that you could run to see the time complexity.
var array = [Int]()
for i in 0..<1000000 {
array.append(i)
}
let startDate = Date()
let reversed = array.reversed() // O(1)
print(Date().timeIntervalSince(startDate)) // ~0s from start
var newArray = Array(reversed) // O(n)
print(Date().timeIntervalSince(startDate)) // ~0.2s from start
newArray[0] = 0
print(Date().timeIntervalSince(startDate)) // ~0.2s from start

Swift : Performing operations on certain elements of an array

So, something is bugging me with the syntax in Swift for performing operations on Arrays of Ints.
What I wanna do is this : I have an array of Ints which is outputted from a function, its size (count) varies between say 2 and 6 for now, depending on buttons I press in my app.
For each array that is outputted and that contain n ints, I want to create n arrays on which to perform an other action later on.
These "sub" arrays are supposed to be calculated this way :
newArray1's values should be array's values - the value of the first index of newArray1
newArray2's values should be array's values - the value of the second index of newArray2
etc... (I'll automate the number of newArrays according to the array.count)
An other condition applying for those new arrays is that if at a given index the value is negative, I add 12 (so it'll occur for newArray2 at index 1, for newArray3 at indexes 1 & 2, etc... as long as those newArrays are created).
Here's how I wanted to perform that (I created this with dummy arbitrary array in the playground for the sake of testing before inserting the correct stuff in my app code) :
var array : [Int] = [2,4,6,8,9]
var newArray2 = [Int]()
var increment2 = Int()
increment2 = array[1]
newArray2 = array.map {$0 - increment2}
for i in 0..<newArray2.count {
if array[i] < 0 {
newArray2[i] = array[i] + 12
} else {
newArray2[i] = array[i]
}
}
print(array)
print(newArray2)
So of course it doesn't work because I can't seem to figure how to correctly perform operations on Arrays...
Intuitively it seems in my first if statement I'm comparing not the element at index i but i itself, not sure how to reformat that though...
Any help is most welcome, thanks in advance ! :)
[EDIT: I just edited the names of newArray1 to newArray2, same for increments, so that I have negative values and it matches the index value of 1 which is the second element of my main array]
You seem to mean this:
let arr = [2,4,6,8,9]
var results = [[Int]]()
for i in arr.indices {
results.append(arr.map {
var diff = $0-arr[i]
if diff < 0 { diff += 12 }
return diff
})
}
// results is now:
// [[0, 2, 4, 6, 7],
// [10, 0, 2, 4, 5],
// [8, 10, 0, 2, 3],
// [6, 8, 10, 0, 1],
// [5, 7, 9, 11, 0]]

Kotlin initialize an Array using another array

I can initialize an array in Kotlin like this:
val mArr = Array<Int>(5) {0}
and I'll have the following array [0,0,0,0,0]
The thing is, I need to initialise an array and put the values of another array into it.
i.e:
initialArray = [1, 4, 5 ,-2, 7]
val offset = 5
And should get mArr = [6, 9, 10, 3, 12]
Is there a way to set the value of each mArr[i] based on each initialArray[i]?
Something like
val mArr = Array<Int>(initialArray.size) { offset + initialArray[index]}
Without wrapping it in a for loop
There is map function for array.
So:
val initialArray = arrayOf(1, 4, 5 ,-2, 7)
val offset = 5
val newArray = initialArray.map { it + offset }.toTypedArray()
But this way you create new array without modifying the old one.
If you want modify old array you can use forEachIndexed extension method:
initialArray.forEachIndexed { index, value ->
initialArray[index] = initialArray[index] + offset
// or:
initialArray[index] = value + offset
}
val mArr = Array<Int>(initialArray.size) { offset + initialArray[index] }
already nearly works. It's just that index isn't defined here. You want it to be the function's parameter, so { index -> offset + initialArray[index] } or shorter { offset + initialArray[it] }. Also, for this you probably want IntArray instead of Array<Int> (and for initialArray as well). Combining these changes:
val mArr = IntArray(initialArray.size) { offset + initialArray[it] }

Transferring one Integer from one array to another causes invalid array size

In my project, I have two arrays of Ints
In pseduocode;
var existingOrders:[ExistingOrder] ...
var completedOrders:[CompletedOrder] ..
protocol ValueProtocol {
var value: Int { get set }
}
class ExistingOrder: ValueProtocol {
var value: Int = 0
}
class CompletedOrder: ValueProtocol {
var value: Int = 0
}
Yes, I know that functionality is the same; but I'm needing it to be two classes for a reason that is outside the scope of this question.
One function I'm writing I need to transfer one order from Existing Order to Completed.
In my code I loop through all the values I want to transfer, then transfer them
for (index, item) in self.completedOrders.enumerated() {
item.value = Die.roll()
self.transfer(index: index, destination: .existingOrder)
}
The transfer function moves it from existingOrder -> completedOrder and vice versa.
The problem is this:
When it steps through the array shown above it'll pop an object during the transfer; and now the size of the array has changed and is no longer correct.
Visually stepping through it, it looks like this;
ie;
// stepping through the for-loop
existingOrders = [3,2]
transfer > index 0 (Integer value of 3) -> completed
existingOrders = [2]
transfer > index 1 .. crash; because the size of the array isn't correct any more.
So the for-loop is going through each item it needs to transfer, but because the transfer itself is amending the for-loop it changes the contents of said array and causes a crash.
The reason I use an index is because sometimes I want a specific item within the existing orders to be transferred.
I'm wondering how I can avoid this issue?
Thanks
Loop through your array in reverse order. That way, the earlier indices will still be valid as the later items are removed:
for (index, item) in self.completedOrders.enumerated().reversed() {
item.value = Die.roll()
self.transfer(index: index, destination: .existingOrder)
}
Here's an example of how this works with an array of numbers in which we remove the odds ones:
var numbers = Array(1...10) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var odds = [Int]()
for (index, number) in numbers.enumerated().reversed() {
if number % 2 == 1 {
odds.insert(number, at: 0)
numbers.remove(at: index)
}
}
print(numbers) // [2, 4, 6, 8, 10]
print(odds) // [1, 3, 5, 7, 9]

Resources