21

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 ifs? 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.

haccks
  • 104,019
  • 25
  • 176
  • 264
MegamanEXE
  • 351
  • 1
  • 3
  • 12
  • 2
    Well, there is at least one thing wrong with the above: if you enter the same number four times it prints nothing at all. – Jon Oct 05 '13 at 15:38
  • 1
    You need to implement a partial 4-wire [sorting network](https://en.wikipedia.org/wiki/Sorting_network) (yes, that’s just a fancy name for nested `if` statements, but it shows the optimal configuration of those statements). – Konrad Rudolph Oct 05 '13 at 15:40
  • 2
    @jon Even if any two are equal...! – Gangadhar Oct 05 '13 at 15:41
  • There might be some clever tricks to reduce the line numbers by a few, but nothing significant. Whatever you have is going to end up being 'ugly'. – David says Reinstate Monica Oct 05 '13 at 15:42
  • @KonradRudolph: Having not only taken but also taught "light programming" classes in the past, I say *LOL* to that ;-) I can picture the faces when you say "partial 4-wire sorting network". – Jon Oct 05 '13 at 15:42
  • 3
    @Hamza Masud: The whole point of the problem that requests finding the largest and the smallest *simultaneously* is to make 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 a candidate for the smallest, while `b` is no longer a candidate for the largest. Basically, with 4 numbers, two tests `a > b` and `c > d` already clearly separate the numbers into two candidates for the largest and two candidates for the smallest. The rest is straightforward. – AnT stands with Russia Oct 05 '13 at 15:54
  • Voting to close, this belongs on code-review.SE – BlueRaja - Danny Pflughoeft Oct 05 '13 at 17:46
  • Let's say A and B are two of the four numbers. When you compare A against B, and you find A > B, there is no way A can be the smallest number, and there is no way B is the largest number. Thus in four comparisons, you can establish the largest and smallest of four numbers. – Happy Green Kid Naps Oct 05 '13 at 21:58
  • Sorry, it looks like I have said pretty much what @AndreyT has said. – Happy Green Kid Naps Oct 05 '13 at 21:58
  • 1
    **if** statements to select numeric values can always be replaced by appropriate combinations of bit-shift operations (to extract sign) and subtractions; see my answer below. – Pieter Geerkens Oct 05 '13 at 23:55

19 Answers19

28

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 ifs?

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;
}
haccks
  • 104,019
  • 25
  • 176
  • 264
  • 1
    Aw yiss, I couldn't point my finger at it but this is much more better than "for" loop way I was TRYING to visualize. – MegamanEXE Oct 05 '13 at 17:18
13

Do a "manual" merge sort, or well, just the second bit of it:

Conceptually, a merge sort works as follows

  1. Divide the unsorted list into n sublists, each containing 1 element (a list of 1 element is considered sorted).
  2. Repeatedly merge sublists to produce new sublists until there is only 1 sublist remaining. This will be the sorted list.

Merge sort merging step illustration

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)) ifs (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 ifs.. Though you could try to see if manually performing one of the other algorithms results in fewer ifs ;-).

m01
  • 9,033
  • 6
  • 32
  • 58
  • 1
    Funny, I posted basicall the same solution, only using macros for min and max and got -3 – Ingo Oct 05 '13 at 17:05
  • While I can't read the mind of those who downvoted your answer (or of those who upvoted mine), I suppose that's because the OP explicitly said that "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." - and I guess macros are close to functions and similalry not part of pre-first-lab syllabus. I also hope that the theory & explanation in my answer is of some use to the readers :) – m01 Oct 05 '13 at 17:10
  • it is, therefore I plussed you – Ingo Oct 05 '13 at 17:33
  • Well spotted, thank you - I've updated the code, it should now be fixed. – m01 Aug 07 '18 at 12:54
10

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

