I am new to bash and I don’t quite get how the conditionals work here. I tried running the following code to solve this exercise. My exact problem is with the value of flag. The code enters the final if block even when flag is true. Why is that happening?
main () {
res=""
flag="false"
echo "$(( $1 % 3 == 0))"
if [[ "$(( $1 % 3 == 0 ))" -eq 1 ]]
then
echo "here"
res+="Pling"
flag="true"
echo $res
echo $flag
fi
if [[ "$(( $1 % 5 == 0 ))" -eq 1 ]]
then
res+="Plang"
flag="true"
fi
if [[ "$(( $1 % 7 == 0 ))" -eq 1 ]]
then
res+="Plong"
flag="true"
fi
echo $flag
if [[ $flag -eq "false" ]]
then
echo "why"
res=$1
fi
echo $res
}
main "$@"
P.S. - General improvements to the code are also welcome :)
-eq is the arithmetic equality operator. In arithmetic context, bash allows you to refer to variables without the “parameter expansion syntax”, i.e. without the $.
The quoted conditional is equivalent to (( $true == $false ))
In arithmetic expressions, empty or unset variables get the value zero. Since both variables (named true and false) are unset, we have “does zero equal zero?”
At an interactive bash prompt, to see the list of conditional operators, do this sequence of commands:
There is an arithmetic conditional expression ((...)) – see Conditional Constructs in the manual. Instead of wrapping an arithmetic expansion inside the string-oriented [[...]], use
if (( $1 % 3 == 0 )); then
As mentioned above, you can even put “bare” variables in there:
x=10
if [[ "$(( $x < 20 ))" -eq 1 ]]; then echo "smaller"; fi
# or, this is much tidier
if (( x < 20 )); then echo "smaller"; fi
Even works with arrays
arr=(11 22 33)
idx=1
if (( arr[idx] == 22 )); then echo "it's twenty-two"; fi
For some reason (( $1 % 3 == 0 )) doesn’t work for me - It simply won’t evaluate to a truthy value from what I understand. That’s why I’m using [[ "$(( $1 % 3 == 0 ))" -eq 1 ]].
If you’re using bash, it should work. Every command sets an exit value in the standard OS process model. The exit status of 0 is considered a success and all other values are failures. You can test it out manually in a terminal:
» a=1
» (( a == 1 )); echo $?
0
» (( a == 2 )); echo $?
1
» (( a == 1 )) && echo Yes || echo No
» (( a == 2 )) && echo Yes || echo No
No
Thanks a lot for trying to help, Glenn. I managed to hack together some code that passes all testcases, but I still am a bit clueless about what’s happening with (( $1 % 3 == 0 )). I am being mentored by @IsaacG right now. I’ll summarize what went wrong with my code and my understanding of bash once I submit my code.
Coming to your question, I’m pretty sure "$1" is supposed to be the first argument, which is the input number.
By the way, you are using Exercism exactly as it was designed to be used: attempt to solve the exercise, request mentoring, discuss challenges on the forum.
So, to close this thread, this is what I actually got wrong - I was assuming that my code wasn’t working because something went wrong, and that the code wasn’t entering the if block.
main () {
res=""
if (( $1 % 3 == 0 ));then
res+="Pling"
fi
if (( $1 % 5 == 0 ));then
res+="Plang"
flag=1
fi
if (( $1 % 7 == 0 ));then
res+="Plong"
flag=1
fi
if $res
then
res="$1"
fi
echo "$res"
}
main "$@"
Turns out that wasn’t the case when I looked at the error again. The actual error in the code was if $res. My experience with other programming languages led me to the wrong assumption that $res would evaluate to falsey value if it was an empty string and a truthy value if it wasn’t. What I didn’t realize was that if $res would treat the string as a command.
Thanks a lot for helping @glennj and @IsaacG :). I had a lot of fun figuring it out.