How to change the count of a for loop during the loop - arrays

I'm trying to change the number of items in array, over which a for loop is running, during the for loop, with the objective that this changes the number of loops. In a very simplified version, the code would look something like this:
var loopArray: [Int] = []
loopArray.append(1)
loopArray.append(2)
loopArray.append(3)
loopArray.append(4)
loopArray.append(5)
for x in 0..<Int(loopArray.count) {
print(x)
if x == 4 {
loopArray.append(6)
}
}
When running this code, 5 numbers are printed, and while the number 6 is added to the Array, the loopArray.count does not seem to update. How can I make the .count dynamic?
This is a very simplified example, in the project I'm working on, appending numbers to the array depends on conditions that may or may not be met.
I have looked for examples online, but have not been able to find any similar cases. Any help or guidance is much appreciated.

sfung3 gives the correct way to do what you want, but I think there needs to be a bit of explanation as to why your solution doesn't work
The line
for x in 0..<Int(loopArray.count)
only evaluates loopArray.count once, the first time it is hit. This is because of the way for works. Conceptually a for loop iterates through the elements of a sequence. The syntax is something like
for x in s
where
s is a sequence, give it type S
x is a let constant (you can also make it a var but that is not relevant to the current discussion) with type S.Element
So the bit after the in is a sequence - any sequence. There's nothing special about the use of ..< here, it's just a convenient way to construct a sequence of consecutive integers. In fact, it constructs a Range (btw, you don't need the cast to Int, Array.count is already an Int).
The range is only constructed when you first hit the loop and it's effectively a constant because Range is a value type.
If you don't want to use Joakim's answer, you could create your own reference type (class) that conforms to Sequence and whose elements are Int and update the upper bound each time through the loop, but that seems like a lot of work to avoid a while loop.

you can use a while loop instead of a for loop.
var i = 0
while i < loopArray.count {
print(i)
if i == 4 {
loopArray.append(6)
}
i += 1
}
which prints
0 1 2 3 4 5

Related

Can a recursive function containing a for loop that contains a call of the mentioned function be implemented using only for loops?

Similar questions have been asked and the general consensus is that anything can be converted from recursion to for loops and vice versa. However, I can't find a way to convert a function of the following pseudocode type to a for loop:
def recursive(n):
if n == 0:
return
for i in range(some_number):
do_sth...
recursive(n-1)
In this case, there is n nested loops and n varies depending on the given argument. When using only for loops, the number of nested loops seems to be always predetermined in the code, it doesn't vary depending on "input". Is there a way to make something like this using only for loops?
Is there a way to make something like this using only for loops?
Well, if you admit a while loop as a case of a pseudocode for loop, at least your example can be made:
def nonrecursive(n):
a = []
z = 0
while n:
while n:
i = z
if i == some_number: break
print((n, i))
a += [[n, i]]
n -= 1
z = 0
if not a: break
n, i = a.pop()
i += 1
z = i
We need to be careful here.
The general true statement is that loops can replace recursion and vice versa. This can be shown lots of ways; see the structured programming theorem for ideas.
Whether for loops can replace recursion depends upon your definitions. Can your for loops run forever, or for an indefinite amount of time not known in advance? If so, they are functionally equivalent to while loops, and they can replace recursion. If your for loops cannot be made to run forever or for an unknown (initially) number of iterations, recursion cannot always be replaced.
Really, it's while loops (plus a stack data structure) that can replace recursion without much trouble.

Kotlin array <init>ialization [duplicate]

This question already has answers here:
Order of init calls in Kotlin Array initialization
(2 answers)
Closed 3 years ago.
I will be reading data from a byte stream. Are the indices given by Kotlin to an array generation function (as described in https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/-init-.html) guaranteed to be called in order, ascending from zero?
The Array.kt file is under builtins so I'm at a loss as to where to find the actual code.
Take a look at the source code for Array:
public inline constructor(size: Int, init: (Int) -> T)
The init parameter is a function that takes an int (the index for a specific item), to which it expects a return value of type T, which the array consists of.
As the other answers have shown by examples, these are called in order, because it's the "natural" way of doing it. If you don't get what I mean, think about the implementation alternatives:
for (i in 0..size) {
this.addToArray(init(i));
}
Alternatively:
for (i in (size - 1)..0 {
this.addToArray(init(i));
}
Compared to:
val indices = mutableListOf<Int>()
while (indices.size != size) {
val i = random.nextInt(size);
if (i !in indices) {
indices.add(i);
this.addToArray(init(i));
}
}
While we can't see the source code for the constructor, the examples show in the other answers alone show they cannot be using a random approach. Applying the code from the first answer, mathematically speaking, the odds of using random and getting 0-49 printed out in order are extremely low.
Additionally, this is backed up by an answer here. The resulting compiled Java code creates a for-loop going from 0 to size. For the JVM, assuming they don't change the implementation, you can assume it'll go from 0 to size. But whether it goes from 0 to size or from size to 0, you can always reverse it if you don't like the order.
If you need to be 100% sure it goes from 0 to size, or if the implementation changes, you can do something like:
var a = (0 until 10).step(1).toList().toTypedArray()
Which, in this case, yields an array with the numbers 0-9.
If you want objects, or otherwise alter the object, you can add a .map {} before the list creation. That being said, this is an overkill alternative as long as the init function works as you'd expect.
And you can always confirm by decompiling the code using IntelliJ, Android Studio, some other IDE, or a decompiler of your choice. But regardless of the implementation, they'll always end up in order - so you don't need to worry about that. The only thing they oculd possibly change is the order the init function is called in, but it'll still end up in the same order in the resulting array.
That does seem to be the case.
Code:
fun main() {
val x = Array(50) {println(it)}
}

How does this code work? They are removing an item in an array based on a condition. The syntax confuses me

Image of problem
They lost me at the part where " = -1"
This is my understanding of the solution(so far).
They took the arr variable and scanned for elements that have a remainder of 1 when divided by 2. The = -1 part is where I'm confused.
What are the steps going on in here to replace those odd numbers as
negative 1?
Could someone explain in more depth how "arr[arr % 2 == 1]"
works? I think I have a very simple understanding of it.
Also, what is this particular technique called?
EDIT:
So I tried the solution they gave and it doesn't even run...Not sure if I did something wrong on my end.
Original site link: Source
Just like anything else you're trying to understand, take it step by step. Try printing out each of these intermediate expressions:
arr is a numpy array. This is important, because all of these steps depend on special numpy features - they wouldn't work on an ordinary list.
arr % 2 is an array of the same size, containing the parity of each of the original numbers - 0 for even, 1 for odd.
arr % 2 == 1 turns that into an array of booleans - False for even, True for odd.
arr[arr % 2 == 1] invokes numpy's special boolean indexing feature - it gives you a view of a (possibly discontiguous) subset of the array, wherever the index value was True. In this case, the view contains only the odd numbers of the original array.
arr[arr % 2 == 1] = -1 assigns the same value to each element in the view, overwriting all of the original odd numbers.
A key numpy concept used in all of the steps is "broadcasting" - basically, whenever an operation is attempted between an array and a single element, the single element is effectively replicated to match the size of the array. So, in arr % 2, the 2 notionally becomes an array of 2s, the same size as arr.

use five point stencil to evaluate function with vector inputs and converge to maximum output value

I am familiar with iterative methods on paper, but MATLAB coding is relatively new to me and I cannot seem to find a way to code this.
In code language...
This is essentially what I have:
A = { [1;1] [2;1] [3;1] ... [33;1]
[1;2] [2;2] [3;2] ... [33;2]
... ... ... ... ....
[1;29] [2;29] [3;29] ... [33;29] }
... a 29x33 cell array of 2x1 column vectors, which I got from:
[X,Y] = meshgrid([1:33],[1:29])
A = squeeze(num2cell(permute(cat(3,X,Y),[3,1,2]),1))
[ Thanks to members of stackOverflow who helped me do this ]
I have a function that calls each of these column vectors and returns a single value. I want to institute a 2-D 5-point stencil method that evaluates a column vector and its 4 neighbors and finds the maximum value attained through the function out of those 5 column vectors.
i.e. if I was starting from the middle, the points evaluated would be :
1.
A{15,17}(1)
A{15,17}(2)
2.
A{14,17}(1)
A{14,17}(2)
3.
A{15,16}(1)
A{15,16}(2)
4.
A{16,17}(1)
A{16,17}(2)
5.
A{15,18}(1)
A{15,18}(2)
Out of these 5 points, the method would choose the one with the largest returned value from the function, move to that point, and rerun the method. This would continue on until a global maximum is reached. It's basically an iterative optimization method (albeit a primitive one). Note: I don't have access to the optimization toolbox.
Thanks a lot guys.
EDIT: sorry I didn't read the iterative part of your Q properly. Maybe someone else wants to use this as a template for a real answer, I'm too busy to do so now.
One solution using for loops (there might be a more elegant one):
overallmax=0;
for v=2:size(A,1)-1
for w=2:size(A,2)-1
% temp is the horizontal part of the "plus" stencil
temp=A((v-1):(v+1),w);
tmpmax=max(cat(1,temp{:}));
temp2=A(v,(w-1):(w+1));
% temp2 is the vertical part of the "plus" stencil
tmpmax2=max(cat(1,temp2{:}));
mxmx=max(tmpmax,tmpmax2);
if mxmx>overallmax
overallmax=mxmx;
end
end
end
But if you're just looking for max value, this is equivalent to:
maxoverall=max(cat(1,A{:}));

Matlab array of struct : Fast assignment

Is there any way to "vector" assign an array of struct.
Currently I can
edges(1000000) = struct('weight',1.0); //This really does not assign the value, I checked on 2009A.
for i=1:1000000; edges(i).weight=1.0; end;
But that is slow, I want to do something more like
edges(:).weight=[rand(1000000,1)]; //with or without the square brackets.
Any ideas/suggestions to vectorize this assignment, so that it will be faster.
Thanks in advance.
This is much faster than deal or a loop (at least on my system):
N=10000;
edge(N) = struct('weight',1.0); % initialize the array
values = rand(1,N); % set the values as a vector
W = mat2cell(values, 1,ones(1,N)); % convert values to a cell
[edge(:).weight] = W{:};
Using curly braces on the right gives a comma separated value list of all the values in W (i.e. N outputs) and using square braces on the right assigns those N outputs to the N values in edge(:).weight.
You can try using the Matlab function deal, but I found it requires to tweak the input a little (using this question: In Matlab, for a multiple input function, how to use a single input as multiple inputs?), maybe there is something simpler.
n=100000;
edges(n)=struct('weight',1.0);
m=mat2cell(rand(n,1),ones(n,1),1);
[edges(:).weight]=deal(m{:});
Also I found that this is not nearly as fast as the for loop on my computer (~0.35s for deal versus ~0.05s for the loop) presumably because of the call to mat2cell. The difference in speed is reduced if you use this more than once but it stays in favor of the for loop.
You could simply write:
edges = struct('weight', num2cell(rand(1000000,1)));
Is there something requiring you to particularly use a struct in this way?
Consider replacing your array of structs with simply a separate array for each member of the struct.
weights = rand(1, 1000);
If you have a struct member which is an array, you can make an extra dimension:
matrices = rand(3, 3, 1000);
If you just want to keep things neat, you could put these arrays into a struct:
edges.weights = weights;
edges.matrices = matrices;
But if you need to keep an array of structs, I think you can do
[edges.weight] = rand(1, 1000);
The reason that the structs in your example don't get initialized properly is that the syntax you're using only addresses the very last element in the struct array. For a nonexistent array, the rest of them get implicitly filled in with structs that have the default value [] in all their fields.
To make this behavior clear, try doing a short array with clear edges; edges(1:3) = struct('weight',1.0) and looking at each of edges(1), edges(2), and edges(3). The edges(3) element has 1.0 in its weight like you want; the others have [].
The syntax for efficiently initializing an array of structs is one of these.
% Using repmat and full assignment
edges = repmat(struct('weight', 1.0), [1 1000]);
% Using indexing
% NOTE: Only correct if variable is uninitialized!!!
edges(1:1000) = struct('weight', 1.0); % QUESTIONABLE
Note the 1:1000 instead of just 1000 when indexing in to the uninitialized edges array.
There's a problem with the edges(1:1000) form: if edges is already initialized, this syntax will just update the values of selected elements. If edges has more than 1000 elements, the others will be left unchanged, and your code will be buggy. Or if edges is a different type, you could get an error or weird behavior depending on its existing datatype. To be safe, you need to do clear edges before initializing using the indexing syntax. So it's better to just do full assignment with the repmat form.
BUT: Regardless of how you initialize it, an array-of-structs like this is always going to be inherently slow to work with for larger data sets. You can't do real "vectorized" operations on it because your primitive arrays are all broken up in to separate mxArrays inside each struct element. That includes the field assignment in your question – it is not possible to vectorize that. Instead, you should switch a struct-of-arrays like Brian L's answer suggests.
You can use a reverse struct and then do all operations without any errors
like this
x.E(1)=1;
x.E(2)=3;
x.E(2)=8;
x.E(3)=5;
and then the operation like the following
x.E
ans =
3 8 5
or like this
x.E(1:2)=2
x =
E: [2 2 5]
or maybe this
x.E(1:3)=[2,3,4]*5
x =
E: [10 15 20]
It is really faster than for_loop and you do not need other big functions to slow your program.

Resources