Related
I'm trying to solve MexDoubleSliceSum problem without Kandane's bidirectional algorithm.
Problem Definition:
A non-empty array A consisting of N integers is given.
A triplet (X, Y, Z), such that 0 ≤ X < Y < Z < N, is called a double
slice.
The sum of double slice (X, Y, Z) is the total of A[X + 1] + A[X + 2]
+ ... + A[Y − 1] + A[Y + 1] + A[Y + 2] + ... + A[Z − 1].
For example, array A such that:
A[0] = 3
A[1] = 2
A[2] = 6
A[3] = -1
A[4] = 4
A[5] = 5
A[6] = -1
A[7] = 2
The goal is to find the maximal sum of any double slice.
that, given a non-empty array A consisting of N integers, returns the
maximal sum of any double slice.
For example, given:
A[0] = 3
A[1] = 2
A[2] = 6
A[3] = -1
A[4] = 4
A[5] = 5
A[6] = -1
A[7] = 2
the function should return 17, because no double slice of array A has
a sum of greater than 17.
I have figured out following idea:
I'm taking a slice and putting lever (value in the middle that's being dropped) to lowest value included in this slice. If I notice that next value is lowering total sum i'm changing lever to it and reducing sum with values before last lever(including old lever).
int solution(vector<int> &A) {
if(A.size()<4)
return 0;
int lever=A[1];
int sum=-lever;
int presliceValue=0;
int maxVal=A[1];
for(int i=1;i<A.size()-1;i++){
if(sum+A[i]<sum || A[i]<lever){
sum+=lever;
if(presliceValue<0)
sum=sum-presliceValue;
lever=A[i];
presliceValue=sum+lever;
}
else
sum=sum+A[i];
if(sum>maxVal)
maxVal=sum;
}
return maxVal;
}
This solution returns wrong value on few test cases (unfortunately cannot tell what's tested values):
unfortunately i cannot reproduce following error and codility does not share test values.
Failed Test cases
many the same small sequences, length = ~100,000
large random: random, length = ~100,000
random, numbers from -30 to 30, length = 300
random, numbers form -104 to 104, length = 70
I just finished coding a C++ program to manage a 3D matrix with dynamically allocated memory.
In order to use a contiguous chunk of memory, I decided to use a mapping function to physically store the elements of my matrix to 1D array.
For this purpose, I have a T *_3D_matrix pointer to the array, which is defined as
_3D_matrix = new T[height * width * depth];
where height, width and depth are input parameters for the constructor.
The program works just fine, I even tested it with Valgrind and no memory problems happen.
What I don't get is: my array has got height * width * depth = 12 elements, and the mapping function seems to map some elements out of the [0..11] range.
What am I missing here?
EDIT:
This is the output I get from recreating the same matrix and printing it in my program.
Lets say we have a "3D" array defined as
some_type m[1][3][2];
That would look something like this if we draw it:
+------------+-------------+------------+-------------+------------+------------+
| m[0] |
+------------+-------------+------------+-------------+------------+------------+
| m[0][0] | m[0][1] | m[0][2] |
+------------+-------------+------------+-------------+------------+------------+
| m[0][0][0] | m[0][0][1] | m[0][1][0] | m[0][1][1] | m[0][2][0] | m[0][2][1] |
+------------+-------------+------------+-------------+------------+------------+
If x represents the first "dimension", y the second, and z the third, then an expressions such as m[x][y][z] would with a flat array be like m[x * 3 * 2 + y * 3 + z]. The number 3 is the number of elements in the second dimension, and 2 is the number of elements in the third dimension.
Generalized, an array like
some_type m[X][Y][Z];
would as a flat array have the formula x * Y * Z + y * Z + z for the index. Compared to your formula the x and the y have been switched.
You computed the mapped index for out-of-bounds values of y.
You said height * width * depth= 12, and:
index = y * width * depth + x * depth + z
And we see in your table:
#.| Y | X | Z | index
--+---+---+---+------
1 | 0 | 1 | 0 | 2
2 | 1 | 0 | 0 | 6
This implies:
0 * width * depth + 1 * depth + 0 = 2 => depth = 2
1 * width * depth + 0 * depth + 0 = 6 => width * depth + 6 => width = 3
height * width * depth= 12 => height = 2
Thus:
y is in [0, 1]
x is in [0, 2]
z is in [0, 1]
The maximum index is at {x, y, z} = {2, 1, 1} and its value is 1 * 2 * 3 + 2 * 2 + 1 = 11.
Assuming from your example:
width = 2, height = 3, and depth = 2
x is in [0, width), y is in [0, height), z is in [0, depth)
Mapping second element should be:
1*2*2 + 0*2 + 0 = 4, but you get 6. I think the reason is that some of the dimensions or indices are swapped somewhere else in your code. Seems that width or depth is 3 in your case.
I have these indexes:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,etc...
Which are indexes of nodes in a matrix (including diagonal elements):
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21
etc...
and I need to get i,j coordinates from these indexes:
1,1
2,1 2,2
3,1 3,2 3,3
4,1 4,2 4,3 4,4
5,1 5,2 5,3 5,4 5,5
6,1 6,2 6,3 6,4 6,5 6,6
etc...
When I need to calculate coordinates I have only one index and cannot access others.
Not optimized at all :
int j = idx;
int i = 1;
while(j > i) {
j -= i++;
}
Optimized :
int i = std::ceil(std::sqrt(2 * idx + 0.25) - 0.5);
int j = idx - (i-1) * i / 2;
And here is the demonstration:
You're looking for i such that :
sumRange(1, i-1) < idx && idx <= sumRange(1, i)
when sumRange(min, max) sum integers between min and max, both inxluded.
But since you know that :
sumRange(1, i) = i * (i + 1) / 2
Then you have :
idx <= i * (i+1) / 2
=> 2 * idx <= i * (i+1)
=> 2 * idx <= i² + i + 1/4 - 1/4
=> 2 * idx + 1/4 <= (i + 1/2)²
=> sqrt(2 * idx + 1/4) - 1/2 <= i
In my case (a CUDA kernel implemented in standard C), I use zero-based indexing (and I want to exclude the diagonal) so I needed to make a few adjustments:
// idx is still one-based
unsigned long int idx = blockIdx.x * blockDim.x + threadIdx.x + 1; // CUDA kernel launch parameters
// but the coordinates are now zero-based
unsigned long int x = ceil(sqrt((2.0 * idx) + 0.25) - 0.5);
unsigned long int y = idx - (x - 1) * x / 2 - 1;
Which results in:
[0]: (1, 0)
[1]: (2, 0)
[2]: (2, 1)
[3]: (3, 0)
[4]: (3, 1)
[5]: (3, 2)
I also re-derived the formula of Flórez-Rueda y Moreno 2001 and arrived at:
unsigned long int x = floor(sqrt(2.0 * pos + 0.25) + 0.5);
CUDA Note: I tried everything I could think of to avoid using double-precision math, but the single-precision sqrt function in CUDA is simply not precise enough to convert positions greater than 121 million or so to x, y coordinates (when using 1,024 threads per block and indexing only along 1 block dimension). Some articles have employed a "correction" to bump the result in a particular direction, but this inevitably falls apart at a certain point.
If I have the upper triangular portion of a matrix, offset above the diagonal, stored as a linear array, how can the (i,j) indices of a matrix element be extracted from the linear index of the array?
For example, the linear array [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 is storage for the matrix
0 a0 a1 a2 a3
0 0 a4 a5 a6
0 0 0 a7 a8
0 0 0 0 a9
0 0 0 0 0
And we want to know the (i,j) index in the array corresponding to an offset in the linear matrix, without recursion.
A suitable result, k2ij(int k, int n) -> (int, int) would satisfy, for example
k2ij(k=0, n=5) = (0, 1)
k2ij(k=1, n=5) = (0, 2)
k2ij(k=2, n=5) = (0, 3)
k2ij(k=3, n=5) = (0, 4)
k2ij(k=4, n=5) = (1, 2)
k2ij(k=5, n=5) = (1, 3)
[etc]
The equations going from linear index to (i,j) index are
i = n - 2 - floor(sqrt(-8*k + 4*n*(n-1)-7)/2.0 - 0.5)
j = k + i + 1 - n*(n-1)/2 + (n-i)*((n-i)-1)/2
The inverse operation, from (i,j) index to linear index is
k = (n*(n-1)/2) - (n-i)*((n-i)-1)/2 + j - i - 1
Verify in Python with:
from numpy import triu_indices, sqrt
n = 10
for k in range(n*(n-1)/2):
i = n - 2 - int(sqrt(-8*k + 4*n*(n-1)-7)/2.0 - 0.5)
j = k + i + 1 - n*(n-1)/2 + (n-i)*((n-i)-1)/2
assert np.triu_indices(n, k=1)[0][k] == i
assert np.triu_indices(n, k=1)[1][k] == j
for i in range(n):
for j in range(i+1, n):
k = (n*(n-1)/2) - (n-i)*((n-i)-1)/2 + j - i - 1
assert triu_indices(n, k=1)[0][k] == i
assert triu_indices(n, k=1)[1][k] == j
First, let's renumber a[k] in opposite order. We'll get:
0 a9 a8 a7 a6
0 0 a5 a4 a3
0 0 0 a2 a1
0 0 0 0 a0
0 0 0 0 0
Then k2ij(k, n) will become k2ij(n - k, n).
Now, the question is, how to calculate k2ij(k, n) in this new matrix. The sequence 0, 2, 5, 9 (indices of diagonal elements) corresponds to triangular numbers (after subtracting 1): a[n - i, n + 1 - i] = Ti - 1. Ti = i * (i + 1)/2, so if we know Ti, it's easy to solve this equation and get i (see formula in the linked wiki article, section "Triangular roots and tests for triangular numbers"). If k + 1 is not exactly a triangular number, the formula will still give you the useful result: after rounding it down, you'll get the highest value of i, for which Ti <= k, this value of i corresponds to the row index (counting from bottom), in which a[k] is located. To get the column (counting from right), you should simply calculate the value of Ti and subtract it: j = k + 1 - Ti. To be clear, these are not exacly i and j from your problem, you need to "flip" them.
I didn't write the exact formula, but I hope that you got the idea, and it will now be trivial to find it after performing some boring but simple calculations.
The following is an implimentation in matlab, which can be easily transferred to another language, like C++. Here, we suppose the matrix has size m*m, ind is the index in the linear array. The only thing different is that here, we count the lower triangular part of the matrix column by column, which is analogus to your case (counting the upper triangular part row by row).
function z= ind2lTra (ind, m)
rvLinear = (m*(m-1))/2-ind;
k = floor( (sqrt(1+8*rvLinear)-1)/2 );
j= rvLinear - k*(k+1)/2;
z=[m-j, m-(k+1)];
For the records, this is the same function, but with one-based indexing, and in Julia:
function iuppert(k::Integer,n::Integer)
i = n - 1 - floor(Int,sqrt(-8*k + 4*n*(n-1) + 1)/2 - 0.5)
j = k + i + ( (n-i+1)*(n-i) - n*(n-1) )÷2
return i, j
end
Here is a more efficient formulation for k:
k = (2 * n - 3 - i) * i / 2 + j - 1
In python 2:
def k2ij(k, n):
rows = 0
for t, cols in enumerate(xrange(n - 1, -1, -1)):
rows += cols
if k in xrange(rows):
return (t, n - (rows - k))
return None
In python, the most efficient way is:
array_size= 3
# make indices using k argument if you want above the diagonal
u, v = np.triu_indices(n=array_size,k=1)
# assuming linear indices above the diagonal i.e. 0 means (0,1) and not (0,0)
linear_indices = [0,1]
ijs = [(i,j) for (i,j) in zip(u[linear_indices], v[linear_indices])]
ijs
#[(0, 1), (0, 2)]
I have a big matrix as input, and I have the size of a smaller matrix. I have to compute the sum of all possible smaller matrices which can be formed out of the bigger matrix.
Example.
Input matrix size: 4 × 4
Matrix:
1 2 3 4
5 6 7 8
9 9 0 0
0 0 9 9
Input smaller matrix size: 3 × 3 (not necessarily a square)
Smaller matrices possible:
1 2 3
5 6 7
9 9 0
5 6 7
9 9 0
0 0 9
2 3 4
6 7 8
9 0 0
6 7 8
9 0 0
0 9 9
Their sum, final output
14 18 22
29 22 15
18 18 18
I did this:
int** matrix_sum(int **M, int n, int r, int c)
{
int **res = new int*[r];
for(int i=0 ; i<r ; i++) {
res[i] = new int[c];
memset(res[i], 0, sizeof(int)*c);
}
for(int i=0 ; i<=n-r ; i++)
for(int j=0 ; j<=n-c ; j++)
for(int k=i ; k<i+r ; k++)
for(int l=j ; l<j+c ; l++)
res[k-i][l-j] += M[k][l];
return res;
}
I guess this is too slow, can anyone please suggest a faster way?
Your current algorithm is O((m - p) * (n - q) * p * q). The worst case is when p = m / 2 and q = n / 2.
The algorithm I'm going to describe will be O(m * n + p * q), which will be O(m * n) regardless of p and q.
The algorithm consists of 2 steps.
Let the input matrix A's size be m x n and the size of the window matrix being p x q.
First, you will create a precomputed matrix B of the same size as the input matrix. Each element of the precomputed matrix B contains the sum of all the elements in the sub-matrix, whose top-left element is at coordinate (1, 1) of the original matrix, and the bottom-right element is at the same coordinate as the element that we are computing.
B[i, j] = Sum[k = 1..i, l = 1..j]( A[k, l] ) for all 1 <= i <= m, 1 <= j <= n
This can be done in O(m * n), by using this relation to compute each element in O(1):
B[i, j] = B[i - 1, j] + Sum[k = 1..j-1]( A[i, k] ) + A[j] for all 2 <= i <= m, 1 <= j <= n
B[i - 1, j], which is everything of the sub-matrix we are computing except the current row, has been computed previously. You keep a prefix sum of the current row, so that you can use it to quickly compute the sum of the current row.
This is another way to compute B[i, j] in O(1), using the property of the 2D prefix sum:
B[i, j] = B[i - 1, j] + B[i, j - 1] - B[i - 1, j - 1] + A[j] for all 1 <= i <= m, 1 <= j <= n and invalid entry = 0
Then, the second step is to compute the result matrix S whose size is p x q. If you make some observation, S[i, j] is the sum of all elements in the matrix size (m - p + 1) * (n - q + 1), whose top-left coordinate is (i, j) and bottom-right is (i + m - p + 1, j + n - q + 1).
Using the precomputed matrix B, you can compute the sum of any sub-matrix in O(1). Apply this to compute the result matrix S:
SubMatrixSum(top-left = (x1, y1), bottom-right = (x2, y2))
= B[x2, y2] - B[x1 - 1, y2] - B[x2, y1 - 1] + B[x1 - 1, y1 - 1]
Therefore, the complexity of the second step will be O(p * q).
The final complexity is as mentioned above, O(m * n), since p <= m and q <= n.