You see, I've self-taught myself C++ (not completely, I'm still procrastinating -_-). So, now I started university and they're teaching C and they made us do a program of inputting four integers and we have to tell the largest and smallest out of them. Simple, no?
The thing is, I already have good understanding of functions and arrays. Yes, I CAN program this in arrays, no problem. But since this was the first lab, we haven't 'learned' that yet, so I can't use any of those, it'd be very simple with that.
This is what I wrote there (it feels wrong somehow).
#include<stdio.h>
int main(void)
{
int first, second, third, fourth;
printf("Enter four integers (separated by space): ");
scanf("%d %d %d %d", &first, &second, &third, &fourth);
if((first>second) && (first>third) && (first>fourth))
printf("\nFirst number is largest");
else if((second>first) && (second>third) && (second>fourth))
printf("\nSecond number is largest");
else if((third>second) && (third>first) && (third>fourth))
printf("\nThird number is largest");
else if((fourth>second) && (fourth>third) && (fourth>first))
printf("\nFourth number is largest");
if((first<second) && (first<third) && (first<fourth))
printf("\nFirst number is smallest");
else if((second<first) && (second<third) && (second<fourth))
printf("\nSecond number is smallest");
else if((third<second) && (third<first) && (third<fourth))
printf("\nThird number is smallest");
else if((fourth<second) && (fourth<third) && (fourth<first))
printf("\nFourth number is smallest");
printf("\n");
return 0;
}
As you can see, it's too long and boring and complex. But seeing that all we've covered in class for now are loops and decision statements. Is there a more elegant way of doing this? One which uses fewer if
s? Not that there is something wrong with this, but it could be better.
P.S. This isn't exactly 'homework' or anything. I made a program, I just wanted to know what I could have done to make it better and to learn better programming practices.
As per the OP's condition
But seeing that all we've covered in class for now are loops and decision statements. Is there a more elegant way of doing this? One which uses fewer
if
s?
Only one if
and one else if
statement and one for
loop can do this task. Simple and short!
#include <stdio.h>
int main()
{
int num, max, min;
printf ("Enter four numbers: ");
scanf ("%d", &num);
max = min = num;
for (int i = 0; i < 3; i++)
{
scanf ("%d", &num);
if (max < num)
max = num;
else if (min > num)
min = num;
}
printf ("The smallest and largest of given four numbers are %d and %d respectively.\n", min, max);
return 0;
}
Do a "manual" merge sort, or well, just the second bit of it:
Conceptually, a merge sort works as follows
- Divide the unsorted list into n sublists, each containing 1 element (a list of 1 element is considered sorted).
- Repeatedly merge sublists to produce new sublists until there is only 1 sublist remaining. This will be the sorted list.
Code:
int a = 5, b=4, c=7, d=9;
int min_ab, min_cd, min;
min_ab = a < b ? a : b;
min_cd = c < d ? c : d;
min = min_ab < min_cd ? min_ab : min_cd;
printf("%d", min);
.. and similarly for max.
If you prefer, you can expand the ternary operator into if (a < b) { min_ab = a; } else { min_ab = b; }
(spread over multiple lines for readability).
Merge sort has a complexity of O(n*log(n))
, so you should at most need O(n*log(n))
if
s (see the wikipedia article on merge sort). According to Wikipedia, "... These are all comparison sorts, and so cannot perform better than O(n log n) in the average or worst case" (source), so I think this shouldn't be too far off in terms of minimum number of if
s.. Though you could try to see if manually performing one of the other algorithms results in fewer if
s ;-).
Try something like this
int main(void) {
int a=-2,b=-3,c=-4,d=-5;
int max=a,min=a;
if(b>max){
max=b;
}else if(b<min){
min=b;
}
if(c>max){
max=c;
}else if(c<min){
min=c;
}
if(d>max){
max=d;
}else if(d<min){
min=d;
}
printf("max: %d min : %d",max,min);
return 0;
}
Demo
The whole point of the classroom problem that requests finding the largest and the smallest simultaneously is to teach you to extract maximum valuable information from each comparison.
For example, if you know that a > b
is true, from that single comparison you should realize that a
is no longer candidate for the smallest and should no longer participate in any comparisons dedicated to finding the smallest. And, at the same time, you should realize that b
is no longer candidate for the largest. With 4 numbers, two tests a > b
and c > d
already clearly separate the numbers into two independent classes: two candidates for the largest and two candidates for the smallest. The rest is straightforward.
In other words, the whole idea is to find the extreme values in parallel, using the information provided by each comparison to further the task of finding both the smallest and the largest value.
if (first > second) {
int t = first; first = second; second = t;
}
if (third > fourth) {
int t = third; third = fourth; fourth = t;
}
/* Now 'first' and 'third' are candidates for the smallest,
while 'second' and 'fourth' are candidates for the largest */
int min = first < third ? first : third;
int max = second > fourth ? second : fourth;
As you can see, this requires only four comparisons to find both numbers.
Note that the above code gives you the values of the smallest and the largest, but it does not tell you the original "index" of the number that provided each value. It is not immediately clear whether it is really necessary. The text of your question says nothing about that, while the code sample you provided implements it. In any case, it is not difficult to update the above code to make it to "track" the origins of the numbers.
This is too easy, given that the numbers are a,b,c,d:
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
biggest = max (max(a,b), max(c,d))
smallest = min (min(a,b), min(c,d))
Here you go, no if statements, no functions (though the latter is the most stupid and harmful to adepts requirement I ever heard of).
Here is a solution with no if or elseif or function or macro, but using bit-shift and subtraction instead; only using a single for loop:
#include <stdio.h>
int main(){
int num , max, min;
printf("Enter four numbers: ");
scanf("%d", &num);
max = min = num;
for(int i = 0; i < 3; i++)
{
scanf("%d", &num);
max = max * (1 - ( (max-num) >> 31) )
+ num * ( (max-num) >> 31);
min = min * (1 - ( (num-min) >> 31) )
+ num * ( (num-min) >> 31);
}
printf("\n%d %d", max, min);
return 0;
}
The (max-num) >> 31)
operation captures the sign of the difference, which when multiplied by the second number yields the minimum value of the comparison.
This comes from an old SQL coding trick from the days before there was a CASE WHEN construct in that language.
Try this
Function implementaion
int max_of_four(int a,int b,int c,int d){
int max=a;
if(b>max) max=b;
if(c>max) max=c;
if(d>max) max=d;
return max;
}
without if would be like this
int max_of_four(int a, int b, int c, int d) {
return ((a > b && a > c && a > d) ? a: ((b > c && b > d) ? b : (c > d ? c : d)));
}
One idea may be to compute the maximum and minimum of the first two numbers. Then, you compare the rest of the numbers in pairs. The greater one of each pair is compared against the current maximum, and the smaller one of each pair is compared against the current minimum. This way you do 3 comparisons for every 2 elements, which is slightly more efficient than Arpit's answer (2 comparisons for each element).
In code:
#include <stdio.h>
int main(int argc, char **argv) {
int a, b, c, d;
printf("Enter four integers (separated by space): ");
scanf("%d %d %d %d", &a, &b, &c, &d);
int max, min;
if (a > b) {
max = a;
min = b;
}
else {
max = b;
min = a;
}
if (c > d) {
if (c > max) {
max = c;
}
if (d < min) {
min = d;
}
}
else {
if (d > max) {
max = d;
}
if (c < min) {
min = c;
}
}
printf("max = %d, min = %d\n", max, min);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With