Arpit
  • 12,767
  • 3
  • 27
  • 40
  • What if the numbers entered are all negative? – Jon Oct 05 '13 at 15:45
  • 2
    `int max = -INT_MIN`. Or simply `int max = a`. – Aaron McDaid Oct 05 '13 at 15:47
  • 1
    Brilliant! Thanks. Every time I read an answer here on StackOverflow, I learn something new. Like this "merge sort", I know how to USE it but I never knew what it was called. I hope to become one of you one day! – MegamanEXE Oct 05 '13 at 16:22
  • This approach often wastes information obtained from the comparisons, which is why its worst case behavior will make 6 comparisons when 4 is always sufficient. – AnT stands with Russia Oct 05 '13 at 16:30
  • @AndreyT The moment i saw the `Homework and Firs lab` in problem statement, This was looking best solution for this problem statement to me. – Arpit Oct 05 '13 at 16:32
  • 1
    @Arpit: Could be. I don't know what the teacher's intent was in this case. But I'm almost sure the teacher is certainly hoping to see if some students will recognize the natural "hierarchical" structure of the problem. It is not rocket science, really. – AnT stands with Russia Oct 05 '13 at 16:38
  • 1
    I'm happy that you also answered the question, This is the specialty of SO that allow us to solve one question in variety of ways with skills that matches from novice to expert. :) . You indeed have more experience so you judged the intent of the teacher but i'm a student so i guessed what teacher generally means according to student. – Arpit Oct 05 '13 at 16:43
  • 1
    Too much `if`s and `else`. This answer does not meets the OP's requirements (although it is accepted :) ). – haccks Oct 05 '13 at 16:57
  • Thanks. Although it does not need that much brackets since there is a single statement in each "if". It looks much less 'scarier' without them. :) – MegamanEXE Oct 05 '13 at 17:43
  • 1
    @MegamanEXE Always use brackets , it increases the readability of your code. and for other reason check this http://stackoverflow.com/questions/97506/formatting-of-if-statements , http://stackoverflow.com/questions/691476/are-singleline-if-statements-or-if-statements-without-bad-practice , http://stackoverflow.com/questions/779332/do-you-put-conditional-code-on-a-new-line-or-only-sometimes – Arpit Oct 05 '13 at 19:05
  • @Ingo your solution uses the ternary operator, which is just a masked if-else. – rubenvb Oct 14 '13 at 14:23
9

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.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
5

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).

Ingo
  • 36,037
  • 5
  • 53
  • 100
2

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.

Pieter Geerkens
  • 11,775
  • 2
  • 32
  • 52
  • That's a good approach but....it doesn't full fill the OP's requirements. I think bit operation has not been taught in early classes. – haccks Oct 06 '13 at 00:05
  • @hacks: (1) It fulfills all stated requirements of the OP; you are just surmising that an unstated additional requirement exists. (2) It is a valuable concept, and can possibly avoid cache invalidation in deeply nested loops with extreme performance requirements. – Pieter Geerkens Oct 06 '13 at 00:19
  • I never said it not a good concept. I appreciate your approach. – haccks Oct 06 '13 at 00:28
  • @fintelia: Emphasis on **was**; 20 or so years ago. – Pieter Geerkens Oct 06 '13 at 01:13
  • 1
    @hacks: Also, one can optionally use the **signof** operator, in languages which supply it, in place of the bit shifts. (If such operator returns 0 for a zero value, then the formulation here is probably simpler to use.) – Pieter Geerkens Oct 06 '13 at 23:57
2

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)));
}
Suman Saurabh
  • 401
  • 5
  • 9
1

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;
}
Daniel Martín
  • 7,815
  • 1
  • 29
  • 34
  • Uff! Unnecessary comparisons. – haccks Oct 05 '13 at 17:22
  • @haccks There are only four comparisons per execution. It is the optimal number of comparisons for the problem of computing both the minimum and maximum. – Daniel Martín Oct 05 '13 at 17:43
  • Oh please! Although this is one of the solution but not optimal. I given +1 just because your code considering the input from user, unlike many answers here. – haccks Oct 05 '13 at 17:49
  • Well, code execution is not the only complexity measurement, and frequently the less important one. One other measurement is code brevity. And even though the CPU will execute the minimal number of comparisons, this answer encodes many unnecessary comparisons. So not really much gain compared to the version in the question. – cmaster - reinstate monica Oct 17 '13 at 17:07
