creating 2 dimensional array of unspecified (varying) size - arrays

Newbie question: I want to dynamically create an integer 2D array M[i,j], whose sizes (in both dimensions) are unknown beforehand. Moreover, for each index i, the size of the i-th row may vary.
Question 1: How do I declare such an array (do I even have to)? I have tried Array[], Array(Int64,1...), and Array((Int,Int),0)as in this hint and others.
Question 2: once created, how to I populate the array in a smart and concise way? Say my i-th row is suppose to be equal to a given 1-dimensional B, I would like to write
A[i] = B
or
A[i,:] = B
or even
A[i,1:n] = B
where n is the size of B. All of these give me a BoundsError(). Slicemight do the trick, but I cannot make it agree with my declaration.

You don't want a 2D array here, because in a 2D array all rows are of the same size. Instead, you want a vector-of-vectors. For example:
A = Array(Vector{Int}, 5)
A[1] = rand(1:10, 3)
A[2] = rand(1:100, 22)
If you inspect A, you'll see something like this:
julia> A
5-element Array{Array{Int64,1},1}:
[5,7,7]
[1,63,40,86,61,39,98,5,68,97 … 78,49,44,89,48,63,90,90,86,83]
#undef
#undef
#undef
Another great tool is to use a comprehension:
julia> A = Vector{Int}[ [1:m] for m = 1:5]
5-element Array{Array{Int64,1},1}:
[1]
[1,2]
[1,2,3]
[1,2,3,4]
[1,2,3,4,5]
The main thing you'll want to be careful about is that each element of A is a reference to a vector; if you assign
A[1] = b
A[2] = b
then any change to b will affect both A[1] and A[2]. If you don't want that, use
A[1] = copy(b)
A[2] = copy(b)

Related

Seg faulting with 4D arrays & initializing dynamic arrays

