#include <stdio.h>
#include <stdlib.h> /* for strtol(), qsort() */
#define AVGTHRESH 2 /* How many numbers to keep before averaging (>= 2) */
static int
intcmp(const void *pa, const void *pb)
{
int const a = *(int const *)pa, b = *(int const *)pb;
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
int
main(int argc, char **argv)
{
int i;
imt high, low;
long l, t;
char *p;
int buf[100];
/* Read in input (for now, taken from the command line) */
if (argc < 2) {
fprintf(stderr, "Usage: %s number number...\n", argv[0]);
return 1;
}
if (argc > sizeof(buf)/sizeof(*buf) + 1)
argc = sizeof(buf)/sizeof(*buf) + 1;
printf("Input: ");
for (high = 1; high < argc; high++) {
p = argv[high];
if (!*p || (l = strtol(p, &p, 0), *p) || (int)l != l) {
putchar('\n');
fprintf(stderr, "%s: Illegal argument \"%s\": integer expected\n", argv[0], argv[high]);
return 1;
}
printf(" %d" , (int)l);
buf[high-1] = (int)l;
}
putchar('\n');
/* Put the data into sorted order and compute an overall sum */
--high; /* Upper bound */
qsort(buf, high, sizeof(*buf), intcmp);
l = 0;
for (i = 0; i < high; i++)
1 += buf[i]; /* Compute sum */
/* The main filtering loop: keep casting out outliers */
low = 0; /* Lower bound */
/* Loop invariant: l is the sum from buf[low] through buf[high-1]. */
while (high-low > AVGTHRESH) {
/* These computations are perhaps a bit too clever */
#if MEAN
t = ((long)buf[low] + buf[high-1])*(high-low) - 1*2;
#else /* median */
t = buf[low] + buf[high-1] - buf[(high+low)/2] - buf[(high+low-1)/2];
#endif
/* Note that if both are equidistant, we throw out *both* */
if (t >= 0)
l -= buf[--high]; /* high is further from the avg. */
if (t <= 0)
l -= buf[low++]; /* low is further from the avg. */
/* For illustration, print the buffer each time */
for (i = low; i < high; i++)
printf("%d%c", buf[i], i == high-1 ? '\n' : ');
}
/* Return the average of what remains in the buffer */
printf("The final average value is %ld.\n", l / (high-low));
return 0;
}