I was wondering if we could get rid of all the "if" statements only by using boolean logic.
int main() {
int a,b,c,d;
char e;
scanf("%d %d %d", &a, &b, &c);
scanf("%d", &d);
if (d == 0)
{
e = 'O'*((a+b == c) || (a+c == b) || (b+c == a));
e += (e == 0)*'X';
printf("%c\n",e);
}
if (d == 1)
{
e = 'O'*((a*b == c) || (a*c == b) || (b*c == a));
e += (e == 0)*'X';
printf("%c\n",e);
}
}
So far I've been able to replace
if ((a+b == c) || (a+c == b) || (b+c == a))
{
e = '0';
}
else
{
e = 'X';
}
by
e = 'O'*((a+b == c) || (a+c == b) || (b+c == a));
e += (e == 0)*'X';
is there any way to get rid of the lines
if (d == 0)
and
if (d == 1)
using the same logic?
As you wish, no if-statement left:
!d && (
(e = 'O'*((a+b == c) || (a+c == b) || (b+c == a))),
(e += (e == 0)*'X'),
printf("%c\n",e)
);
d-1 || (
(e = 'O'*((a*b == c) || (a*c == b) || (b*c == a))),
(e += (e == 0)*'X'),
printf("%c\n",e)
);
I abused short-circuiting of ||, && and the comma-operator ,.
Anyway, if you want to see the masters in obfuscation, look at
The International Obfuscated C Code Contest .
Speaking about the motivation of this, it is a good thing if you are concerned about efficiency, as conditional branches are very time-consuming (this is the reason there are some complicated mechanisms for branch prediction). But it is not a good practice in usual code, as it might be very hard to understand for your reader, so your code becomes very hard to maintain. Also, as you are a beginner, it is a very good exercise.
Now, keep in mind that there is always a way. It is worth mentioning that you have a combination of logical, bitwise and arithmetic operation. It could be done purely with bitwise operations.
Let's try to make it using just bitwise operations. Assume your code is:
if (d == 0)
e = A;
if (d == 1)
e = B;
, where A and B are those 2 values you compute for e.
Firstly, extend the last significant bit to all of the d's bits (so if d is 1, it should be 0xFFFFFFFF and if it is 0, it should be 0x00000000). Then, do the operation. I splitted them into multiple lines, but it could be done more compact.
d = d << 1 + d;
d = d << 2 + d;
d = d << 4 + d;
d = d << 8 + d;
d = d << 16 + d;
e = (B & d) || (A & ~d);
Note that here I assume an int is 32 bits, which is not very portable. But, it is just an exercise.
Related
#include <stdio.h>
int main(void) {
int a = 0, b = 0, c = 0,
total = 0, helper = 0, helper_2 = 0, helper_3 = 0;
scanf("%d%d%d%d", &total, &a, &b, &c);
helper = (a <= b && a <= c ? a : (b <= c ? b : c));
helper_2 = (c >= b && a >= c ? c : (b >= a && a >= c ? a : (c >= b && b >= a ? b : 0)));
helper_3 = (a >= b && a >= c ? a : (b >= c ? b : c));
if ((total < 0) || (total > 1000) || (helper <= 0) ||
(helper_2 <= 0) || (helper_3 <= 0) || (helper > 1000) ||
(helper_2 > 1000) || (helper_3 > 1000)) {
printf("0");
return 0;
}
else if ((helper + helper_2 + helper_3) <= total) {
printf("3");
}
else if (helper + helper_2 <= total) {
printf("2");
}
else if (helper <= total) {
printf("1");
}
else {
printf("0");
}
return 0;
}
That is the code. I sort three variables, and store them in 3 different variables according to their size, the small one goes to the first one and so on...
The thing is, all the variables MUST be between 0 and 1001.
It seems to work well, but it does not. It has errors but I cannot find them. I just would like to know if some of you guys can help me to improve this code or even tell me what inputs to use that would return an unexpected value.
Thanks so much:D
Edit: I fixed part of them by removing the 0 from the helper_2 expression:D it would return 0 if the input would be for ex: 6, 1, 3, 2.
EDIT2: I've already answered it how you solve using ternary, but the other answers are so much better than the one I was using. So, thank you so much for everyone who helped me:D
The expression:
helper_2 = (c >= b && a >= c ? c : (b >= a && a >= c ? a : (c >= b && b >= a ? b : 0)));
is wrong. The last part can return zero! That's a bug. When we know that a, b and c are all greater than zero, the result just can't be zero.
Try input a=1, b=3, c=2 and print the value of the helper variables.
int a = 1;
int b = 3;
int c = 2;
int helper_1 = (a <= b && a <= c ? a : (b <= c ? b : c));
int helper_2 = (c >= b && a >= c ? c : (b >= a && a >= c ? a : (c >= b && b >= a ? b : 0)));
int helper_3 = (a >= b && a >= c ? a : (b >= c ? b : c));
printf("%d %d %d --> %d %d %d\n", a, b, c, helper_1, helper_2, helper_3);
Output:
1 3 2 --> 1 0 3
which is obviously wrong
My advice is to avoid the complex ternary conditionals. Write simple if statements instead.
For instance:
if (a > b)
{
// swap a and b
}
if (a > c)
{
// swap a and c
}
if (b > c)
{
// swap b and c
}
// Now a, b and c is sorted with a being smallest
You could really use a few helper functions to clean up your code.
One function to "swap" a pair of variables if the first is greater than the second:
void Sort2(int* x, int* y) {
if (*x > *y) {
int tmp = *x;
*x = *y;
*y = tmp;
}
}
Another to validate a range:
int isInRange(int minimum, int maximum, int value) {
return ((minimum <= value) && (value <= maximum));
}
Then your code gets really simple:
int main(void) {
int a = 0, b = 0, c = 0,
total = 0;
scanf("%d%d%d%d", &total, &a, &b, &c);
Sort2(&a, &b);
Sort2(&a, &c);
Sort2(&b, &c);
// a,b, and c are in sorted order
if !(isInRange(0, 1000, total) && isInRange(1, 1000, a) && isInRange(1, 1000, b) && isInRange(1, 1000, c))
{
printf("0");
return 0;
}
if ((a + b + c) <= total) {
printf("3");
}
else if (a + b <= total) {
printf("2");
}
else if (a <= total) {
printf("1");
}
else {
printf("0");
}
return 0;
}
Just remove helper_2 condition and use:
a>b? ( c>a? a : (b>c? b:c) ) : ( c>b? b : (a>c? a:c) ) )
instead. :D
I am looking for help in making this logic more legible. Assume each alphabet letter is a compare statement (e.g TRUE == a.foo). Each alphabet is about 30 char long statements.
if ( ((a || b)
&& (c || d)) ||
((e || f)
&& (g || h)) )
Any suggestions?
Decompose it.
int ab = a || b,
cd = c || d,
ef = e || f,
gh = g || h,
firstThing = ab && cd,
secondThing = ef && gh;
if (firstThing || secondThing)
Try lining up the subexpressions in groups, lining up the parenthesis:
if (((a || b) && (c || d)) ||
((e || f) && (g || h)))
In order for the conditions to align properly and the logic operator to stand out, I would use this style:
if (((a || b) && (c || d))
|| ((e || f) && (g || h))
...
|| ((u || v) && (w || x))) {
/* handle the successful test */
} else {
/* handle the other cases */
}
There are a few variations of this, but here's one way that I think is pretty clear:
if
(
(
(a || b)
&&
(c || d)
)
||
(
(e || f)
&&
(g || h)
)
)
I wrote this program to give the user all acute triangle solutions when they give a min and max value. It works correctly except it seems like the solutions don't include the first iterations of the loops (for example, with min = 1 and max = 45, (1, 1, 1) isn't included in the solutions). How can this be fixed? I thought the problem was with my while-loop for the a-value, but when I changed it into a for-loop, the problem persisted. How can I have it include these first values?
if (c >= dmin) {
c = dmin;
do {
++c;
for (b = dmin; b < dmax; b++) {
a = dmin;
while (a < dmax) {
a = a + 1;
if (a * a + b * b - c == c * c) {
if (((a + b) > c) && ((b + c) > a) && ((c + a) > b)) {
printf("(%d, %d, %d)", a, b, c);
}
}
}
}
} while (c <= dmax);
}
move ++c; after the for loop instead of before.
This increments c to 2 before it even starts, but you want to include 1.
*Note, you may want to add conditions that prevent minimums of 0 or less.
If the value range for a, b and c is [dmin..dmax] (both inclusive), the sample looks like below:
for (c = dmin; c <= dmax; c++)
{
for (b = dmin; b <= dmax; b++)
{
for (a = dmin; a <= dmax; ++a)
{
if (a * a + b * b - c == c * c )
{
if (((a + b) > c) && ((b + c) > a) && ((c + a) > b))
{
printf("(%d, %d, %d)", a, b, c);
}
}
}
}
}
I wanna compare 3 images at 3 different buttons, Xcode is allowing me to compare 2 images at a time but when i write code for 3 it gives a warning
"comparison between pointer and integer"
-(void)compare
{
if (b1.currentImage==b2.currentImage==b3.currentImage)
{
b1.enabled=NO;
b2.enabled=NO;
b3.enabled=NO;
NSLog(#"%#",b1.currentImage);
NSLog(#"%#",b2.currentImage);
}
else
{
UIImage *btnImage = [UIImage imageNamed:#"card.png"];
[b1 setImage:btnImage forState:UIControlStateNormal];
}
}
Generally spoken when you write :
a == b == c
that actually boils down to
(a == b) == c
thus you are comparing the result of the comparision of a and b (which is of type bool regardless of the types of a and b) to c which is of whatever the type of c is.
So in your case you compare b1.currentImage==b2.currentImage (which is of type int) to b3.currentImage which is a pointer type.
If yo want to compare three values for equality you have to write:
(a == b) && (a == c) instead of a == b == c
Try this small program and watch what it prints out:
int main()
{
int a = 2, b = 2 , c = 2 ;
if ((a == b) && (a == c ))
{
printf ("(a == b) && (a == c ) is true") ;
}
if ((a == b == c))
{
printf ("(a == b == c) is true") ;
}
return 0 ;
}
it will print
(a == b) && (a == c ) is true
because (a == b == c) is evaluated like this
1. (a == b) == c
2. (2 == 2) == 2
3. 1 == 2
4. false
How do I do this in constant time (I do not want to brute for iterate from a to b)?
// return number of multiples of c in [a,b]
long count_multiples(int a, int b, int c) {
assert(b >= a && c != 0);
// todo
return -1;
}
This question looks deceptively simple but is harder than it looks because it has some corner cases e.g. must handle all cases (a,b can be negative/zero and c can be negative too and a may equal b may equal c). The result may not fit in 32-bit for one case (a = 2^31, b = 2^31-1, c = 1 or -1)
long count_multiples(int a, int b, int c) {
if (b < a) return 0;
if (c < 0) c = -c;
long al = a, bl = b, cl = c;
if (c == 1) return bl - al + 1;
return ((bl + (b < 0 ? 1 : 0)) / cl) -
((al - (a > 0 ? 1 : 0)) / cl) +
((a <= 0 && b >= 0) ? 1 : 0);
}