1

For absolute performance ie. Minimum comparisons and assignments.

The comments at each level show the candidate values for min and max. The idea is to reduce the sets at each level until there is only one item for each set. This can be done with 4 comparisons and 2 assignments only.

        // min = a b c d
        // max = a b c d
        if (a <= b)
        {
            // min = a c d
            // max = b c d
            if ( c <= d){
                // min = a c
                // max = b d
                min = a <= c ? a : c;
                max = b > d ? b : d;
            }else{
                // min = a d
                // max = b c
                min = a <= d ? a : d;
                max = b > c ? b : c;
            }
        }
        else
        {
            // min = b c d
            // max = a c d
            if ( c <= d){
                // min = b c
                // max = a d
                min = b < c ? b : c;
                max = a > d ? a : d;
            }else{
                // min = b d
                // max = a c
                min = b < d ? b : d;
                max = a > c ? a : c;
            }
        }
bradgonesurfing
  • 30,949
  • 17
  • 114
  • 217
  • 1
    As of the date on this post... Out of the solutions on this page that maximize information (instead of treating the min and max functions separately): this solution by bradgonesurfing has the best time complexity with 4 comparisons and 2 assignments. Daniel Martin's solution comes in second with a worst case of 4 comparisons and 4 assignments. AnT's solutions is the most concise of the 3, but uses 4 comparisons and 8 assignments. – Ph0t0n Aug 25 '20 at 05:41
1
int max(int a, int b) {
    return a > b ? a : b;    
}

int max_of_four(int a, int b, int c, int d) {
    return max(a, max(b, max(c, d)));
}

int main() {
    int a, b, c, d;
    scanf("%d %d %d %d", &a, &b, &c, &d);
    int ans = max_of_four(a, b, c, d);
    printf("%d", ans);

    return 0;
}
0

This is C code has only 4 if statements. It moves max number to d position and min number to a position. Values b and c are not properly arranged within a sequence, but since requirements ask for min and max this code completes a job:

#include <stdio.h>


    int main() {
        int a, b, c, d, temp;
        printf("Enter four digits: ");
        scanf("%d %d %d %d", &a, &b, &c, &d);
        if ( a > b){
            temp = a; a = b ; b = temp;
        }
        if ( c > d){
            temp = c; c = d ; d = temp;
        }
        if ( b > d ){
            temp = b; b = d; d = temp;
        }
        if ( a > c){
            temp = a; a = c ; c = temp;
        }
        printf("Max %d\nMin %d\n", d, a);

        return 0;
    }
motu
  • 13
  • 1
0
 Please have at the following    

 private int GetLargerValue(int num1, int num2, int num3, int num4)
            {
                int largeValue = 0;
                if (num1 > num2)
                {
                    if (num1 > num3)
                        largeValue = (num1 > num4) ? num1 : num4;
                    else
                        largeValue = (num3 > num4) ? num3 : num4;

                }
                else if (num2 > num3)
                    largeValue = (num2 > num4) ? num2 : num4;
                else
                    largeValue = (num3 > num4) ? num3 : num4;

                return largeValue;
            }
Nandha kumar
  • 693
  • 7
  • 15
0
int max_of_four(int a, int b, int c, int d){
        int res=a;
        if(b/res)
            res=b;
        if(c/res)
            res=c;
        if(d/res)
            res=d;
        return res;
    }
int main() {
    int a, b, c, d;
    scanf("%d %d %d %d", &a, &b, &c, &d);
    int ans = max_of_four(a, b, c, d);
    printf("%d", ans);

    return 0;
}
0

