Get minimum element in constant time - c++

Lets say I have an array A of size n, where 0 <= A[i] <= n.
Lets say I have 2 arrays Forward and Backward, size n, where:
Forward[i] = index j where
A[j] = min(A[i], A[i+1], ..., A[n-1])
and
Backward[i] = index j where
A[j] = min(A[i], A[i-1], ..., A[0])
My question is:
given A, Forward and Backward
given 2 indexes l and r
Can I discover the index k such that A[k] = min(A[l], A[l+1], ..., A[r]) in constant time?

No. Atleast not in O(1) time. A counter example is as follows. 0-based indexing is used here. Let
index = {0, 1, 2, 3, 4, 5, 6, 7, 8}
A = {1, 3, 5, 7, 9, 6, 4, 2, 0}
Forward = {8, 8, 8, 8, 8, 8, 8, 8, 8}
Backward = {0, 0, 0, 0, 0, 0, 0, 0, 8}
Now, if I ask you to get the index of the minimum value in range [3, 7], how will you do it?
Basically they will be of no use to find in the range [a, b]
if forward[a] > b and backward[b] < a.

No you cant. A counter example is:
A = {0, 4, 3, 2, 3, 4, 0}
Forward = {6, 6, 6, 6, 6, 6, 6}
Backward = {0, 0, 0, 0, 0, 0, 0}
l = 1, k = 5
ie Forward and Backward are of no use in that case and you have to search the array which is O(k-l).

Related

Question about Eigen::MatrixXd column-wise calculation

