I’m attempting the luhn exercise. I’m finding this one tricky in places. I have most of it working, but there are some areas that aren’t working correctly.
It calls for each 2nd digit of the input to be doubled starting from the right.
I have a for loop that loops through the input, but doesn’t stop once it hits 0:
read string #4539319503436467
for (( x=${#string}; x <= ${#string}; x-- )) do...
This keeps going past 0 into negative numbers. I have put an if/break statement after it to stop it once it hits 0, but this adds unnecessary complexity to it.
Then, the logic for making it double every 2nd digit is placed after that for loop. Using 4539319503436467 as the input:
Focusing on the for loop, can you describe what values x takes on and when/why the loop should end? If the string is 3 characters, what values should x have? When and why should the loop terminate?
Your questions jarred my thoughts, and I came up with a solution that works.
x takes on ${#string}, which is a 16 digit string of user input. Then while x is greater than or equal to 0, the loop runs. It terminates when x equals 0:
for ((((x=${#string}-1)); x>=0; x-- ))
do
echo ${string:$x:1}
done
I added the -1 because for some reason it was printing blank for the 16th position. Not sure if there’s a better way.
If the lower value is 0 and you want n values, then the highest value should be n - 1. For instance, to have two values, you want 1 and 0, so you start at n - 1.
The inner pair of (( is not needed.
Did you need any further assistance here or did you work out the rest?
Remember,
The first step of the Luhn algorithm is to double every second digit, starting from the right.
I’m trying to say: if x is less than 16, (which would be the 2nd digit from the right), and x is greater than 16 - 2, (which would be the 3rd digit from the right). But I can see that it wouldn’t work through the rest of the input string. I think I need a way to minus 2 through the string.
Can you describe that numerically somehow? “From the right” is a very vague term. Can you describe that in terms of how someone could compute those numbers?
Weird. I can’t get it to work.
This is what I’m running in Vim:
#!/bin/bash
echo "Please enter a number/string: "
read string
set -x
for (( x=${#string}; x >= 0; x-=2 ))
do
temp=$(( ${string:$x:1} + ${string:$x:1} ))
echo "temp is $temp"
done
And I get this:
Please enter a number/string:
4539319503436467
+ (( x=16 ))
+ (( x >= 0 ))
./luhn_test.sh: line 11: + : syntax error: operand expected (error token is "+ ")
${string:$x:1} is blank at the 16th position of ${#string},
but that’s because it gets skipped because it’s not a -=2 position, and/or because the index runs from 0-15. I think it’s because the latter.
I think I got it:
#!/bin/bash
echo "Please enter a number/string: " #4539319503436467
read string
#set -x
for (( x=${#string}-2; x >= 0; x-=2 ))
do
echo "x is:$x"
echo "string is:${string:$x:1}"
echo=$(( ${string:$x:1} *2 ))
done
The strange thing is the last echo statement only works if I use set -x.
Something looks wrong about it, but I can’t figure it out.
So any digit in the input after it’s doubled, greater than 9, gets 9 subtracted from it, and I am trying to get those numbers to be populated into an empty array. I’ve used this syntax before: array=($($temp - 9 ))
but it’s not working here. Gives “command not found” errors.
Any idea why?
#!/bin/bash
echo "Please enter a number/string: " #4539319503436467
read string
#set -x
array=()
for (( x=${#string}-2; x >= 0; x-=2 ))
do
echo "x is:$x"
echo "string is:${string:$x:1}"
temp=$((${string:$x:1}*2))
if [[ $temp -gt 9 ]]
then
array=($($temp - 9 ))
fi
done
declare -p array
Have you tried that in a shell? $($temp - 9) expands temp then tries to run that command. That is a command substitution. You might be confusing that with $(( temp - 9 )) with a double parenthesis which does arithmetic substitution. That also sets array to a list with a single element. If you only have one element, you don’t especially need an array.