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

2 Answers2

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[@]} ))
steeldriver
  • 81,074
-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
user1133275
  • 5,574