I am working on a game, and I am finding myself very often checking that certain quantities are in the bounds of the indexes accepted by the vector that represents my world:
if(a >= 0 && a < 16 && b >= 0 && b < 16 && c >= 0 && c < 16 &&
d >= 0 && d < 16 && e >= 0 && e < 16)
{
//do things with vector[a][b][c][d][e]
}
I often have to check even more conditions than this. Is there a way that I can make these checks more concise and/or easier to read?
Alternatively, is there a way that I can avoid doing the checks entirely? The vector is 16x16x16x16x16; can I make it so that if I were to give it a 16 as an index, it would do nothing rather than segfault?
You could write a variadic check function:
bool check(int a) {
return 0 <= a && a < 16;
}
template<typename... Args>
bool check(int a, Args... args) {
return check(a) && check(args...);
}
You can use it like check(a, b, c, d, e, ...). It also has the advantage of being able to take any number of conditions.
Here's a demo
Here's a compact and efficient way to do the check. It assumes two's complement arithmetic.
bool IsInBounds(int a, int b, int c, int d, int e)
{
// Make sure only bits 0-3 are set (i.e. all values are 0-15)
return ((a | b | c | d | e) & ~0xf) == 0;
}
This works by noting that all values outside the 0-15 range all have a bit set that isn't one of the four least significant ones, and all values inside the range don't.
Of course it's only worth using this sort of optimization if the gains in efficiency outweigh the loss of code readability.
The point of functions is reusability. If you find yourself writing certain long expressions or groups of statements repeatedly, it might be time to refactor it out.
In this case, I would write a simple function to do the bounds checking:
bool isInBounds(int a, int b, int c, int d, int e)
{
return a >= 0 && a < 16 &&
b >= 0 && b < 16 &&
c >= 0 && c < 16 &&
d >= 0 && d < 16 &&
e >= 0 && e < 16;
}
Then use it instead of your long condition:
if (isInBounds(a, b, c, d, e))
{
// do things with array[a][b][c][d][e]
}
You can store your variables as elements in a std::vector rather than separate variabes like this:
bool test(const std::vector<int>& values)
{
for(auto v: values)
if(v < 0 || v >= 16)
return false;
return true;
}
Alternatively if you are using C++11 or later you can use std::all_of:
if(std::all_of(std::begin(values), std::end(values),
[](int i){ return i >= 0 && i < 16; }))
{
// do stuff with values
}
In that case you may also be able to use a std::array.
You could combine the 5 integers making up your index into one std::array or your own class.
using Index5 = std::array<int, 5>;
Then you can write a function like:
bool contains(Index5 bounds, Index5 point) {
for (Index5::size_type d = 0; d != bounds.size(); ++d) {
if ((unsigned)point[d] > bounds[d]) // using the trick mentioned in comments
return false;
}
return true;
}
Then use it like this:
auto bounds = Index5{16, 16, 16, 16, 16};
auto point = Index5{a, b, c, d, e};
if (contains(bounds, point)) {
// do things with point
}
Generally, I would suggest using something like Index5 instead of managing five integers.
If the quantities a, b, c, d, and e are something that occur
together quite frequently and all need to stay within the bounds
of your "world" (e.g. they represent the "state" of something in that world)
then it might make sense to define a class whose primary purpose is
to hold one "state" consisting of those five quantities.
Then make sure that if any code ever tries to store values in an object
of that class that are not within the bounds, something reasonable
(not a segfault) happens instead,
and no out-of-bounds values are ever stored there.
That way, an object of that class is safe to pass to any function that
requires a, b, c, d, and e to be within bounds,
and there is no need for any such function to do bounds-checking
on those five values.
Related
As far as I know, integers in C++ can be treated like booleans, and we can have a code like this:
int a = 6, b = 10;
if (a && b) do something ---> true as both a and b are non-zero
Now, assume that we have:
__m256i a, b;
I need to apply logical_and (&&) for all 4 long variables in __m256i, and return true if one pair is non-zero. I mean something like:
(a[0] && b[0]) || (a[1] && b[1]) || ...
Do we have a fast code in AVX or AVX2 for this purpose?
I could not find any direct instruction for this purpose, and definitely, using the bitwise and (&) also is not the same. Any help will be greatly appreciated.
You can cleverly combine a vpcmpeqq with a vptest:
__m256i mask = _mm256_cmpeq_epi64(a, _mm256_set1_epi64x(0));
bool result = ! _mm256_testc_si256(mask, b);
The result is true if and only if (~mask & b) != 0 or
((a[i]==0 ? 0 : -1) & b[i]) != 0 // for some i
// equivalent to
((a[i]==0 ? 0 : b[i])) != 0 // for some i
// equivalent to
a[i]!=0 && b[i]!=0 // for some i
which is equivalent to what you want.
Godbolt-link (play around with a and b): https://godbolt.org/z/aTjx7vMKd
If result is a loop condition, the compiler should of course directly do a jb/jnb instruction instead of setnb.
I need to combine 3 bools to test for the entire truth table (8 combinations) in c++.
I have 2 special cases that need to be attended to, they are a, b and c are all true, and a, b are true but c is false.
The rest don't need to be catered for specifically (they will work automatically together without case-specific instructions)
is there a way to only test for these two cases, and then the individual cases but still allow the individuals to work together?
Such as,
if(a && b && c)
and if(a && b && !c)
then if a, if b, if c respectively
I think it uses if else, but I'm having no luck, the way I have it now performs some operations twice as "a" is true in a b c, a b !c and also in a.
I hope this is clear enough, my first time posting here so apologies if it is not.
Your two special cases can be handled something like:
if (a && b)
if (c)
all_true();
else
ab_true_c_false();
Another possibility would be to combine the three arithmetically, then use the result as an index:
typedef void (*action)();
// handlers for the individual cases:
void all_false() { std::cout << "all_false"; }
void a_true() { std::cout << "a true"; }
// ...
// table of handlers. The order of handlers in the array is critical.
static const action actions[] = {
all_false, a_true, b_true, ab_true,
c_true, ac_true, bc_true, abc_true };
// Create index into array
int x = a | (b << 1) | (c << 2);
// invoke correct handler:
actions[x]();
I am looking for a simple way to increment/decrement a number away from n, without using if statements, or creating a function. Here is an example:
Increment x from 9 to 10, n is 6
Decrement x from 3 to 2, n is 6
An obvious way to do this is with if statements, but that seems like too much code in my opinion. Here is a function that I could imagine using:
x += 1 * GetSign(6, 9) //GetSign(A, B) returns 1 or -1 depending on what would
Be necessary to move farther away from 6. The made up function above would look something like:
int GetSign(A, B)
{
if( A < B) return -1;
else return 1;
}
You can use the ternary operator:
int A = 6;
int B = 9;
x += (A < B) ? (-1) : (1);
I have a function that deals with arbitrarily large grids. I need to compute if a grid to the power of another number will fit into a double due to using std::pow. If it cannot, I want to take a different branch and use gnu multiprecision library instead of normal.
Is there a quick way to see if:
int a = 1024;
int b = 0-10;
if(checkPowFitsDouble(a, b)) {
long c = static_cast<long>(std::pow(a, b)); //this will only work if b < 6
} else {
mpz_t c; //yada yada gmp
}
I am completely stumped on checkPowFitsDouble; perhaps there is some math trick I don't know of.
A common trick to check whether exponentiations will overflow uses logarithms. The idea is based on these relationships:
a^b <= m <=> log(a^b) <= log(m) <=> b * log(a) <= log(m) <=> b <= log(m) / log(a)
For instance,
int a = 1024;
for (int b = 0; b < 10; ++b) {
if (b * std::log(a) < std::log(std::numeric_limits<long>::max())) {
long c = std::pow(a, b);
std::cout << c << '\n';
}
else
std::cout << "overflow\n";
}
This gives the idea. I hope this helps.
Unless it's particularly performance-critical, the suggestion would be to try it and see. If it overflows a double, std::pow will return HUGE_VAL. Hence something like:
double val = std::pow(a, b);
if(val != HUGE_VAL) {
...
} else {
mpz_t c;
//...
}
You can easily use the reverse functions in the test:
if ( std::log( DBL_MAX ) / std::log( a ) < b ) {
// std::pow( a, b ) will not overflow...
} else {
}
It might be just as good to just do the pow, and see if it
succeeds:
errno = 0;
double powab = std::pow( a, b );
if ( errno == 0 ) {
// std::pow succeeded (without overflow)
} else {
// some error (probably overflow) with std::pow.
}
You won't gain much time by just calculating std::log( a ).
(std::log( DBL_MAX ) is, of course, a constant, so only needs
to be calculated once.)
With a logarithm base 10, you can deduce that std:pow(a, b) has log(a^b) = b log a digits. You can then trivially see if it fits a double, which can fit values up to DBL_MAX.
However, this method performs additional computation than just computing a^b once. Measure a version with GMP first and see if checking for overflow actually provides any measurable and reproducible benefits.
EDIT: Ignore this, std::pow already returns an appropriate value in case an overflow occurs, so use that.
I need help with this problem POUR1. I think
it can be solved with bruteforce approach, but I read that it is a graph problem (BFS). I solved problems like ABCPATH, LABYR1, PT07Y, PT07Z, BITMAP, ...
But I don't know how to approach POUR1 in BFS manner.
Can someone give me some advice?
Problem statement:
Given two vessels, one of which can accommodate a litres of water and the other - b litres of water, determine the number of steps required to obtain exactly c litres of water in one of the vessels.
At the beginning both vessels are empty. The following operations are counted as 'steps':
emptying a vessel,
filling a vessel,
pouring water from one vessel to the other, without spilling, until one of the vessels is either full or empty.
Input:
An integer t, 1<=t<=100, denoting the number of testcases, followed by t sets of input data, each consisting of three positive integers a, b, c, not larger than 40000, given in separate lines.
Output:
For each set of input data, output the minimum number of steps required to obtain c litres, or -1 if this is impossible.
Example:
Sample input:
2
5
2
3
2
3
4
Sample output:
2
-1
This question has a simpler solution. No need for BFS. Ad-hoc would do good.
method 1 - fill A, empty it into B. whenever A becomes empty fill it back, whenever B becomes full empty it. (all the above-mentioned actions count as individual moves). Continue this process until you arrive at the required amount of water in any one of the vessels. Get the number of moves here. (say C1).
method 2 - fill B, empty it into A. whenever B becomes empty fill it back, whenever A becomes full empty it. Continue this until you arrive at the required amount. Get the number of moves say C2).
The answer is min(C1,C2).
Source code in C++:
#include < cstdio >
#include < algorithm >
using namespace std;
int pour(int A, int B, int C) {
int move = 1, a = A, b = 0, tfr;
while (a != C && b != C) {
tfr = min(a, B - b);
b += tfr;
a -= tfr;
move++;
if (a == C || b == C)
break;
if (a == 0) {
a = A;
move++;
}
if (b == B) {
b = 0;
move++;
}
}
return move;
}
/** Reason for calculating GCD of a,b is to check whether an integral solution of
* equation of form ax + by = c exist or not, to dig deeper read Diophantine Equations
*/
int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
int main() {
int t, a, b, c;
scanf("%d", & t);
while (t--) {
scanf("%d%d%d", & a, & b, & c);
if (c > a && c > b)
printf("-1\n");
else if (c % gcd(a, b) != 0)
printf("-1\n");
else if (c == a || c == b)
printf("1\n");
else
printf("%d\n", min(pour(a, b, c), pour(b, a, c)));
}
return 0;
}
Consider the set of all a priori possibles states (eg [3, 7] meaning Vessel1 contains 3 litters and vessel2 contains 7 litters). You have a directed graph whose vertices are those states and whose edges are the possible moves. The question is to find a path in the graph joining the state [0, 0] to either a state of type [c, ?] or a state of type [?, c]. Such a path is typically searched by a BFS.