Logical operation between all elements in array - c++

I want to compare all items in my array using a boolean operator in the most efficient way. Currently, I have something like this :
bool myFunction(int i)
{
bool *myArray = {true, true, false, false, true};
//suppose we know that i = 5 and that i is the length of the array...
return myArray[0] && myArray[1] && myArray[2] && myArray[3] && myArray[4];
}
Since the size of the array is not fixed, the value of 'i' can change and my return statement would no longer be working, so I would have to implement something like this
bool myFunction(int i)
{
bool *myArray = //some other array of bools
//should work with any value of i
bool result = myArray[0];
for (int a = 1; a < i; ++a)
{
result &= myArray[i];
}
return result;
}
I was wondering if there was a better way to do this other than making a for loop and going through each elements and comparing the value of the next item in list with the stored result from the previous two items. Like some bitwise operators that would make this easy or something, anything to take out the loop.

You probably need to know that &= is not a logical operator; it is the "bitwise and" operator. As long as you only use it on booleans, I guess it will work ok; but C won't stop a value other than 1 or 0 from slipping into the array, so you should probably not make that assumption. Semantically if you're doing a logical or you want && instead of &.
That said, you can certainly use short-circuiting to refine what you're doing. Once you've found a single 0 (false), nothing from then on is going to make your aggregate go back to 1 (true), so you might as well stop.
for (int a = 1; result && a < i; ++a)
{
result &= myArray[i];
}
Other than that, there's not much you can improve. Not sure why you're averse to a loop, but if you want to combine an unknown number of values you're going to have to iterate. You might find (or write) some utility function to do it, but it'll be using a loop internally anyway. (Unless it tries to leverage a vector processor that natively does what you want, maybe... but that would be rather pointless and, if you truly don't have a limit on number of values, will still involve a loop.)

You can use all_of (replacestd::begin(myArray) + i with std::end(myArray) if you want to check entire array and not first i elements):
#include <vector>
#include <algorithm>
bool myFunction(int i)
{
std::vector<bool> myArray = { true, true, false, false, true };
return std::all_of(std::begin(myArray), std::begin(myArray) + i, [](bool elem) { return elem; });
}

I would change the condition of your for-loop so you won't continue if you encounter a false value and use an iterator instead of an index.
bool myFunction(int i) {
bool myArray[i] = //some other array of bools
//should workwith any value of i
bool result;
bool * a;
for (a = myArray, result = *a; a < myArray+i && result; result=*(++i)) {}
//no need to use the AND operator since we stop if we meet one false
return result;
}
Or if you really prefer with index:
bool myFunction(int i) {
bool myArray[i] = //some other array of bools
//should workwith any value of i
bool result;
unsigned int a;
for (a = 0, result = myArray[a]; a < i && result; result=myArray[++i]) {}
//no need to use the AND operator since we stop if we meet one false
return result;
}
Maybe I'm wrong, but I wouldn't use the bitwise AND assignment (&=) if it's not on bit range operation, it's not really relevant on the bool type though.

You can exit the loop as soon as you encounter false:
for (int a = 0; a < i; a++)
{
if (!myArray[i])
return false;
}
return true;
If you're allowed to change the last value in the array, then here's a trick for optimizing it:
If the last value in the array is false, then return false
Write false into the last entry in the array
Iterate the array until you encounter false
Write true into the last entry in the array
If you stopped before the last entry, then return false
Return true
The code:
int a;
if (!myArray[i-1])
return false;
myArray[i-1] = false;
for (a = 0; a < i; a++)
{
if (!myArray[i])
break;
}
myArray[i-1] = true;
return a != i-1;
This yields one branch per iteration instead of two branches per iteration.
If you're allowed to allocate i+1 entries, then you can get rid of the "last entry swapping" part:
int a;
myArray[i] = false;
for (a = 0; myArray[i]; i++);
return a != i;
You can also get rid of the additional arithmetic embedded in myArray[i]:
bool *arrayPtr;
myArray[i] = false;
for (arrayPtr = myArray; *arrayPtr; arrayPtr++);
return arrayPtr != myArray+i;
If the compiler doesn't already apply it, then this function will do so for sure. On the other hand, it might make it harder on the optimizer to unroll the loop, so you will have to verify that in the generated assembly code...

You can use a boost::dynamic_bitset, it has a member fuction any() that will return true if any bits in this bitset are set. And none() will return true if no bits are set.
But the implementation of any() is:
template <typename Block, typename Allocator>
bool dynamic_bitset<Block, Allocator>::any() const
{
for (size_type i = 0; i < num_blocks(); ++i)
if (m_bits[i])
return true;
return false;
}
So you have inside a for loop!
But if you are searching for something like parallel computing, you may want to use arrayfire:
For example it has an algorithm that do it.
template<typename T >
T af::allTrue( const array & in )
//C++ Interface for checking if all values in an array are true.

Related

Function to check if an array is a permutation

I have to write a function which accepts an int array parameter and checks to see if it is a
permutation.
I tried this so far:
bool permutationChecker(int arr[], int n){
for (int i = 0; i < n; i++){
//Check if the array is the size of n
if (i == n){
return true;
}
if (i == arr[n]){
return true;
}
}
return false;
}
but the output says some arrays are permutations even though they are not.
When you write i == arr[n], that doesn't check whether i is in the array; that checks whether the element at position n is i. Now, that's even worse here, as the array size is n, so there's no valid element at position n: it's UB, array is overindexed.
If you'd like to check whether i is in the array, you need to scan each element of the array. You can do this using std::find(). Either that, or you might sort (a copy of) the array, then check if i is at position i:
bool isPermutation(int arr[], int n){
int* arr2 = new int[n]; // consider using std::array<> / std::vector<> if allowed
std::copy(arr, arr + n, arr2);
std::sort(arr2, arr2 + n);
for (int i = 0; i < n; i++){
if (i != arr2[i]){
delete[] arr2;
return false;
}
}
delete[] arr2;
return true;
}
One approach to checking that the input contains one of each value is to create an array of flags (acting like a set), and for each value in your input you set the flag to true for the corresponding index. If that flag is already set, then it's not unique. And if the value is out of range then you instantly know it's not a permutation.
Now, you would normally expect to allocate additional data for this temporary set. But, since your function accepts the input as non-constant data, we can use a trick where you use the same array but store extra information by making values negative.
It will even work for all positive int values, since as of C++20 the standard now guarantees 2's complement representation. That means for every positive integer, a negative integer exists (but not the other way around).
bool isPermutation(int arr[], int n)
{
// Ensure everything is within the valid range.
for (int i = 0; i < n; i++)
{
if (arr[i] < 1 || arr[i] > n) return false;
}
// Check for uniqueness. For each value, use it to index back into the array and then
// negate the value stored there. If already negative, the value is not unique.
int count = 0;
while (count < n)
{
int index = std::abs(arr[count]) - 1;
if (arr[index] < 0)
{
break;
}
arr[index] = -arr[index];
count++;
}
// Undo any negations done by the step above
for (int i = 0; i < count; i++)
{
int index = std::abs(arr[i]) - 1;
arr[index] = std::abs(arr[index]);
}
return count == n;
}
Let me be clear that using tricky magic is usually not the kind of solution you should go for because it's inevitably harder to understand and maintain code like this. That should be evident simply by looking at the code above. But let's say, hypothetically, you want to avoid any additional memory allocation, your data type is signed, and you want to do the operation in linear time... Well, then this might be useful.
A permutation p of id=[0,...,n-1] a bijection into id. Therefore, no value in p may repeat and no value may be >=n. To check for permutations you somehow have to verify these properties. One option is to sort p and compare it for equality to id. Another is to count the number of individual values set.
Your approach would almost work if you checked (i == arr[i]) instead of (i == arr[n]) but then you would need to sort the array beforehand, otherwise only id will pass your check. Furthermore the check (i == arr[n]) exhibits undefined behaviour because it accesses one element past the end of the array. Lastly the check (i == n) doesn't do anything because i goes from 0 to n-1 so it will never be == n.
With this information you can repair your code, but beware that this approach will destroy the original input.
If you are forced to play with arrays, perhaps your array has fixed size. For example: int arr[3] = {0,1,2};
If this were the case you could use the fact that the size is known at compile time and use an std::bitset. [If not use your approach or one of the others given here.]
template <std::size_t N>
bool isPermutation(int const (&arr)[N]) {
std::bitset<N> bits;
for (int a: arr) {
if (static_cast<std::size_t>(a) < N)
bits.set(a);
}
return bits.all();
}
(live demo)
You don't have to pass the size because C++ can infer it at compile time. This solution also does not allocate additional dynamic memory but it will get into problems for large arrays (sat > 1 million entries) because std::bitset lives on automatic memory and therefore on the stack.

Fastest way to check if array is equal to? [duplicate]

This question already has answers here:
How to check if all the values of an array are equal to 0?
(5 answers)
Closed 4 years ago.
I am writing a game simulation that tests if any piece is on the board. If a piece is not I would like the AI to place a piece on the board, for this I created a bool function to test if all the pieces are set to 0 which means they are yet to enter the board. The current function boots, but I feel there is a much simpler way to do this:
bool checkPiece(int a[])
{
int n = 0;
bool e = true;
while (e == true && n < 4)
{
if (a[n] == 0 )
{
n++;
}
else
{
return false;
}
}
return true;
}
I'd use the standard library, something on this general order:
bool checkPiece(int const *a) {
return std::all_of(a, a+4, [](int i) { return i == 0; });
}
If you really wanted to do the job on your own, perhaps something on this order:
bool checkPiece(int const *a) {
for (int i=0; i<4; i++)
if (a[i] != 0)
return false;
return true;
}
Most of the time, you'd also rather pass something collection-like, such as an std::array or std::vector (by const reference), or something range-like such as a gsl::span rather than a pointer though. This would (for one obvious example) make it trivial to get the size of what was passed instead of blindly assuming was 4 items.
This is basically all you need:
for (size_t n = 0; n < 4; ++n) {
if (a[n]) return false;
}
return true;
You dont need e and when iterating an array from begin till end (or return before) a for loop is easier to read and write than a while. You could use a algorithm, but I doubt that it will make your code more readable and you should avoid magic numbers like the plague (what if you ever change the size of the array to be something else than 4?).
You can solve this with little code using std::count.
bool checkPiece(int const *a) {
return std::count(a, a+4, 0) == 4;
}
First, don't use magic numbers instead of passing array sizes. If you change the size of your board you'll have to find every 4 in your program and decide whether it's actually the number 4 or the size of the array. Pass the size to your function.
Second, give the function a name that describes what it does. checkPiece doesn't tell me anything.
And when you've made those changes, use standard algorithms:
bool noPieces(int const *a, int size) {
return std::all_of(a, a + size, [](int pc) { return pc == 0; }
}

Sorting array of chars alphabetically then by length

I have an array of structs where I keep track of how many times each unique word was seen in a given text:
struct List {
char word[20];
int repeat;
};
Now I need to sort this:
as 6
a 1
appetite 1
angry 1
are 2
and 4
...
To this:
a 1
as 6
and 4
are 2
angry 1
appetite 1
...
(By alphabetically I mean only by first letter)
So far, I have come up with this:
for (i = 0; i < length - 1; i++) {
min_pos = i;
for (j = i + 1; j < length; j++) // find min
if (array[j].word[0] < array[min_pos].word[0]) {
min_pos = j;
}
swap = array[min_pos]; // swap
array[min_pos] = array[i];
array[i] = swap;
}
This code works perfectly for sorting alphabetically, but I just can't write proper code to sort BOTH alphabetically and by length.
Make a comparator function.
Add an operator< to your List:
bool operator<(const List &lhs) const {
if(word[0] != lhs.word[0]) {
return word[0] < lhs.word[0];
}
return strlen(word) < strlen(lhs.word);
}
And now use this operator to sort, using whichever algorithm strikes your fancy.
Others have pointed out that there are faster and cleaner ways to sort. But if you want to use your own selection sort, as you've written, then you just need to make a few changes to your code.
Separate the "do I need to swap" logic from the swapping logic itself. Then the code becomes much cleaner and it's more clear where to add the extra check.
I've only copied the inner loop here. You'd want to replace your existing inner loop with this one. I'm not clear on why you need swap_pos and min_pos, so I've left the semantics alone.
for (j = i + 1; j < length; j++) { // find min
// first, determine whether you need to swap
// You want to swap if the first character of the new word is
// smaller, or if the letters are equal and the length is smaller.
bool doSwap = false;
if (array[j].word[0] < array[min_pos].word[0]) {
doSwap = true;
}
else if (array[j].word[0] == array[min_pos].word[0] &&
strlen(array[j].word) < array[min_pos].word) {
doSwap = true;
}
// do the swap if necessary
if (doSwap) {
swap_pos = j;
swap = array[min_pos]; // swap
array[min_pos] = array[i];
array[i] = swap;
}
}
To more clearly illustrate the necessary logic changes, I've purposely avoided making major style changes or simple optimizations.
You can pass a lambda to sort to do this:
sort(begin(array), end(array), [](const auto& lhs, const auto& rhs){ return *lhs.word < *rhs.word || *lhs.word == *rhs.word && (strlen(lhs.word) < strlen(rhs.word) || strlen(lhs.word) == strlen(rhs.word) && strcmp(lhs.word, rhs.word) < 0); });
Live Example
Use tuple lexicographical compare operators
An easy way to not write this condition is to
#include <tuple>
Then std::tie can be used:
std::tie(array[j].word[0], array[j].repeat) < std::tie(array[min_pos].word[0], array[min_pos].repeat)
This works because std::tie creates a tuple of lvalue references to its arguments. (Which means std::tie requires variables. If You want to compare results from functions std::make_tuple or std::forward_as_tuple would be better)
And std::tuple has operators which
Compares lhs and rhs lexicographically, that is, compares the first elements, if they are equivalent, compares the second elements, if those are equivalent, compares the third elements, and so on.
And the above description is also the idea how to make a comparison of more than value.

How to write shorter this "or" statement and is it right?

fail = 0;
if (masivs[0][0]>0 | masivs[0][1]>0 | masivs[0][2]>0| masivs[0][3]>0 |masivs[0][4]>0| masivs[0][5]>0|masivs[0][6]>0| masivs[0][7]>0|masivs[0][8]>0|masivs[0][9]>0)
{
fail = 1;
}
else {
fail = 0;
}
I need to check if in the 0 row is some positive element if yes then need to change fail to 1.
Use std::any_of (C++11) to clearly show your intent. I'll assume you have an array of ints. In C++14, however, you could replace the int below with auto and it would work for whatever type it is.
fail = std::any_of(
std::begin(masivs[0]), std::end(masivs[0]),
[](int i) {return i > 0;}
);
Make sure the array size is known such that std::begin and std::end will actually work (i.e., the array isn't actually a pointer).
For a completely pre-C++11 solution, you could use std::find_if and if you don't want to write your own predicate, you could use the now-deprecated std::bind2nd with the std::greater functor to bind 0:
int *end = masivs[0] + 9;
fail = (std::find_if(masivs[0], end, std::bind2nd(std::greater<int>(), 0)) != end);
Just use a for loop:
fail = 0;
int i;
for(i = 0; i < 10; i++) {
if(masivs[0][i] > 0) {
fail = 1;
break;
}
}
use a for loop to iterate through the columns in the row you want to check.

conditionally testing for equality of vector's elements

Although it seems pretty simple, I'm not sure of the most efficient way of doing this.
I have two vectors:
std::vector<bool> a;
std::vector<int> b;
a.size() necessarily equals b.size().
each bool in a corresponds to an int in b. I want to create a function:
bool test(std::vector<bool> a, std::vector<int> b);
This function returns true if the values in a are equal. However, it only considers values in a that correspond to true values in b.
I could do this:
bool test(std::vector<int> a, std::vector<bool> b){
int x;
unsigned int i;
for(i = 0; i < a.size(); ++i){
if(b.at(i) == true){
x = a.at(i);
break;
}
}
for(i = 0; i < a.size(); ++i){
if(b.at(i) == true){
if(a.at(i) != x){
return false;
}
}
}
return true;
}
But then I have to create two loops. Although the first loop will stop at the first true value, is there a better way?
Your solution looks good enough to me:
Each loop does a different thing anyway (so you shouldn't worry about duplication)
You don't use extranious variables or flags that complicate the code.
The only problems I see are:
You start the second loop at 0 instead of where you left off.
Doing if(condition == true) is very ugly. Just do if(condition) instead.
bool test(std::vector<int> a, std::vector<bool> b){
int x;
unsigned i;
for(i = 0; i < a.size(); i++){
if(b.at(i)){
x = a.at(i);
break;
}
}
for(i++; i < a.size(); i++){
if(b.at(i)){
if(a.at(i) != x){
return false;
}
}
return true;
}
You can do it in one loop if you remember if you have seen the first true element in b or not. Also, you should take the a and b parameters by reference to avoid unnecessary copying. And finally, if you know that the indices into a vector are always within valid range (i.e. between 0 and vector.size() - 1, inclusive), you can use operator[] instead of at, and achieve better peformance (at does a range check, while operator[] does not). Heres a modified version of your test function considering all the above points:
bool test(std::vector<int> const& a, std::vector<bool> const& b){
int x;
bool first = true;
for(unsigned i = 0, n = a.size(); i != n; ++i){
if( b[i] ){
if( first ) {
x = a[i];
first = false;
}
else if( x != a[i] ) {
return false;
}
}
}
return true;
}
Provided you know a.size() == b.size() just create a single loop that compares an 'a' element to a 'b' element at the same time at each iteration. Once you see that a[i] != b[i] then you know the containers don't match and you can break out.
I am not 100% certain I know what you want to do but a straight compare once you know you have equal size
std::equal(a.begin(), a.end(), b.begin(), std::equal_to<bool>())