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; }
}
Related
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1043:9
was the remainder of the error message.
I have been working to solve the Merge 2 sorted arrays problem (https://leetcode.com/explore/learn/card/fun-with-arrays/525/inserting-items-into-an-array/3253/) for the past hour, using the vector insert function as below:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int j=0;
if(nums1.empty() || nums1.size()==1){
nums1.push_back(nums2[0]);
return;
}
if(nums2.empty()){
return;
}
for(int i=0; i<(m+n); i++){
if(j<n){
if(nums1[i]<nums2[j] && nums1[i+1] >= nums2[j]){
nums1.insert(nums1.begin()+i+1, nums2[j]);
j++;
}
if(nums1[i]<nums2[j] && nums1[i+1]==0){
nums1.insert(nums1.begin()+i+1, nums2[j]);
j++;
}
}
cout << j;
}
int size = nums1.size()-1;
if(nums1.size()>1){
int resiz = m+n;
nums1.resize(resiz);
}
return;
}
};
I have got to the right solution using this. I have to resize at the end to get rid of the trailing 0s since the insert() method increases the vector size each time.
The problem lies in the test case
[1] // contents of array 1
1 // size of vct 1
[] // contents of array 2
0 // size of vct 2
Of course there may be better ways to solve the problem (and I'd appreciate those suggestions), but I'd like to understand what's causing this, since I have explicitly tried to deal with these edge cases in code.
Your solution
The only edge case is m=0 which should easily be handled by setting nums1=nums2. Aside from that, there are a few logic bugs presented in your code. I have put comments besides the lines I changed.
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int j=0;
if(m==0){ //edge case
nums1 = nums2;
return;
}
constexpr int IMPOSSIBLE = int(1e9+1);
for (int i=m; i<n+m; i++) {
// initialize it to an "impossible" value instead of 0 which could be a valid value!
nums1[i]=IMPOSSIBLE;
}
for(; j<n; j++){ // handle element in nums2 smaller than nums[0] first
if(nums2[j]<=nums1[j]){
nums1.insert(nums1.begin()+j,nums2[j]);
} else {
break;
}
}
for(int i=0; i<(m+n); i++){
if(j<n){
if(nums1[i]<=nums2[j] && i+1<int(nums1.size()) && nums1[i+1] >= nums2[j]){
// The correct logic should be nums1[i]<=nums2[j](e.g. nums1=[1,0,0],n=1,nums2=[2,2],m=2)
nums1.insert(nums1.begin()+i+1, nums2[j]);
j++;
} else if(nums1[i]<=nums2[j] && i+1<int(nums1.size()) && nums1[i+1]==IMPOSSIBLE){
/*
1. The correct logic should be nums1[i] <=nums2[j],
but since IMPOSSIBLE is initialized to the largest value possible,
either < and <= will work here.
2. You must use elseif here, otherwise j may be incremented!
3. 0 does not mean empty cause it could be the real value in nums1[i+1]
*/
nums1.insert(nums1.begin()+i+1, nums2[j]);
j++;
}
}
}
int size = nums1.size()-1;
if(nums1.size()>1){
int resiz = m+n;
nums1.resize(resiz);
}
return;
}
};
Suggestions
Merging two sorted arrays is a very well-known and standard problem. The canonical way is to use two pointers. It will be much cleaner and I highly advise you to read about it.
An even cleaner approach is to use std::merge provided by C++ STL which achieves exactly the same purpose, although it might be a bit... cheaty for your purpose? (I assume you are learning algorithms)
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
vector<int> nums3;
nums3.reserve(n+m);
std::merge(nums1.begin(), nums1.begin()+m, nums2.begin(), nums2.begin(), std::back_inserter(nums3));
nums1=nums3;
return;
}
};
Both solutions above takes O(n+m) time, while your solution is O((n+m)*m), as std::vector::insert takes O(n+m) time
I have been working on a project for school to develop a poker game. I have the code that randomly generates the cards, but I am having problems using functions to sort them. I believe the algorithm itself works, but I am not sure about how to properly access the variables in an array. Visual Studio gives me the errors argument of type "int (*)[5] is incompatible with parameter of type int *(*)[5] and 'void sortPokerHand(int *[][5])': cannot convert argument 1 from 'int [2][5]' to 'int *[][5]'.
The declaration of pokerHand within main()
int pokerHand[2][5];
My functions
//swap the two values
void swap(int* pokerHand, int* x, int* y)
{
int tempVal = pokerHand[0][x];
int tempSuit = pokerHand[1][x];
pokerHand[0][x] = pokerHand[0][y];
pokerHand[1][x] = pokerHand[1][y];
pokerHand[0][y] = tempVal;
pokerHand[1][y] = tempSuit;
}
void sortPokerHand(int* pokerHand[2][5])
{
//bubble sort poker hand
bool swapped;
for (int i = 0; i < 4; i++)
{
swapped = false;
for (int j = 0; j < (5 - i - 1); j++)
{
if (pokerHand[0][j] > pokerHand[0][j + 1])
{
swap(pokerHand[2][5], pokerHand[0][j], pokerHand[0][j + 1]);
swapped = true;
}
}
// If no two elements were swapped by inner loop, then break
if (swapped == false)
break;
}
}
How I am attempting to use the function
sortPokerHand(pokerHand);
Thanks for any help
You're making this much, much harder than it should be. Consider the following pre-conditions:
A "hand" is a sequence of five int values
Only cards in a single hand are sorted relative to each other.
Given that, your swap routine is completely wrong. It should take two int by address (so, pointers to int), and use those to swap contents:
void swapInt(int *left, int *right)
{
int tmp = *left;
*left = *right;
*right = tmp;
}
Next, when sorting, we're sorting a single hand. That means a single sequence of five int. Therefore, there is no need to pass arrays of arrays, pointers to arrays, arrays of pointers, or any of that. Just do this, clean and basic:
// assumption: a hand has five cards
void sortPokerHand(int hand[])
{
// bubble sort sequence of int
size_t len = 5;
bool swapped = true;
while (swapped && len-- > 0)
{
swapped = false;
for (size_t i = 0; i < len; ++i)
{
if (hand[i] > hand[i + 1])
{
swapInt(hand + i, hand + i + 1); // note: uses our new swap function
swapped = true;
}
}
}
}
Finally, we need somehands, both needing sorting. For the sake of this example I'm declaring them in main() as inline array of arrays, then making two calls to actually sort them, one at a time. First, however, we need a print function:
void printHand(const int hand[])
{
fputc('{', stdout);
for (size_t i = 0; i < 5; ++i)
printf("%d ", hand[i]);
puts("}");
}
Simple enough. Now main()
int main()
{
int hands[2][5] =
{
{ 5,10,7,4,1 },
{ 3,6,8,2,9 }
};
for (size_t i = 0; i < 2; ++i)
{
sortPokerHand(hands[i]);
printHand(hands[i]);
}
return EXIT_SUCCESS;
}
The output of this program is:
{1 4 5 7 10 }
{2 3 6 8 9 }
Exactly as we expect.
That's it. In more general solutions we would have an arbitrary hand-size an have to ripple that through the sort and print functions to ensure complete and proper activity. Knowing it is statically size five makes that a little easier.
Also note that you can completely change the definition of hands to use pointers-to-arrays rather than arrays of arrays, or even pointers to pointers, and it will still work, so long as the thing going to sortHand and/or printHand is int* pointing to five int values.
The real question would be how you're ending up with something like int *pokerHand[2][5] in the first place.
One of the strengths of C++ is a fairly rich type system. If I were doing this, I'd probably start by defining a type for a card:
class card {
enum { clubs, diamonds, spades, hearts } suit;
int value; // 1-13 = Ace - King
public:
bool operator<(card const &other) {
if (suit < other.suit)
return true;
if (other.suit < suit)
return false;
return value < other. value;
}
};
So, that operator< sorts first by suit, then by value within the suit, so all the cards in the same suit will get sorted together.
From there, a poker hand is typically going to be five cards, so we just have:
std::vector<card> poker_hand;
Sorting the hand is something like:
std::sort(poker_hand.begin(), poker_hand.end());
If you want to write your own sort routine you obviously can, but it still ends up pretty trivial--a single-dimension vector of cards, which you just compare directly, such as:
if (secondCard < firstCard)
swap(secondCard, firstCard);
Change int* pokerHand[2][5] to int** pokerHand.
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.
I'm need of some advice and helpful pointers to get me in the right direction. My function is intended to calculate how many even numbers there are between input a and input b.
int evens(int a, int b)
{
int p = 0;
for(int i=a; i<=b; i++)
{
if(i % 2==0)
++p;
return (p);
}
}
Logically, this function makes sense to me and it's easy to understand what's going on. However, when I run the program it returns P as being "1" no matter what the input #'s are. This leads me to believe that the loop is for some reason only run once and then that's it.
You're returning too early. Put it outside of the loop.
Could rewrite it like this though:
int evens(int a, int b) {
if(a != b)
return ((b-a)/2)+1; //I can't think straight, I don't know why
else {
if(a % 2 == 0)
return 1;
else
return 0;
}
}
I have a vector containing large number of elements. Now I want to write a small function which counts the number of even or odd elements in the vector. Since performance is a major concern I don't want to put an if statement inside the loop. So I wrote two small functions like:
long long countOdd(const std::vector<int>& v)
{
long long count = 0;
const int size = v.size();
for(int i = 0; i < size; ++i)
{
if(v[i] & 1)
{
++count;
}
}
return count;
}
long long countEven(const std::vector<int>& v)
{
long long count = 0;
const int size = v.size();
for(int i = 0; i < size; ++i)
{
if(0 == (v[i] & 1))
{
++count;
}
}
return count;
}
My question is can I get the same result by writing a single template function like this:
template <bool countEven>
long long countTemplate(const std::vector<int>& v1)
{
long long count = 0;
const int size = v1.size();
for(int i = 0; i < size; ++i)
{
if(countEven)
{
if(v1[i] & 1)
{
++count;
}
}
else if(0 == (v1[i] & 1))
{
++count;
}
}
return count;
}
And using it like this:
int main()
{
if(somecondition)
{
countTemplate<true>(vec); //Count even
}
else
{
countTemplate<false>(vec); //Count odd
}
}
Will the code generated for the template and non-template version be the same ? or will there be some additional instructions emitted?
Note that the counting of numbers is just for illustration hence please don't suggest other methods for counting.
EDIT:
Ok. I agree that it may not make much sense from performance point of view. But atleast from maintainability point of view I would like to have only one function to maintain instead of two.
The templated version may and, very probably, will be optimized by the compiler when it sees a certain branch in the code is never reached. The countTemplate code for instance, will have the countEven template argument set to true, so the odd branch will be cut away.
(sorry, I can't help suggesting another counting method)
In this particular case, you could use count_if on your vector:
struct odd { bool operator()( int i )const { return i&1; } };
size_t nbOdd = std::count_if( vec.begin(), vec.end(), odd() );
This can also be optimized, and writes way shorter :) The standard library developers have given possible optimization much thought, so better use it when you can, instead of writing your own counting for-loop.
Your template version will generate code like this:
template <>
long long countTemplate<true>(const std::vector<int>& v1)
{
long long count = 0;
const int size = v1.size();
for(int i = 0; i < size; ++i)
{
if(true)
{
if(v1[i] & 1)
{
++count;
}
}
else if(0 == (v1[i] & 1))
{
++count;
}
}
return count;
}
template <>
long long countTemplate<false>(const std::vector<int>& v1)
{
long long count = 0;
const int size = v1.size();
for(int i = 0; i < size; ++i)
{
if(false)
{
if(v1[i] & 1)
{
++count;
}
}
else if(0 == (v1[i] & 1))
{
++count;
}
}
return count;
}
So if all optimizations are disabled, the if will in theory still be there. But even a very naive compiler will determine that you're testing a constant, and simply remove the if.
So in practice, no, there should be no difference in the generated code. So you can use the template version and don't worry about this.
I guess that good compiler will cut redundant code in your template as countEven is compile time constant and it is very simple to implement such optimization during template instantiation.
Anyway it seems pretty strange. You wrote a template but do "dynamic switching" inside.
May be try something like that:
struct CountEven {}
struct CountOdd {}
inline void CountNum(int & num, long long & count, const CountEven &)
{
if(num & 1)
{
++count;
}
}
inline void CountNum(int & num, long long & count, const CountOdd &)
{
if(0 == (num & 1))
{
++count;
}
}
template <class T>
long long countTemplate(const std::vector<int>& v1)
{
long long count = 0;
const int size = v1.size();
for(int i = 0; i < size; ++i)
{
CountNum(v1[i], count, T());
}
return count;
}
It will select necessary CountNum() function version on compilation stage:
int main()
{
if(somecondition)
{
countTemplate<CountEven>(vec); //Count even
}
else
{
countTemplate<CountOdd>(vec); //Count odd
}
}
Code is messy, but I think you got the idea.
This will depend on how smart the compiler optimizer is. The compiler might be able to see that really the if-statement is redundant and only one branch of it is executed and optimize the whole thing.
The best way to check is to try and look at the assembly - this code will not produce too much of machine code.
The first thing that comes to my mind are the two optimization "rules":
Don't optmized prematurely.
Don't do it yet.
The point is that sometimes we bother about a performance bottleneck which will never happen in practice. There are studies that say that 20 percent of the code is responsible for 80 percent of the software execution time. Of course this doesn't mean you pessimize prematurely, but I don't think that's your case.
In general, you should do this kind of optmization only after you have actually run a profiler on your program and identified the real bottlenecks.
Regarding your function versions, as other have said this depends on your compiler. Just remember that with the template approach you won't be able to switch calls at runtime (template is a compile-time tool).
A final note: long long is not standard C++ (yet).
If you care about optimization issues try to make it like the following:
template <bool countEven>
long long countTemplate(const std::vector<int>& v1)
{
long long count = 0;
const int size = v1.size();
for ( int i = 0; i < size; ++i ) {
// According to C++ Standard 4.5/4:
// An rvalue of type bool can be converted to an rvalue of type int,
// with false becoming zero and true becoming one.
if ( v1[i] & 1 == countEven ) ++count;
}
return count;
}
I believe that the code above will be compiled in the same code as without templates.
Use STL, Luke :-) It's even as example in reference
bool isOdd(int i)
{
return i%2==1;
}
bool isEven(int i)
{
return i%2==0;
}
std::vector<int>::size_type count = 0;
if(somecondition)
{
count = std::count_if(vec.begin(), vec.end(), isEven);
}
else
{
count = std::count_if(vec.begin(), vec.end(), isOdd);
}
In general, the outcome will be much the same. You are describing an O(n) iteration over the linear memory of the vector.
If you had a vector of pointers, suddenly the performance would be way worse because the memory locality of reference would be lost.
However, the more general thing is that even netbook CPUs can do gazallions of operations per second. Looping over your array is most unlikely to be performance-critical code.
You should write for readability, then profile your code, and consider doing more involved hand-tweaked things when the profiling highlights the root cause of any performance issue you have.
And performance gains typically come from algorithmic changes; if you kept count of the number of odds as you added and removed elements from the vector, for example, it would be O(1) to retrieve...
I see that you're using long long for counter, and that probably means that you expect huge number of elements in vector. In that case, I would definitely go for template implementation (because of code readability) and just move that if condition outside for loop.
If we assume that compiler makes no optimization whatsoever, you would have 1 condition and possibly more than 2 billion iterations through vector. Also, since the condition would be if (true) or if (false) the branch prediction would work perfectly and execution would be less than 1 CPU instruction.
I'm pretty sure that all compilers on the market have this optimization, but I would quote my favorite when it comes to performance: "Premature optimization is the root of all evil" and "There're only 3 rules of optimization: Measure, measure and measure".
If you absolutely absurdly care about fast looking code:
(a clever compiler, or one otherwise hinted at using directives or intrinsics, could do this in parallel using SIMD; CUDA and OpenCL would of course eat this for breakfast!)
int count_odd(const int* array,size_t len) {
int count = 0;
const int* const sentinal = array+len;
while(array<sentinal)
count += (*array++ & 1);
return count;
}
int count_even(const int* array,size_t len) {
return len-count_odd(array,len);
}