I ran into a big of a problem with a tetris program I'm writing currently in C.
I am trying to use a 4D multi-dimensional array e.g.
uint8_t shape[7][4][4][4]
but I keep getting seg faults when I try that, I've read around and it seems to be that I'm using up all the stack memory with this kind of array (all I'm doing is filling the array with 0s and 1s to depict a shape so I'm not inputting a ridiculously high number or something).
Here is a version of it (on pastebin because as you can imagine its very ugly and long).
If I make the array smaller it seems to work but I'm trying to avoid a way around it as theoretically each "shape" represents a rotation as well.
https://pastebin.com/57JVMN20
I've read that you should use dynamic arrays so they end up on the heap but then I run into the issue how someone would initialize a dynamic array in such a way as linked above. It seems like it would be a headache as I would have to go through loops and specifically handle each shape?
I would also be grateful for anybody to let me pick their brain on dynamic arrays how best to go about them and if it's even worth doing normal arrays at all.
Even though I have not understood why do you use 4D arrays to store shapes for a tetris game, and I agree with bolov's comment that such an array should not overflow the stack (7*4*4*4*1 = 448 bytes), so you should probably check other code you wrote.
Now, to your question on how to manage 4D (N-Dimensional)dynamically sized arrays. You can do this in two ways:
The first way consists in creating an array of (N-1)-Dimensional arrays. If N = 2 (a table) you end up with a "linearized" version of the table (a normal array) which dimension is equal to R * C where R is the number of rows and C the number of columns. Inductively speaking, you can do the very same thing for N-Dimensional arrays without too much effort. This method has some drawbacks though:
You need to know beforehand all the dimensions except one (the "latest") and all the dimensions are fixed. Back to the N = 2 example: if you use this method on a table of C columns and R rows, you can change the number of rows by allocating C * sizeof(<your_array_type>) more bytes at the end of the preallocated space, but not the number of columns (not without rebuilding the entire linearized array). Moreover, different rows must have the same number of columns C (you cannot have a 2D array that looks like a triangle when drawn on paper, just to get things clear).
You need to carefully manage the indicies: you cannot simply write my_array[row][column], instead you must access that array with my_array[row*C + column]. If N is not 2, then this formula gets... interesting
You can use N-1 arrays of pointers. That's my favourite solution because it does not have any of the drawbacks from the previous solution, although you need to manage pointers to pointers to pointers to .... to pointers to a type (but that's what you do when you access my_array[7][4][4][4].
Solution 1
Let's say you want to build an N-Dimensional array in C using the first solution.
You know the length of each dimension of the array up to the (N-1)-th (let's call them d_1, d_2, ..., d_(N-1)). We can build this inductively:
We know how to build a dynamic 1-dimensional array
Supposing we know how to build a (N-1)-dimensional array, we show that we can build a N-Dimensional array by putting each (N-1)-dimensional array we have available in a 1-Dimensional array, thus increasing the available dimensions by 1.
Let's also assume that the data type that the arrays must hold is called T.
Let's suppose we want to create an array with R (N-1)-dimensional arrays inside it. For that we need to know the size of each (N-1)-dimensional array, so we need to calculate it.
For N = 1 the size is just sizeof(T)
For N = 2 the size is d_1 * sizeof(T)
For N = 3 the size is d_2 * d_1 * sizeof(T)
You can easily inductively prove that the number of bytes required to store R (N-1)-dimensional arrays is R*(d_1 * d_2 * ... * d_(n-1) * sizeof(T)). And that's done.
Now, we need to access a random element inside this massive N-dimensional array. Let's say we want to access the item with indicies (i_1, i_2, ..., i_N). For this we are going to repeat the inductive reasoning:
For N = 1, the index of the i_1 element is just my_array[i_1]
For N = 2, the index of the (i_1, i_2) element can be calculated by thinking that each d_1 elements, a new array begins, so the element is my_array[i_1 * d_1 + i_2].
For N = 3, we can repeat the same process and end up having the element my_array[d_2 * ((i_1 * d_1) + i_2) + i_3]
And so on.
Solution 2
The second solution wastes a bit more memory, but it's more straightforward, both to understand and to implement.
Let's just stick to the N = 2 case so that we can think better. Imagine to have a table and to split it row by row and to place each row in its own memory slot. Now, a row is a 1-dimensional array, and to make a 2-dimensional array we only need to be able to have an ordered array with references to each row. Something like the following drawing shows (the last row is the R-th row):
+------+
| R1 -------> [1,2,3,4]
|------|
| R2 -------> [2,4,6,8]
|------|
| R3 -------> [3,6,9,12]
|------|
| .... |
|------|
| RR -------> [R, 2*R, 3*R, 4*R]
+------+
In order to do that, you need to first allocate the references array (R elements long) and then, iterate through this array and assign to each entry the pointer to a newly allocated memory area of size d_1.
We can easily extend this for N dimensions. Simply build a R dimensional array and, for each entry in this array, allocate a new 1-Dimensional array of size d_(N-1) and do the same for the newly created array until you get to the array with size d_1.
Notice how you can easily access each element by simply using the expression my_array[i_1][i_2][i_3]...[i_N].
For example, let's suppose N = 3 and T is uint8_t and that d_1, d_2 and d_3 are known (and not uninitialized) in the following code:
size_t d1 = 5, d2 = 7, d3 = 3;
int ***my_array;
my_array = malloc(d1 * sizeof(int**));
for(size_t x = 0; x<d1; x++){
my_array[x] = malloc(d2 * sizeof(int*));
for (size_t y = 0; y < d2; y++){
my_array[x][y] = malloc(d3 * sizeof(int));
}
}
//Accessing a random element
size_t x1 = 2, y1 = 6, z1 = 1;
my_array[x1][y1][z1] = 32;
I hope this helps. Please feel free to comment if you have questions.

Multidimensional array : Split and put back together

I am trying to turn a 3 dimensional array "upside-down" as:
I have tried the inverse function, but if we look at the inverse operation in mathematical terms, it gives us another result. I need to turn without changing the data in the array. How to do that?
To split the 3-dimensional array (A x B x C) into A-sub-array (2d, B x C) I have used squeeze: k=squeeze(array(n,:,:)). Now I have a 2-dimensional array of size B x C. How to put it back together (in 3 dimensional array)?
You can use permute() to change the order of dimensions, which can be used as a multidimensional transpose.
Putting 2D matrices into a 3D one then is a simple indexing operation. Read more in indexing here.
A = rand(10,10,10);
B = permute(A, [ 3 2 1 ]); % Permute he order of dimensions
mat1 = rand(10,10);
mat2 = rand(10,10);
mat_both(:,:,2) = mat2; % Stack 2D matrices along the third dimension
mat_both(:,:,1) = mat1;
mat_both = cat(3,mat1, mat2); % Stacks along the third dimension in a faster way

Subtracting from each element in array in python

I've got a sort of array in python, and i'm looking to subtract one from each int in all of it. for example:
arr = [[2,3,4],
[5,6,7],
[8,9,10]]
#this should become this:
arr = [[1,2,3],
[4,5,6],
[7,8,9]]
there's a few ways i've tried to do this
for i in arr:
for j in i:
j-=1 #doesn't work!
I'm aware it would be easier to do this with numpy, but this is for a large project that i'm working on, so implementing numpy would take hours, if not more. Thanks!
So the way that you are doing it is just reassigning the variable j within your loop to one less its original value. However, what you want to do is reassign the value of the array AT the index j to one less its original value. To do this without using numpy, simply loop through all the indexes of the array, and then replace the value:
for i in range(len(arr)):
for j in range(len(arr[i])):
arr[i][j] -= 1
If you're unsure of why this is, look into how variable assignment works in Python.
You could use a nested list comprehension:
arr = [[y - 1 for y in x] for x in arr]
Your solution didn't work, because jis a copy of the value from your array, rather than a pointer to the array item itself.
Below is sample code that works. Essentially, iterate through each location in the array, and modify the original array at that location.
arr = [[2,3,4],
[5,6,7],
[8,9,10]]
for x_idx, x in enumerate(arr):
for y_idx, y in enumerate(x):
arr[x_idx][y_idx] -= 1
print(arr)

Array of slices - GO

1)
For below slice declaration,
var a [][3]string
creates a single slice(a) that points to array of 3 strings, len(a) = 3 and cap(a) =3 but not cap(a) >= 3
a = make([][3]string, 5)
creates 5 slices, where each slice(say a[0]) points to array of 3 strings, len(a[0]) = 3 and cap(a[0]) = 3
2)
For slice declaration,
var b [][3][6]string
creates a single slice(b) that points to 3 arrays of 6 strings each, where len(b) = 3 and cap(b) =3
b = make([][3][6]string, 5)
creates 5 slices, where each slice(say b[0]) points to 3 arrays of 6 strings each
In both cases, after making slices, I said, creates 5 slices,
Considering the syntax, below are my two questions,
a = make([][3]string, 5)
My question:
1)
Is it 5 slices, where each slice(a[0]) is array of 3 strings?
or
Is it a single slice(a) pointing to 5 arrays of 3 strings each?
2)
How do I know the type of an element? slice or array?
1) In such scenarios, "array of" terminology has to be cautiously used.
2) There are no implicit pointers involved in GO unlike C
Slices and arrays are two different types: an array in memory is a contiguous sequences of values of the same type. In Go a type has a fixed size. The very same concept is present for example in C++ and
int x[5]; // C and C++
x [5]int // Go
are basically the same thing (not 100% the same because arrays in C and C++ are "second class citizens" and behave strangely in a few places, Go is more uniform on that).
A slice in Go is instead a "view" of a portion of an array, and is more or less equivalent to a C++ structure with a pointer to the first element, a number of used elements (relative to first) and a number of available elements (relative to first)
// C++
template<typename T>
struct Slice {
T *first;
int size, capacity;
};
Slice<int> x{nullptr, 0, 0};
// Go
var x []int
The Make special function is able to create slices associated to newly created arrays, given size and optional capacity:
// C++
template<typename T>
Slice<T> make(int size, int capacity=-1) {
if (capacity == -1) capacity = size;
return Slice<T>{new T[capacity], size, capacity};
}
// Go
x := Make([]int, size, capacity)
Slices can be efficiently passed around in O(1) (independently on size/capacity) and you can also take a sub-slice of a slice in O(1)... note that Go is garbage collected, doing the same in C++ would require some extra work (for example also keeping a pointer to the original array object and its size in the slice).
You can of course have arrays of slices, slices of slices, slices of arrays and arrays of arrays. Note however that in Go Make is used only to create slices (and maps) not for arrays...
x := Make([][2]int, 3) // a slice of 3 arrays of 2 ints each
// Same thing (except for content)
y := [][2]int{[2]int{1, 2},
[2]int{3, 4},
[2]int{5, 6}}
// An array of 3 slices of two ints each
z := [3][]int{[]int{1, 2},
[]int{3, 4},
[]int{5, 6}}
While for example both y and z in the playground would look the same [[1, 2], [3, 4], [5, 6]] when using fmt.Println, they are very different types, for example you can add a new pair to y with
y = append(y, [2]int{7, 8}) // now [[1, 2], [3, 4], [5, 6], [7, 8]]
and you can instead increase the length of first element of z with
z[0] = append(z[0], 99) // now [[1, 2, 99], [3, 4], [5, 6]]
but you cannot add new elements to z (it's an array) and you cannot extend an element of y (because elements are arrays)
1) Considering the syntax,
a = make([][3]string, 5)
Is it 5 slices, where each slice(a[0]) is array of 3 strings?
or
Is it a single slice(a) pointing to 5 arrays of 3 strings each?
Its a single slice with 5 elements where each element is an array of 3 strings.
2)
How do I know the type of an element? slice or array?
Slices and arrays are different types. You can not interchangeably assign arrays and slices to the same variable, hence if the declaration declares it as an array, its an array, if it declares it as a slice, its a slice. If it has a number in the brackets ([5]string) its an array, if the brackets are empty ([]string) its a slice.
2) For slice declaration,
var b [][3][6]string
creates a single slice(b) that points to 3 arrays of 6 strings each,
where len(b) = 3 and cap(b) =3
b = make([][3][6]string, 5)
creates 5 slices, where each slice(say b[0]) points to 3 arrays of 6 strings each
No. Former code just declares a variable, it doesn't hold a slice yet. Latter code creates one slice with five elements.

