ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Hi, I have an array of eight, single digit numbers, whats the easiest way (ideally without expr) to add all the numbers together?
I also need to figure out a way of generating a number which will round the total up to the nearest 10. So basically if the total of all the numbers in my array is 8 I need to get a 2 from somewhere and add it to the complete list of numbers, so the final list will be 11111112. I can think of complicated slow ways to do this (setup numbers 10-80 as variables and then work out what the smallest positive difference between the total and the variable), however this just seems crap and innefficient. I can probably work this out myself, just haven't got started yet and could do with some pointers.
how are you getting those arrays? hardcoded into the script? or parsed from somewhere.. number of tools such as awk, bc can be used to sum them up. Even bash itself can be used by going over the arrays and doing the addition. As for the second part, don't understand what you are saying. better to give more clearer example.
Distribution: slackware64 13.37 and -current, Dragonfly BSD
Posts: 1,810
Rep:
Quote:
I also need to figure out a way of generating a number which will round the total up to the nearest 10. So basically if the total of all the numbers in my array is 8 I need to get a 2 from somewhere and add it to the complete list of numbers, so the final list will be 11111112. I can think of complicated slow ways to do this (setup numbers 10-80 as variables and then work out what the smallest positive difference between the total and the variable), however this just seems crap and innefficient. I can probably work this out myself, just haven't got started yet and could do with some pointers.
Here's an idea for using bc to round up to the nearest 10. I set TOT to some test amounts to demonstrate and get the result in RES:
The numbers are randomly generated, they go through a bit of a complex formular and then get changed into other numbers. Theres no predicting what the numbers will be, except they'll be less than 10 and there will be 8 of them.
bgeddy, thanks for your help with the last bit, it's a good starting point for me .
P.S did not know awk had arithmatic functions!
The last part is basically the difference between the total and the nearest 10 (rounded up). I'll try to explain the maths a bit better:
random numbers: 5, 1, 6, 3, 2, 8, 9, 1
total = 35
rounded total = 5 (rounded up to 40)
final number = 5, 1, 6, 3, 2, 8, 9, 1, (5 my final number)
Last edited by genderbender; 05-16-2009 at 11:25 AM.
Just thought of a clever way of doing the second bit!!
If the numbers greater than 10, e.g 18, take off the second digit (the 8), add 1 to the first and put a 0 on the end. Psuedo code coming up, looks tricky...
Code:
if totals bigger than 10 (e.g 18)
take off the second digit to leave the first digit (the 1)
add 1 to that number = 2
stick a zero on the end of that = 20
calculate total (18) - the number weve just got(20).
if the totals smaller than 10 (e.g 8)
do 10 - the total (10 - 8)
Because I don't know perl, python or ruby and the 70+ lines I've wrote so far are in bash, I can't see this being massively more simpler in any other programming language anyway.
Because I don't know perl, python or ruby and the 70+ lines I've wrote so far are in bash, I can't see this being massively more simpler in any other programming language anyway.
I do not quite understand the algorithm you ant to implement, but here is random numbers generation and summation:
Code:
sergei@amdam2:~/junk> cat -n gen_and_add_random_number.pl
1 #!/usr/bin/perl -w
2
3 use strict;
4
5 my $number_of_random_numbers = 15;
6 my $max_random_number = 10;
7
8 my @random_numbers = map{int(rand($max_random_number + 1))} (1 .. $number_of_random_numbers); # this is random numbers generation
9
10 my $sum_of_random_numbers = 0;
11 map {$sum_of_random_numbers += $_;} @random_numbers; # actual summation
12
13 warn "\@random_numbers=@random_numbers";
14 warn "\$sum_of_random_numbers=$sum_of_random_numbers";
15
sergei@amdam2:~/junk> ./gen_and_add_random_number.pl
@random_numbers=2 2 1 1 9 6 2 8 5 3 0 2 7 1 0 at ./gen_and_add_random_number.pl line 13.
$sum_of_random_numbers=49 at ./gen_and_add_random_number.pl line 14.
Just thought of a clever way of doing the second bit!!
If the numbers greater than 10, e.g 18, take off the second digit (the 8), add 1 to the first and put a 0 on the end. Psuedo code coming up, looks tricky...
Code:
if totals bigger than 10 (e.g 18)
take off the second digit to leave the first digit (the 1)
add 1 to that number = 2
stick a zero on the end of that = 20
calculate total (18) - the number weve just got(20).
if the totals smaller than 10 (e.g 8)
do 10 - the total (10 - 8)
Your if condition is wrong, this algorithm would round 30 up to 40. How about
Code:
Take only the first digit (e.g. 18 mod 10 = 8)
if it's not 0 then
(10 - digit) is the number you want (10 - 8 = 2)
else
You don't need another number
I realised that about 8 minutes after I started typing, got the total working (ending up using expr) and this is the beginning of my if statement:
Code:
if [ "$total" -lt "10" ];
then let "chkbit = 10"
elif [ "$total" == "10" || "$total" == "20" || $total" == "30" || "$total" == "40" || "$total" == "50" || $total" == "60" || "$total" == "70" ];
then let "chkbit = 0"
else
#this is jut in for testing purposes.
let "chkbit = 500"
fi
It's not working right not, probably some syntax error. I'll explain the algorithm as best I can:
Quote:
1. take a random 13 digit number
2. double every other digit (1, 3, 5 etc)
3. if the doubled total is more than 10, take 9 from the number, otherwise leave it alone.
4. Add all the doubled digits together
5. Add a 14th digit which will make the total perfectly divisible by 10
I've almost finished it though, the name of the algorithm is Luhn, I don't plan to 'use it' and it was more of an experiment with how efficient bash was and how easy this would be. In retrospect something like perl would be easier and I'm sure there are LOTS of other scripts to do the same thing.
Last edited by genderbender; 05-16-2009 at 07:18 PM.
Heres the finished script, it's a little messy as the variables have inconsistant names and such, but it seems to function at a basic level, algorithm can be tested at the following site http://www.ee.unb.ca/cgi-bin/tervo/luhn.pl
If anyone wants to make this more interesting or use parts of it feel free. Just so people are aware, I got the algorithm wrong originally and didn't include the other digits in the total.
Code:
#code below was nicked and heavily modified from a dice random number generator
#
PIPS=10 #generate numbers from 0 - 9
MAXTHROWS=13 #This is the number of single digit numbers
throw=0 # Throw count.
#generate 13 one digit numbers...
number2=`while [ "$throw" -lt "$MAXTHROWS" ]
do
let "die1 = RANDOM % $PIPS"
echo $die1
let "throw += 1"
done`
#
#thats all the stolen code...
#select only the even digits (2, 4, 6 etc)
array2=($number2)
for (( i = 0 ; i < ${#array2[@]} ; i++ ))
do
let "i += 1"
addevens=`echo ${array2[$i]}`
ADDEVE=( "${ADDEVE[@]}" "$addevens" )
done
array=($number2)
for (( i = -1 ; i < ${#array[@]} ; i++ ))
do
do let "i += 1"
#echo out the other digits, if the numbers are greater than 10 double them and then subtract 9
NUMB=`echo ${array[$i]}`
let MULT=`expr $NUMB*2`
if [ "$MULT" -gt "9" ];
then let "MULT -= 9"
fi
#write numbers into an array
addodds=`echo $MULT`
ADDAR=( "${ADDAR[@]}" "$addodds" )
done
let totaleve=`expr ${ADDEVE[0]}+${ADDEVE[1]}+${ADDEVE[2]}+${ADDEVE[3]}+${ADDEVE[4]}+${ADDEVE[5]}`
#add all the numbers contained in the array together
let totalodd=`expr ${ADDAR[0]}+${ADDAR[1]}+${ADDAR[2]}+${ADDAR[3]}+${ADDAR[4]}+${ADDAR[5]}+${ADDAR[6]}`
let total=`expr $totalodd+$totaleve`
#the following was just for testing purposes, it was done in the early stages so arrays may be invalid now.
#
#echo the odd total is $totalodd
#echo the even total is $totaleve
#echo the grand total is $total
#echo "list of odd (doubled) elements : ${ADDAR[@]}"
#echo "list of even array elements : ${ADDEVE[@]}"
#echo "total of all elements in the array: $total"
#if the total is 10 the checkbit will be zero as the totals already divisible by 10
if [ "$total" -lt "10" ];then
let "chkbit = 10"
let LAST=`expr $chkbit - $total`
#if the totals already a possible multiple of 10 the checkbit will be zero
elif [[ "$total" -eq "10" || "$total" -eq "20" || "$total" -eq "30" || "$total" -eq "40" || "$total" -eq "50" || "$total" -eq "60" || "$total" -eq "70"|| "$
total" -eq "80" || "$total" -eq "90" || "$total" -eq "100" || "$total" -eq "110" || "$total" -eq "120" || "$total" -eq "130" ]]; then
let "chkbit = 0"
let LAST=$chkbit
#if the total is a number not divisible by 10 take the first digit of the total, add one to it and then multiply it by 10 and assign it a variable called chkbit, subtract the total from the checkbit to give a grand total divisible by 10.
else
totalup=`echo $total | cut -c1`
let chkbit=`expr $totalup+1`
let chkbit=`expr $chkbit*10`
let LAST=`expr $chkbit - $total`
fi
echo -n $number2 $LAST
echo
exit 0
Last edited by genderbender; 06-08-2009 at 07:41 AM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.