I saw this answer that used for loop and if else decision statement , however I will post a solution that I suppose will run faster and will use only four variables. So here it goes...

#include<stdio.h>
void main()
{
int a,b,c,d;
printf("Enter four numbers of your choice");
scanf("%d%d%d%d",&a,&b,&c,&d);
a>b&&a>c?a>d?printf("%d",a):printf("%d" ,d):(b>c&&b>d)?printf("%d",b):c>d?printf("%d", c):printf("%d",d);
}
0
#include <stdio.h>

int main(void) {

int int_1, int_2, int_3, int_4;
int pair_1_largest = 0, pair_1_smallest = 0;
int pair_2_largest = 0, pair_2_smallest = 0;
int quartet_largest = 0, quartet_smallest = 0;

printf("Example: 15 38 8 21\n");

printf("\nEnter four integers: ");
scanf("%d %d %d %d", &int_1, &int_2, &int_3, &int_4);

if(int_1 > int_2)
{
    pair_1_largest = int_1;
    pair_1_smallest = int_2;
}
else
{
    pair_1_largest = int_2;
    pair_1_smallest = int_1;
}

if(int_3 > int_4)
{
    pair_2_largest = int_3;
    pair_2_smallest = int_4;
}
else
{
    pair_2_largest = int_4;
    pair_2_smallest = int_3;
}

if(pair_1_largest > pair_2_largest)
    quartet_largest = pair_1_largest;
else
    quartet_largest = pair_2_largest;

if(pair_1_smallest < pair_2_smallest)
    quartet_smallest = pair_1_smallest;
else
    quartet_smallest = pair_2_smallest;

printf("The largest number is: %d\n", quartet_largest);
printf("The smallest number is: %d\n", quartet_smallest);

return 0;

}

Hey everybody! I'm a beginner in programming so don't be to harsh on me :) "Native C Programming" by K.N. King is of help!

0

We can make use of condition statements here.

int max,max1,max2,min,min1,min2;
max = (max1 = a>b?a:b)>(max2 = c>d?c:d)?max1:max2 ;
min = (min1 = a<b?a:b)<(min2 = c<d?c:d)?min1:min2 ;
0
#include <stdio.h>

int max_of_four(int a, int b, int c, int d){
    int mx_A_B = (a > b) * a + (a <= b) * b;
    int mx_C_D = (c > d) * c + (c <= d) * d;

    return (mx_A_B > mx_C_D) * mx_A_B + (mx_A_B <= mx_C_D) * mx_C_D;
}


int main() {
    int a, b, c, d;
    scanf("%d %d %d %d", &a, &b, &c, &d);
    int ans = max_of_four(a, b, c, d);
    printf("%d", ans);
    
    return 0;
}
hunter
  • 1
0

This doesn't use any loops and only 4 conditionals:

#include <stdio.h>

int main(void)
{
  int i, j, k, l, t, max, min;

  printf("Enter four integers: ");
  scanf("%d%d%d%d", &i, &j, &k, &l);

  if (i < j) {
    t = i;
    i = j;
    j = t;
  }
  if (k < l) {
    t = k;
    k = l;
    l = t;
  }
  max = (i >= k) ? i : k;
  min = (j <= l) ? j : l;

  printf("Largest: %d\n", max);
  printf("Smallest: %d", min);

  return 0;
}
  

  
0
int n1, n2, n3, n4;
int max, min, max1, min1;

printf("Enter 4 integers: ");
scanf("%d %d %d %d", &n1, &n2, &n3, &n4);

max = min = n1;
max1 = min1 = n3;

if (n2 > max) max = n2;
else min = n2;

if (n4 > max1) max1 = n4;
else min1 = n4;

if (max1 > max) max = max1;
if (min1 < min) min = min1;


printf("%d, %d\n", max, min);
SimoX
  • 250
  • 6
  • 13