Sorting 2D Vector Array Based On a Column - c++

I have a 2d vector array which contains :
row id r b main
1 0 26 3
2 1 11 2
3 1 46 4
4 2 26 1
5 3 11 2
I want to sort every row based on its "main"-column value
smaller "main"-column.
smaller value => the entire row should be on the top.
if there is tow rows or more and there "main"-column have the same value, I want to check "r"-column.
smaller value => the entire row should be on the top.
after sorting it will look like this:
row id r b main
4 2 26 1
2 1 11 2
5 3 11 2
1 0 26 3
3 1 46 4

Try using std::sort like
using int_arr = std::array<int, 4>;
std::sort(std::begin(arr), std::end(arr), [](const int_arr& a, const int_arr& b){
return a[3] != b[3] ? a[3] < b[3] : a[1] < b[1];
});
Demo
#include <iostream>
#include <array>
#include <algorithm>
int main() {
using int_arr = std::array<int, 4>;
int_arr arr[5] = {
{1, 0, 26, 3},
{2, 1, 11, 2},
{3, 1, 46, 4},
{4, 2, 26, 1},
{5, 3, 11, 2}
};
for(const auto& i_arr : arr) {
for(const auto& i : i_arr)
std::cout<< i <<", ";
std::cout << "\n";
}
std::cout << "**************\n";
std::sort(std::begin(arr), std::end(arr), [](const int_arr& a, const int_arr& b){
return a[3] != b[3] ? a[3] < b[3] : a[1] < b[1];
});
for(const auto& i_arr : arr) {
for(const auto& i : i_arr)
std::cout<< i <<", ";
std::cout << "\n";
}
}
OutPut
1, 0, 26, 3,
2, 1, 11, 2,
3, 1, 46, 4,
4, 2, 26, 1,
5, 3, 11, 2,
**************
4, 2, 26, 1,
2, 1, 11, 2,
5, 3, 11, 2,
1, 0, 26, 3,
3, 1, 46, 4,

Related

std::sort of vector of struct sorted by field where all are zeros causing different results for different length of vector

Hello I have this piece of code for sorting vector. Basically sorting vector of structure where at the start all elements of vector has score equal to 0. I thought that if all elements equals score 0 sort will keep for multiple sort but only when uint8_t length = 17; is under 17. It is probably caused by implementation of sort that 16 is somehow important for sorting.
reference code here https://www.onlinegdb.com/C_wj9_87L
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct {
uint8_t index;
uint8_t score;
} test;
uint8_t length = 17;
int main()
{
std::vector<test> vec;
for (uint8_t i = 0; i < length; i++) {
vec.push_back({i, 0});
}
for (uint8_t j = 0; j < 3; j++) {
std::sort(vec.begin(), vec.end(), [](const test &m1, const test &m2) {
return m1.score > m2.score;
});
for (uint8_t i = 0; i < length; i++) {
std::cout << (int)vec[i].index << ", ";
}
std::cout << "\n";
}
return 0;
}
Result with uint8_t length = 17;
8, 16, 15, 14, 13, 12, 11, 10, 9, 0, 7, 6, 5, 4, 3, 2, 1,
9, 1, 2, 3, 4, 5, 6, 7, 0, 8, 10, 11, 12, 13, 14, 15, 16,
0, 16, 15, 14, 13, 12, 11, 10, 8, 9, 7, 6, 5, 4, 3, 2, 1,
Result with uint8_t length = 16;
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
Do you know what is going wrong here ?
Expected result is always same sort so indexes will remain its position.
Yeah the answer is stable_sort Thank you #Mat

How to make Kronecker product of two random vectors of vectors?

