Array value as a condition - c++

I have an array of integers called test containing 7 elements,I want to write an if statement to check if the 6 first values of the array are equal to a certain collection of values,what I tried was:
if (test == {1, 0, 1, 0, 0, 0} ) {
//statement(s)
}
However,the line containing the condition gives me an "expected an expression error",what am I doing wrong?
Thanks in advance.

C++17 versions using deduction guides:
std::array
std::array test{1, 0, 1, 0, 0, 0};
if(test == std::array{1, 0, 1, 0, 0, 0}) {
std::cout << "equal\n";
}
std::vector
std::vector test{1, 0, 1, 0, 0, 0};
if(test == std::vector{1, 0, 1, 0, 0, 0}) {
std::cout << "equal\n";
}

If you use std::array you can simply rely on operator==
std::array<int, 7> a1 = {1, 2, 3, 4, 5, 6, 7};
std::array<int, 7> a2 = {2, 3, 4, 5, 6, 7, 8};
std::cout << "a1 == a1 " << (a1 == a1) << std::endl;
std::cout << "a1 == a2 " << (a1 == a2) << std::endl;
However, if for some reason you need to use C-style array, then you can use std::memcmp, which will compare the arrays byte by byte:
int ca1[7] = {1, 2, 3, 4, 5, 6, 7};
int ca2[7] = {2, 3, 4, 5, 6, 7, 8};
std::cout << "ca1 == ca1 " << (std::memcmp(ca1, ca1, sizeof(ca1)) == 0) << std::endl;
std::cout << "ca1 == ca2 " << (std::memcmp(ca1, ca2, sizeof(ca1)) == 0) << std::endl;
Note that you need to compare the std::memcmpy result with 0, which means that they are equal. reference However, in this approach you should first check if the dimensions are equal.

Here is a way to do it (if your test is an std::array):
#include <algorithm>
...
std::vector<int> v({1, 0, 1, 0, 0, 0});
if( (v.size()==test.size()) && std::equal(test.begin(), test.end(), v.begin()) ) {
// statement(s)
}
or
#include <algorithm>
...
std::vector<int> v({1, 0, 1, 0, 0, 0});
if( std::equal(test.begin(), test.end(), v.begin(), v.end()) ) {
// statement(s)
}

Related

How to find minimum value from vector with some condition?

I need to get the min element value (x) in a vector.
Given the index i of x, I need to check if flag[i] == 0 to return i.
I don't want to sort or discard any value because I need its ordinal number, I need the vector to hold its "structure".
How can I get the index of that minimum element?
A = {1, 2, 3, 4, 0, -1}
flag = {0, 0, 1, 0, 1, 1}
min_element = -1, but flag[5] = 1, same for element 0, so min_element should be 1 at index 0.
Ps: I want to shortest solution
You can have a filter view of A with only the elements where flag is 0, and pass that to std::ranges::min.
With C++23 range views:
namespace views = std::ranges::views;
// min is undefined if passed an empty range
assert(std::ranges::any_of(flag, [](auto f){ return f == 0; });
auto value = std::ranges::min(views::zip(A, flag)
| views::filter([](auto && item){ return std::get<1>(item) == 0; })
| views::transform([](auto && item){ return std::get<0>(item); }));
See it on godbolt
If you store both arrays in a single std::vector<std::pair<int,int>> you can use std::min_element directly:
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
std::vector<int> A = {1, 2, 3, 4, 0, -1};
std::vector<int> flag = {0, 0, 1, 0, 1, 1};
std::vector<std::pair<int,int>> flag_and_A;
for (int i=0;i<A.size();++i){
flag_and_A.push_back({flag[i],A[i]});
}
auto it = std::min_element(flag_and_A.begin(),flag_and_A.end());
std::cout << it->second;
}
Live Demo
std::pair::operator< induces a lexicographical odering, ie first first (the flag) is compared then second (A). In other words, entries with flag == 0 are considered smaller than entries with flag == 1.
If you do not want to construct the vector<pair<int,int>> you can still use std::pair::operator< (more precisely the following uses std::tuple<int,int>::operator< which is basically the same):
#include <vector>
#include <iostream>
#include <algorithm>
#include <tuple>
int main() {
std::vector<int> A = {1, 2, 3, 4, 0, -1};
std::vector<int> flag = {0, 0, 1, 0, 1, 1};
auto it = std::min_element(A.begin(),A.end(),[&](const int& a,const int& b){
unsigned index_a = &a - &A[0];
unsigned index_b = &b - &A[0];
return std::tie(flag[index_a],a) < std::tie(flag[index_b],b);
});
std::cout << *it;
}
Live Demo
I think you can make a copy of the vector, to sort, record the min-element,and then clear the copy vector.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> A = {1, 2, 3, 4, 0, -1};
vector<int> flag = {0, 0, 1, 0, 1, 1};
size_t index = -1;
int min_value = 0;
for(size_t i = 0; i < A.size(); ++i) {
if ((flag[i] == 0) && (index == -1 || A[i] < min_value)) {
index = i;
min_value = A[i];
}
}
if (index == -1) {
cout << "not found";
}
else {
cout << "min is A[" << index << "]: " << A[index];
}
return 0;
}
Online demo

What is the meaning of "error: invalid conversion from 'int' to 'int (*)[8]' [-fpermissive]"?

