element address in 3 dimensional array - arrays

I am looking for the formulas to find the memory location of an element in a 3-D Array for row major and for column major. After using my logic I end up with the following formulas.
say array is A[L][M][N].
row-major:Loc(A[i][j][k])=base+w(M*N(i-x)+N*(j-y)+(k-z))
column-major:Loc(A[i][j][k])=base+w(M*n(i-x)+M*(k-z)+(j-y))
where x, y, z are lower bounds of 1st(L) 2nd(M) and 3rd(N) index.
I tried this formula and got the correct result but when I applied this formula on a Question in the book then the answer did not match. Please can anyone help me out with this.

Formula for 3D Array
Row Major Order:
Address of
A[I, J, K] = B + W * [(D - Do)*RC + (I - Ro)*C + (J - Co)]
Column Major Order:
Address of
A[I, J, K] = B + W * [(D - Do)*RC + (I - Ro) + (J - Co)*R]
Where:
B = Base Address (start address)
W = Weight (storage size of one element stored in the array)
R = Row (total number of rows)
C = Column (total number of columns)
D = Width (total number of cells depth-wise)
Ro = Lower Bound of Row
Co = Lower Bound of Column
Do = Lower Bound of Width

Right one is:
row-major:Loc(A[i][j][k])=base+w(N*(i-x)+(j-y)+M*N(k-z))
column-major:Loc(A[i][j][k])=base+w((i-x)+M*N(k-z)+M*(j-y))

Thanks! #Vinay Yadav for your comment. As suggested by Vinay please visit the link to understand this in great detail: https://eli.thegreenplace.net/2015/memory-layout-of-multi-dimensional-arrays.
Keep this in mind and you never get it wrong:
Row Major: Lexicographical Order
Column Major: Co-lexicographical Order
If you don't know what Co-lexicographical and Lexicographical are: Check out this Wikipedia page for more. Let me highlight important part for you, do give it a read:
The words in a lexicon (the set of words used in some language) have a
conventional ordering, used in dictionaries and encyclopedias, that
depends on the underlying ordering of the alphabet of symbols used to
build the words. The lexicographical order is one way of formalizing
word order given the order of the underlying symbols.
The formal notion starts with a finite set A, often called the
alphabet, which is totally ordered. That is, for any two symbols a and
b in A that are not the same symbol, either a < b or b < a.
The words of A are the finite sequences of symbols from A, including
words of length 1 containing a single symbol, words of length 2 with 2
symbols, and so on, even including the empty sequence varepsilon with no symbols
at all. The lexicographical
order on the set of all these finite words orders the words as
follows:
Given two different words of the same length, say a = a1a2...ak and b
= b1b2...bk, the order of the two words depends on the alphabetic order of the symbols in the first place i where the two words differ
(counting from the beginning of the words): a < b if and only if ai <
bi in the underlying order of the alphabet A. If two words have
different lengths, the usual lexicographical order pads the shorter
one with "blanks" (a special symbol that is treated as smaller than
every element of A) at the end until the words are the same length,
and then the words are compared as in the previous case.
After this you can learn about Co-Lexicographical Order from the same Wikipedia page mentioned above. Above quoted part is taken directly from the Motivation and Definition titled part of the Wikipedia page mentioned above. Visit it once and you will have a better understanding of both.
You just need to find the Lexicographical and Co-Lexicographical position of (i, j, k) among all possible (foo1, foo2, foo3) in the array A of yours:
foo1 -> L possibilities: [Lower Bound x, Upper Bound x + L - 1]
foo2 -> M possibilities: [Lower Bound y, Upper Bound y + M - 1]
foo3 -> N possibilities: [Lower Bound z, Upper Bound z + N - 1]
Based on the this knowledge, you will get that:
1). Number of elements A[foo1][foo2][foo3] (foo1, foo2, foo3) present before element A[i][j][k] (i, j, k) in Row Major Order or Lexicographical Order are:
[ (i - x)*M*N + (j - y)*N + (k - z) ]
2). Number of elements A[foo1][foo2][foo3] (foo1, foo2, foo3) present before element A[i][j][k] (i, j, k) in Column Major Order or Co-lexicographical Order are:
[ (i - x) + (j - y)*L + (k - z)*L*M ]
Now, you can do the rest of your calculation where you bring in your base and W thing to get the final answer you need.