I need to make a function which takes two parameters (two vectors of vectors) and as a result returns a vector of vectors which is a Kronecker product of two given vectors of vectors.
Whatever I do, my new vector of vectors is created by the same number (the one which should be only on the last position). For example if I have vector of vectors A: {3, -1},{0, 5} and B:{4,3,15},{0, -5, 2} my Kronecker product will be: {10, 10, 10, 10, 10, 10}, {10, 10, 10, 10, 10, 10} etc, instead of {12, 9, 45, -4, -3, -15}, {0, -15, 6, 0, 5, -2}, {0, 0, 0, 20, 15, 75}, {0, 0, 0, 0, -25, 10}
Matrix KroneckersProduct(Matrix A, Matrix B){
Matrix mat=CreateMatrix(NoRows(A)*NoRows(B),NoCols(A)*NoCols(B));
for(int i=0;i<NoRows(A)*NoRows(B);i++){
for(int j=0;j<NoCols(A)*NoCols(B);j++){
for(int k=0;k<NoRows(A);k++){
for(int l=0;l<NoRows(B);l++){
for(int m=0;m<NoCols(A);m++){
for(int n=0;n<NoCols(B);n++){
mat.at(i).at(j)=A.at(k).at(m)*B.at(l).at(n);
}
}
}
}
}
}
return mat;
}
This is the algorithm for Kronecker product. Maybe I switched v1 and v2
#include <vector>
#include <iostream>
using Matrix = std::vector<std::vector<double>>;
Matrix KroneckersProduct(Matrix v1, Matrix v2){
Matrix v(v1.size() * v2.size(), std::vector<double>(v1[0].size() * v2[0].size()));
for (std::size_t z1(0); z1 < v1.size(); ++z1) {
for (std::size_t z2(0); z2 < v2.size(); ++z2) {
for (std::size_t z3(0); z3 < v1[0].size(); ++z3) {
for (std::size_t z4(0); z4 < v2[0].size(); ++z4) {
v[z1*v2.size() + z2][z3*v2[0].size() + z4] = v1[z1][z3] * v2[z2][z4];
}
}
}
}
return v;
}
int main() {
Matrix v1{{3, -1},{0, 5}};
Matrix v2{{4,3,15}, {0, -5, 2}};
Matrix v(KroneckersProduct(v1, v2));
for (const auto& row : v) {
for (const auto& cell : row) {
std::cout << cell << " ";
}
std::cout << '\n';
}
return 0;
}
Output:
12 9 45 -4 -3 -15
0 -15 6 -0 5 -2
0 0 0 20 15 75
0 -0 0 0 -25 10

C++: std::map, find cycles, algorithm

