Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Biggest and smallest of four integers (No arrays, no functions, fewest 'if' statements)

Tags:

c

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.

like image 886
MegamanEXE Avatar asked Oct 05 '13 15:10

MegamanEXE


Video Answer


8 Answers

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;
}
like image 92
haccks Avatar answered Sep 29 '22 12:09

haccks


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

like image 36
m01 Avatar answered Sep 29 '22 13:09

m01


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

like image 27
Arpit Avatar answered Sep 29 '22 14:09

Arpit


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.

like image 20
AnT Avatar answered Sep 29 '22 12:09

AnT


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

like image 45
Ingo Avatar answered Sep 29 '22 14:09

Ingo


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.

like image 22
Pieter Geerkens Avatar answered Sep 29 '22 14:09

Pieter Geerkens


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)));
}
like image 26
Suman Saurabh Avatar answered Sep 29 '22 12:09

Suman Saurabh


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;
}
like image 22
Daniel Martín Avatar answered Sep 29 '22 13:09

Daniel Martín