Reputation: 387
i need help to calculate and display the largest and average of a group of input numbers.
The program should accept a group of numbers, each can be up to 3 digits.
For example, input of 246, 321, 16, 10, 12345, 4, 274 and 0 should result in 321 as the largest and the average of 145, with an error message indicating that 12345 is invalid.
Any ideas how to sort in bash ? Sorry I am not developer in this low level, any help is great :)
Upvotes: 1
Views: 370
Reputation: 47089
A piped coreutils
option with bc
:
echo 246 321 16 10 12345 4 274 0 \
| grep -o '\b[0-9]{1,3}\b' \
| tee >(sort -n | tail -n1 > /tmp/max) \
| tr '\n' ' ' \
| tee >(sed 's/ $//; s/ \+/+/g' > /tmp/add) \
>(wc -w > /tmp/len) > /dev/null
printf "Max: %d, Min: %.2f\n" \
$(< /tmp/max) \
$((echo -n '('; cat /tmp/add; echo -n ')/'; cat /tmp/len) | bc -l)
Output:
Max: 321, Min: 124.43
grep
ensures that the number format constraint.sort
finds max, as suggested by chepnersed
and wc
generate the sum and divisor.Note that this generates 3 temporary files: /tmp/{max,add,len}
, so you might want to use mktemp
and/or deletion:
rm /tmp/{max,add,len}
Stick this into the front of the pipe if you want to know about invalid input:
tee >(tr ' ' '\n' \
| grep -v '\b.{1,3}\b' \
| sed 's/^/Invalid input: /' > /tmp/err)
And do cat /tmp/err
after the printf
.
Upvotes: 0
Reputation: 15345
I see that you ask for a Bash
solution but since you tagged it also Unix
I suggest a pure awk
solution (awk
is just ideal for such problems):
awk '
{
if(length($1) <= 3 && $1 ~ /^[0-9]+$/) {
if($1 > MAX) {MAX = $1}
SUM+=$1
N++
print $1, N, SUM
} else {
print "Illegal Input " $1
}
}
END {
print "Average: " SUM / N
print "Max: " MAX
}
' < <(echo -e "246\n321\n16\n10\n12345\n4\n274\n0")
prints
246 1 246
321 2 567
16 3 583
10 4 593
Illegal Input 12345
4 5 597
274 6 871
0 7 871
Average: 124.429
Max: 321
However, I cannot comprehend why the above input yields 145 as average?
Upvotes: 1
Reputation: 97918
tmpfile=`mktemp`
while read line ; do
if [[ $line =~ ^[0-9]{1,3}$ ]] ; then
# valid input
if [ $line == "0" ] ; then
break
fi
echo $line >> $tmpfile
else
echo "ERROR: invalid input '$line'"
fi
done
awk ' { tot += $1; if (max < $1) max = $1; } \
END { print tot / NR; print max; } ' $tmpfile
rm $tmpfile
Upvotes: 0