How to create a two dimensional array of two dimensional arrays? - arrays

I it possible to create a two dimensional array of two dimensional arrays in Delphi; and if so how do you access the addresses in it?
My aim is to create something similar to a sudoku grid where you have smaller grids inside of a bigger one.
It would work much better in stead of ex. Declaring multiple 2D arrays of the same type or one big array.

Something like
type
TSmallGrid = array[1..3, 1..3] of Integer;
TBigGrid = array[1..3, 1..3] of TSmallGrid;
should work. Access to BigArray: TBigGrid would be with standard Pascal array syntax:
MyInt := BigArray[1, 2, 1, 2]; // or even BigArray[1, 2][1, 2] to emphasize the nesting
or
SmallArray := BigArray[1, 2];

Related

Pre-allocation of array of array

In julia, one can pre-allocate an array of a given type and dims with
A = Array{<type>}(undef,<dims>)
example for a 10x10 matrix of floats
A = Array{Float64,2}(undef,10,10)
However, for array of array pre-allocation, it does not seem to be possible to provide a pre-allocation for the underlying arrays.
For instance, if I want to initialize a vector of n matrices of complex floats I can only figure this syntax,
A = Vector{Array{ComplexF64,2}}(undef, n)
but how could I preallocate the size of each Array in the vector, except with a loop afterwards ? I tried e.g.
A = Vector{Array{ComplexF64,2}(undef,10,10)}(undef, n)
which obviously does not work.
Remember that "allocate" means "give me a contiguous chunk of memory, of size exactly blah". For an array of arrays, which is really a contiguous chunk of pointers to other contiguous chunks, this doesn't really make sense in general as a combined operation -- the latter chunks might just totally differ.
However, by stating your problem, you make clear that you actually have more structural information: you know that you have n 10x10 arrays. This really is a 3D array, conceptually:
A = Array{Float64}(undef, n, 10, 10)
At that point, you can just take slices, or better: views along the first axis, if you need an array of them:
[#view A[i, :, :] for i in axes(A, 1)]
This is a length n array of AbstractArrays that in all respects behave like the individual 10x10 arrays you wanted.
In the cases like you have described you need to use comprehension:
a = [Matrix{ComplexF64}(undef, 2,3) for _ in 1:4]
This allocates a Vector of Arrays. In Julia's comprehension you can iterate over more dimensions so higher dimensionality is also available.

What is the difference between these two declarations of array?

I want to know the difference between theses two declarations of these arrays, one is defined like this (double array[a][b][c][d]), the other one is different (double array[a*b*c][d])
double weight4_5[LAYER4][LAYER5][LENGTH_KERNEL][LENGTH_KERNEL];
double weight5_6[LAYER5 * LENGTH_FEATURE5 * LENGTH_FEATURE5][OUTPUT];
if i want to load values to these two arrays with for loops, how can i do it ?
The first one is a 4 Dimensional array.
Access is by weight4_5[i][j][k][l]
The second one is a 2 Dimensional array. It is a flattened array.
Access is basically by weight5_6[x][y] But you need to do some calculations to get the value of x based on the 4D original array.
You can organise it multiple ways as you want, (e.g. row wise, column wise etc) One way is to have
x= ((((i*LAYER5)+j)*LENGTH_FEATURE5)+k)
y = l;

Function to average elements of any array in Delphi

How can we implement a function to average all elements of a dynamic multidimensional array in Delphi 6? Such as:
Function Average(arr:any_array):extended;
Where arr is a dynamic array and may have 1 or more dimensions.
Linked question: how can we linearize a multidimension array? Do you have any example?
I ask this because I have many different arrays which I must average, if possible, with the one same function.
If you have one dimensional array you can simply use Mean function located in Math unit.
But for multidimensional array I'm afraid there is no already available function. The main reason is that Delphi treats multidimensional arrays in a rather specific way.
While in many other programming languages multidimensional array are in fact just one dimensional array with modified mechanism for accessing array elements which works something like this:
Actual Array Item Index = First parameter + (Second parameter * Size of first dimension)
In Delphi multidimensional arrays are represented as multiple one dimensional array referenced by another array like so:
Array of One Dimensional Array
EDIT 2: As mentioned by David in his comment these type of arrays are also known as Jagged arrays or Ragged arrays.
Why is this so different? Why is it so important? Because those One Dimensional Arrays that from multidimensional array in Delphi don't need to be of the same size. So data in your multidimensional array can actually look like this (where each X represents one array item):
XXXX
XXXXXXX
XXXX
XXXXX
So I'm afraid you will have to write your own function for this. But that should not be so hard.
All you need is a mechanism to iterate through every item in your arrays (I bet you have this already implemented in your code somewhere) so you can sum up the value of all elements in your arrays. And then you divide that sum with the number of elements in your arrays in order to get the arithmetical average of all items.
EDIT 3: I'm not sure if you could have single code to iterate through all of your dynamic arrays. I mean at least you need to know how many dimensions does your array have. This is required because for iterating through multiple dimensions of an array you actually need to recursively iterate through each separate array that represents separate dimensions.
The code for summing up elements in a 3D dynamic array would look like this:
type
TDyn3Darray = array of array of array of Single;
implementation
function SumOf3DArray(Dyn3DArray: TDyn3DArray): Single;
var X,Y,Z, a: Integer;
ArrItem: Single;
begin
Result := 0;
SetLength(Dyn3Darray,5,8,40);
for X := Low(Dyn3Darray) to High(Dyn3Darray) do
begin
for Y := Low(Dyn3Darray[X]) to High(Dyn3Darray[X]) do
begin
for Z := Low(Dyn3Darray[X,Y]) to High(Dyn3Darray[X,Y]) do
begin
Result := Result + Dyn3Darray[X,Y,Z];
end;
end;
end;
end;
I believe you will be capable to modify the code accordingly for different number of dimensions yourself.
EDIT 1: As for linearizing of multidimensional arrays in which I believe you mean changing the multidimensional array in one dimensional array you would just copy elements of separate dimensions and add them into one dimensional array.
But doing that just in order to get average value of all elements would not be practical because for first you would need double the amount of memory and as second in order to copy all the elements from multiple dimension into one you would probably have to iterate through every element in the first place. And then whatever method would you use for calculating average value would also have to iterate through all those copied elements again and thus just slowing down the process for no good reason.
And if you are interested in replacing multidimensional arrays with one dimensional arrays while still threating its elements as if they are in multidimensional array check my explanation of how some other programming languages treat multidimensional array.
NOTE that this would require you accessing all items of such arrays through special methods and will thus result in large changes of your code where you interact with these arrays. Unless if you would wrap these arrays in a class with default multi indexed property that will allow you accessing the array items. Such approach would require additional code for initialization and finalization of such classes and require a slightly modified approach when resizing of such arrays.
Delphi does not provide easy ways for you to inspect the dimensions of an arbitrary dynamic array. Indeed it provides no means for you to pass around an arbitrary dynamic array. However, in practice, you will encounter one and two dimensional arrays commonly, and seldom anything of higher dimensions. So you need to write only a handful of functions:
type
TDoubleArray1 = array of Double;
TDoubleArray2 = array of TDoubleArray1;
TDoubleArray3 = array of TDoubleArray2;
function Mean(const arr: TDoubleArray1): Double; overload;
function Mean(const arr: TDoubleArray2): Double; overload;
function Mean(const arr: TDoubleArray3): Double; overload;
Implement like this:
function Mean(const arr: TDoubleArray1): Double;
var
i: Integer;
begin
Result := 0.0;
for i := low(arr) to high(arr) do
Result := Result + arr[i];
Result := Result / Length(arr);
end;
function Mean(const arr: TDoubleArray2): Double;
var
i, j, N: Integer;
begin
Result := 0.0;
N := 0;
for i := low(arr) to high(arr) do
for j := low(arr[i]) to high(arr[i]) do
begin
Result := Result + arr[i,j];
inc(N);
end;
Result := Result / N;
end;
function Mean(const arr: TDoubleArray3): Double;
var
i, j, k, N: Integer;
begin
Result := 0.0;
N := 0;
for i := low(arr) to high(arr) do
for j := low(arr[i]) to high(arr[i]) do
for k := low(arr[i,j]) to high(arr[i,j]) do
begin
Result := Result + arr[i,j,k];
inc(N);
end;
Result := Result / N;
end;
It would astound me if you really needed higher dimensions than this, but it is easy to add.
Some points:
I'm using Double rather than Extended for reasons of performance, as the latter has a size of 10 which leads to a lot of mis-aligned memory access. If you cannot bring yourself to avoid Extended you can readily adapt the code above.
You could probably find low-level methods using RTTI to write a single function that iterates over any dynamic array, however, the RTTI would likely impact performance. I personally don't see any point in going that route. Use a handful of functions like this and be done.

F# how to fill array with for loop

How do you fill an array with a for loop?
I'm trying to do this, but I need to fill my array at declaration. Or Am I just wrong?
I need to do this with a 2 dimensional array, it's not necessary, just 2 arrays is also fine
Don't use a for loop. You can use Array.init or Array.zeroCreate if you want to fill it with the default value.
For 2d arrays the same functions are available in the module Array2D, here's an example:
let x: int [,] = Array2D.zeroCreate 2 6
It creates and initialise an array of 2x6 with 0.
Filling your array at the declaration is actually a good practice, that's why this way is better than using for loops.

Extracting a block out of a multidimensional matrix

Consider the multi-dimensional matrix A where size(A) has the identical even elements N. How should one find the matrix B with size(B)=size(A)/2 such that:
B(1,1,...,1)=A(1,1,...,1),
B(1,1,...,2)=A(1,1,...,2),
...
B(N/2,N/2,...,N/2)=A(N/2,N/2,...,N/2).
I generally don't like arrayfun (or loopy functions), but if the number of dimensions is not in the thousands, then this should be just fine:
Nv = size(A)/2;
S = arrayfun(#(x){1:x},Nv);
B = A(S{:});
Should work with different sized dimensions too. Just decide how you want to deal with dimensions where mod(size(A),2)~=0.

Resources