#include <iostream>
using namespace std;
enum {ROW = 7, COLUMN = 8};
void show(int matrix[][COLUMN], int, int);
int main (){
int horizontal = 0;
int vertical = 5;
int goldCoin[ROW][COLUMN] = {
{5, 1, 0, 4, 1, 1, 2, 0},
{0, 3, 2, 1, 0, 3, 0, 1},
{4, 3, 0, 6, 5, 0, 1, 0},
{3, 1, 0, 3, 4, 0, 1, 3},
{0, 5, 2, 0, 1, 1, 5, 1},
{2, 1, 6, 1, 6, 0, 2, 1},
{0, 0, 4, 3, 2, 3, 0, 2}
};
show(goldCoin[ROW][COLUMN], 1, 1);
return 0;
}
void show(int matrix[][COLUMN], int x, int y){
if(y >= COLUMN)
cout << "[error: column index is beyond array limit]" << endl;
else
cout << "[" << matrix[x][y] << "]" << endl;
}
The error is pointing to the function call 'show(goldCoin[ROW][COLUMN], 1, 1);' inside main. As a beginner I don't see any syntactical errors on that statement. Can somebody help?
In calling show(goldCoin[ROW][COLUMN], 1, 1);, you are passing an int as first argument, not 2D array, as you probably wanted to.
I believe that you meant to do show(goldCoin, 1, 1); instead.
It's the wrong way to pass in the argument. Pass in the array name identifier without the brackets:
show(goldCoin, 1, 1);
The expression goldCoin[ROW][COLUMN] represents one single value of type int in your 2D array. So you are passing int value in place of a int (*)[] value which is what the function expects. In this case this is actually reading out of bounds as there is no element with coordinates of [7][8] represented with the goldCoin[7][8] because arrays are zero indexed.
Only in function declaration / definition the signature is:
void show(int matrix[][COLUMN], int, int);
Don't confuse the two.

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].

Why doesn't std::sort use my operator< implementation

Why doesn't std::sort use my operator< implementation in this code
#include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
using namespace std;
bool operator<(
const tuple<int, int>& t1,
const tuple<int, int>& t2
) {
return get<1>(t1) > get<1>(t2);// `>` so that it gets sorted in reverse
}
int main() {
vector<tuple<int, int>> v;
for (int i = 0; i < 10; ++i) {
v.push_back(make_tuple(0, i));
}
cout << "before sort: ";
for (auto& x : v) { cout << get<1>(x) << ", "; }
cout << endl;
auto v2 = v;
sort(v2.begin(), v2.end());
cout << "after sort(begin, end): ";
for (auto& x : v2) { cout << get<1>(x) << ", "; }
cout << endl;
sort(v.begin(), v.end(), [](auto& t1, auto& t2) {
return get<1>(t1) > get<1>(t2);// `>` so that it gets sorted in reverse
});
cout << "after sort(begin, end, comparator): ";
for (auto& x : v) { cout << get<1>(x) << ", "; }
cout << endl;
return 0;
}
The output is:
before sort: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
after sort(begin, end): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
after sort(begin, end, comparator): 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
The output I expected is:
before sort: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
after sort(begin, end): 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
after sort(begin, end, comparator): 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
This has to do with how name lookup works in function templates (commonly referred to as two-phase lookup). std::sort is defined in <algorithm>, and the lookup for < will find those names in scope at the point of the template definition (which yours is not) and those names in the associated namespaces of the dependent function arguments (which for std::tuple would be namespace std, which also does not include yours).
Since the arguments in question are in namespace std, it's actually undefined behavior to add your overload into that namespace. So your options are to either stick with the default behavior (which would be lexicographical <) or to provide your own custom comparator (as you do in your question).

C++ nested for loops - inner product - marix multiplication

I have a matrix A with 4 rows and 3 columns and a matrix B with 8 rows and 4 columns. The coefficiants in the first column of B should denote those rows of A that I want to take for the inner product with the rows of B.
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
int main()
{
int ik, il, im;
//A Matrix
vector<vector<int>> A(4, vector<int>(3));
A={ {0, 0, 0}, {1, 1, 0}, {0, 0, 1}, {1, 1, 1} };
//B Matrix
vector<vector<int>> B(8, vector<int>(4));
B={ {1, 0, 0, 0}, {2, 1, 0, 0}, {2, 0, 1, 0}, {2, 1, 1, 0} ,{3, 0, 0, 1}, {4, 1, 0, 1}, {4, 0, 1, 1}, {4, 1, 1, 1} };
vector<int> BZI;
BZI={{1},{2},{2},{2},{3},{4},{4},{4}};
//calculate inner products
vector<vector<int>> SKP_AB(4, vector<int>(8));
int skp_temp;
for(ik=0; ik<4; ik++)
{
for(im=0; im<8; im++)
{
for(il=0; il<3; il++)
{
skp_temp=A[BZI[ik]][il]*B[im][il+1];
SKP_AB[ik][im]+=skp_temp;
}
}
}
//Ausgabe von SKP_AB
cout << "\n" << "#SKP_AB" << "\n";
for(ik=0; ik<4; ++ik)
{
for(il=0; il<8; ++il)
{
cout << setw(2) << SKP_AB[ik][il];
}
cout << "\n";
}
return 0;
}
In both BZI and the first column of B you used one based row indexing, but C++ uses zero based row indexing.
So you need to compensate, where you had BZI[ik] you needed BZI[ik]-1
Notice also how hard it was to reach that answer without being told what output you expected (only your program wasn't working) vs. how obvious it was once told what output you expected.