Related

Maximize number of inversion count in array

We are given an unsorted array A of integers (duplicates allowed) with size N possibly large. We can count the number of pairs with indices i < j, for which A[i] < A[j], let's call this X.
We can change maximum one element from the array with a cost equal to the difference in absolute values (for instance, if we replace element on index k with the new number K, the cost Y is | A[k] - K |).
We can only replace this element with other elements found in the array.
We want to find the minimum possible value of X + Y.
Some examples:
[1,2,2] should return 1 (change the 1 to 2 such that the array becomes [2,2,2])
[2,2,3] should return 1 (change the 3 to 2)
[2,1,1] should return 0 (because no changes are necessary)
[1,2,3,4] should return 6 (this is already the minimum possible value)
[4,4,5,5] should return 3 (this can accomplished by changing the first 4 into a 5 or the last 5 in a 4)
The number of pairs can be found with a naive O(n²) solution, here in Python:
def calc_x(arr):
n = len(arr)
cnt = 0
for i in range(n):
for j in range(i+1, n):
if arr[j] > arr[i]:
cnt += 1
return cnt
A brute-force solution is easily written as for example:
def f(arr):
best_val = calc_x(arr)
used = set(arr)
for i, v in enumerate(arr):
for replacement in used:
if replacement == v:
continue
arr2 = arr[0:i] + replacement + arr[i:]
y = abs(replacement - v)
x = calc_x(arr2)
best_val = min(best_val, x + y)
return best_val
We can count for each element the number of items right of it larger than itself in O(n*log(n)) using for instance an AVL-tree or some variation on merge sort.
However, we still have to search which element to change and what improvement it can achieve.
This was given as an interview question and I would like some hints or insights as how to solve this problem efficiently (data structures or algorithm).
Definitely go for a O(n log n) complexity when counting inversions.
We can see that when you change a value at index k, you can either:
1) increase it, and then possibly reduce the number of inversions with elements bigger than k, but increase the number of inversions with elements smaller than k
2) decrease it (the opposite thing happens)
Let's try not to count x every time you change a value. What do you need to know?
In case 1):
You have to know how many elements on the left are smaller than your new value v and how many elements on the right are bigger than your value. You can pretty easily check that in O (n). So what is your x now? You can count it with the following formula:
prev_val - your previous value
prev_x - x that you've counted at the beginning of your program
prev_l - number of elements on the left smaller than prev_val
prev_r - number of elements on the right bigger than prev_val
v - new value
l - number of elements on the right smaller than v
r - number of elements on the right bigger than v
new_x = prev_x + r + l - prev_l - prev_r
In the second case you pretty much do the opposite thing.
Right now you get something like O( n^3 ) instead of O (n^3 log n), which is probably still bad. Unfortunately that's all what I came up for now. I'll definitely tell you if I come up with sth better.
EDIT: What about memory limit? Is there any? If not, you can just for each element in the array make two sets with elements before and after the current one. Then you can find the amount of smaller/bigger in O (log n), making your time complexity O (n^2 log n).
EDIT 2: We can also try to check, what element would be the best to change to a value v, for every possible value v. You can make then two sets and add/erase elements from them while checking for every element, making the time complexity O(n^2 log n) without using too much space. So the algorithm would be:
1) determine every value v that you can change any element, calculate x
2) for each possible value v:
make two sets, push all elements into the second one
for each element e in array:
add previous element (if there's any) to the first set and erase element e from the second set, then count number of bigger/smaller elements in set 1 and 2 and calculate new x
EDIT 3: Instead of making two sets, you could go with prefix sum for a value. That's O (n^2) already, but I think we can go even better than this.

Trimming vals in a matrix of arbitrary dimensions in a specified dimension

I'm writing a function that requires some values in a matrix of arbitrary dimansions to be dropped in a specified dimension.
For example, say I have a 3x3 matrix:
a=[1,2,3;4,5,6;7,8,9];
I might want to drop the third element in each row, in which case I could do
a = a(:,1:2)
But what if the dimensions of a are arbitrary, and the dimension to trim is defined as an argument in the function?
Using linear indexing, and some carefully considered maths is an option but I was wondering if there is a neater soltion?
For those interested, this is my current code:
...
% Find length in each dimension
sz = size(dat);
% Get the proportion to trim in each dimension
k = sz(d)*abs(p);
% Get the decimal part and integer parts of k
int_part = fix(k);
dec_part = abs(k - int_part);
% Sort the array
dat = sort(dat,d);
% Trim the array in dimension d
if (int_part ~=0)
switch d
case 1
dat = dat(int_part + 1 : sz(1) - int_part,:);
case 2
dat = dat(:,int_part + 1 : sz(2) - int_part);
end
end
...
It doesn't get any neater than this:
function A = trim(A, n, d)
%// Remove n-th slice of A in dimension d
%// n can be vector of indices. d needs to be scalar
sub = repmat({':'}, 1, ndims(A));
sub{d} = n;
A(sub{:}) = [];
This makes use of the not very well known fact that the string ':' can be used as an index. With due credit to this answer by #AndrewJanke, and to #chappjc for bringing it to my attention.
a = a(:, 1:end-1)
end, used as a matrix index, always refers to the index of the last element of that matrix
if you want to trim different dimensions, the simplest way is using and if/else block - as MatLab only supports 7 dimensions at most, you wont need an infinite number of these to cover all bases
The permute function allows to permute the dimension of an array of any dimension.
You can place the dimension you want to trim in a prescribed position (the first, I guess), trim, and finally restore the original ordering. In this way you can avoid running loops and do what you want compactly.

Is it always possible to order a multi-dimensional array in all dimensions? How?

Suppose, I have an n-dimensional array of integers (for n=1 it's a vector, for n=2 it's a rectangular matrix, for n=3 it's a parallelepiped, etc). I need to reorder elements of the array so that elements in each row, column, etc are in a non-decreasing order.
Is it possible for any input array?
Is the required ordering unique for any input array? I just realized that the answer for this question in general is no, e.g. for square matrices.
Is the required ordering unique for any input array that has different lengths in all dimensions?
What is the fastest algorithm to produce the required ordering?
Is it possible for any input array?
Yes, if we will look on the array as a single dimension array, with the same number of elements, and then sort it, by traversing it back to the original n-dimensions array, it remains sorted, since for each i1,....,i_k,...,i_m: for all i_k < i_k':
i_1 + n1*i_2 + n2^2*i_3 + .... (n_k-1)^(k-1)(i_k) + ... < i_1 + n1*i_2 + n2^2*i_3 + .... (n_k-1)^(k-1)(i_k') + ...
Thus (the array is ordered):
arr[i_1 + n1*i_2 + n2^2*i_3 + .... (n_k-1)^(k-1)(i_k) + ...] < arr[ i_1 + n1*i_2 + n2^2*i_3 + .... (n_k-1)^(k-1)(i_k') + ...]
Thus (back to original array):
arr[i_1][i_2]...[i_k]... < arr[i_1][i_2]...[i_k']...
As for the 2nd question:
Is the required ordering unique for any input array that has different
lengths in all dimensions?
No:
1 1 1 3
3 4 1 4
5 6 5 6
What is the fastest algorithm to produce the required ordering?
One solution is suggested already: regard it is a big long array and sort it.
Complexity is O(n_1*n_2*...*n_m*log(n_1*n_2*...*n_m))
My gut says if you could do it faster, you could sory faster then O(nlogn), but I have no proof for this claim, so it might be wrong.
Let me elaborate more about Alptigin Jalayr's idea.
Suppose we have rows sorted, so for the following data, we have a <= b and c <= d.
. .
..., a, ..., b, ...
. .
..., c, ..., d, ...
. .
When a is greater than c, i.e. c <a, then swap of them gives us c < b since a <= b, and a <=d since b <= d (if b > d, we swap b and d as well). In a word, sorting rows first and then columns next can give you the desired matrix.

How to use sets of numbers as array indices?

I want to implement the Travelling Salesman Problem (Dynamic Programming) in C. I have the following pseudocode:
** Ignoring the base cases**
** C[i][j] is cost of the edge from i to j**
for m = 2,3,4..n:
for each set S of size m which is subset of {1,2,3...n}:
for each J in S, j ≠ 1:
A[S][j] = min of { A[S-{j}][k] + C[k][j] } for all k is in S and k ≠ j:
return min of { A[{1,2,3...n},j] + C[j][1] } for all j from 2 to n
A[S][j] stores the shortest path from 1 to j which visits all vertices in S exactly once. (S includes 1 and j).
The time complexity is O(n22n).
My problem is that in this pseudocode they have used sets as array indices and the time complexity indicates that the lookup for a set without an element j (S - {j}) takes constant time.
What I have thought of is using a 3D array indexed by m,i and j. Where 'i' points to a set at stored in a different array of sets indexed by m,i.
But the problem is that I cannot do the lookup A[S-{j}[k]] in constant time.
My question is that how do I implement an array indexed by a 'set' without changing the time complexity of the original algorithm.
Let each path be represented by a binary string, where each bit represents whether or not a city is visited.
So
(123456)
011001
means city 2, 3 and 6 are visited.
You use the above as array index.
When you want to look-up the path without a city, just set that bit to 0 and use the output as index.
The first city will always be visited so you really don't need a bit for that city.

Why is the average number of steps for finding an item in an array N/2?

Could somebody explain why the average number of steps for finding an item in an unsorted array data-structure is N/2?
This really depends what you know about the numbers in the array. If they're all drawn from a distribution where all the probability mass is on a single value, then on expectation it will take you exactly 1 step to find the value you're looking for, since every value is the same, for example.
Let's now make a pretty strong assumption, that the array is filled with a random permutation of distinct values. You can think of this as picking some arbitrary sorted list of distinct elements and then randomly permuting it. In this case, suppose you're searching for some element in the array that actually exists (this proof breaks down if the element is not present). Then the number of steps you need to take is given by X, where X is the position of the element in the array. The average number of steps is then E[X], which is given by
E[X] = 1 Pr[X = 1] + 2 Pr[X = 2] + ... + n Pr[X = n]
Since we're assuming all the elements are drawn from a random permutation,
Pr[X = 1] = Pr[X = 2] = ... = Pr[X = n] = 1/n
So this expression is given by
E[X] = sum (i = 1 to n) i / n = (1 / n) sum (i = 1 to n) i = (1 / n) (n)(n + 1) / 2
= (n + 1) / 2
Which, I think, is the answer you're looking for.
The question as stated is just wrong. Linear search may perform better.
Perhaps a simpler example that shows why the average is N/2 is this:
Assume you have an unsorted array of 10 items: [5, 0, 9, 8, 1, 2, 7, 3, 4, 6]. This is all the digits [0..9].
Since the array is unsorted (i.e. you know nothing about the order of the items), the only way you can find a particular item in the array is by doing a linear search: start at the first item and go until you find what you're looking for, or you reach the end.
So let's count how many operations it takes to find each item. Finding the first item (5) takes only one operation. Finding the second item (0) takes two. Finding the last item (6) takes 10 operations. The total number of operations required to find all 10 items is 1+2+3+4+5+6+7+8+9+10, or 55. The average is 55/10, or 5.5.
The "linear search takes, on average, N/2 steps" conventional wisdom makes a number of assumptions. The two biggest are:
The item you're looking for is in the array. If an item isn't in the array, then it takes N steps to determine that. So if you're often looking for items that aren't there, then your average number of steps per search is going to be much higher than N/2.
On average, each item is searched for approximately as often as any other item. That is, you search for "6" as often as you search for "0", etc. If some items are looked up significantly more often than others, then the average number of steps per search is going to be skewed in favor of the items that are searched for more frequently. The number will be higher or lower than N/2, depending on the positions of the most frequently looked-up items.
While I think templatetypedef has the most instructive answer, in this case there is a much simpler one.
Consider permutations of the set {x1, x2, ..., xn} where n = 2m. Now take some element xi you wish to locate. For each permutation where xi occurs at index m - k, there is a corresponding mirror image permutation where xi occurs at index m + k. The mean of these possible indices is just [(m - k) + (m + k)]/2 = m = n/2. Therefore the mean of all all possible permutations of the set is n/2.
Consider a simple reformulation of the question:
What would be the limit of
lim (i->inf) of (sum(from 1 to i of random(n)) /i)
Or in C:
int sum = 0, i;
for (i = 0; i < LARGE_NUM; i++) sum += random(n);
sum /= LARGE_NUM;
If we assume that our random have even distribution of values (each value from 1 to n is equally likely to be produced), then the expected result would be (1+n)/2.

Resources