two dimensional Arrays access using pointers

Is
*(ary[3]+8)
and
ary[3][8]
are the same ? If yes, please explain how ? ary[3] returns the address of first element or the value in ary[3][0] ? ary is a two dimensional array.
Thanks in advance.
Yes
a[i] is same as *(a+i)
ary[i][j] is same as *( *(ary+i)+j))
If x is an array (int, say) x[i] is just a syntactic sugar for *(x+i). In your case, ary is a two-dimensional array (again of int, say). By the same syntactic sugar mechanism, ary[i][j] is equivalent to *((*(ary+i))+j), from which it is clear what happens under the hood.
*(ary[3]+8) says value at 8th column of third row.ary[3] is base address of third Row.ary[3][8] will also access to same element at third row and 8th column.
For Example i am taking an 2D array of two row and 4 column which is equivalent to 1D array of 8 elements.As shown below.
int a[8] = {0,1,2,3,4,5,6,7};
int b[2][4] = {{0,1,2,3},{4,5,6,7}};
since b is 2D array , so you can consider it as array of two 1D arrays.when you pass b[1] or b[1][0] it says address of first row.Rectangular array allocated in memory by Row.so if you want to find address of element a[row][col] it will get calculated as
address = baseAddress + elementSize * (row*(total number of column) + col);
As others already have said, a[i] is just a sugar for *(a+i).
I just would like to add that it always works, that allows us to do things like that:
char a[10];
char b;
char c[10][20];
// all of these are the same:
b = a[5]; // classic
b = *(a + 5); // pointer shifting
b = 5[a]; // even so!
b = c[5][9];
b = *(c[5] + 9);
b = *(*(c + 5) + 9);
b = *(c + 5)[9];
b = 5[c][9];
b = 5[9][c]; // WRONG! Compiling error

Resources