Add an Exercism exercise from Bash track

This commit is contained in:
Gabriel Arazas 2021-06-22 20:05:04 +08:00
parent 1c1be4a496
commit 91b10b4de8

View File

@ -3,11 +3,11 @@
:END: :END:
#+title: Exercism track: Bash #+title: Exercism track: Bash
#+date: "2021-05-11 15:06:43 +08:00" #+date: "2021-05-11 15:06:43 +08:00"
#+date_modified: "2021-06-05 11:13:09 +08:00" #+date_modified: "2021-06-22 17:50:43 +08:00"
#+language: en #+language: en
#+source: https://exercism.io/my/tracks/bash #+source: https://exercism.io/my/tracks/bash
#+property: header-args :cache yes #+property: header-args :cache yes
#+property: header-args:bash :shebang "#/usr/bin/env bash" #+property: header-args:bash :shebang "#!/usr/bin/env bash"
These are my submitted solutions for the Bash track in Exercism. These are my submitted solutions for the Bash track in Exercism.
@ -343,3 +343,114 @@ else
echo "$resistance" ohms echo "$resistance" ohms
fi fi
#+end_src #+end_src
* Raindrops
Your task is to convert a number into a string that contains raindrop sounds corresponding to certain potential factors. A factor is a number that evenly divides into another number, leaving no remainder. The simplest way to test if a one number is a factor of another is to use the modulo operation.
The rules of raindrops are that if a given number:
- has 3 as a factor, add 'Pling' to the result.
- has 5 as a factor, add 'Plang' to the result.
- has 7 as a factor, add 'Plong' to the result.
- does not have any of 3, 5, or 7 as a factor, the result should be the digits of the number.
Examples:
- 28 has 7 as a factor, but not 3 or 5, so the result would be "Plong".
- 30 has both 3 and 5 as factors, but not 7, so the result would be "PlingPlang".
- 34 is not factored by 3, 5, or 7, so the result would be "34".
** Initial working solution
After finding out that Bash arithmetic expression exists, we'll have to use the modulo operator.
#+begin_src bash :tangle (my/concat-assets-folder "raindrops.sh")
n=$1
valid=0
function is_factor {
local factor=$1
shift
local msg=$@
[[ $(( $n % $factor )) -eq 0 ]] && printf $msg && valid=1
}
is_factor 3 "Pling"
is_factor 5 "Plang"
is_factor 7 "Plong"
[[ $valid -eq 0 ]] && echo $n || printf '\n'
#+end_src
** Findings after solution
The [[https://exercism.io/my/solutions/04bcb4f6de304cd891afd87f1fcf9830][solution]] was approved by the mentor.
They did point out a few details such as ~[\[...]]~ being string-oriented.
You can also use
#+begin_src bash
# Instead of this which compares numbers...
n=10
factor=10
[[ $(( $n % $factor )) -eq 0 ]] && echo "Hello"
# Do it like this...
(( $n % $factor == 0 )) && echo "Hello"
#+end_src
#+results[2f32aabc4f71df02cff19faef77296081516089b]:
: Hello
: Hello
Secondly, assigning a vector variable (i.e., ~$@~) to a scalar variable can be problematic.
It is advisable to put the vector variable to another vector variable instead.
#+begin_src bash
msg=$@ # Wrong
msg=("$@") # Right
#+end_src
Apparently, Bash really is a picky interpreter.
I really like [[https://exercism.io/tracks/bash/exercises/raindrops/solutions/b882430d0b4841a4acaf7c8d5ba24a24][this simple solution]].
If improved with the tips given by the mentor, this is my improved solution.
#+begin_src bash
if (( $1 % 3 == 0 )); then
result+="Pling"
fi
if (( $1 % 5 == 0 )); then
result+="Plang"
fi
if (( $1 % 7 == 0 )); then
result+="Plong"
fi
echo ${result:-$1}
#+end_src
But without entirely rewriting my solution, here's the improved solution of it.
#+begin_src bash :tangle (my/concat-assets-folder "raindrops-improved.sh")
n=$1
valid=0
function is_factor {
local factor=$1 msg=$2
(( n % factor == 0 )) && printf $msg && valid=1
}
is_factor 3 "Pling"
is_factor 5 "Plang"
is_factor 7 "Plong"
(( valid == 0 )) && echo $n || printf '\n'
#+end_src
Also, the [[https://github.com/koalaman/shellcheck/wiki/SC2124][ShellCheck wiki]] is a pretty handy resource.