Kotlin array <init>ialization [duplicate] - arrays

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

Related

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

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

Theory of arrays in Z3: (1) model is difficult to understand, (2) do not know how to implement functions and (3) difference with sequences

Following to the question published in How expressive can we be with arrays in Z3(Py)? An example, I expressed the following formula in Z3Py:
Exists i::Integer s.t. (0<=i<|arr|) & (avg(arr)+t<arr[i])
This means: whether there is a position i::0<i<|arr| in the array whose value a[i] is greater than the average of the array avg(arr) plus a given threshold t.
The solution in Z3Py:
t = Int('t')
avg_arr = Int('avg_arr')
len_arr = Int('len_arr')
arr = Array('arr', IntSort(), IntSort())
phi_1 = And(0 <= i, i< len_arr)
phi_2 = (t+avg_arr<arr[i])
phi = Exists(i, And(phi_1, phi_2))
s = Solver()
s.add(phi)
print(s.check())
print(s.model())
Note that, (1) the formula is satisfiable and (2) each time I execute it, I get a different model. For instance, I just got: [avg_a = 0, t = 7718, len_arr = 1, arr = K(Int, 7719)].
I have three questions now:
What does arr = K(Int, 7719)] mean? Does this mean the array contains one Int element with value 7719? In that case, what does the K mean?
Of course, this implementation is wrong in the sense that the average and length values are independent from the array itself. How can I implement simple avg and len functions?
Where is the i index in the model given by the solver?
Also, in which sense would this implementation be different using sequences instead of arrays?
(1) arr = K(Int, 7719) means that it's a constant array. That is, at every location it has the value 7719. Note that this is truly "at every location," i.e., at every integer value. There's no "size" of the array in SMTLib parlance. For that, use sequences.
(2) Indeed, your average/length etc are not related at all to the array. There are ways of modeling this using quantifiers, but I'd recommend staying away from that. They are brittle, hard to code and maintain, and furthermore any interesting theorem you want to prove will get an unknown as answer.
(3) The i you declared and the i you used as the existential is completely independent of each other. (Latter is just a trick so z3 can recognize it as a value.) But I guess you removed that now.
The proper way to model such problems is using sequences. (Although, you shouldn't expect much proof performance there either.) Start here: https://microsoft.github.io/z3guide/docs/theories/Sequences/ and see how much you can push it through. Functions like avg will need a recursive definition most likely, for that you can use RecAddDefinition, for an example see: https://stackoverflow.com/a/68457868/936310
Stack-overflow works the best when you try to code these yourself and ask very specific questions about how to proceed, as opposed to overarching questions. (But you already knew that!) Best of luck..

Does Ruby create a copy when referencing an array with its [..] (slice) method?

I want to loop on a slice of an array. I have basically two main options.
ar.each_with_index{|e,i|
next if i < start_ind
break if i > end_ind
foo(e)
#maybe more code...
}
Another option, which I think is more elegant, would be to run:
ar[start_ind..end_ind].each{|e|
foo(e)
#maybe more code...
}
My concern is Ruby potentially creating a huge array under the hood and doing a lot of memory allocation. Or is there something "smarter" at play that does not create a copy?
You could do a loop of index values... not as elegant as your second solution but economical.
(start_ind..end_ind).each do |index|
foo(ar[index])
# maybe more code
end
You may want to refer to methods' C source code, but it takes a bit of time to read the code. May I help you in this
First: each_index
It's source code in C is tricky, but boils down to something similar to 'each' which looks like
VALUE rb_ary_each(VALUE ary) {
long i;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
for (i=0; i<RARRAY_LEN(ary); i++) {
rb_yield(RARRAY_AREF(ary, i));
}
return ary;
}
It does not create any other array internally by itself. What it effectively does is it simply loops through elements, takes each element and passes it into the block provided (rb_yield part). What's actually inside the block that you provide is a different story.
Second: [...].each
You actually have to notice it is two function calls. The second being 'each' is of little interest to us since it is described above The first function call is '[]'. Logically you expect it to output an subarray as variable, which has to be stored at least temporary.
Let's verify. Source code for C is rather long, but the piece of the greatest importance to you is:
VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary) {
// some code
if (argc == 2) {
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
if (beg < 0) {
beg += RARRAY_LEN(ary);
}
return rb_ary_subseq(ary, beg, len);
}
// some more code
}
It's actually for a function call like ar[start_ind, end_ind] and not ar[start_ind..end_ind]. The difference is immaterial, but this way is easier to understand.
The thing that answers your question is called "rb_ary_subseq". As you may guess from its name or learn from its source, it actually does create a new array. So it would create a copy under the hood of size equal or less of the array given.
You'd want to consider computational cost of functional calls, but the question is about memory.

Frama-C Plugin: Resolve array-values

