Converting for() loop to do{}while in C with nested loops - c

I am trying to write a program that will find all acute triangle solutions after the user enters a min and max value (dmin and dmax). Right now I think I have the program working using only for() loops, but I need to change the first for() loop to a do{}while loop, which is confusing me. I'm not able to figure out how to write the do{}while loop so that is also includes these nested for() loops and the if statements. Everything I've tried either tells me b and c aren't being used or it just runs and provides no output. Here is my code with the for() loops.
double a = 0, b = 0, c = 0;
printf("Here are the acute triangle solutions the program found:\n");
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) && ((b + a) > b))
{printf("(%lf %lf %lf)\n", a, b, c);}
//sum of two sides must be greater than the third
//and angle across from c must be <90 degrees
}
}
}
}

a for (e1;e2;e3) something loop can be transformed in:
e1;
while (e2) {
something;
e3;
}
or:
e1;
if (e2) {
do {
something;
e3;
} while (e2);
}

In a do while, you simply do an initialization before and the check after. It is really somewhat similar to what the system does for a for loop.
The following code:
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) > c))
{printf("(%lf %lf %lf)\n", a, b, c);}
//sum of two sides must be greater than the third
//and angle across from c must be <90 degrees
}
}
}
}
Becomes:
c = dmin;
if(c < dmax) { //Make sure not to run once if c is greater
do
{
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("(%lf %lf %lf)\n", a, b, c);}
//sum of two sides must be greater than the third
//and angle across from c must be <90 degrees
}
}
}
} while( ++c <= dmax );
}

Related

Sorting 3 variables in C just does not work

#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

Optimizing a nested loop in C

I have a nested loop to find all possible combinations of numbers between 1 and x in groups of 4, where a < b < c < d.
A method is called as each group is discovered to do a simple equivalency test on the sum of those numbers.
The loop does work and produces expected output (1 set of numbers for this particular x), however it takes 12+ seconds to find this answer and another ~5 to test the remaining possibilities, which is definitely bad, considering the x values are < 1000.
I tried having the outer loop iterate a < x - 3 times, the b loop b < x - 2 times, down to d < x times which didn't make a noticeable difference.
What would be a better approach in changing this loop?
for (a = 1; a < x; a++) {
for (b = a + 1; b < x; b++) {
for (c = b + 1; c < x; c++) {
for (d = c + 1; d < x; d++) {
check(a, b, c, d);
}
}
}
}
With such a deep level of nesting, any early exit you can introduce - particularly at the outer loops - could net big gains.
For example, you write that check is testing a + b + c + d == x && a * b * c * d == x - so you can compute the intermediate sum and product, and break when you encounter numbers that would make any selection of later numbers impossible.
An example:
for (a = 1; a < x; a++) {
for (b = a + 1; b < x; b++) {
int sumAB = a + b;
if (sumAB + sumAB > x) break;
int prodAB = a * b;
if (prodAB * prodAB > x) break;
for (c = b + 1; c < x; c++) {
int sumABC = sumAB + c;
if (sumABC + c > x) break;
int prodABC = prodAB * c;
if (prodABC * c > x) break;
for (d = c + 1; d < x; d++) {
int sumABCD = sumABC + d;
if (sumABCD > x) break;
if (sumABCD != x) continue;
int prodABCD = prodABC * d;
if (prodABCD > x) break;
if (prodABCD != x) continue;
printf("%d, %d, %d, %d\n", a, b, c, d);
}
}
}
}
This is just an example - you can constrain all the checks here further (e.g. make the first check be sumAB + sumAB + 3 > x). The point is to focus on early exits.
I added a counter for each loop, counting how many times it was entered, and tried your version and my version, with x = 100. My version has orders of magnitude less loop entries:
No early exits: 99, 4851, 156849, 3764376
With early exits: 99, 4851, 1122, 848

Including first iteration in loop in C

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);
}
}
}
}
}

False position method reached the MAX iterations limit

I am trying to write a program to find roots of a continuous function using False Position Method. But, I am getting the same value of c again and again and same value is assigned to a, resulting in reaching the limit of MAX_ITER. How should I avoid this ? Am I not using the algorithm correctly ?
#include<stdio.h>
#include<math.h>
#define F(x) ((2*x)+1)
#define ERROR 0.00001
#define MAX_ITER 1000
float FalsePosition(float a, float b)
{
float c;
int iter = 0;
do
{
c = (b - F(b)) * (b - a) / (F(b) - F(a));
printf("F(a): %f, F(b) : %f, F(c) : %f, a: %f, b : %f, c : %f\n", F(a), F(b), F(c), a, b, c);
if((F(c) > 0 && F(a) > 0) || (F(c) < 0 && F(a) < 0))
{
a = c;
}
else
{
b=c;
}
iter++;
}
while(fabsf(a-b) > ERROR && iter < MAX_ITER);
return a;
}
int main()
{
float a = -2.5;
float b = 2.5;
printf("Finding root in the interval [%f, %f]\n", a, b);
if((F(a)>0 && F(b)>0) || (F(a)<0 && F(b)<0))
{
printf("No root lie in the interval [%f, %f]", a, b);
}
else
{
printf("The root is : %f\n", FalsePosition(a, b));
}
return 0;
}
Your formula for c is wrong, it should be
c = b - (f(b) * (b - a)) / (f(b) - f(a));
see here
To prevent reaching MAX_ITER iterations, you may want to watch the change in c something like
previousValue = c;
c = b - (f(b) * (b - a)) / (f(b) - f(a));
and then, the while condition would be
while ((fabs(previousValue - c) > ERROR) && (iter < MAX_ITER));
you can initialize previousValue to a befor beginig the loop.
And finally you should return c not a.

O(1) code to count multiples of a number in a range?

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);
}

Resources