Is there anyway to apply the column-wise calculation as follows?
(each column divided by the last entry of the column)
Eigen::MatrixXd A(3,5), B(3,5);
A << 1, 4, 9, 16, 25,
2, 4, 6, 8, 10,
1, 2, 3, 4, 5;
B = (A.col) / (A.bottomerows<1>).col;
and B would be:
B = 1, 2, 3, 4, 5,
2, 2, 2, 2, 2,
1, 1, 1, 1, 1;
The functions you are looking for are .hnormalized() and .homogeneous(). Both can be applied .colwise() like this:
Eigen::MatrixXd B = A.colwise().hnormalized().colwise().homogeneous();
You can achieve the same with some .replicate() magic like this:
Eigen::MatrixXd B = A.array() / A.row(2).replicate(A.rows(),1).array();
(if A was an ArrayXXd, instead of a MatrixXd, you don't need to write the .array())

Manipulating Tables (or lists) in Mathematcia

For scientific purposes (code research) I am using Mathematica to enumerate all periodic sequences of some linear recurrences. As an example the command
Table[{Mod[i * 2^n + j * 4^n + k * 6^n, 7] },{i, 0, 5}, {j, 0, 5}, {k, 0, 5}, {n, 0, 5}]
allows to enumerate all 216 distinct periodic sequences of linear recurrent sequences in a finite field of order 7 (or mod 7) with characteristic polynomial whose roots are 2,4 and 6. The first five sequences it produces are:
{0, 0, 0, 0, 0, 0}, {1, 6, 1, 6, 1, 6}, {2, 5, 2, 5, 2, 5}, {3, 4, 3, 4, 3, 4}, {4, 3, 4, 3, 4, 3}, …
I have two questions:
i) The first sequence is obtained when i=0,j=0,k=0; the second when i=0,j=0,k=1, the third when i=0,j=0,k=2, etc. Is there a way to join these numbers with the sequence they generate so that I will get to know these parameters and therefore to be able to, later (if needed), generate a particular sequence? That is I would like that the output would be something like this
{{0, 0, 0, 0, 0, 0}, {0, 0, 0}}, {{1, 6, 1, 6, 1, 6}, {0, 0, 1}}, {{2, 5, 2, 5, 2, 5}, {0, 0, 2}} , etc.
ii) In the example above (3rd order linear recurrence, and mod 7) the number of sequences obtained (216) is manageable by hand; but this number grows very quickly when the linear recurrence has order higher than 3 and the field has characteristic higher than 7. And, in those cases, most of the sequences that are produced are of no interest to me. I think that I could throw away at least 99% of the sequences that do not interest me if I could add an instruction that would read the output (the sequences obtained) and would say “I only want the sequences such that the products of its elements is 216 (say)”: from the five sequences above only {1, 6, 1, 6, 1, 6} would remain because 1x6x1x6x1x6=216$; or “I only want the sequences such that the products of its elements is 216 or 1000 (say)” from the five sequences above {1, 6, 1, 6, 1, 6} and {2, 5, 2, 5, 2, 5} would remain because 1x6x1x6x1x6 = 216 and 2x5x2x5x2x 5=1000.
Is it possible to do this? I tried some list and tables manipulation, but had no success.
Thank you in advance.
here is the first part..
Flatten[Table[{Table[Mod[i*2^n + j*4^n + k*6^n, 7], {n, 0, 5}], {i, j,
k}}, {i, 0, 5}, {j, 0, 5}, {k, 0, 5}], 2]
{{{0, 0, 0, 0, 0, 0}, {0, 0, 0}}, {{1, 6, 1, 6, 1, 6}, {0, 0,
1}}, {{2, 5, 2, 5, 2, 5}, {0, 0, 2}}, {{3, 4, 3, 4, 3, 4}, {0, 0,
3}},...
better way:
{Table[Mod[#.{2, 4, 6}^n, 7], {n, 0, 5}],#} & /# Tuples[Range[0, 5], {3}]
example finding cases with a specified product:
Reap[Do[
s = Table[Mod[i*2^n + j*4^n + k*6^n, 7], {n, 0, 5}];
If[Times ## s == 81, Sow[{s, {i, j, k}}]],
{i, 0, 5}, {j, 0, 5}, {k, 0, 5}]][[2, 1]]
{{{3, 3, 1, 3, 3, 1}, {1, 2, 0}}, {{3, 1, 3, 3, 1, 3}, {2, 1,
0}}, {{1, 3, 3, 1, 3, 3}, {4, 4, 0}}}

Max subarray with start and end index

I'm trying to find the maximum contiguous subarray with start and end index. The method I've adopted is divide-and-conquer, with O(nlogn) time complexity.
I have tested with several test cases, and the start and end index always work correctly. However, I found that if the array contains an odd-numbered of elements, the maximum sum is sometimes correct, sometimes incorrect(seemingly random). But for even cases, it is always correct. Here is my code:
int maxSubSeq(int A[], int n, int &s, int &e)
{
// s and e stands for start and end index respectively,
// and both are passed by reference
if(n == 1){
return A[0];
}
int sum = 0;
int midIndex = n / 2;
int maxLeftIndex = midIndex - 1;
int maxRightIndex = midIndex;
int leftMaxSubSeq = A[maxLeftIndex];
int rightMaxSubSeq = A[maxRightIndex];
int left = maxSubSeq(A, midIndex, s, e);
int right = maxSubSeq(A + midIndex, n - midIndex, s, e);
for(int i = midIndex - 1; i >= 0; i--){
sum += A[i];
if(sum > leftMaxSubSeq){
leftMaxSubSeq = sum;
s = i;
}
}
sum = 0;
for(int i = midIndex; i < n; i++){
sum += A[i];
if(sum > rightMaxSubSeq){
rightMaxSubSeq = sum;
e = i;
}
}
return max(max(leftMaxSubSeq + rightMaxSubSeq, left),right);
}
Below is two of the test cases I was working with, one has odd-numbered elements, one has even-numbered elements.
Array with 11 elements:
1, 3, -7, 9, 6, 3, -2, 4, -1, -9,
2,
Array with 20 elements:
1, 3, 2, -2, 4, 5, -9, -4, -8, 6,
5, 9, 7, -1, 5, -2, 6, 4, -3, -1,
Edit: The following are the 2 kinds of outputs:
// TEST 1
Test file : T2-Data-1.txt
Array with 11 elements:
1, 3, -7, 9, 6, 3, -2, 4, -1, -9,
2,
maxSubSeq : A[3..7] = 32769 // Index is correct, but sum should be 20
Test file : T2-Data-2.txt
Array with 20 elements:
1, 3, 2, -2, 4, 5, -9, -4, -8, 6,
5, 9, 7, -1, 5, -2, 6, 4, -3, -1,
maxSubSeq : A[9..17] = 39 // correct
// TEST 2
Test file : T2-Data-1.txt
Array with 11 elements:
1, 3, -7, 9, 6, 3, -2, 4, -1, -9,
2,
maxSubSeq : A[3..7] = 20
Test file : T2-Data-2.txt
Array with 20 elements:
1, 3, 2, -2, 4, 5, -9, -4, -8, 6,
5, 9, 7, -1, 5, -2, 6, 4, -3, -1,
maxSubSeq : A[9..17] = 39
Can anyone point out why this is occurring? Thanks in advance!
Assuming that n is the correct size of your array (we see it being passed in as a parameter and later used to initialize midIndexbut we do not see its actual invocation and so must assume you're doing it correctly), the issue lies here:
int midIndex = n / 2;
In the case that your array has an odd number of elements, which we can represented as
n = 2k + 1
we can find that your middle index will always equate to
(2k + 1) / 2 = k + (1/2)
which means that for every integer, k, you'll always have half of an integer number added to k.
C++ doesn't round integers that receive floating-point numbers; it truncates. So while you'd expect k + 0.5 to round to k+1, you actually get k after truncation.
This means that, for example, when your array size is 11, midIndex is defined to be 5. Therefore, you need to adjust your code accordingly.

How to add sum of rows of a matrix into vector?

Since the question would be a bit long, ill add that here, I also want to add a row in a vector to the Finald vector.
MatrixXf ProdA(7, 7);;
VectorXf Intd(7);
VectorXf Finald(7);
ProdA <<
7, 5, 1, 9, 11, 2, 0,
5, 2, 8, 3, 11, 3, 3,
3, 9, 0, 1, 3, 1, 7,
6, 0, 1, 9, 11, 33, 3,
3, 5, 3, 3, 4, 3, 3,
3, 9, 1, 1, 0, 1, 15,
6, 2, 6, 2, 5, 12, 3,
Intd << 4, 5, 2, 12, 4, 1, 6;
Finald << 0, 0, 0, 0, 0, 0, 0;
for (int i = 0; i < 7; i++){
Finald.row(i) += ProdA.rowwise().sum();
Finald.row(i) += Intd.row(i);
}
So far this is what I have got. Obviously I get an error if I put i in rowwise. So as an example, I want to add the first row of ProdA , and the first number of Intd into the first space in the Finald vector, and then loop through every row of ProdA and Intd, and sum them all into Finald.
Thanks in advance!
I'm not 100% certain that I correctly understand your problem, but the way I understood it, this should work:
VectorXf ones(7);
ones << 1, 1, 1, 1, 1, 1, 1;
Finald = ProdA * ones + Intd;
I'm not sure if your matrix library (which seems to be Eigen) stores vectors as row or column vectors. So you might have to use ones.transpose() instead.

Trying to simulate python combinations in C++ with next_permutation

I need to port a snippet written in Python to C++
but that snippet is using combinations from itertools in python.
The line that I'm really interested to porting over to C++ is this one:
for k in combinations(range(n-i),2*i):
range(n-i) in Python will generate a list from 0 to (n-i) - 1
Let n = 16, i = 5
print range(n-i)
outputs:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
and python combinations will generate all possible combinations in that list.
e.g.
print list(combinations(range(n-i),2*i))
outputs:
[(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
(0, 1, 2, 3, 4, 5, 6, 7, 8, 10),
(0, 1, 2, 3, 4, 5, 6, 7, 9, 10),
(0, 1, 2, 3, 4, 5, 6, 8, 9, 10),
(0, 1, 2, 3, 4, 5, 7, 8, 9, 10),
(0, 1, 2, 3, 4, 6, 7, 8, 9, 10),
(0, 1, 2, 3, 5, 6, 7, 8, 9, 10),
(0, 1, 2, 4, 5, 6, 7, 8, 9, 10),
(0, 1, 3, 4, 5, 6, 7, 8, 9, 10),
(0, 2, 3, 4, 5, 6, 7, 8, 9, 10),
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)]
I want to generate similar output using std::vector and next_permutation from C++ but I'm still getting erroneous results. This is my current approach:
for(int j = 0; j < n-i; j++) {
temp_vector.push_back(j);
}
That snippet is equivalent to range(n-i) in Python.
But the following snippet:
do {
myvector.push_back(temp_vector);
} while(next_permutation(temp_vector.begin(),temp_vector.begin()+2*i));
cout<<myvector.size()<<endl;
Is not equivalent to combinations(range(n-i),2*i)) in Python, and I've tried many variations and still haven't been able to come up with the results I'm expecting.
For example:
Let n = 16
i = 5
Python
>>> print len(list(combinations(range(n-i),2*i)))
11
C++
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> temp_vector;
vector< vector<int> > myvector;
int n = 16, i = 5;
for(int j = 0; j < n - i; j++) {
temp_vector.push_back(j);
}
do {
myvector.push_back(temp_vector);
} while(next_permutation(temp_vector.begin(), temp_vector.begin()+2*i));
cout<<myvector.size()<<endl;
return 0;
}
g++ combinations.cpp
./a.out
3628800
Any guidance will be greatly appreciated! Thanks a lot!
combinations and permutations are not the same thing.
A combination is an unordered list of a subset of the items from another set. A permutation is a unique order of the items in the list.
You're generating all combinations of 10 things from a list of 11 things, so you'll get 11 results, each one missing a different one of the original 11 items.
Generating every permutation will generate every unique order of the original 11 items. Since the items in this case are all unique that means the result would be 11! lists where each contains all 11 items. You're only generating permutations from the first 10 items however, so you're getting 10! lists, none of which contain the 11th item.
You need to find an algorithm for generating combinations instead of permutations.
There's no built-in algorithm for combinations. std::next_permutation can be used as part of an algorithm to generate combinations: See Generating combinations in c++.
Here's an old draft proposal for algorithms for combinations, including code.