I'm working on a frama-c plugin that should resolve the values of all kinds of varibles. I managed to dereference pointers and structs and typedefs and print the correspoinding values.
Now I'm struggling with getting the values of an array.
Here is my approach so far, description below:
| TArray (typ, exp, bitsSizeofTypCache, attributes) -> (
let len = Cil.lenOfArray exp in
let rec loc_rec act max =
if act < max then(
let packed = match exp with
| Some x -> x
in
let inc = Cil.increm packed act in
let new_offset = (Index(inc, offset)) in
rec_struct_solver typ (vi_name^"["^(string_of_int act)^"]") (lhost, new_offset);
loc_rec (act+1) max
);
in
loc_rec 0 len
)
I managed to get the length of the array by using Cil.lenOfArray with the expression-option when matching the type.
Now my approach is to go over the length of the array, increment the describing expression and modify the offset, and then handle the variable like a local variable (in the next recursion-step).
I think this idea basically makes sense, but I don't know if the increment is done correctly (value ok, or multiplied by some size or something), or other things don't work.
The program compiles (with the warning that the matching doesn't include all cases, which is irrelevant, since I can only work with expressions, not with NONE), but doesn't output the (correct) results.
Is this the nearly the right approach, or am I doing it completely wrong? Can someone give me some hints on how to get the array's values?
If something is unclear (since it is hard to describe what I want), please let me know, I will modify my question.
EDIT
The expected result of a Code like this
int arr[3];
arr[0]=0;
arr[1]=1;
arr[2]=2;
arr[0]=3;
Should be something like that:
arr[0]=0;3
arr[1]=1
arr[2]=2
I simply want to get all the values at every index of the array over the program.
While I get only empty results, like arr[1]={ } (also for the other Indizes), so I simply don't get results for this Kind of access I use.
Your original code queries the value for the index Index(inc, offset), where inc is Cil.increm packed act, act is the current index, and packed is the size of the array. So you are basically making queries for size+0, size+1 ... size-+(size-1). All these offsets are invalid, because they are out-of-bounds. This is why you obtain the value Cvalue.V.bottom which pretty-prints as .
The simplest fix to your original code would have been to replace packed by a call to Cil.zero Cil_datatype.Location.unknown, but your own fix is fine.
I figured out how to do it:
The trick was, that with Cil.integer, a new constant exp can be built!
With Cil.integer Cil_datatype.Location.unknown act, I created a new exp.
With this exp, I was able to build an Index-Offset. Then I added this new offset to the actual offset of the array. This new offset was used to build a new lval.
By doing this, I got the access to the arrays indizes.
Now my output looks ok:
arrayTest:arr[0]---> 0; 3
arrayTest:arr[1]---> 1
arrayTest:arr[2]---> 2

AS3/Arrays: impossible duplication after "splice"

I have a function that gets questions from an array called quizQuestions, displays the choosed question, splice it from the array and pushes the question and correct answer to a new array to be used later in the results screen:
// The questions are stored in an array called "quizQuestions"
function makeQuestion()
var randNum:Number = Math.round(1 + (quizQuestions.length - 1) * Math.random());
mc_quiz.question.text = quizQuestions[randNum][0];
answer = quizQuestions[randNum][1];
quizQuestions.splice(randNum,1);
printQuestions.push(new Array(mc_quiz.question.text, answer));
}
It runs fine but time to time, a question is asked twice. You can continue with the test but the result doesn't show the info. In fact, it only shows the results for the questions answered before the duplication. I have checked visually and with a "duplicated elements finder" and there are no duplicated questions in the array.
Could the splice non being executed time to time? Can you see any "bug" in the function? Could it happen due to hardwer issue?
Thanks in advance.
Your random number generation is not only mathematically wrong (i.e. it won't generate truly random items), it will also from time to time generate a number that is beyond the array's bounds. To explain this: 1+(array.length-1) * Math.random() will generate any number greater or equal to 1 (this will also result in the first item of the array never to be returned, because arrays are 0-based), up to a fraction less than the actual length of the array. If you Math.round() the highest possible result, it will round up to the next highest integer, which is the full length again - and if you access array[array.length], an error is thrown, which is probably responsible for the weird behavior you are seeing.
Here's a possible solution:
Math.round() creates random number bias, anyway (see #OmerHassans link), so you're better off using int() or Math.floor(). Also, Math.random() is defined as 0 <= n < 1, so it will never return 1. Therefore, you can simplify your random index generator to int(Math.random()*array.length) => any integer smaller than the length of the array.
splice(), then, returns an array of the items that were removed, so you can pass its first item, instead of creating a new array.
function getRandomItem( arr:Array ):* {
var rand:int = Math.random()*arr.length;
return arr.splice( rand, 1 )[0];
}
function makeQuestion():void {
var q:Array = getRandomItem( quizQuestions );
mc_quiz.question.text = q[0];
answer=q[1];
printQuestions[printQuestions.length] = q;
}
FYI: It won't matter much in this context, but you get much faster performance by replacing array.push(item) with array[array.length]=item;.

Resources