Suppose the following data structure:
std::map <int, std::vector<int> > M,
where val is represented by the sequence of vertices of the graph, and the key is the first vertex of the sequence. For example
{1} {1, 8, 12, 7}
{4} {4, 3, 5}
{7} {7, 9, 13, 18, 0, 2}
{2} {2, 11, 1}
{5} {5, 17, 10, 4}
{9} {9, 6, 19, 14}
{14} {14, 15, 9}
How to find all cycles (analogous start and end vertex) from the segments {}
C1: {1 8 12 7} {7 9 13 18 0 2} {2 11 1}
C2: {4 3 5} {5 17 10 4}
C3: {9 6 19 14} {14, 15, 9}
and how to avoid the duplicate sequence of segments, with the low time complexity (map may contain hundreds of thousands of sequences). Any cycle may contain n segments {}, where n>=1.
The initialization phase:
std::map <int, std::vector <int> > M;
M[1] = std::vector<int>{ 1, 8, 12, 7 };
M[4] = std::vector<int>{ 4, 3, 5 };
M[7] = std::vector<int>{ 7, 9, 13, 18, 0, 2 };
M[2] = std::vector<int>{ 2, 11, 1 };
M[5] = std::vector<int>{ 5, 17, 10, 4 };
M[9] = std::vector<int>{ 9, 6, 19, 14 };
M[14] = std::vector<int>{ 14, 15, 9 };
The draft of the algorithm:
std::vector<std::vector <int> > R;
for (auto im = M.begin(); im != M.end();)
{
std::vector<int> r, ri = im->second;
for(;;)
{
r.insert(r.end(), ri.begin(), ri.end());
ri = M[r.back()];
im = M.erase(M.find(im->first));
if (r.back() == r.front()) break;
}
R.push_back(r);
}
Unfortunately, the repeated deletion represents an expensive operation... I hope, there is a more beautiful and efficient solution :-)
Thanks for your help...
First, your inner loop needs to be a function (what if the paths don't cycle?)
Then, declare failure if either
The end node is numerically less than the start node (could be a cycle, but is not a canonical, so we won't print this shifted version)
The end node isn't found in the master table of paths
And that leads to a solution:
bool try_follow(int from, std::vector<int>& result)
{
int current = from;
while (true) {
auto path = M.find(current);
if (path == M.end()) return false;
current = path->second.back();
if (current < from) return false;
result.insert(result.end(), path->second.begin()+1, path->second.end());
if (current == from) return true;
}
}
int main(void)
{
for( auto& kvp : M )
{
std::vector<int> x;
if (try_follow(kvp.first, x)) {
std::cout << kvp.first;
for( int y : x )
std::cout << " - " << y;
std::cout << std::endl;
}
}
}
Demo: https://rextester.com/DWWZ9457
My first crack:
for (auto it : M)
{
if (it.first < it.second.back() && it.second.front() == M[it.second.back()].back())
std::cout << "Cycle between " << it.first << " and " << it.second.back() << '\n';
}
Won't find cycles that involve 3+ paths, of course.

Removing trailing zeros in an array

I am trying to create a program that doesn't print the trailing zeros in an array.
My array size is 23. I am trying to start from the 23rd position in a for loop and end the for loop once a one is reached. Then I would only print up to that position. I have can't seem to get it right though. Can someone help me with this?
Thanks
void removeTrailZero(int array[]) {
int i = 0;
for (i = 23; array[i] == 0; i--) {
// printf("%d", i);
}
for (int x = 1; x < i + 1; x++) {
printf("%d",array[x]);
}
}
You can do something like this
for (i = 22; i >= 0; --i)
{
if (array[i] != 0)
break;
}
Then print your array between 0 and i (included)
Right now, your code looks like C, not C++. At least assuming the tag is correct and you really want to write C++ rather than C, I'd consider using some of the algorithms in the standard library to handle at least part of the job.
The standard library has an std::find_if to use for finding the value you care about. This works with iterators, not directly with the underlying storage. Since you want to start searching from the end, you can use a reverse_iterator to find the correct point:
auto last = std::find_if(std::crbegin(array), std::crend(array),
[](auto i) { return i != 0; });
When we print out the data, we want to iterate forward through the array from the beginning to that point--but that's a reverse_iterator, so we need to call its base() to get a forward iterator, and give that as the end of the range we want to print:
std::copy(std::cbegin(array), last.base(),
std::ostream_iterator<int>(std::cout, "\n"));
If You compile with C++14 -std=c++14 you can use the answer's #JerryCoffin:
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <string>
template <std::size_t SIZE>
void removeTrailZero(const std::array<int, SIZE>& array) {
auto last = std::find_if(std::crbegin(array), std::crend(array),
[](auto i) { return i != 0; });
std::copy(std::cbegin(array), last.base(),
std::ostream_iterator<int>(std::cout, " "));
}
int main() {
std::array<int, 23> array1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0};
removeTrailZero(array1);
std::cout << std::endl;
std::array<int, 15> array2 = {1, 2, 3, 0, 0, 4, 5, 6, 0, 0, 0, 0, 0, 0};
removeTrailZero(array2);
std::cout << std::endl;
}
Output:
❯❯❯ g++ -std=c++14 ../test.cc -o test && ./test
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 2 3 0 0 4 5 6
For compiling with C++11 -std=c++11 you can use:
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <string>
template <std::size_t SIZE>
void removeTrailZero(const std::array<int, SIZE>& array) {
auto last = std::find_if(array.crbegin(), array.crend(),
[](int i) { return i != 0; });
std::copy(array.cbegin(), last.base(),
std::ostream_iterator<int>(std::cout, " "));
}
int main() {
std::array<int, 23> array1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0};
removeTrailZero(array1);
std::cout << std::endl;
std::array<int, 15> array2 = {1, 2, 3, 0, 0, 4, 5, 6, 0, 0, 0, 0, 0, 0};
removeTrailZero(array2);
std::cout << std::endl;
}
Output:
❯❯❯ g++ -std=c++11 ../test.cc -o test && ./test
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 2 3 0 0 4 5 6
For older version of C++11, you can use:
#include <iostream>
void removeTrailZero(int array[]) {
int i = 22;
for (; i >= 0 && array[i] == 0; --i);
for (int j = 0; j <= i; ++j) {
std::cout << array[j] << " ";
}
}
int main() {
int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0};
removeTrailZero(array);
std::cout << std::endl;
int array2[] = {1, 2, 3, 0, 0, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
removeTrailZero(array2);
std::cout << std::endl;
}
Output:
❯❯❯ g++ ../test.cc -o test && ./test
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 2 3 0 0 4 5 6
Note: For C++11 and C++14, removeTrailZero is a template function and can receive diferent sizes of std::array. For older version of C++11 removeTrailZerois design for receive a int[23].

