2

I am trying to detect armstrong numbers with this code:

declare -i INPUT=$1 arr=($(fold -w1 <<< "$INPUT")) for index in "${!arr[@]}" do armstrong_sum+=$((${arr[index]}**${#arr[@]})) done echo "$armstrong_sum" 

Commands to run the code: ./armstrong_sum 9, armstrong_sum 10 and ./armstrong_sum 153

Output: 9, 10 and 112527

Expected output: 9, 1 and 153

An armstrong number is a number that is the sum of its own digits each raised to the power of number of digits

More importantly I want to be able to debug the script myself. Not exactly sure how one debugs in bash. Like get type of operand and see pause iteration at each step

3
  • your expected output doesnt make sense - by your own definition 153 should return 729 Commented Dec 7, 2018 at 3:46
  • 1^3 + 5^3 + 3^3 = 153. This my expected output, i.e an armstrong number Commented Dec 7, 2018 at 3:50
  • Your second question (the bold part) already has an answer, easily found by searching: unix.stackexchange.com/questions/155551/… Commented Dec 7, 2018 at 9:24

2 Answers 2

2

As noted in man bash (emphasis mine)

When += is applied to a variable for which the integer attribute has been set, value is evaluated as an arithmetic expression and added to the variable's current value, which is also evaluated. When += is applied to an array variable using compound assignment (see Arrays below), the variable's value is not unset (as it is when using =), and new values are appended to the array beginning at one greater than the array's maximum index (for indexed arrays) or added as additional key-value pairs in an associative array. When applied to a string-valued variable, value is expanded and appended to the variable's value.

You are clearly getting the latter, i.e.

1 + 125 + 27 = 112527 

So you have a couple of options - either declare armstrong_sum as integer

#!/bin/bash declare -i INPUT=$1 declare -i armstrong_sum=0 arr=($(fold -w1 <<< "$INPUT")) for index in "${!arr[@]}" do armstrong_sum+=$(( ${arr[index]}**${#arr[@]} )) done echo "$armstrong_sum" 

or ensure arithmetic evaluation by surrounding the whole expression in (( and )) i.e.

(( armstrong_sum += ${arr[index]}**${#arr[@]} )) 
-1

Use https://www.shellcheck.net (I use it as syntactic vim plugin making a crude IDE)

I'd go with this;

#!/bin/bash P="$(echo -n "$1" | wc -c)" SUM=0; for X in $(echo "$1" | fold -w 1) ; do SUM=$(echo "$SUM+($X^$P)" | bc ); done echo "$SUM" 

It's not "pure" bash but I find the power of bash is the wide selection of tools, and prioritizing legibility.

for stack traces if you add the following to the top of all your scripts it will inform you of errors;

set -e trap 'echo "ERROR: $BASH_SOURCE:$LINENO $BASH_COMMAND" >&2' ERR 

it will stop the script on the error line, make output like

test.sh: line 7: no: command not found ERROR: test.sh:7 no + 5 

instead of (potentially silently) ignoring errors. Use -x for debugging;

bash -x armstrong.sh 222 ++ echo -n 222 ++ wc -c + P=3 + SUM=0 ++ fold -w 1 ++ echo 222 + for X in $(echo "$1" | fold -w 1) ++ echo '0+(2^3)' ++ bc + SUM=8 + for X in $(echo "$1" | fold -w 1) ++ echo '8+(2^3)' ++ bc + SUM=16 + for X in $(echo "$1" | fold -w 1) ++ echo '16+(2^3)' ++ bc + SUM=24 + echo 24 24 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.