Related
The task is following: find indices of duplicating rows of 2D array. Rows considered to be duplicated if 2nd and 4th elements of one row are equal to 2nd and 4th elements of another row.The simplest way to do it is something like that:
std::unordered_set<int> result;
for (int i = 0; i < rows_count; ++i)
{
for (int j = i + 1; j < rows_count; ++j)
{
if (arr[i][2] == arr[j][2] && arr[i][4] == arr[j][4])
{
result.push_back(j);
}
}
}
But if rows_count is very large this algorithm is too slow. So my question is there any way to get needed indices using some data structures (from stl or other) with only single loop (without nested loop)?
You could take advantage of the properties of a `std::unordered_set.
A small helper class will further ease up things.
So, we can store in a class the 2nd and 4th value and use a comparision function to detect duplicates.
The std::unordered_set has, besides the data type, 2 additional template parameters.
A functor for equality and
a functor for calculating a hash function.
So we will add 2 functions to our class an make it a functor for both parameters at the same time. In the below code you will see:
std::unordered_set<Dupl, Dupl, Dupl> dupl{};
So, we use our class additionally as 2 functors.
The rest of the functionality will be done by the std::unordered_set
Please see below one of many potential solutions:
#include <vector>
#include <unordered_set>
#include <iostream>
struct Dupl {
Dupl() {}
Dupl(const size_t row, const std::vector<int>& data) : index(row), firstValue(data[2]), secondValue(data[4]){};
size_t index{};
int firstValue{};
int secondValue{};
// Hash function
std::size_t operator()(const Dupl& d) const noexcept {
return d.firstValue + (d.secondValue << 8) + (d.index << 16);
}
// Comparison
bool operator()(const Dupl& lhs, const Dupl& rhs) const {
return (lhs.firstValue == rhs.firstValue) and (lhs.secondValue == rhs.secondValue);
}
};
std::vector<std::vector<int>> data{
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, // Index 0
{2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, // Index 1
{3, 4, 42, 6, 42, 8, 9, 10, 11, 12}, // Index 2 ***
{4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, // Index 3
{5, 6, 42, 8, 42, 10, 11, 12, 13, 14}, // Index 4 ***
{6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, // Index 5
{7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, // Index 6
{8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, // Index 7
{9, 10, 42, 12, 42, 14, 15, 16, 17, 18}, // Index 8 ***
{10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, // Index 9
};
int main() {
std::unordered_set<Dupl, Dupl, Dupl> dupl{};
// Find the unique rows
for (size_t i{}; i < data.size(); ++i)
dupl.insert({i, data[i]});
// Show some debug output
for (const Dupl& d : dupl) {
std::cout << "\nIndex:\t " << d.index << "\t\tData: ";
for (const int i : data[d.index]) std::cout << i << ' ';
}
}
I use Maxima CAS to create the list:
a:makelist(i,i,1,20);
result:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
I want to slim the list and leave only every third element. To find it I check index i of the list a :
mod(i,3)>0
to find elements.
My code :
l:length(a);
for i:1 thru l step 1 do if (mod(i,3)>0) then a:delete(a[i],a);
Of course it does not work because length of a is changing.
I can do it using second list:
b:[];
for i:1 thru l step 1 do if (mod(i,3)=0) then b:cons(a[i],b);
Is it the best method ?
There are different ways to solve this, as know already. My advice is to construct a list of the indices you want to keep, and then construct the list of elements from that. E.g.:
(%i1) a:makelist(i,i,1,20);
(%o1) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
(%i2) ii : sublist (a, lambda ([a1], mod(a1, 3) = 0));
(%o2) [3, 6, 9, 12, 15, 18]
(%i3) makelist (a[i], i, ii);
(%o3) [3, 6, 9, 12, 15, 18]
The key part is the last step, makelist(a[i], i, ii), where ii is the list of indices you want to select. ii might be constructed in various ways. Here is a different way to construct the list of indices:
(%i4) ii : makelist (3*i, i, 1, 6);
(%o4) [3, 6, 9, 12, 15, 18]
One simple way (I do not know which one is best or faster) with compact code: makelist(a[3*i],i,1,length(a)/3)
Test example:
l1:makelist(i,i,1,12)$
l2:makelist(i,i,1,14)$
l3:[2,3,5,7,11,13,17,19,23,29]$
for a in [l1,l2,l3] do (
b:makelist(a[3*i],i,1,length(a)/3),
print(a,"=>",b)
)$
Result:
[1,2,3,4,5,6,7,8,9,10,11,12] => [3,6,9,12]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14] => [3,6,9,12]
[2,3,5,7,11,13,17,19,23,29] => [5,13,23]
I'm using Eigen for easy optimization of some of my matrix math. I'm currently trying to make the following operation more efficient:
Given Matrix A:
1, 2, 3
4, 5, 6
Matrix B:
7, 11, 13, 19, 26, 7, 11
8, 9, 15, 6, 8, 4, 1
and "index map" column vector IM:
0, 1, 3, 6
I'd like to append the columns of Matrix B mapping to the indexes in IM, to Matrix A as such:
1, 2, 3, 7, 11, 19, 11
4, 5, 6, 8, 9, 6, 1
I'm currently able to do this with a massive for loop, but this is the bottleneck in my code and I'd like to avoid this:
#pragma unroll
for (int i = 0; i < 25088; i++) {
block.noalias() += _features.col(ff[i]);
}
I've seen the discussion here and poured over the docs but can't seem to figure out the right syntax relating to Eigen matrices: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=329
Any thoughts/tips would be much appreciated!
I wrote a code for calculating the max subarray using brute force method. My code reads a number of arrays from an input file and returns the output file, which contains the max subarray and the sum value.
Everything works fine except the first max subarray on the output file always contains a really large number at the end, which gets added to the sum value. The subsequent sub-arrays don't have this problem. I've included an example at the bottom of this post.
I can't figure out where I went wrong. Any help would be greatly appreciated!
Here is the function that runs the algorithm and prints it to output file:
void a1(int a[], int size, string filename){
//run algorithm 1
int sum = a[0], start = 0, end = 0;
for (int x = 0; x < size; x++) {
int tempSum = 0;
int y = x;
while(y>=0){
tempSum += a[y];
if(tempSum>sum){
sum=tempSum;
start=y;
end=x;
}
y--;
}
}
//print results on file
ofstream output;
output.open(filename.c_str(), ios::out | ios::app);
output << "\nMax sum array: ";
for (int x = start; x <= end; x++) {
output << a[x];
if (x != end) output << ", ";
}
output << "\nMax sum value: " << sum << "\n";
output.close();
}
Here is the main file:
int main() {
int a[50];
ifstream inputFile;
string s;
stringstream ss;
string outputfile = "MSS_Results.txt";
//print title
ofstream output;
output.open(outputfile.c_str(), ios::out | ios::app);
output << "Algorithm 1:\n";
output.close();
//read file and run a1
int size;
char c;
inputFile.open("MSS_Problems.txt");
while (!inputFile.eof()) {
getline(inputFile, s);
size = 0;
ss << s;
ss >> c;
while (ss.rdbuf()->in_avail()) {
ss >> a[size];
size++;
ss >> c;
if (!ss.rdbuf()->in_avail() && c != ']') {
ss.clear();
getline(inputFile, s);
ss << s;
}
}
ss.clear();
if (size > 0) a1(a, size, outputfile);
}
inputFile.close();
return 0;
}
Example of input file:
[1, 2, 4, -1, 4, -10, 4, -19, 18, -1, -3, -4, 11, 3, -20, 19, -33, 50, 66, -22, -4, -55, 91, 100, -102, 9, 10, 19, -10, 10, 11, 11, -10, -18, 50, 90]
[12, 12, 14, -88, -1, 45, 6, 8, -33, 2, 8, -9, -33, -8, -23, -77, -89, 1, 9, 10, 92, 87]
[565, 78, 33, 9, 10, 84, 71, -4, -22, -55, -10, 76, -9, -9, -11, 76, 89, 11, 10, -33, 9]
[2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
Example of output file:
Algorithm 1:
Max sum array: 50, 66, -22, -4, -55, 91, 100, -102, 9, 10, 19, -10, 10, 11, 11, -10, -18, 50, 90, 3897136
Max sum value: 3897432
Max sum array: 1, 9, 10, 92, 87, 91
Max sum value: 290
Max sum array: 565, 78, 33, 9, 10, 84, 71, -4, -22, -55, -10, 76, -9, -9, -11, 76, 89, 11, 10, -33, 9, 87
Max sum value: 1055
Max sum array: 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 11
Max sum value: 103
As you can see, for the first array, there is a 3897136 that does not belong to the original array.
If I delete the first line from the input, the input looks like this:
[12, 12, 14, -88, -1, 45, 6, 8, -33, 2, 8, -9, -33, -8, -23, -77, -89, 1, 9, 10, 92, 87]
[565, 78, 33, 9, 10, 84, 71, -4, -22, -55, -10, 76, -9, -9, -11, 76, 89, 11, 10, -33, 9]
[2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
Now my output looks something like this:
Algorithm 1:
Max sum array: 1, 9, 10, 92, 87, 624
Max sum value: 823
Max sum array: 565, 78, 33, 9, 10, 84, 71, -4, -22, -55, -10, 76, -9, -9, -11, 76, 89, 11, 10, -33, 9, 87
Max sum value: 1055
Max sum array: 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
Max sum value: 92
I initialized the array incorrectly, which is why it sometimes gave me a garbage number at the end. To initialize properly, I simply changed
a[100];
to
a[100] = {0}
and that fixed the problem of abnormally large numbers at the end of the array.
I then moved a[100] = {0} into the while loop where the code reads the input file. That seems to have fixed the new issue of reading wrong elements into the array.
Final unresolved issue: 0 at the end of array.
Will update once I solve that.
Since all the problem is finding the maximum subarray , therefore the "large number" at the end will need to get added to produce the correct results.
In the first example that you provided, all the numbers were positive.
This means that the maximum sum subarray will actually be the sum of all the array elements.
Your algorithm part is OK;
I have a std::array with several items and I want to compare it from a certain position and also insert in a certain position, for example.
std::array<int, 10> numbers {{ 9, 5, 6, 4, 5, 6, 1, 10, 15, 25 }};
I want to compare the array numbers from item 5 until the last one, with this one, from the beginning, that is position 0 until position 4.
std::array<int, 10> compare {{ 6, 1, 10, 15, 25, 0, 0, 0, 0, 0 }};
It will (in this case) return true.
And how to insert items from a position? I want to insert on the array compare from the position 5 until the last position, that is 9.
For example, if I want to insert these numbers: 5, 45, 32, 14, 10. It will turn:
std::array<int, 10> compare {{ 6, 1, 10, 15, 25, 5, 45, 32, 14, 10 }};
Thanks in advance.