I have the following code:
bool s = true;
for (...; ...; ...) {
// code that defines A, B, C, D
// and w, x, y, z
if (!(A < w) && s == true) {
s = false;
}
if (!(B < x) && s == true) {
s = false;
}
if (!(C < y) && s == true) {
s = false;
}
if (!(D < z) && s == true) {
s = false;
}
}
This code is working well. However, I want to, for several (unimportant) reasons, change the code so that I can initiate s = false; and set it to true inside the if-statement. It tried the following:
bool s = false;
for (...; ...; ...) {
// code that defines A, B, C, D
// and w, x, y, z
if (A >= w && s == false) {
s = true;
}
if (B >= x && s == false) {
s = true;
}
if (C >= y && s == false) {
s = true;
}
if (D >= z && s == false) {
s = true;
}
}
However, this is not working properly as the code above is working. I know thought wrong somewhere in the logic, but I can't figure out where. Does anbyone see my probably obvious error?
EDIT: Added three more if-statemets. Missed them since they were commented away.
De Morgan's laws says, you should also change && to || .
!(A < x) is the same as A >= x so your function hasn't reversed the logic at all. You need to use A < x.
I probably wouldn't bother checking the current state of s in the loop. Either you're flipping it or your not. And unless there's some reason to continue through the loop, I'd probably break after flipping s.
I found the answer on Wikipedias page on De Morgan's laws. The correct code for my problem is:
bool s = false;
for (...; ...; ...) {
// code that defines A, B, C, D
// and w, x, y, z
if (!(A >= w || s == false)) {
s = true;
}
if (!(B >= x || s == false)) {
s = true;
}
if (!(C >= y || s == false)) {
s = true;
}
if (!(D >= z || s == false)) {
s = true;
}
}
Thanks #EJP for the tip!
The part of the loop body that sets s is logically equivalent to this:
if(A >= w || B >= x || C >= y || D >= z)
s = false;
Which, abstracting the condition, is equivalent to this:
s &= some_function(A, B, C, D, w, x, y, z);
You want to change it to this:
s |= some_other_function(A, B, C, D, w, x, y, z);
In the first case, s is true after the loop if some_function returns false on every iteration of the loop. In the second true, s is true after the loop if some_other_function returns true on any iteration of the loop.
some_other_function can only ever return true if some_function would return true on any iteration. But some_other_function only has access to the values from the current iteration. Therefore a valid some_other_function cannot exist.
This is assuming s must have the same value after the loop in both cases. Otherwise, you could trivially swap true and false in all the places relating to s.
Related
I have following struct,
struct cube
{
int index l , b , h;
bool operator<(const cube & c2) const
{
if (l == c2.l && b == c2.b && h == c2.h)
return index < c2.index;
if (l == c2.l && b == c2.b)
return h < c2.h;
if (l == c2.l )
return b < c2.b;
return l < c2.l;
}
bool operator==(const cube c2)
{
return index != c2.index && l == c2.l && b == c2.b;
}
};
Now I want to apply upper_bound on vector of this struct as per condition in == operator.
However , it is still returning me those iterators where index are same
int pos2 = upper_bound(v.begin(),v.end(),v[i]) - v.begin();
i.e v[i].index is equal to v[pos2].index
It's possible that for two cube instances foo and bar that foo < bar is true when foo == bar is also true. You could fix that by writing index == c2.index && l == c2.l && b == c2.b as the returned expression in operator==.
This contradiction is the root cause of your issues, although note that std::upper_bound does itself only require that operator< is implemented appropriately; which yours is.
Isn't index more of a property of a collection of cubes rather than a given cube? That is, it shouldn't appear in the cube class?
here's a simple logic error I can't quite wrap my head around:
Why does the following statement always equate to true?
if ( (grid[i][0] && grid[i][1] && grid[i][2]) == ('X' || 'x') ) return true;
It works flawlessly for
if ( (grid[i][0] && grid[i][1] && grid[i][2]) == ('X') return true;
Do it like this:
create a function to check a character of being x:
bool isX(char c)
{
return c == 'X' || c == 'x';
}
and the you can write:
if ( isX(grid[i][0]) && isX(grid[i][1]) && isX(grid[i][2]))
return true;
That's because the expressions
'X' || 'x'
and
grid[i][0] && grid[i][1] && grid[i][2]
use the || and && operators between non-zero integer-typed values (because char is an integer type) and so they both evaluate to true.
To translate into C++ (or almost any other somewhat similar language, for that matter) that you want characters x, y and z to be equal to either of the characters c and C, you must compute
(x == c || x == C) && (y == c || y == C) && (z == c || z == C)
so apply that to your problem.
More importantly though, learn about boolean operators and programming in general before you try to tackle C++.
In the first case, it returns true because none of the grid elements has the value of zero. The && operator produces 0 or 1, depending on the values that you pass.
In the second case, it does not work as expected either: you wouldn't get an 'X' by &&-ing values together.
The proper way of checking if three items are equal to 'X' or not would be as follows:
if (toupper(grid[i][0]) == 'X'
&& toupper(grid[i][1]) == 'X'
&& toupper(grid[i][2]) == 'X') {
return true;
}
To generalize the concept of "win" in TiCTacToe, write a function that returns true when a sequence of three items with a specific step in each direction holds a sequence of a given character, like this:
bool isWin(int r, int c, int dr, int dc, char ch) {
return toupper(grid[r+0*dr][c+0*dc] == ch
&& toupper(grid[r+1*dr][c+1*dc] == ch
&& toupper(grid[r+2*dr][c+2*dc] == ch;
}
bool isWin(char ch) {
return isWin(0,0,0,1,ch)
|| isWin(0,0,1,0,ch)
|| isWin(1,0,0,1,ch)
|| isWin(0,1,1,0,ch)
|| isWin(2,0,0,1,ch)
|| isWin(0,2,1,0,ch)
|| isWin(0,0,1,1,ch)
|| isWin(2,0,-1,1,ch);
}
I've got a double[9] and want to check if it contains the values (1,0,0,0,1,0,0,0,1). Is there a cleaner way than this?
if (ornt1[0] == 1 && ornt1[1] == 0 && ornt1[2] == 0
&& ornt1[3] == 0 && ornt1[4] == 1 && ornt1[5] == 0
&& ornt1[6] == 0 && ornt1[7] == 0 && ornt1[8] == 1 )
I'm using C++.
It is not a good idea to compare double values strictly. I would recommend you create a constant array to compare against and then use a cycle and also use a tolerance(e.g. 1e-9):
bool doublesEqual(double a, double b) {
return fabs(a - b) < 1e-9;
}
const double expected[9] = {1,0,0,0,1, 0, 0, 0, 1};
bool equal = true;
for (int i = 0; i< 9; ++i) {
if (!doublesEqual(expected[i], ornt1[i])) {
equal = false;
break;
}
}
if (equal) { // do smth
EDIT: as suggested by John Zwinck I have edited the code to be able to handle the case when the array we compare contains only NAN. I have edited his suggestion a bit to make the code more readable. Please refer to his comment below for clarification why this is needed.
I was just writing an improved linear version of a recursive Fibonacci algorithm, and realized that my boolean expressions look really bad and unreadable. Is there a cleaner way to do what I'm trying to do?
int fibonacci(int num) {
if (num <= 1)
return num;
// starts looking ugly here
int a = intExists(num-1);
int b = intExists(num-2);
bool aAndB = (a != -1 && b != -1);
bool justA = (a != -1 && b == -1);
bool justB = (a == -1 && b != -1);
int number = 0;
if (aAndB)
number = (a + b);
else if (justA)
number = (a + fibonacci(num - 2));
else if (justB)
number = (fibonacci(num-1) + b);
else
number = (fibonacci(num - 1) + fibonacci(num - 2));
map.push_back(Pair(num, number));
return number;
}
Thanks
If you're talking about:
bool aAndB = (a != -1 && b != -1);
then I would say, "no."
This code looks perfectly expressive to me. aAndB is initialized at the moment it comes in to being, and the conditions are very clear. This might look a bit odd when you're first starting out in C++, but before you know it it will be second nature and other constructs will seem silly.
One thing I would suggest is to make aAndB const if you don't intend to change it:
const bool aAndB = (a != -1 && b != -1);
This is even more expressive.
It also might give the compiler an additional opportunity to optimize your code.
Remember -- write code for humans to understand. Not for computers to understand.
Why don't you make a and b as bools and assign those as true if a == -1 and false otherwise. Then, the expressions will become easier to handle.
Could do a switch statement to clean up the if else statements a little. Other than that just add comments
You could rewrite it to use conditional branching, like this:
int fibonacci(int num) {
if (num <= 1)
return num;
int a = intExists(num-1);
int b = intExists(num-2);
const bool isA = (a != -1); // change in the definition
const bool isB = (b != -1); // change in the definition
int number = 0;
if (isA && isB)
number = (a + b);
else if (isA) // conditionnal branching
number = (a + fibonacci(num - 2));
else if (isB) // conditionnal branching
number = (fibonacci(num-1) + b);
else
number = (fibonacci(num - 1) + fibonacci(num - 2));
map.push_back(Pair(num, number));
return number;
}
I'm assuming that intExists(n) looks up map and if finds n in there, returns fibonacci(n) else it returns -1. Then you could do this:
int fibonacci(int num) {
if (num <= 1)
return num;
int a = intExists(num-1);
int b = intExists(num-2);
if (a == -1) // if a wasn't found, then compute it
a = fibonacci(num-1);
if (b == -1) // if b wasn't found, then compute it
b = fibonacci(num-2);
int number = a + b;
map.push_back(std::make_pair(num, number));
return number;
}
Bonus:
Here is another completely different implementation of fibonnacci() based on Binet's formula:
#include <cmath>
int fibonacci(int n) {
static const double e1 = 1.6180339887498948482045868343656; // = (1 + sqrt(5)) / 2
static const double e2 = -0.61803398874989484820458683436564; // = (1 - sqrt(5)) / 2
static const double c = 0.44721359549995793928183473374626; // = 1 / sqrt(5);
double f = c * (std::pow(e1, n) - std::pow(e2, n));
return static_cast<int>(f + 0.5);
}
int main() {
for (int n = 1; n < 15; ++n)
std::cout << fibonacci(n) << ' ';
}
It outputs:
1 1 2 3 5 8 13 21 34 55 89 144 233 377
Plain C++ code is clean enough:
bool a = intExists(num-1);
bool b = intExists(num-2);
if (a && b) {
//
} else if (a) {
//
} else if (b) {
//
} else {
//
}
int a = intExists(num-1);
int b = intExists(num-2);
bool aAndB = (a != -1 && b != -1);
bool justA = (a != -1 && b == -1);
bool justB = (a == -1 && b != -1);
Quick look into the approach you took. Under what circumstances can justB be true? (Hint: never)
That should help you simplify your approach, although there are better approaches than memoization.
Changing intExists to return boolean values, you can do a switch-case statements like that:
bool a = intExists(num-1);
bool b = intExists(num-2);
switch ((a << 1) + b) {
default: // none exists
case 1: // only b exist
case 2: // only a exist
case 3: // both exists
}
The rationale is to transform those booleans in a binary number
A slightly drastic rewrite is to let an external function handle the lookup table.
That way you don't need to care about more than one value at a time.
This one uses map so I didn't have to write so much in order to test it, but it should be easy enough to adapt:
std::map<int, int> table;
int fibonacci(int num);
int value(int num)
{
int result = table[num];
if (!result)
{
result = fibonacci(num);
table[num] = result;
}
return result;
}
int fibonacci(int num)
{
if (num <= 2)
return 1;
return value(num - 1) + value(num - 2);
}
I am trying to use the std::set to contain a struct of three member variables.
struct blah{
int a,b,c;
bool operator < ( const blah& blo ) const{
return ( a < blo.a || (a == blo.a && (b != blo.b || c != blo.c ) ) );
}
};
But I keep getting an error that my operator < is invalid. What is wrong with my approach?
struct blah {
int a,b,c;
blah(int aa,int bb,int cc){ a=aa; b=bb; c=cc; }
bool operator < ( const blah& blo ) const{
return ( a < blo.a
|| (a == blo.a && b < blo.b )
|| (a == blo.a && b == blo.b && c < blo.c )
);
}
};
int main() {
std::set<blah> st;
st.insert(blah(1,2,3));
st.insert(blah(1,1,1));
st.insert(blah(1,3,2));
return 0;
}
After altering the code following #paxdiablo code, this worked well. Thanks y'all!
That code compiles fine for me in the following complete program:
#include <iostream>
struct blah {
int a,b,c;
bool operator < ( const blah& blo ) const{
return ( a < blo.a || (a == blo.a && (b != blo.b || c != blo.c ) ) );
}
};
int main (void) {
blah x, y;
x.a=2; x.b=2; x.c=2;
y.a=2; y.b=2; y.c=2;
if (x < y) std::cout << "x<y\n";
if (y < x) std::cout << "x>y\n";
if (!(y < x) && !(x < y)) std::cout << "x=y\n";
return 0;
}
Changing the fields of x and y outputs different messages.
But I see one major problem with the function. It can tell you that both x < y and y < x, in the situation where the two a fields are identical but the b fields differ between the two. If you set both a fields to 1 and set the b fields to 2 and 1, you see:
x<y
y<x
That's not going to end well :-)
The fact that what you're getting is a debug assertion (something specifically built to catch runtime errors in mostly debug code) leads me to believe that the runtime libraries may explicitly be checking for incorrect operator< overloads by detecting that latter case (ie, both x < y and y < x are true).
You should really fix that because it will cause all sorts of problems with collections where (for example) you need to keep things sorted.
By way of example, let's say you wanted to use a, b and c as keys in that priority. A function to do that would contain something like:
// Check primary key.
if (a < blo.a) return true;
if (a > blo.a) return false;
// Primary key equal here, use secondary key.
if (b < blo.b) return true;
if (b > blo.b) return false;
// Primary and secondary keys equal here, use tertiary key.
return (c < blo.c);