Storing input file into a 2d array C++

I have an input file that I would like to use by using cin.
My input file contains a list of 9x9 numbers, such as:
1 2 3 4 5 6 7 8 9
2 2 3 4 5 6 7 8 9
3 2 3 4 5 6 7 8 9
4 2 3 4 5 6 7 8 9
5 ...
6 ...
7 ...
8 ...
9 ...
I want to store these values into a 2d array, so they would look like:
int board[9][9] = {{1, 2, 3, 4, 5, 6, 7, 8, 9},
{2, 2, 3, 4, 5, 6, 7, 8, 9},
{3, 2, 3, 4, 5, 6, 7, 8, 9},
{4, 2, 3, 4, 5, 6, 7, 8, 9},
{5, 2, 3, 4, 5, 6, 7, 8, 9},
{6, 2, 3, 4, 5, 6, 7, 8, 9},
{7, 2, 3, 4, 5, 6, 7, 8, 9},
{8, 2, 3, 4, 5, 6, 7, 8, 9},
{9, 2, 3, 4, 5, 6, 7, 8, 9}};
I tried to do:
int board[9][9];
for (int i=0;i<9;i++) {
for (int j=0;j<9;j++) {
std::cin >> board[i][j];
}
}
However, I don't think it's working. I'm going to use them as inputs when I run my code.
This works for me in GCC 4.9.0 with C++11:
Sample Code:
#include <iostream>
int main() {
int board[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
std::cin >> board[i][j];
}
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
std::cout << board[i][j];
}
std::cout << std::endl;
}
return 0;
}
You should change C array for std::vector or other container from STL, it provide a lot of benefice (automatic memory management, array bound check, etc...). If you could use C++11, the new range for loop is a big improvement too (syntactical and performance wise, it avoid error as off by one, incorrect bounds, etc...).
Here is a C++11 version:
#include <iostream>
#include <vector>
int main() {
typedef std::vector<int> row_t;
typedef std::vector<row_t> board_t;
board_t board(9, row_t(9));
for (auto& row : board) {
for (auto& cell : row) {
std::cin >> cell;
}
}
for (const auto& row : board) {
for (auto cell : row) {
std::cout << cell;
}
std::cout << std::endl;
}
return 0;
}
The inner loop is wrong, there you have j++ as the loop condition. And as in the first iteration j will be zero (which in C++ is the same as false) the loop will not iterate at all. Besides, the inner loop is missing a semicolon, so it shouldn't even compile.