initial commit
This commit is contained in:
54
bash/acronym/README.md
Normal file
54
bash/acronym/README.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Acronym
|
||||
|
||||
Convert a phrase to its acronym.
|
||||
|
||||
Techies love their TLA (Three Letter Acronyms)!
|
||||
|
||||
Help generate some jargon by writing a program that converts a long name
|
||||
like Portable Network Graphics to its acronym (PNG).
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats acronym_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats acronym_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Julien Vanier [https://github.com/monkbroc](https://github.com/monkbroc)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
58
bash/acronym/acronym.sh
Executable file
58
bash/acronym/acronym.sh
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env bash
|
||||
# V1: original version
|
||||
# V2: final printf changeto avoid subshell
|
||||
|
||||
# external tools: none
|
||||
|
||||
# v1: initial version
|
||||
|
||||
# set to mask to enable logs
|
||||
debug=0
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
usage() {
|
||||
echo "acronym.sh word1 [...]" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# $1: log level, then strings to display.
|
||||
log () {
|
||||
(( debug & $1 )) && shift && echo "${@}"
|
||||
}
|
||||
|
||||
|
||||
# check for basic errors. We will accept multiple args:
|
||||
# acronym.sh i love suchi = acronym "i love suchi"
|
||||
(( $# < 1 )) && usage
|
||||
|
||||
# valid word separators
|
||||
VALID_SEPARATORS="-_*"
|
||||
|
||||
# replace valid chars with space, merge args in 1 string
|
||||
words="${*//[$VALID_SEPARATORS]/ }"
|
||||
log 1 valid separators ${#words[@]} "$words"
|
||||
|
||||
# remove remaining non alpha chars (keep blanks)
|
||||
words="${words//[^[:alpha:][:blank:]]/}"
|
||||
log 1 keep alpha "${words[@]}"
|
||||
|
||||
# capitalize, make an array
|
||||
words=(${words^^})
|
||||
log 1 "words ${#words[@]} ${words[@]}"
|
||||
|
||||
# print 1st chars
|
||||
printf -v result "%c" ${words[@]}
|
||||
log 1 result "$result"
|
||||
|
||||
echo "$result"
|
||||
|
||||
exit 0
|
||||
|
||||
# Indent style for emacs
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# sh-indentation: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 60
|
||||
# End:
|
54
bash/anagram/README.md
Normal file
54
bash/anagram/README.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Anagram
|
||||
|
||||
An anagram is a rearrangement of letters to form a new word.
|
||||
Given a word and a list of candidates, select the sublist of anagrams of the given word.
|
||||
|
||||
Given `"listen"` and a list of candidates like `"enlists" "google"
|
||||
"inlets" "banana"` the program should return a list containing
|
||||
`"inlets"`.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats anagram_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats anagram_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Inspired by the Extreme Startup game [https://github.com/rchatley/extreme_startup](https://github.com/rchatley/extreme_startup)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
60
bash/anagram/anagram.sh
Executable file
60
bash/anagram/anagram.sh
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# External tools: none.
|
||||
# Subshells: none.
|
||||
#
|
||||
# V1: initial version
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
(( debug=2#00000000 ))
|
||||
(( debug=2#00001111 ))
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo Line ${BASH_LINENO[0]}: "${@}" >&2
|
||||
#local -i i
|
||||
#if (( debug & $1 )) ; then
|
||||
# for ((i=1; i<$1; ++i)); do
|
||||
# echo -n " "
|
||||
# done
|
||||
# shift
|
||||
# echo "${BASH_LINENO[0]}: ${@}" >&2
|
||||
#fi
|
||||
}
|
||||
|
||||
die () {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
usage() {
|
||||
die "usage: anagram.sh word anagrams-list"
|
||||
}
|
||||
|
||||
# check for basic args
|
||||
(($# < 2)) && usage
|
||||
word="$1"
|
||||
shift
|
||||
# we will accept more than 1 anagram list:
|
||||
# anagram.sh "BANANA" "banana BANANA" = anagram "BANANA" "banana" "BANANA"
|
||||
# we start to split words
|
||||
declare -a words
|
||||
while (($# > 0)); do
|
||||
words=("${words[@]}" $1)
|
||||
typeset -p words
|
||||
shift
|
||||
done
|
||||
debug 1 words=${#words[@]}:${words[@]}
|
||||
typeset -p words
|
||||
|
||||
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 40
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
58
bash/armstrong-numbers/README.md
Normal file
58
bash/armstrong-numbers/README.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Armstrong Numbers
|
||||
|
||||
An [Armstrong number](https://en.wikipedia.org/wiki/Narcissistic_number) is a number that is the sum of its own digits each raised to the power of the number of digits.
|
||||
|
||||
For example:
|
||||
|
||||
- 9 is an Armstrong number, because `9 = 9^1 = 9`
|
||||
- 10 is *not* an Armstrong number, because `10 != 1^2 + 0^2 = 1`
|
||||
- 153 is an Armstrong number, because: `153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153`
|
||||
- 154 is *not* an Armstrong number, because: `154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190`
|
||||
|
||||
Write some code to determine whether a number is an Armstrong number.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats armstrong_numbers_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats armstrong_numbers_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Wikipedia [https://en.wikipedia.org/wiki/Narcissistic_number](https://en.wikipedia.org/wiki/Narcissistic_number)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
44
bash/armstrong-numbers/armstrong_numbers.sh
Executable file
44
bash/armstrong-numbers/armstrong_numbers.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
(( DEBUG=2#00000000 ))
|
||||
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( DEBUG & $1 )) && shift && echo "${@}" >&2
|
||||
}
|
||||
|
||||
usage () {
|
||||
echo "usage: ./armstrong_numbers.sh <number>" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# basic args checks: 1 arg, digits (at least 1) only
|
||||
(( $# != 1)) || [[ ! "$1" =~ ^[[:digit:]]+$ ]] && usage
|
||||
|
||||
number="$1"
|
||||
digits=${#number}
|
||||
armstrong=0
|
||||
result="false"
|
||||
|
||||
debug 1 d=$digits n=$number
|
||||
|
||||
# armstrong number calculation
|
||||
for (( i=0; i<digits; ++i )); do
|
||||
((armstrong += ${number:$i:1} ** digits ))
|
||||
done
|
||||
|
||||
debug 2 "armstrong=$armstrong"
|
||||
|
||||
((number == armstrong)) && result="true"
|
||||
|
||||
echo "$result"
|
||||
|
||||
exit 0
|
||||
|
||||
# Indent style for emacs
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 60
|
||||
# End:
|
75
bash/atbash-cipher/README.md
Normal file
75
bash/atbash-cipher/README.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Atbash Cipher
|
||||
|
||||
Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East.
|
||||
|
||||
The Atbash cipher is a simple substitution cipher that relies on
|
||||
transposing all the letters in the alphabet such that the resulting
|
||||
alphabet is backwards. The first letter is replaced with the last
|
||||
letter, the second with the second-last, and so on.
|
||||
|
||||
An Atbash cipher for the Latin alphabet would be as follows:
|
||||
|
||||
```text
|
||||
Plain: abcdefghijklmnopqrstuvwxyz
|
||||
Cipher: zyxwvutsrqponmlkjihgfedcba
|
||||
```
|
||||
|
||||
It is a very weak cipher because it only has one possible key, and it is
|
||||
a simple monoalphabetic substitution cipher. However, this may not have
|
||||
been an issue in the cipher's time.
|
||||
|
||||
Ciphertext is written out in groups of fixed length, the traditional group size
|
||||
being 5 letters, and punctuation is excluded. This is to make it harder to guess
|
||||
things based on word boundaries.
|
||||
|
||||
## Examples
|
||||
|
||||
- Encoding `test` gives `gvhg`
|
||||
- Decoding `gvhg` gives `test`
|
||||
- Decoding `gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt` gives `thequickbrownfoxjumpsoverthelazydog`
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats atbash_cipher_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats atbash_cipher_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Wikipedia [http://en.wikipedia.org/wiki/Atbash](http://en.wikipedia.org/wiki/Atbash)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
108
bash/atbash-cipher/atbash_cipher.sh
Executable file
108
bash/atbash-cipher/atbash_cipher.sh
Executable file
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# External tools: none.
|
||||
# Subshell: no.
|
||||
#
|
||||
# Tested on: bash 5.0, 3.2
|
||||
#
|
||||
# V1: initial version
|
||||
# V2: changed +() to @() in args check. Fixed typo on lines 48-52 formulas.
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
(( debug=2#00000000 ))
|
||||
#(( debug=2#00001111 ))
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo Line ${BASH_LINENO[0]}: "${@}" >&2
|
||||
}
|
||||
|
||||
die () {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
usage() {
|
||||
die "usage: atbash_cypher.sh encode|decode text [...]"
|
||||
}
|
||||
|
||||
# we will accept the syntax:
|
||||
# atbash_cypher.sh encode|decode text [...]
|
||||
# in case text is separated as multiple arguments, we will consider a space is
|
||||
# in between.
|
||||
# example:
|
||||
# atbash_cypher.sh encode "I am happy"
|
||||
# will also be accepted as:
|
||||
# atbash_cypher.sh encode I am happy
|
||||
|
||||
# basic args check & set all chars to lowercase
|
||||
(($# < 2)) || [[ "$1" != @(encode|decode) ]] && usage
|
||||
action="$1"
|
||||
shift
|
||||
string="${*,,}"
|
||||
len="${#string}"
|
||||
debug 1 "string=$string" "len=$len"
|
||||
|
||||
# algorithm we will use:
|
||||
# to get rev element c' of c in a consecutive integer n-m list :
|
||||
# c = n+i i is distance from n to c
|
||||
# c' = m-i and also reverse distance from m to c'
|
||||
# ------------
|
||||
# c+c' = n+m sum the 2
|
||||
# c' = n+m-c after simplification
|
||||
|
||||
# for printf, a '<char> arg is the ascii value of <char>
|
||||
# and yes, we should use a constant, any programmer knows ascii value of 'a'
|
||||
# and # of letters in alphabet, we could simply set tval to 219
|
||||
printf -v aval "%d" "'a" # 'a' ascii value
|
||||
printf -v zval "%d" "'z" # 'z' ascii value
|
||||
printf -v tval "%d" $((aval+zval)) # their sum
|
||||
|
||||
# tval=219 # correct code for this exercise, for me
|
||||
|
||||
debug 1 "aval:$aval zval:$zval tval:$tval"
|
||||
|
||||
# many options here:
|
||||
# - for encode, add <spaces> in loop, or at the end
|
||||
# - use a table with all alphabet ({a..z}), to avoid multiple printf
|
||||
# - fill acceptable chars only (my choice), insert spaces at end.
|
||||
# I preferred that one to avoid multiple encode/decode tests in loop.
|
||||
# - likely many others
|
||||
result="" # resulting string, with no spaces
|
||||
for ((i=0; i<len; ++i)); do
|
||||
c=${string:$i:1} # current char
|
||||
printf -v cval "%d" "'$c" # $c's ascii value
|
||||
debug 2 "c='$c' cval=$cval"
|
||||
|
||||
case "$c" in
|
||||
[[:alpha:]]) # rev $c's in alphabet (with hex value)
|
||||
printf -v rval "%x" $((tval - cval))
|
||||
printf -v c "\\x$rval" # shellcheck unhappy here
|
||||
debug 4 "rev c=$c"
|
||||
;;
|
||||
[![:digit:]]) # we avoid 1 case (digits)
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
result+="$c"
|
||||
done
|
||||
|
||||
# for encoding, we split in 5 chars groups.
|
||||
if [[ $action == encode ]]; then
|
||||
[[ $result =~ ${result//?/(.)} ]]
|
||||
# we use REMATCH here, to avoid loop, but we could end with a space.
|
||||
printf -v result "%c%c%c%c%c " "${BASH_REMATCH[@]:1}"
|
||||
fi
|
||||
|
||||
debug 1 "result: =${result%% }="
|
||||
echo "${result%% }" # fix possible REMATCH extra final space
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 40
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
62
bash/bob/README.md
Normal file
62
bash/bob/README.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Bob
|
||||
|
||||
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
|
||||
|
||||
Bob answers 'Sure.' if you ask him a question, such as "How are you?".
|
||||
|
||||
He answers 'Whoa, chill out!' if you YELL AT HIM (in all capitals).
|
||||
|
||||
He answers 'Calm down, I know what I'm doing!' if you yell a question at him.
|
||||
|
||||
He says 'Fine. Be that way!' if you address him without actually saying
|
||||
anything.
|
||||
|
||||
He answers 'Whatever.' to anything else.
|
||||
|
||||
Bob's conversational partner is a purist when it comes to written communication and always follows normal rules regarding sentence punctuation in English.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats bob_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats bob_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [http://pine.fm/LearnToProgram/?Chapter=06](http://pine.fm/LearnToProgram/?Chapter=06)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
56
bash/bob/bob.sh
Executable file
56
bash/bob/bob.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
# V1: initial version
|
||||
# V2: cosmetic changes
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
#(( debug=2#00001111 ))
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo "${@}" >&2
|
||||
}
|
||||
|
||||
arg="$1"
|
||||
|
||||
# trim all blank characters safely
|
||||
arg="${arg//[[:space:]]/}"
|
||||
debug 1 trim "$arg"
|
||||
|
||||
# and check if last char is question mark
|
||||
[[ ${arg: -1} == "?" ]] && question=+
|
||||
|
||||
# the tricky part in test is that non alpha characters are considered
|
||||
# differently in tests, depending on the rest of the string (having
|
||||
# letters or not). So we remove them in that case.
|
||||
[[ "$arg" == *[[:alpha:]]* ]] && arg="${arg//[![:alpha:]]/}"
|
||||
debug 1 special "$arg" $question
|
||||
|
||||
# and now proceed with rules
|
||||
case "$arg$question" in
|
||||
"")
|
||||
echo "Fine. Be that way!"
|
||||
;;
|
||||
+([[:upper:]])+)
|
||||
echo "Calm down, I know what I'm doing!"
|
||||
;;
|
||||
*+)
|
||||
echo "Sure."
|
||||
;;
|
||||
+([[:upper:]]))
|
||||
echo "Whoa, chill out!"
|
||||
;;
|
||||
*)
|
||||
echo "Whatever."
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 50
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
107
bash/bowling/README.md
Normal file
107
bash/bowling/README.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Bowling
|
||||
|
||||
Score a bowling game.
|
||||
|
||||
Bowling is a game where players roll a heavy ball to knock down pins
|
||||
arranged in a triangle. Write code to keep track of the score
|
||||
of a game of bowling.
|
||||
|
||||
## Scoring Bowling
|
||||
|
||||
The game consists of 10 frames. A frame is composed of one or two ball
|
||||
throws with 10 pins standing at frame initialization. There are three
|
||||
cases for the tabulation of a frame.
|
||||
|
||||
* An open frame is where a score of less than 10 is recorded for the
|
||||
frame. In this case the score for the frame is the number of pins
|
||||
knocked down.
|
||||
|
||||
* A spare is where all ten pins are knocked down by the second
|
||||
throw. The total value of a spare is 10 plus the number of pins
|
||||
knocked down in their next throw.
|
||||
|
||||
* A strike is where all ten pins are knocked down by the first
|
||||
throw. The total value of a strike is 10 plus the number of pins
|
||||
knocked down in the next two throws. If a strike is immediately
|
||||
followed by a second strike, then the value of the first strike
|
||||
cannot be determined until the ball is thrown one more time.
|
||||
|
||||
Here is a three frame example:
|
||||
|
||||
| Frame 1 | Frame 2 | Frame 3 |
|
||||
| :-------------: |:-------------:| :---------------------:|
|
||||
| X (strike) | 5/ (spare) | 9 0 (open frame) |
|
||||
|
||||
Frame 1 is (10 + 5 + 5) = 20
|
||||
|
||||
Frame 2 is (5 + 5 + 9) = 19
|
||||
|
||||
Frame 3 is (9 + 0) = 9
|
||||
|
||||
This means the current running total is 48.
|
||||
|
||||
The tenth frame in the game is a special case. If someone throws a
|
||||
strike or a spare then they get a fill ball. Fill balls exist to
|
||||
calculate the total of the 10th frame. Scoring a strike or spare on
|
||||
the fill ball does not give the player more fill balls. The total
|
||||
value of the 10th frame is the total number of pins knocked down.
|
||||
|
||||
For a tenth frame of X1/ (strike and a spare), the total value is 20.
|
||||
|
||||
For a tenth frame of XXX (three strikes), the total value is 30.
|
||||
|
||||
## Requirements
|
||||
|
||||
Write code to keep track of the score of a game of bowling. It should
|
||||
support two operations:
|
||||
|
||||
* `roll(pins : int)` is called each time the player rolls a ball. The
|
||||
argument is the number of pins knocked down.
|
||||
* `score() : int` is called only at the very end of the game. It
|
||||
returns the total score for that game.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats bowling_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats bowling_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
The Bowling Game Kata at but UncleBob [http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata](http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
86
bash/bowling/bowling.sh
Executable file
86
bash/bowling/bowling.sh
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# V1: initial version
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
(( debug=2#00000000 ))
|
||||
(( debug=2#00001111 ))
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo Line ${BASH_LINENO[0]}: "${@}" >&2
|
||||
}
|
||||
|
||||
die () {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
usage() {
|
||||
die "usage: bowling.sh r1-20 [r21 [r22]]"
|
||||
}
|
||||
# pincount > 10. $1: frame
|
||||
highroll() {
|
||||
die Frame "Frame $1: Pin count exceeds pins on the lane."
|
||||
}
|
||||
# pincount > 10. $1: frame
|
||||
negativeroll() {
|
||||
die Frame "Frame $1: Negative roll is invalid."
|
||||
}
|
||||
|
||||
|
||||
# args test: 10 rolls mandatory
|
||||
#(($# < 20)) && usage
|
||||
rolls=($@)
|
||||
debug 1 rolls=${rolls[@]}
|
||||
|
||||
((score = 0)) # total score
|
||||
((tempscore = 0)) # tmp score (for spare/strike)
|
||||
|
||||
declare -a frames # frames scores
|
||||
declare -a opened # spare:2, strike:1
|
||||
|
||||
((frame=-1)) # current frame
|
||||
|
||||
((curroll=1)) # roll in frame: 1:1st, 2:2nd
|
||||
((i=0))
|
||||
for ((roll=0; roll<$#; ++roll)); do
|
||||
debug 2 loop roll="$roll"
|
||||
|
||||
(( ! roll % 2 && frame++ ))
|
||||
exit 0
|
||||
(( score=${rolls[$i]} ))
|
||||
#(( score < 0 )) && || score > 10)) && echo 1
|
||||
#if ((!roll % 2)); then # first roll in frame
|
||||
|
||||
|
||||
((framescore=0)) # current frame score
|
||||
|
||||
|
||||
for j in 0 1; do
|
||||
(( roll = ${rolls[$i]} ))
|
||||
((roll < 0)) && die Frame $((curframe+1)): Negative roll is invalid.
|
||||
(( framescore += roll ))
|
||||
((framescore == 10)) && ((opened[$curframe] = j+1))
|
||||
(( i++ ))
|
||||
done
|
||||
debug 2 curframe=$curframe score=$framescore
|
||||
|
||||
#if ((roll))
|
||||
|
||||
((framescore > 10)) && wrongroll $curframe $curroll $framescore
|
||||
|
||||
frame[$curframe]=$framescore
|
||||
|
||||
|
||||
((curroll = -curroll))
|
||||
done
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 50
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
64
bash/darts/README.md
Normal file
64
bash/darts/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Darts
|
||||
|
||||
Write a function that returns the earned points in a single toss of a Darts game.
|
||||
|
||||
[Darts](https://en.wikipedia.org/wiki/Darts) is a game where players
|
||||
throw darts to a [target](https://en.wikipedia.org/wiki/Darts#/media/File:Darts_in_a_dartboard.jpg).
|
||||
|
||||
In our particular instance of the game, the target rewards with 4 different amounts of points, depending on where the dart lands:
|
||||
|
||||
* If the dart lands outside the target, player earns no points (0 points).
|
||||
* If the dart lands in the outer circle of the target, player earns 1 point.
|
||||
* If the dart lands in the middle circle of the target, player earns 5 points.
|
||||
* If the dart lands in the inner circle of the target, player earns 10 points.
|
||||
|
||||
The outer circle has a radius of 10 units (This is equivalent to the total radius for the entire target), the middle circle a radius of 5 units, and the inner circle a radius of 1. Of course, they are all centered to the same point (That is, the circles are [concentric](http://mathworld.wolfram.com/ConcentricCircles.html)) defined by the coordinates (0, 0).
|
||||
|
||||
Write a function that given a point in the target (defined by its `real` cartesian coordinates `x` and `y`), returns the correct amount earned by a dart landing in that point.
|
||||
|
||||
This particular exercise, since it deals with floating point arithmetic, is natural to rely on external tools (see below). As an extra challenging challenge, find a way to implement this with plain bash.
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats darts_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats darts_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Inspired by an exercise created by a professor Della Paolera in Argentina
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
82
bash/darts/darts.sh
Executable file
82
bash/darts/darts.sh
Executable file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# external tools: none (only integer operations).
|
||||
#
|
||||
# V1 : Initial version.
|
||||
# V2 : Using reference instead of subshell, as of
|
||||
# https://stackoverflow.com/questions/540298
|
||||
# moved valid numbers in parseval function.
|
||||
# V3/4 : added some quotes following suggestions
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
#((DEBUG=2#00001111))
|
||||
((DEBUG=2#00000000))
|
||||
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( DEBUG & $1 )) && shift && echo "${@}" >&2
|
||||
}
|
||||
|
||||
usage () {
|
||||
echo "usage: darts x y" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# To be able to use bash only, all numbers will be miltiplied by 1,000.
|
||||
# Could be higher if we want more precision.
|
||||
#
|
||||
# So: 0.1 will be 100, 1 will be 1,000, 10 will br 10000, etc...
|
||||
|
||||
# circles. as we will use Pythagoras' theorem, so square value calc here
|
||||
outer=$(( (10 * 1000 ) ** 2 ))
|
||||
middle=$(( ( 5 * 1000 ) ** 2 ))
|
||||
inner=$(( ( 1 * 1000 ) ** 2 ))
|
||||
|
||||
debug 1 outer=$outer middle=$middle inner=$inner
|
||||
|
||||
# basic args check: 2 args, and decimal numbers, which are:
|
||||
# optional +- sign, optional digits, optional . and optional digits
|
||||
(( ${#} != 2 )) && usage
|
||||
|
||||
parseval() {
|
||||
# integer and decimal parts, final value by ref
|
||||
local int dec
|
||||
local -n calc=$1
|
||||
|
||||
# check for valid decimal number
|
||||
[[ ${2} != ?([-+])+([0-9])?(.*([0-9])) ]] && usage
|
||||
|
||||
IFS=. read int dec <<< "$2"
|
||||
debug 2 ${int} ${dec}
|
||||
|
||||
# we accept up to 3 decimals: add 3 zeroes to dec, then keep 3 first digits
|
||||
# So a decimal part of "1" will become 100, 01 will become 10, etc...
|
||||
# we also take care of leadings 0 (octal notation), and remove leading "-".
|
||||
dec="$dec"000
|
||||
dec="10#"${dec:0:3}
|
||||
int="10#"${int#-}
|
||||
|
||||
debug 2 mult ${int} ${dec}
|
||||
calc=$(( (int*1000 + dec) ** 2 ))
|
||||
}
|
||||
|
||||
parseval x "$1"
|
||||
parseval y "$2"
|
||||
total=$(( x+y ))
|
||||
debug 1 x=$x y=$y x+y=$total
|
||||
|
||||
(( total <= inner )) && echo 10 && exit 0
|
||||
(( total <= middle )) && echo 5 && exit 0
|
||||
(( total <= outer )) && echo 1 && exit 0
|
||||
echo 0 && exit 0
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 60
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
63
bash/difference-of-squares/README.md
Normal file
63
bash/difference-of-squares/README.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Difference Of Squares
|
||||
|
||||
Find the difference between the square of the sum and the sum of the squares of the first N natural numbers.
|
||||
|
||||
The square of the sum of the first ten natural numbers is
|
||||
(1 + 2 + ... + 10)² = 55² = 3025.
|
||||
|
||||
The sum of the squares of the first ten natural numbers is
|
||||
1² + 2² + ... + 10² = 385.
|
||||
|
||||
Hence the difference between the square of the sum of the first
|
||||
ten natural numbers and the sum of the squares of the first ten
|
||||
natural numbers is 3025 - 385 = 2640.
|
||||
|
||||
You are not expected to discover an efficient solution to this yourself from
|
||||
first principles; research is allowed, indeed, encouraged. Finding the best
|
||||
algorithm for the problem is a key skill in software engineering.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats difference_of_squares_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats difference_of_squares_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Problem 6 at Project Euler [http://projecteuler.net/problem=6](http://projecteuler.net/problem=6)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
84
bash/difference-of-squares/difference_of_squares.sh
Executable file
84
bash/difference-of-squares/difference_of_squares.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# External tools: none.
|
||||
# subshell: none.
|
||||
#
|
||||
# V1: initial version
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
(( debug=2#00000000 ))
|
||||
#(( debug=2#00001111 ))
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo Line ${BASH_LINENO[0]}: "${@}" >&2
|
||||
}
|
||||
|
||||
die () {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
usage() {
|
||||
die "usage: difference_of_squares.sh command color"
|
||||
}
|
||||
|
||||
debug 1 "#=$#" "arg=$1"
|
||||
(($# != 2)) || [[ $1 != @(square_of_sum|sum_of_squares|difference) ]] || \
|
||||
[[ "$2" != +([[:digit:]]) ]] && usage
|
||||
|
||||
# the 2 next functions will set $1 to the calculated value for $2
|
||||
sum_of_squares () { # set $1 to sum of squares ($2)
|
||||
local -n res=$1
|
||||
local val=$2
|
||||
|
||||
# the sum of 1st n integers squares is:
|
||||
# S = 1² + 2² + 3² ..... + (n-1)² + n²
|
||||
# = [ n * (n+1) * (2n+1) ] / 6
|
||||
# demonstration on:
|
||||
# http://www.takayaiwamoto.com/Sums_and_Series/sumsqr_1.html
|
||||
(( res = val * (val+1) * (2*val + 1) / 6 ))
|
||||
debug 2 "sum_of_squares($val) = $res"
|
||||
}
|
||||
square_of_sum () { # set $1 to square of sum ($2)
|
||||
local -n res=$1
|
||||
local val=$2
|
||||
|
||||
# The sum of n 1st integers is:
|
||||
# S = 1 + 2 + 3 ... + (n-1) + n
|
||||
# = [ n * (n+1) ] / 2
|
||||
# demonstration is trivial for this one.
|
||||
(( res = (val * (val+1) / 2 ) ** 2 ))
|
||||
debug 2 "square_of_sum($val) = $res"
|
||||
}
|
||||
|
||||
action="$1"
|
||||
(( num = $2 ))
|
||||
|
||||
case "$action" in
|
||||
square_of_sum)
|
||||
square_of_sum result "$num"
|
||||
debug 3 "result after calling square_of_sum: $result"
|
||||
;;
|
||||
sum_of_squares)
|
||||
sum_of_squares result "$num"
|
||||
debug 3 "result after calling sum_of_squares: $result"
|
||||
;;
|
||||
difference)
|
||||
square_of_sum SqSum "$num"
|
||||
sum_of_squares SumSq "$num"
|
||||
((result = SqSum - SumSq))
|
||||
debug 3 "result after calling difference: $result"
|
||||
esac
|
||||
|
||||
echo $result
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 40
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
79
bash/dnd-character/README.md
Normal file
79
bash/dnd-character/README.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# D&D Character
|
||||
|
||||
For a game of [Dungeons & Dragons][DND], each player starts by generating a
|
||||
character they can play with. This character has, among other things, six
|
||||
abilities; strength, dexterity, constitution, intelligence, wisdom and
|
||||
charisma. These six abilities have scores that are determined randomly. You
|
||||
do this by rolling four 6-sided dice and record the sum of the largest three
|
||||
dice. You do this six times, once for each ability.
|
||||
|
||||
Your character's initial hitpoints are 10 + your character's constitution
|
||||
modifier. You find your character's constitution modifier by subtracting 10
|
||||
from your character's constitution, divide by 2 and round down.
|
||||
|
||||
Write a random character generator that follows the rules above.
|
||||
|
||||
For example, the six throws of four dice may look like:
|
||||
|
||||
* 5, 3, 1, 6: You discard the 1 and sum 5 + 3 + 6 = 14, which you assign to strength.
|
||||
* 3, 2, 5, 3: You discard the 2 and sum 3 + 5 + 3 = 11, which you assign to dexterity.
|
||||
* 1, 1, 1, 1: You discard the 1 and sum 1 + 1 + 1 = 3, which you assign to constitution.
|
||||
* 2, 1, 6, 6: You discard the 1 and sum 2 + 6 + 6 = 14, which you assign to intelligence.
|
||||
* 3, 5, 3, 4: You discard the 3 and sum 5 + 3 + 4 = 12, which you assign to wisdom.
|
||||
* 6, 6, 6, 6: You discard the 6 and sum 6 + 6 + 6 = 18, which you assign to charisma.
|
||||
|
||||
Because constitution is 3, the constitution modifier is -4 and the hitpoints are 6.
|
||||
|
||||
## Notes
|
||||
|
||||
Most programming languages feature (pseudo-)random generators, but few
|
||||
programming languages are designed to roll dice. One such language is [Troll].
|
||||
|
||||
[DND]: https://en.wikipedia.org/wiki/Dungeons_%26_Dragons
|
||||
[Troll]: http://hjemmesider.diku.dk/~torbenm/Troll/
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats dnd_character_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats dnd_character_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Simon Shine, Erik Schierboom [https://github.com/exercism/problem-specifications/issues/616#issuecomment-437358945](https://github.com/exercism/problem-specifications/issues/616#issuecomment-437358945)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
115
bash/dnd-character/dnd_character.sh
Executable file
115
bash/dnd-character/dnd_character.sh
Executable file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# v1: initial version
|
||||
# v2: cleanup, replaced while loops with for loops when possible
|
||||
|
||||
# external tools: none
|
||||
|
||||
# set to 0 to disable log function output, 1 otherwise
|
||||
debug=0
|
||||
|
||||
declare -a abilities=( strength dexterity intelligence wisdom charisma constitution )
|
||||
|
||||
|
||||
usage() {
|
||||
echo "dnd_characters.sh generate|modifier <n>" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# log function takes 1 argument which is echoed if $debug is > 0
|
||||
# todo: Add another argument (mask ?) to selectively log portions of code
|
||||
log () {
|
||||
(( $debug )) && echo "$*"
|
||||
}
|
||||
|
||||
# simple bubble sort for numeric array (descending)
|
||||
# args: 1: the array
|
||||
# todo: add a parameter for asc/desc order.
|
||||
sort_n() {
|
||||
local -a array=( "$@" )
|
||||
local -i max=$(( ${#array[@]} - 1 ))
|
||||
|
||||
for (( max= $(( ${#array[@]} - 1 )); max > 0; max-- )); do
|
||||
local -i i
|
||||
for (( i=0; i<max; i++ )); do
|
||||
local -i val1=${array[$i]}
|
||||
local -i val2=${array[$((i + 1))]}
|
||||
|
||||
# switch if necessary
|
||||
if (( $val1 < $val2 )); then
|
||||
local tmp=$val1
|
||||
array[$i]=$val2
|
||||
array[$(($i + 1))]=$tmp
|
||||
fi
|
||||
done
|
||||
done
|
||||
echo "${array[@]}"
|
||||
}
|
||||
|
||||
# roll $2 times a $1 faces dice
|
||||
roll() {
|
||||
local -a rolls
|
||||
local -i i
|
||||
for (( i=1; i<=$2; i++ )); do
|
||||
rolls[$i]=$((RANDOM % $1 + 1))
|
||||
done
|
||||
|
||||
echo ${rolls[@]}
|
||||
}
|
||||
|
||||
modifier() {
|
||||
local -i res
|
||||
local -i in=$1
|
||||
local -i out=$(( $in - 10 ))
|
||||
|
||||
log modifier in "$1"
|
||||
res=$(( $out / 2 )) # will alwaid round down
|
||||
log modifier div "$res"
|
||||
# adjust for negative numbers
|
||||
(( $out < 0 )) && (( $out % 2 )) && (( res-- ))
|
||||
log modifier adjust negative "$res"
|
||||
|
||||
echo $res
|
||||
}
|
||||
|
||||
generate() {
|
||||
local -i s
|
||||
local -a dices
|
||||
|
||||
for ability in ${abilities[@]}; do
|
||||
dices=( $(roll 6 4) )
|
||||
s=( $(sort_n ${dices[@]}) )
|
||||
|
||||
sum=$(( ${s[1]} + ${s[2]} + ${s[3]} ))
|
||||
echo $ability $sum
|
||||
|
||||
if [[ $ability == "constitution" ]]; then
|
||||
echo "hitpoints $(( 10 - $(modifier $sum) ))"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
command="$1"
|
||||
case "$command" in
|
||||
"modifier")
|
||||
(( $# != 2 )) && usage
|
||||
modifier "$2"
|
||||
;;
|
||||
"generate")
|
||||
(( $# != 1 )) && usage
|
||||
generate
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Indent style for emacs
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# sh-indentation: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 60
|
||||
# End:
|
53
bash/error-handling/README.md
Normal file
53
bash/error-handling/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Error Handling
|
||||
|
||||
Implement various kinds of error handling and resource management.
|
||||
|
||||
An important point of programming is how to handle errors and close
|
||||
resources even if errors occur.
|
||||
|
||||
This exercise requires you to handle various errors. Because error handling
|
||||
is rather programming language specific you'll have to refer to the tests
|
||||
for your track to see what's exactly required.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats error_handling_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats error_handling_test.sh
|
||||
```
|
||||
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
12
bash/error-handling/error_handling.sh
Executable file
12
bash/error-handling/error_handling.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Note: I don't like the test on empty arg or whitespaces only arg:
|
||||
# 'error_handling.sh ""' and 'error_handling.sh " "'
|
||||
# should be faulty, instead of displaying a strange message ("Hello, ")
|
||||
usage() {
|
||||
echo "Usage: ./error_handling <greetee>"
|
||||
exit 1
|
||||
}
|
||||
(( $# != 1 )) && usage
|
||||
|
||||
echo "Hello, $1"
|
73
bash/grains/README.md
Normal file
73
bash/grains/README.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Grains
|
||||
|
||||
Calculate the number of grains of wheat on a chessboard given that the number
|
||||
on each square doubles.
|
||||
|
||||
There once was a wise servant who saved the life of a prince. The king
|
||||
promised to pay whatever the servant could dream up. Knowing that the
|
||||
king loved chess, the servant told the king he would like to have grains
|
||||
of wheat. One grain on the first square of a chess board, with the number
|
||||
of grains doubling on each successive square.
|
||||
|
||||
There are 64 squares on a chessboard (where square 1 has one grain, square 2 has two grains, and so on).
|
||||
|
||||
Write code that shows:
|
||||
- how many grains were on a given square, and
|
||||
- the total number of grains on the chessboard
|
||||
|
||||
## For bonus points
|
||||
|
||||
Did you get the tests passing and the code clean? If you want to, these
|
||||
are some additional things you could try:
|
||||
|
||||
- Optimize for speed.
|
||||
- Optimize for readability.
|
||||
|
||||
Then please share your thoughts in a comment on the submission. Did this
|
||||
experiment make the code better? Worse? Did you learn anything from it?
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats grains_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats grains_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
JavaRanch Cattle Drive, exercise 6 [http://www.javaranch.com/grains.jsp](http://www.javaranch.com/grains.jsp)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
65
bash/grains/grains.sh
Executable file
65
bash/grains/grains.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# V1: initial version
|
||||
#
|
||||
# Note: untested on 32 bits and big-endian architectures
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
(( debug=2#00000000 ))
|
||||
#(( debug=2#00001111 ))
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo Line ${BASH_LINENO[0]}: "${@}" >&2
|
||||
}
|
||||
|
||||
die () {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
usage() {
|
||||
die "Error: invalid input"
|
||||
}
|
||||
|
||||
# we want 1 arg only, "total" or digits only.
|
||||
(($# !=1 )) || \
|
||||
[[ "$1" != +([[:digit:]]) ]] && \
|
||||
[[ "$1" != "total" ]] && usage
|
||||
|
||||
arg="${1##+(0)}" # we strip leading zeroes if any
|
||||
debug 1 arg="$arg"
|
||||
|
||||
case "$arg" in
|
||||
total)
|
||||
# formula to calculate a geometric series of common ratio r and first
|
||||
# term f, that is: S=f + fr² + fr³ ... + frⁿ
|
||||
# is: S = f * [ (1 - rⁿ⁺¹) / (1 - r) ]
|
||||
#
|
||||
# for r=2 and f=1, it becomes:
|
||||
# S = 1 * (1 - 2ⁿ⁺¹) / -1 = 2ⁿ⁺¹ - 1
|
||||
# So here, as total does not accept an argument, such as "last square",
|
||||
# the value is 2⁶⁴-1.
|
||||
# Notes: (2**64) is 0 on 64 bits, but better not to use this property.
|
||||
# We could also directly output the value, as it is a constant.
|
||||
printf -v result "%llu" $(( 2**64 - 1 ))
|
||||
;;
|
||||
*) # always digits here
|
||||
debug 2 "digits=args"
|
||||
(( arg < 1 || arg > 64 )) && usage
|
||||
printf -v result "%llu" $(( 2**(arg-1) ))
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$result"
|
||||
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 40
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
111
bash/grep/README.md
Normal file
111
bash/grep/README.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# Grep
|
||||
|
||||
Search a file for lines matching a regular expression pattern. Return the line
|
||||
number and contents of each matching line.
|
||||
|
||||
The Unix [`grep`](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html) command can be used to search for lines in one or more files
|
||||
that match a user-provided search query (known as the *pattern*).
|
||||
|
||||
The `grep` command takes three arguments:
|
||||
|
||||
1. The pattern used to match lines in a file.
|
||||
2. Zero or more flags to customize the matching behavior.
|
||||
3. One or more files in which to search for matching lines.
|
||||
|
||||
Your task is to implement the `grep` function, which should read the contents
|
||||
of the specified files, find the lines that match the specified pattern
|
||||
and then output those lines as a single string. Note that the lines should
|
||||
be output in the order in which they were found, with the first matching line
|
||||
in the first file being output first.
|
||||
|
||||
As an example, suppose there is a file named "input.txt" with the following contents:
|
||||
|
||||
```text
|
||||
hello
|
||||
world
|
||||
hello again
|
||||
```
|
||||
|
||||
If we were to call `grep "hello" input.txt`, the returned string should be:
|
||||
|
||||
```text
|
||||
hello
|
||||
hello again
|
||||
```
|
||||
|
||||
### Flags
|
||||
|
||||
As said earlier, the `grep` command should also support the following flags:
|
||||
|
||||
- `-n` Print the line numbers of each matching line.
|
||||
- `-l` Print only the names of files that contain at least one matching line.
|
||||
- `-i` Match line using a case-insensitive comparison.
|
||||
- `-v` Invert the program -- collect all lines that fail to match the pattern.
|
||||
- `-x` Only match entire lines, instead of lines that contain a match.
|
||||
|
||||
If we run `grep -n "hello" input.txt`, the `-n` flag will require the matching
|
||||
lines to be prefixed with its line number:
|
||||
|
||||
```text
|
||||
1:hello
|
||||
3:hello again
|
||||
```
|
||||
|
||||
And if we run `grep -i "HELLO" input.txt`, we'll do a case-insensitive match,
|
||||
and the output will be:
|
||||
|
||||
```text
|
||||
hello
|
||||
hello again
|
||||
```
|
||||
|
||||
The `grep` command should support multiple flags at once.
|
||||
|
||||
For example, running `grep -l -v "hello" file1.txt file2.txt` should
|
||||
print the names of files that do not contain the string "hello".
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats grep_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats grep_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Conversation with Nate Foster. [http://www.cs.cornell.edu/Courses/cs3110/2014sp/hw/0/ps0.pdf](http://www.cs.cornell.edu/Courses/cs3110/2014sp/hw/0/ps0.pdf)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
88
bash/grep/grep.sh
Executable file
88
bash/grep/grep.sh
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
usage () {
|
||||
echo "usage: grep.sh [-nlivx] [-e] pattern file [...]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# no arguments
|
||||
LN= # be sure variables are reset
|
||||
FN=
|
||||
RV=
|
||||
FL=
|
||||
MULTI=
|
||||
|
||||
# parse args:
|
||||
while getopts ":nlivxe" arg; do
|
||||
case $arg in
|
||||
n) LN=t ;; # will print line number
|
||||
l) FN=t ;; # only file names
|
||||
i) shopt -s nocasematch ;; # case insensitive
|
||||
v) RV=t ;; # reverse search
|
||||
x) FL=t ;; # full line search
|
||||
e) break ;; # not in exercise: end args
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
# need at least pattern and 1 file.
|
||||
# TODO: consider stdin if no file
|
||||
[[ $# < 2 ]] && usage
|
||||
[[ $# > 2 ]] && MULTI=t
|
||||
|
||||
# full line match
|
||||
if [[ $FL = t ]]; then
|
||||
pattern="^$1\$"
|
||||
else
|
||||
pattern=".*$1.*"
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
# will prevent leading/trailing whitespaces to be trimmed
|
||||
IFS=""
|
||||
|
||||
while [[ $# > 0 ]]; do
|
||||
file="$1"
|
||||
if [[ ! -r "$file" ]]; then
|
||||
echo "$file: no such file, or not readable."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
lnum=0 # line number
|
||||
|
||||
match=n
|
||||
while read -r line ; do # will consider '\' as normal char
|
||||
(( lnum ++ ))
|
||||
|
||||
if [[ $line =~ $pattern ]] ; then # line match
|
||||
match=y
|
||||
|
||||
# print only filename, go to next file
|
||||
[[ $FN = t ]] && echo "$file" && break
|
||||
|
||||
# not reverse matching only
|
||||
if [[ $RV != t ]]; then
|
||||
# multiple files: print filename
|
||||
[[ $MULTI == t ]] && echo -n "$file:"
|
||||
[[ $LN = t ]] && echo -n "$lnum:"
|
||||
echo "$line"
|
||||
fi
|
||||
else
|
||||
# reverse match
|
||||
if [[ $RV == t ]]; then
|
||||
# print only filename, go to next file
|
||||
[[ $FN = t ]] && echo "$file" && break
|
||||
|
||||
# multiple files: print filename
|
||||
[[ $MULTI == t ]] && echo -n "$file:"
|
||||
[[ $LN = t ]] && echo -n "$lnum:"
|
||||
echo "$line"
|
||||
fi
|
||||
fi
|
||||
done < "$1"
|
||||
|
||||
shift # next file
|
||||
done
|
||||
exit 0
|
70
bash/hamming/README.md
Normal file
70
bash/hamming/README.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Hamming
|
||||
|
||||
Calculate the Hamming Distance between two DNA strands.
|
||||
|
||||
Your body is made up of cells that contain DNA. Those cells regularly wear out and need replacing, which they achieve by dividing into daughter cells. In fact, the average human body experiences about 10 quadrillion cell divisions in a lifetime!
|
||||
|
||||
When cells divide, their DNA replicates too. Sometimes during this process mistakes happen and single pieces of DNA get encoded with the incorrect information. If we compare two strands of DNA and count the differences between them we can see how many mistakes occurred. This is known as the "Hamming Distance".
|
||||
|
||||
We read DNA using the letters C,A,G and T. Two strands might look like this:
|
||||
|
||||
GAGCCTACTAACGGGAT
|
||||
CATCGTAATGACGGCCT
|
||||
^ ^ ^ ^ ^ ^^
|
||||
|
||||
They have 7 differences, and therefore the Hamming Distance is 7.
|
||||
|
||||
The Hamming Distance is useful for lots of things in science, not just biology, so it's a nice phrase to be familiar with :)
|
||||
|
||||
# Implementation notes
|
||||
|
||||
The Hamming distance is only defined for sequences of equal length, so
|
||||
an attempt to calculate it between sequences of different lengths should
|
||||
not work. The general handling of this situation (e.g., raising an
|
||||
exception vs returning a special value) may differ between languages.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats hamming_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats hamming_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
The Calculating Point Mutations problem at Rosalind [http://rosalind.info/problems/hamm/](http://rosalind.info/problems/hamm/)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
42
bash/hamming/hamming.sh
Executable file
42
bash/hamming/hamming.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# set to 0 to disable log function output, 1 otherwise
|
||||
debug=0
|
||||
|
||||
# echoes $1, then exit 1
|
||||
die () {
|
||||
echo "$1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# log function takes 1 argument which is echoed if $debug is > 0
|
||||
# todo: Ad another argument (mask?) to selectively log portions of code
|
||||
log () {
|
||||
(( $debug )) && echo "$1"
|
||||
}
|
||||
|
||||
# check basic errors
|
||||
(( $# != 2 )) && die "Usage: hamming.sh <string1> <string2>"
|
||||
(( ${#1} != ${#2} )) && die "left and right strands must be of equal length"
|
||||
|
||||
# compare strings
|
||||
declare -i cur hamming=0
|
||||
|
||||
for (( cur=0; cur < ${#1}; cur++ )); do
|
||||
log "$cur ${1:$cur:1} ${2:$cur:1}"
|
||||
c1="${1:$cur:1}"
|
||||
c2="${2:$cur:1}"
|
||||
[[ "$c1" != "$c2" ]] && ((hamming++))
|
||||
log "hamming in loop=$hamming"
|
||||
done
|
||||
|
||||
echo "$hamming"
|
||||
exit 0
|
||||
|
||||
# Indent style for emacs
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# sh-indentation: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 60
|
||||
# End:
|
101
bash/hello-world/README.md
Normal file
101
bash/hello-world/README.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Hello World
|
||||
|
||||
The classical introductory exercise. Just say "Hello, World!".
|
||||
|
||||
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is
|
||||
the traditional first program for beginning programming in a new language
|
||||
or environment.
|
||||
|
||||
The objectives are simple:
|
||||
|
||||
- Write a function that returns the string "Hello, World!".
|
||||
- Run the test suite and make sure that it succeeds.
|
||||
- Submit your solution and check it at the website.
|
||||
|
||||
If everything goes well, you will be ready to fetch your first real exercise.
|
||||
|
||||
# Welcome to Bash!
|
||||
|
||||
Unlike many other languages here, bash is a bit of a special snowflake.
|
||||
If you are on a Mac or other unix-y platform, you almost definitely
|
||||
already have bash. In fact, anything you type into the terminal is
|
||||
likely going through bash.
|
||||
|
||||
The downside to this is that there isn't much of a development
|
||||
ecosystem around bash like there is for other languages, and there are
|
||||
multiple versions of bash that can be frustratingly incompatible. Luckily
|
||||
we shouldn't hit those differences for these basic examples, and if you
|
||||
can get the tests to pass on your machine, we are doing great.
|
||||
|
||||
## Installation
|
||||
|
||||
As mentioned above, if you are on a unix-like OS (Mac OS X, Linux, Solaris,
|
||||
etc), you probably already have bash.
|
||||
|
||||
## Testing
|
||||
|
||||
As there isn't much of a bash ecosystem, there also isn't really a de
|
||||
facto leader in the bash testing area. For these examples we are using
|
||||
[bats](https://github.com/sstephenson/bats). You should be able to
|
||||
install it from your favorite package manager, on OS X with homebrew
|
||||
this would look something like this:
|
||||
|
||||
```
|
||||
$ brew install bats
|
||||
==> Downloading
|
||||
https://github.com/sstephenson/bats/archive/v0.4.0.tar.gz
|
||||
==> Downloading from
|
||||
https://codeload.github.com/sstephenson/bats/tar.gz/v0.4.0
|
||||
########################################################################
|
||||
100.0%
|
||||
==> ./install.sh /opt/boxen/homebrew/Cellar/bats/0.4.0
|
||||
🍺 /opt/boxen/homebrew/Cellar/bats/0.4.0: 10 files, 60K, built in 2
|
||||
seconds
|
||||
```
|
||||
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats hello_world_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats hello_world_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
5
bash/hello-world/hello_world.sh
Normal file
5
bash/hello-world/hello_world.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# exercism: hello world
|
||||
|
||||
echo "Hello, World!"
|
70
bash/leap/README.md
Normal file
70
bash/leap/README.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Leap
|
||||
|
||||
Given a year, report if it is a leap year.
|
||||
|
||||
The tricky thing here is that a leap year in the Gregorian calendar occurs:
|
||||
|
||||
```text
|
||||
on every year that is evenly divisible by 4
|
||||
except every year that is evenly divisible by 100
|
||||
unless the year is also evenly divisible by 400
|
||||
```
|
||||
|
||||
For example, 1997 is not a leap year, but 1996 is. 1900 is not a leap
|
||||
year, but 2000 is.
|
||||
|
||||
## Notes
|
||||
|
||||
Though our exercise adopts some very simple rules, there is more to
|
||||
learn!
|
||||
|
||||
For a delightful, four minute explanation of the whole leap year
|
||||
phenomenon, go watch [this youtube video][video].
|
||||
|
||||
[video]: http://www.youtube.com/watch?v=xX96xng7sAE
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats leap_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats leap_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
JavaRanch Cattle Drive, exercise 3 [http://www.javaranch.com/leap.jsp](http://www.javaranch.com/leap.jsp)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
13
bash/leap/leap.sh
Executable file
13
bash/leap/leap.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
[[ $# != 1 || ! $1 =~ ^[0-9]+$ ]] && echo "Usage: $0 <year>" && exit 1
|
||||
|
||||
year=$1
|
||||
leap=false
|
||||
if ! (($year % 4)) && (($year % 100)) || ! (($year % 400))
|
||||
then
|
||||
leap=true
|
||||
fi
|
||||
echo $leap
|
||||
|
||||
exit 0
|
111
bash/luhn/README.md
Normal file
111
bash/luhn/README.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# Luhn
|
||||
|
||||
Given a number determine whether or not it is valid per the Luhn formula.
|
||||
|
||||
The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is
|
||||
a simple checksum formula used to validate a variety of identification
|
||||
numbers, such as credit card numbers and Canadian Social Insurance
|
||||
Numbers.
|
||||
|
||||
The task is to check if a given string is valid.
|
||||
|
||||
Validating a Number
|
||||
------
|
||||
|
||||
Strings of length 1 or less are not valid. Spaces are allowed in the input,
|
||||
but they should be stripped before checking. All other non-digit characters
|
||||
are disallowed.
|
||||
|
||||
## Example 1: valid credit card number
|
||||
|
||||
```text
|
||||
4539 1488 0343 6467
|
||||
```
|
||||
|
||||
The first step of the Luhn algorithm is to double every second digit,
|
||||
starting from the right. We will be doubling
|
||||
|
||||
```text
|
||||
4_3_ 1_8_ 0_4_ 6_6_
|
||||
```
|
||||
|
||||
If doubling the number results in a number greater than 9 then subtract 9
|
||||
from the product. The results of our doubling:
|
||||
|
||||
```text
|
||||
8569 2478 0383 3437
|
||||
```
|
||||
|
||||
Then sum all of the digits:
|
||||
|
||||
```text
|
||||
8+5+6+9+2+4+7+8+0+3+8+3+3+4+3+7 = 80
|
||||
```
|
||||
|
||||
If the sum is evenly divisible by 10, then the number is valid. This number is valid!
|
||||
|
||||
## Example 2: invalid credit card number
|
||||
|
||||
```text
|
||||
8273 1232 7352 0569
|
||||
```
|
||||
|
||||
Double the second digits, starting from the right
|
||||
|
||||
```text
|
||||
7253 2262 5312 0539
|
||||
```
|
||||
|
||||
Sum the digits
|
||||
|
||||
```text
|
||||
7+2+5+3+2+2+6+2+5+3+1+2+0+5+3+9 = 57
|
||||
```
|
||||
|
||||
57 is not evenly divisible by 10, so this number is not valid.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats luhn_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats luhn_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
The Luhn Algorithm on Wikipedia [http://en.wikipedia.org/wiki/Luhn_algorithm](http://en.wikipedia.org/wiki/Luhn_algorithm)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
57
bash/luhn/luhn.sh
Executable file
57
bash/luhn/luhn.sh
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# External tools: none.
|
||||
#
|
||||
# V1: initial version
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
(( debug=2#00000000 ))
|
||||
#(( debug=2#00001111 ))
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo Line ${BASH_LINENO[0]}: "${@}" >&2
|
||||
}
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# basic args usage. We will accept the args to be splitted (out of scope
|
||||
# for exercise): "luhn.sh '0 0'" is considered equivalent to "luhn.sh 0 0"
|
||||
IFS="" number="${*// /}" # merge args, remove all <spaces>
|
||||
debug 1 number="${number}"
|
||||
|
||||
((${#number} < 2)) || # args check: only [0-9], at least 2
|
||||
[[ "$number" != +([0-9]) ]] &&
|
||||
echo false && exit 0
|
||||
|
||||
((len=${#number}))
|
||||
((sum=0)) # final sum
|
||||
|
||||
for ((i=1; i<=len; ++i)); do # we loop on each digit, from end
|
||||
digit=${number:((-i)):1}
|
||||
case $((i % 2)) in
|
||||
0) # even position (relative to end)
|
||||
((digit *= 2))
|
||||
((digit >= 10)) && ((digit-=9))
|
||||
debug 3 even ${digit}
|
||||
;;
|
||||
1) # odd position (relative to end)
|
||||
debug 3 odd ${digit}
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
((sum+=digit))
|
||||
debug 2 sum=${sum}
|
||||
done
|
||||
((sum % 10)) && echo false || echo true
|
||||
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 40
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
51
bash/matching-brackets/README.md
Normal file
51
bash/matching-brackets/README.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Matching Brackets
|
||||
|
||||
Given a string containing brackets `[]`, braces `{}`, parentheses `()`,
|
||||
or any combination thereof, verify that any and all pairs are matched
|
||||
and nested correctly.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats matching_brackets_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats matching_brackets_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Ginna Baker
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
23
bash/matching-brackets/matching_brackets.sh
Executable file
23
bash/matching-brackets/matching_brackets.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash -x
|
||||
shopt -s extglob
|
||||
str=$1
|
||||
# Brute force algorithm:
|
||||
# 1 - remove all unwanted chars: keep only {}[]()
|
||||
str=${str//[^\{\}\(\)\[\]]}
|
||||
|
||||
res=true
|
||||
# 2- remove all pairs of [], {}, (). loop until string is empty (match ok) or unchanged
|
||||
# (nok)
|
||||
loop=1
|
||||
while [[ ${#str} > 0 ]]
|
||||
do
|
||||
str2=${str//+(\[\]|\(\)|\{\})}
|
||||
if [[ ${#str2} == ${#str} ]]; then
|
||||
res=false
|
||||
break
|
||||
fi
|
||||
str="$str2"
|
||||
done
|
||||
|
||||
echo $res
|
||||
exit 0
|
55
bash/pangram/README.md
Normal file
55
bash/pangram/README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Pangram
|
||||
|
||||
Determine if a sentence is a pangram. A pangram (Greek: παν γράμμα, pan gramma,
|
||||
"every letter") is a sentence using every letter of the alphabet at least once.
|
||||
The best known English pangram is:
|
||||
> The quick brown fox jumps over the lazy dog.
|
||||
|
||||
The alphabet used consists of ASCII letters `a` to `z`, inclusive, and is case
|
||||
insensitive. Input will not contain non-ASCII symbols.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats pangram_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats pangram_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Wikipedia [https://en.wikipedia.org/wiki/Pangram](https://en.wikipedia.org/wiki/Pangram)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
49
bash/pangram/pangram.sh
Executable file
49
bash/pangram/pangram.sh
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
# (( debug=2#00001111 ))
|
||||
(( debug=2#00000000 ))
|
||||
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & "$1" )) && shift && echo "${@}" >&2
|
||||
}
|
||||
|
||||
usage () {
|
||||
echo "usage: ./pangram.sh <string> [...]" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# basic args checks: at least 1 arg
|
||||
(( $# )) || usage
|
||||
|
||||
# We will accept mutiple args here: "a" "b" is equivalent to "ab".
|
||||
# get args in one string, change it to lower case.
|
||||
IFS="" # not really needed
|
||||
string="${*,,}"
|
||||
debug 1 "string=$string"
|
||||
|
||||
# empty string
|
||||
if (( ! ${#string} )); then
|
||||
debug 2 "empty string"
|
||||
result=false
|
||||
else
|
||||
result=true
|
||||
|
||||
# loop on all characters, from a to z. We need to check each one.
|
||||
for c in {a..z} ; do
|
||||
[[ ! ${string} =~ "$c" ]] && result=false && break
|
||||
done
|
||||
fi
|
||||
|
||||
echo "$result"
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 60
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
63
bash/proverb/README.md
Normal file
63
bash/proverb/README.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Proverb
|
||||
|
||||
For want of a horseshoe nail, a kingdom was lost, or so the saying goes.
|
||||
|
||||
Given a list of inputs, generate the relevant proverb. For example, given the list `["nail", "shoe", "horse", "rider", "message", "battle", "kingdom"]`, you will output the full text of this proverbial rhyme:
|
||||
|
||||
```text
|
||||
For want of a nail the shoe was lost.
|
||||
For want of a shoe the horse was lost.
|
||||
For want of a horse the rider was lost.
|
||||
For want of a rider the message was lost.
|
||||
For want of a message the battle was lost.
|
||||
For want of a battle the kingdom was lost.
|
||||
And all for the want of a nail.
|
||||
```
|
||||
|
||||
Note that the list of inputs may vary; your solution should be able to handle lists of arbitrary length and content. No line of the output text should be a static, unchanging string; all should vary according to the input given.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats proverb_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats proverb_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Wikipedia [http://en.wikipedia.org/wiki/For_Want_of_a_Nail](http://en.wikipedia.org/wiki/For_Want_of_a_Nail)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
15
bash/proverb/proverb.sh
Executable file
15
bash/proverb/proverb.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
[[ $# == 0 ]] && echo "" && exit 0
|
||||
|
||||
first="$1"
|
||||
prev="$first"
|
||||
shift
|
||||
while [[ $# > 0 ]]; do
|
||||
cur="$1"
|
||||
echo "For want of a $prev the $cur was lost."
|
||||
prev=$cur
|
||||
shift
|
||||
done
|
||||
echo "And all for the want of a $first."
|
||||
exit 0
|
64
bash/raindrops/README.md
Normal file
64
bash/raindrops/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Raindrops
|
||||
|
||||
Convert a number to a string, the contents of which depend on the number's factors.
|
||||
|
||||
- If the number has 3 as a factor, output 'Pling'.
|
||||
- If the number has 5 as a factor, output 'Plang'.
|
||||
- If the number has 7 as a factor, output 'Plong'.
|
||||
- If the number does not have 3, 5, or 7 as a factor,
|
||||
just pass the number's digits straight through.
|
||||
|
||||
## Examples
|
||||
|
||||
- 28's factors are 1, 2, 4, **7**, 14, 28.
|
||||
- In raindrop-speak, this would be a simple "Plong".
|
||||
- 30's factors are 1, 2, **3**, **5**, 6, 10, 15, 30.
|
||||
- In raindrop-speak, this would be a "PlingPlang".
|
||||
- 34 has four factors: 1, 2, 17, and 34.
|
||||
- In raindrop-speak, this would be "34".
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats raindrops_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats raindrops_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
A variation on a famous interview question intended to weed out potential candidates. [http://jumpstartlab.com](http://jumpstartlab.com)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
20
bash/raindrops/raindrops.sh
Executable file
20
bash/raindrops/raindrops.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
function usage() {
|
||||
echo "Usage: ./raindrop.sh number"
|
||||
exit 1
|
||||
}
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
(( $# == 1 )) || usage
|
||||
number="$1"
|
||||
[[ "$number" == +([0-9]) ]] || usage
|
||||
|
||||
output=""
|
||||
(( $number % 3 )) || output+="Pling"
|
||||
(( $number % 5 )) || output+="Plang"
|
||||
(( $number % 7 )) || output+="Plong"
|
||||
|
||||
echo ${output:-$number}
|
||||
exit 0
|
68
bash/resistor-color-duo/README.md
Normal file
68
bash/resistor-color-duo/README.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Resistor Color Duo
|
||||
|
||||
If you want to build something using a Raspberry Pi, you'll probably use _resistors_. For this exercise, you need to know two things about them:
|
||||
|
||||
* Each resistor has a resistance value.
|
||||
* Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read.
|
||||
To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values. Each band acts as a digit of a number. For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15.
|
||||
|
||||
In this exercise, you are going to create a helpful program so that you don't have to remember the values of the bands. The program will take two colors as input, and output the correct number.
|
||||
|
||||
The band colors are encoded as follows:
|
||||
|
||||
- Black: 0
|
||||
- Brown: 1
|
||||
- Red: 2
|
||||
- Orange: 3
|
||||
- Yellow: 4
|
||||
- Green: 5
|
||||
- Blue: 6
|
||||
- Violet: 7
|
||||
- Grey: 8
|
||||
- White: 9
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats resistor_color_duo_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats resistor_color_duo_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Maud de Vries, Erik Schierboom [https://github.com/exercism/problem-specifications/issues/1464](https://github.com/exercism/problem-specifications/issues/1464)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
39
bash/resistor-color-duo/resistor_color_duo.sh
Executable file
39
bash/resistor-color-duo/resistor_color_duo.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
usage () {
|
||||
if [[ $# == 1 ]]; then
|
||||
echo "$1: invalid color."
|
||||
else
|
||||
echo "usage: resistor_color.sh color1 color2"
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
declare -A colors
|
||||
colors=(
|
||||
[black]=0
|
||||
[brown]=1
|
||||
[red]=2
|
||||
[orange]=3
|
||||
[yellow]=4
|
||||
[green]=5
|
||||
[blue]=6
|
||||
[violet]=7
|
||||
[grey]=8
|
||||
[white]=9
|
||||
)
|
||||
result=""
|
||||
|
||||
# not sure here if 1 color only should be accepted (case is not in test). I assume yes:
|
||||
# "resistor_color.sh Black" will return 0
|
||||
# also (not in test cases), no args will return an error.
|
||||
[[ $# == 0 ]] && usage
|
||||
|
||||
# we will accept capitalized colors: converting to lower case
|
||||
for i in ${1,,} ${2,,}
|
||||
do
|
||||
[[ ${colors[$i]} == "" ]] && usage "$i"
|
||||
result+=${colors[$i]}
|
||||
done
|
||||
echo $result
|
||||
exit 0
|
91
bash/resistor-color-trio/README.md
Normal file
91
bash/resistor-color-trio/README.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Resistor Color Trio
|
||||
|
||||
If you want to build something using a Raspberry Pi, you'll probably use _resistors_. For this exercise, you need to know only three things about them:
|
||||
|
||||
- Each resistor has a resistance value.
|
||||
- Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read.
|
||||
To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values.
|
||||
- Each band acts as a digit of a number. For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15.
|
||||
In this exercise, you are going to create a helpful program so that you don't have to remember the values of the bands. The program will take 3 colors as input, and outputs the correct value, in ohms.
|
||||
The color bands are encoded as follows:
|
||||
|
||||
* Black: 0
|
||||
* Brown: 1
|
||||
* Red: 2
|
||||
* Orange: 3
|
||||
* Yellow: 4
|
||||
* Green: 5
|
||||
* Blue: 6
|
||||
* Violet: 7
|
||||
* Grey: 8
|
||||
* White: 9
|
||||
|
||||
In `resistor-color duo` you decoded the first two colors. For instance: orange-orange got the main value `33`.
|
||||
The third color stands for how many zeros need to be added to the main value. The main value plus the zeros gives us a value in ohms.
|
||||
For the exercise it doesn't matter what ohms really are.
|
||||
For example:
|
||||
|
||||
- orange-orange-black would be 33 and no zeros, which becomes 33 ohms.
|
||||
- orange-orange-red would be 33 and 2 zeros, which becomes 3300 ohms.
|
||||
- orange-orange-orange would be 33 and 3 zeros, which becomes 33000 ohms.
|
||||
|
||||
(If Math is your thing, you may want to think of the zeros as exponents of 10. If Math is not your thing, go with the zeros. It really is the same thing, just in plain English instead of Math lingo.)
|
||||
|
||||
This exercise is about translating the colors into a label:
|
||||
|
||||
> "... ohms"
|
||||
|
||||
So an input of `"orange", "orange", "black"` should return:
|
||||
|
||||
> "33 ohms"
|
||||
|
||||
When we get more than a thousand ohms, we say "kiloohms". That's similar to saying "kilometer" for 1000 meters, and "kilograms" for 1000 grams.
|
||||
So an input of `"orange", "orange", "orange"` should return:
|
||||
|
||||
> "33 kiloohms"
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats resistor_color_trio_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats resistor_color_trio_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Maud de Vries, Erik Schierboom [https://github.com/exercism/problem-specifications/issues/1549](https://github.com/exercism/problem-specifications/issues/1549)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
93
bash/resistor-color-trio/resistor_color_trio.sh
Executable file
93
bash/resistor-color-trio/resistor_color_trio.sh
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# V1: initial version
|
||||
# V2: merged power tables, add index one, improved unit str calculation
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
((debug=2#00000000))
|
||||
#((debug=2#00011111))
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo Line ${BASH_LINENO[0]}: "${@}" >&2
|
||||
}
|
||||
|
||||
die () {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
usage() {
|
||||
die "usage: resistor_color_trio.sh color1 [color2 [color3]]"
|
||||
}
|
||||
|
||||
# not sure here if 1 or 2 colors only should be accepted (not in test cases).
|
||||
# I will assume yes, it looks more coherent, even if out of scope:
|
||||
# "resistor_color_trio.sh Black" will return 0
|
||||
# "resistor_color_trio.sh yellow violet" will return 47
|
||||
# also: (not in test cases), no args will return an error.
|
||||
# (in test case), extra colors are ignored, I don't like it, personally
|
||||
(( $# == 0 )) && usage
|
||||
|
||||
# value/power of different colors
|
||||
declare -A colors=([black]=0 [brown]=1 [red]=2 [orange]=3 [yellow]=4
|
||||
[green]=5 [blue]=6 [violet]=7 [grey]=8 [white]=9)
|
||||
|
||||
# available multiplicators (powers of 10).
|
||||
declare -a powers=([9]=giga [6]=mega [3]=kilo)
|
||||
idx=("${!powers[@]}") # keys copy for reverse loop
|
||||
|
||||
params=( ${@,,} ) # converting to lower case
|
||||
|
||||
(( result=0 )) # final number to display
|
||||
|
||||
# I would have preferred to throw an error if $# > 3, instead of ignoring
|
||||
# extra args...
|
||||
for ((i=0; i<3 && i<${#params[@]}; ++i)); do
|
||||
color="${params[$i]}" # color name
|
||||
val="${colors[$color]}" # color value
|
||||
|
||||
[[ -z "$val" ]] && die "$color: invalid color."
|
||||
case $i in
|
||||
0) (( result=val ))
|
||||
debug 2 "new color 1 $color/$val. result=$result"
|
||||
;;
|
||||
# probably case 0 and 1 could be merged. Easier to read for me
|
||||
# by separating them.
|
||||
1) (( result*=10 ))
|
||||
(( result+=val ))
|
||||
debug 2 "new color 2 $color/$val. result=$result"
|
||||
;;
|
||||
2) (( result *= 10 ** val ))
|
||||
debug 2 "new color 3 $color/$val. result=$result"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# we have final number, scaling to corresponding strings.
|
||||
scalestr="" # "giga", etc...
|
||||
|
||||
if (( result )); then
|
||||
for (( i = ${#idx[@]} - 1; i >= 0; i-- )); do # reverse loop by value
|
||||
j=${idx[$i]} # also actual power (9, 6, 3)
|
||||
(( power = 10 ** $j )) # actual value
|
||||
debug 8 $i $j ${powers[$j]} $power $result
|
||||
if ! (( result % power )); then # found power
|
||||
scalestr=${powers[$j]}
|
||||
(( result /= power ))
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "$result ${scalestr}ohms"
|
||||
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings below.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 50
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
98
bash/resistor-color-trio/resistor_color_trio.sh.1
Executable file
98
bash/resistor-color-trio/resistor_color_trio.sh.1
Executable file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
# ((debug=2#00011111))
|
||||
((debug=2#00000000))
|
||||
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo "${@}" >&2
|
||||
}
|
||||
|
||||
die () {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
usage() {
|
||||
die "usage: resistor_color_trio.sh color1 [color2 [color3]]"
|
||||
}
|
||||
|
||||
# value/power of different colors
|
||||
declare -A colors=([black]=0 [brown]=1 [red]=2 [orange]=3 [yellow]=4
|
||||
[green]=5 [blue]=6 [violet]=7 [grey]=8 [white]=9)
|
||||
# available multiplicators (powers of 10)
|
||||
declare -a powers=(9 6 3)
|
||||
# corresponding strings
|
||||
declare -a powernames=(giga mega kilo)
|
||||
|
||||
# not sure here if 1 or 2 colors only should be accepted (not in test cases).
|
||||
# I will assume yes, it looks more coherent, even if out of scope:
|
||||
# "resistor_color_trio.sh Black" will return 0
|
||||
# "resistor_color_trio.sh yellow violet" will return 47
|
||||
# also: (not in test cases), no args will return an error.
|
||||
# (in test case), extra colors are ignored, I don't like it, personally
|
||||
(( $# == 0 )) && usage
|
||||
|
||||
scalestr="" # "giga", etc...
|
||||
(( result=0 )) # number to display
|
||||
|
||||
debug 64 "params=${#params[@]} ${params[@]}"
|
||||
|
||||
# converting to lower case
|
||||
params=( ${@,,} )
|
||||
debug 2 "#params=${#params[@]} ${params[@]}"
|
||||
|
||||
# I would have preferred to throw an error if $# > 3, instead of ignoring
|
||||
# extra args...
|
||||
for ((i=0; i<3 && i<${#params[@]}; ++i)); do
|
||||
color="${params[$i]}" # color name
|
||||
val="${colors[$color]}" # color value
|
||||
|
||||
debug 8 "i=$i - color=$color - val=$val"
|
||||
|
||||
debug 4 val="$val" color="${color[$i]}"
|
||||
[[ -z "$val" ]] && die "$color: invalid color."
|
||||
case $i in
|
||||
0) (( result=val ))
|
||||
debug 2 "new color 1 $color/$val. result=$result"
|
||||
;;
|
||||
|
||||
# probably case 0 and 1 could be merged. Easier to read for me
|
||||
# separating them.
|
||||
1) (( result*=10 ))
|
||||
(( result+=val ))
|
||||
debug 2 "new color 2 $color/$val. result=$result"
|
||||
;;
|
||||
|
||||
2) (( result *= 10 ** val ))
|
||||
debug 2 "new color 3 $color/$val. result=$result"
|
||||
|
||||
# we have final number, scaling to multiple strings.
|
||||
for (( j=0; result && j<${#powers[@]}; ++j )); do
|
||||
(( pow = 10 ** ${powers[j]} ))
|
||||
debug 8 "val=$val result=$result j=$j pow=$pow"
|
||||
if ! (( result && result % pow )); then
|
||||
((result /= pow))
|
||||
scalestr=${powernames[$j]}
|
||||
break
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
done
|
||||
debug 4 res="$result" scalestr="$scalestr"
|
||||
|
||||
echo "$result ${scalestr}ohms"
|
||||
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings below.
|
||||
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 60
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
99
bash/resistor-color-trio/resistor_color_trio.sh.sav
Executable file
99
bash/resistor-color-trio/resistor_color_trio.sh.sav
Executable file
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# V1: initial version
|
||||
# V2: merged the
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
# ((debug=2#00011111))
|
||||
((debug=2#00000000))
|
||||
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo "${@}" >&2
|
||||
}
|
||||
|
||||
die () {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
usage() {
|
||||
die "usage: resistor_color_trio.sh color1 [color2 [color3]]"
|
||||
}
|
||||
|
||||
# value/power of different colors
|
||||
declare -A colors=([black]=0 [brown]=1 [red]=2 [orange]=3 [yellow]=4
|
||||
[green]=5 [blue]=6 [violet]=7 [grey]=8 [white]=9)
|
||||
# available multiplicators (powers of 10)
|
||||
declare -a powers=(9 6 3)
|
||||
|
||||
scalestr="" # "giga", etc...
|
||||
(( result=0 )) # number to display
|
||||
# corresponding strings
|
||||
declare -a powernames=(giga mega kilo)
|
||||
|
||||
# not sure here if 1 or 2 colors only should be accepted (not in test cases).
|
||||
# I will assume yes, it looks more coherent, even if out of scope:
|
||||
# "resistor_color_trio.sh Black" will return 0
|
||||
# "resistor_color_trio.sh yellow violet" will return 47
|
||||
# also: (not in test cases), no args will return an error.
|
||||
# (in test case), extra colors are ignored, I don't like it, personally
|
||||
(( $# == 0 )) && usage
|
||||
|
||||
debug 64 "params=${#params[@]} ${params[@]}"
|
||||
|
||||
# converting to lower case, adding default values if args missing
|
||||
params=( ${@,,} black black black )
|
||||
debug 2 "#params=${#params[@]} ${params[@]}"
|
||||
|
||||
# I would have preferred to throw an error if $# > 3, instead of ignoring
|
||||
# extra args...
|
||||
for ((i=0; i<3 && i<${#params[@]}; ++i)); do
|
||||
color="${params[$i]}" # color name
|
||||
val="${colors[$color]}" # color value
|
||||
|
||||
debug 4 val="$val" color="${color[$i]}"
|
||||
[[ -z "$val" ]] && die "$color: invalid color."
|
||||
case $i in
|
||||
0) (( result=val ))
|
||||
debug 2 "new color 1 $color/$val. result=$result"
|
||||
;;
|
||||
# probably case 0 and 1 could be merged. Easier to read for me
|
||||
# by separating them.
|
||||
1) (( result*=10 ))
|
||||
(( result+=val ))
|
||||
debug 2 "new color 2 $color/$val. result=$result"
|
||||
;;
|
||||
2) (( result *= 10 ** val ))
|
||||
debug 2 "new color 3 $color/$val. result=$result"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# we have final number, scaling to corresponding strings.
|
||||
for (( j=0; result && j<${#powers[@]}; ++j )); do
|
||||
(( pow = 10 ** ${powers[j]} ))
|
||||
debug 8 "val=$val result=$result j=$j pow=$pow"
|
||||
if ! (( result && result % pow )); then
|
||||
((result /= pow))
|
||||
scalestr=${powernames[$j]}
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
debug 4 res="$result" scalestr="$scalestr"
|
||||
|
||||
echo "$result ${scalestr}ohms"
|
||||
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings below.
|
||||
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 50
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
53
bash/reverse-string/README.md
Normal file
53
bash/reverse-string/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Reverse String
|
||||
|
||||
Reverse a string
|
||||
|
||||
For example:
|
||||
input: "cool"
|
||||
output: "looc"
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats reverse_string_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats reverse_string_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Introductory challenge to reverse an input string [https://medium.freecodecamp.org/how-to-reverse-a-string-in-javascript-in-3-different-ways-75e4763c68cb](https://medium.freecodecamp.org/how-to-reverse-a-string-in-javascript-in-3-different-ways-75e4763c68cb)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
14
bash/reverse-string/reverse_string.sh
Executable file
14
bash/reverse-string/reverse_string.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
[[ $# != 1 ]] && echo "usage: $0 string" && exit 1
|
||||
|
||||
|
||||
str=$1
|
||||
len=${#str}
|
||||
rev=""
|
||||
|
||||
for (( i=0; i<len; ++i ))
|
||||
do
|
||||
rev="${str:i:1}$rev"
|
||||
done
|
||||
echo "$rev"
|
65
bash/rna-transcription/README.md
Normal file
65
bash/rna-transcription/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# RNA Transcription
|
||||
|
||||
Given a DNA strand, return its RNA complement (per RNA transcription).
|
||||
|
||||
Both DNA and RNA strands are a sequence of nucleotides.
|
||||
|
||||
The four nucleotides found in DNA are adenine (**A**), cytosine (**C**),
|
||||
guanine (**G**) and thymine (**T**).
|
||||
|
||||
The four nucleotides found in RNA are adenine (**A**), cytosine (**C**),
|
||||
guanine (**G**) and uracil (**U**).
|
||||
|
||||
Given a DNA strand, its transcribed RNA strand is formed by replacing
|
||||
each nucleotide with its complement:
|
||||
|
||||
* `G` -> `C`
|
||||
* `C` -> `G`
|
||||
* `T` -> `A`
|
||||
* `A` -> `U`
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats rna_transcription_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats rna_transcription_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Hyperphysics [http://hyperphysics.phy-astr.gsu.edu/hbase/Organic/transcription.html](http://hyperphysics.phy-astr.gsu.edu/hbase/Organic/transcription.html)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
60
bash/rna-transcription/rna_transcription.sh
Executable file
60
bash/rna-transcription/rna_transcription.sh
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# External tools: none.
|
||||
#
|
||||
# V1: initial version
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
(( debug=2#00000000 ))
|
||||
#(( debug=2#00001111 ))
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo Line ${BASH_LINENO[0]}: "${@}" >&2
|
||||
}
|
||||
|
||||
die () {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
usage() {
|
||||
die "usage: rna_transcription.sh [seq1] [...]"
|
||||
}
|
||||
|
||||
declare -A complement=([G]='C'
|
||||
[C]='G'
|
||||
[T]='A'
|
||||
[A]='U')
|
||||
debug 1 keys/vals=${!complement[@]}/${complement[@]}
|
||||
# we will accept multiple args (out of topic for exercise), meaning that:
|
||||
# rna_transcription.sh GCTA
|
||||
# is equivalent to
|
||||
# rna_transcription.sh G C T A
|
||||
# or
|
||||
# rna_transcription.sh G CTA
|
||||
dna="${@}"
|
||||
dna="${dna// /}" # remove spaces
|
||||
(($# > 0 )) && [[ "$dna" != +([GCTA]) ]] && die "Invalid nucleotide detected."
|
||||
|
||||
((ldna=${#dna}))
|
||||
debug 1 "dna=$dna, length=$ldna"
|
||||
rna="" # rna sequence
|
||||
|
||||
for ((i=0; i<ldna; ++i)); do
|
||||
seq=${dna:$i:1}
|
||||
rna+="${complement[$seq]}"
|
||||
debug 2 "rna=$rna"
|
||||
done
|
||||
|
||||
echo "$rna" # not perfect, empty line if no args.
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 40
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
86
bash/scrabble-score/README.md
Normal file
86
bash/scrabble-score/README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Scrabble Score
|
||||
|
||||
Given a word, compute the scrabble score for that word.
|
||||
|
||||
## Letter Values
|
||||
|
||||
You'll need these:
|
||||
|
||||
```text
|
||||
Letter Value
|
||||
A, E, I, O, U, L, N, R, S, T 1
|
||||
D, G 2
|
||||
B, C, M, P 3
|
||||
F, H, V, W, Y 4
|
||||
K 5
|
||||
J, X 8
|
||||
Q, Z 10
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
"cabbage" should be scored as worth 14 points:
|
||||
|
||||
- 3 points for C
|
||||
- 1 point for A, twice
|
||||
- 3 points for B, twice
|
||||
- 2 points for G
|
||||
- 1 point for E
|
||||
|
||||
And to total:
|
||||
|
||||
- `3 + 2*1 + 2*3 + 2 + 1`
|
||||
- = `3 + 2 + 6 + 3`
|
||||
- = `5 + 9`
|
||||
- = 14
|
||||
|
||||
## Extensions
|
||||
|
||||
- You can play a double or a triple letter.
|
||||
- You can play a double or a triple word.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats scrabble_score_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats scrabble_score_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Inspired by the Extreme Startup game [https://github.com/rchatley/extreme_startup](https://github.com/rchatley/extreme_startup)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
56
bash/scrabble-score/scrabble_score.sh
Executable file
56
bash/scrabble-score/scrabble_score.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# V1: initial version
|
||||
# V2: check for alphabetic chars only
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
(( debug=2#00000000 ))
|
||||
#(( debug=2#00001111 ))
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo Line ${BASH_LINENO[0]}: "${@}" >&2
|
||||
}
|
||||
|
||||
die () {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
usage() {
|
||||
die "usage: scrabble_score.sh word"
|
||||
}
|
||||
|
||||
declare -A values=(
|
||||
[A]=1 [E]=1 [I]=1 [O]=1 [U]=1 [L]=1 [N]=1 [R]=1 [S]=1 [T]=1
|
||||
[D]=2 [G]=2
|
||||
[B]=3 [C]=3 [M]=3 [P]=3
|
||||
[F]=4 [H]=4 [V]=4 [W]=4 [Y]=4
|
||||
[K]=5
|
||||
[J]=8 [X]=8
|
||||
[Q]=10 [Z]=10
|
||||
)
|
||||
|
||||
(($# != 1)) && usage
|
||||
word="${1^^}" # capitalize
|
||||
[[ "$word" != +([[:upper:]]) ]] && usage # accept only alpha chars
|
||||
|
||||
debug 1 arg="$word"
|
||||
((score=0))
|
||||
|
||||
for (( i=0; i<${#word}; ++i )); do
|
||||
c="${word:$i:1}"
|
||||
((score += ${values[$c]}))
|
||||
done
|
||||
|
||||
echo "$score"
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 50
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
75
bash/secret-handshake/README.md
Normal file
75
bash/secret-handshake/README.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Secret Handshake
|
||||
|
||||
> There are 10 types of people in the world: Those who understand
|
||||
> binary, and those who don't.
|
||||
|
||||
You and your fellow cohort of those in the "know" when it comes to
|
||||
binary decide to come up with a secret "handshake".
|
||||
|
||||
```text
|
||||
1 = wink
|
||||
10 = double blink
|
||||
100 = close your eyes
|
||||
1000 = jump
|
||||
|
||||
|
||||
10000 = Reverse the order of the operations in the secret handshake.
|
||||
```
|
||||
|
||||
Given a decimal number, convert it to the appropriate sequence of events for a secret handshake.
|
||||
|
||||
Here's a couple of examples:
|
||||
|
||||
Given the input 3, the function would return the array
|
||||
["wink", "double blink"] because 3 is 11 in binary.
|
||||
|
||||
Given the input 19, the function would return the array
|
||||
["double blink", "wink"] because 19 is 10011 in binary.
|
||||
Notice that the addition of 16 (10000 in binary)
|
||||
has caused the array to be reversed.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats secret_handshake_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats secret_handshake_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Bert, in Mary Poppins [http://www.imdb.com/title/tt0058331/quotes/qt0437047](http://www.imdb.com/title/tt0058331/quotes/qt0437047)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
26
bash/secret-handshake/secret_handshake.sh
Executable file
26
bash/secret-handshake/secret_handshake.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
num=$1
|
||||
|
||||
strings=(
|
||||
"wink"
|
||||
"double blink"
|
||||
"close your eyes"
|
||||
"jump"
|
||||
)
|
||||
reverse=n
|
||||
result=()
|
||||
|
||||
(( $num & 2#10000 )) && reverse=y
|
||||
|
||||
# get matching bits
|
||||
for (( i=0 ; i<4 ; ++i )); do
|
||||
(( $num & 1<<$i )) && result+=( "${strings[$i]}" )
|
||||
done
|
||||
# output in normal or reverse order
|
||||
for (( i=0 ; i<${#result[@]} ; ++i)) ; do
|
||||
[[ $reverse == n ]] && echo -n "$sep${result[i]}" || echo -n "$sep${result[~i]}"
|
||||
sep=","
|
||||
done
|
||||
echo
|
||||
exit 0
|
76
bash/sieve/README.md
Normal file
76
bash/sieve/README.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Sieve
|
||||
|
||||
Use the Sieve of Eratosthenes to find all the primes from 2 up to a given
|
||||
number.
|
||||
|
||||
The Sieve of Eratosthenes is a simple, ancient algorithm for finding all
|
||||
prime numbers up to any given limit. It does so by iteratively marking as
|
||||
composite (i.e. not prime) the multiples of each prime, starting with the
|
||||
multiples of 2. It does not use any division or remainder operation.
|
||||
|
||||
Create your range, starting at two and continuing up to and including the given limit. (i.e. [2, limit])
|
||||
|
||||
The algorithm consists of repeating the following over and over:
|
||||
|
||||
- take the next available unmarked number in your list (it is prime)
|
||||
- mark all the multiples of that number (they are not prime)
|
||||
|
||||
Repeat until you have processed each number in your range.
|
||||
|
||||
When the algorithm terminates, all the numbers in the list that have not
|
||||
been marked are prime.
|
||||
|
||||
The wikipedia article has a useful graphic that explains the algorithm:
|
||||
https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
|
||||
|
||||
Notice that this is a very specific algorithm, and the tests don't check
|
||||
that you've implemented the algorithm, only that you've come up with the
|
||||
correct list of primes. A good first test is to check that you do not use
|
||||
division or remainder operations (div, /, mod or % depending on the
|
||||
language).
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats sieve_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats sieve_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
Sieve of Eratosthenes at Wikipedia [http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes](http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
24
bash/sieve/sieve.sh
Executable file
24
bash/sieve/sieve.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
usage() {
|
||||
echo "Usage: ./seave.sh <number>"
|
||||
exit 1
|
||||
}
|
||||
end=$1
|
||||
|
||||
[[ ! "$end" =~ ^[[:digit:]]*$ ]] && usage
|
||||
|
||||
declare -a numbers
|
||||
|
||||
sep=""
|
||||
for (( i=2; i<=end; ++i )); do
|
||||
if [[ ${numbers[$i]} == "" ]]; then
|
||||
echo -n "$sep$i"
|
||||
for (( j=i*2; j<=end; j+=i )); do
|
||||
numbers[$j]=t
|
||||
done
|
||||
sep=" "
|
||||
fi
|
||||
done
|
||||
echo
|
||||
exit 0
|
43
bash/template.sh
Executable file
43
bash/template.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# External tools: none.
|
||||
#
|
||||
# V1: initial version
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# set to mask to enable logs. 0: none, 255: all
|
||||
(( debug=2#00000000 ))
|
||||
# (( debug=2#00001111 ))
|
||||
# $1: log level (mask), then strings to display.
|
||||
debug () {
|
||||
(( debug & $1 )) && shift && echo Line ${BASH_LINENO[0]}: "${@}" >&2
|
||||
#local -i i
|
||||
#if (( debug & $1 )) ; then
|
||||
# for ((i=1; i<$1; ++i)); do
|
||||
# echo -n " "
|
||||
# done
|
||||
# shift
|
||||
# echo "${BASH_LINENO[0]}: ${@}" >&2
|
||||
#fi
|
||||
|
||||
}
|
||||
|
||||
die () {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
usage() {
|
||||
die "usage: resistor_color_trio.sh color1 [color2 [color3]]"
|
||||
}
|
||||
|
||||
exit 0
|
||||
|
||||
# emacs/vim settings.
|
||||
# Local Variables:
|
||||
# sh-basic-offset: 4
|
||||
# indent-tabs-mode: nil
|
||||
# comment-column: 40
|
||||
# fill-column: 80
|
||||
# End:
|
||||
# vim: set tabstop=4 expandtab:
|
108
bash/tournament/README.md
Normal file
108
bash/tournament/README.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# Tournament
|
||||
|
||||
Tally the results of a small football competition.
|
||||
|
||||
Based on an input file containing which team played against which and what the
|
||||
outcome was, create a file with a table like this:
|
||||
|
||||
```text
|
||||
Team | MP | W | D | L | P
|
||||
Devastating Donkeys | 3 | 2 | 1 | 0 | 7
|
||||
Allegoric Alaskans | 3 | 2 | 0 | 1 | 6
|
||||
Blithering Badgers | 3 | 1 | 0 | 2 | 3
|
||||
Courageous Californians | 3 | 0 | 1 | 2 | 1
|
||||
```
|
||||
|
||||
What do those abbreviations mean?
|
||||
|
||||
- MP: Matches Played
|
||||
- W: Matches Won
|
||||
- D: Matches Drawn (Tied)
|
||||
- L: Matches Lost
|
||||
- P: Points
|
||||
|
||||
A win earns a team 3 points. A draw earns 1. A loss earns 0.
|
||||
|
||||
The outcome should be ordered by points, descending. In case of a tie, teams are ordered alphabetically.
|
||||
|
||||
###
|
||||
|
||||
Input
|
||||
|
||||
Your tallying program will receive input that looks like:
|
||||
|
||||
```text
|
||||
Allegoric Alaskans;Blithering Badgers;win
|
||||
Devastating Donkeys;Courageous Californians;draw
|
||||
Devastating Donkeys;Allegoric Alaskans;win
|
||||
Courageous Californians;Blithering Badgers;loss
|
||||
Blithering Badgers;Devastating Donkeys;loss
|
||||
Allegoric Alaskans;Courageous Californians;win
|
||||
```
|
||||
|
||||
The result of the match refers to the first team listed. So this line
|
||||
|
||||
```text
|
||||
Allegoric Alaskans;Blithering Badgers;win
|
||||
```
|
||||
|
||||
Means that the Allegoric Alaskans beat the Blithering Badgers.
|
||||
|
||||
This line:
|
||||
|
||||
```text
|
||||
Courageous Californians;Blithering Badgers;loss
|
||||
```
|
||||
|
||||
Means that the Blithering Badgers beat the Courageous Californians.
|
||||
|
||||
And this line:
|
||||
|
||||
```text
|
||||
Devastating Donkeys;Courageous Californians;draw
|
||||
```
|
||||
|
||||
Means that the Devastating Donkeys and Courageous Californians tied.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats tournament_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats tournament_test.sh
|
||||
```
|
||||
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
132
bash/tournament/tournament.sh
Executable file
132
bash/tournament/tournament.sh
Executable file
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env bash
|
||||
# v1: - initial version
|
||||
# v2-3: - backport bubble sort (while -> for) & debug system from next exercises
|
||||
# - always read from stdin
|
||||
# - some syntax improvement
|
||||
# v4: - cosmetic/syntax changes
|
||||
# - change from empty file handling (empty string becomes valid filename)
|
||||
# v5: - cosmetic changes following "shellcheck" usage.
|
||||
# v6: - removed debug calls.
|
||||
# v7-8: - cosmetic changes
|
||||
|
||||
die() {
|
||||
echo "${@}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# the results, associative arrays with team name as key. Some tables look
|
||||
# redundant, but easier to understand.
|
||||
declare -A mp # matches played
|
||||
declare -A win # matches won
|
||||
declare -A draw # matches tied
|
||||
declare -A loss # matches lost
|
||||
declare -A points # points
|
||||
declare -a order # final order.
|
||||
|
||||
nteams=0
|
||||
|
||||
# create a team entry in arrays if non existent. $1: team
|
||||
create_team() {
|
||||
if ! [[ -v "mp[$1]" ]]; then
|
||||
(( nteams++ ))
|
||||
(( mp["$1"]=0 ))
|
||||
(( win["$1"]=0 ))
|
||||
(( loss["$1"]=0 ))
|
||||
(( draw["$1"]=0 ))
|
||||
(( points["$1"]=0 ))
|
||||
order[$nteams]="$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# update results for a team: $1, $2: teams, $3: result for $1: win/draw/loss
|
||||
update_results() {
|
||||
create_team "$1"
|
||||
create_team "$2"
|
||||
|
||||
((mp["$1"]++))
|
||||
((mp["$2"]++))
|
||||
case "$3" in
|
||||
win)
|
||||
((win["$1"]++))
|
||||
((loss["$2"]++))
|
||||
((points["$1"]+=3))
|
||||
;;
|
||||
loss)
|
||||
((win["$2"]++))
|
||||
((loss["$1"]++))
|
||||
((points["$2"]+=3))
|
||||
;;
|
||||
draw)
|
||||
((draw["$1"]++))
|
||||
((draw["$2"]++))
|
||||
((points["$1"]++))
|
||||
((points["$2"]++))
|
||||
;;
|
||||
*) # should not happen
|
||||
die "fatal: invalid result $3, exiting."
|
||||
esac
|
||||
}
|
||||
|
||||
# inspired from https://stackoverflow.com/questions/7442417/how-to-sort-an-array-in-bash
|
||||
# (bubble sort)
|
||||
sort_teams()
|
||||
{
|
||||
local max i
|
||||
|
||||
for ((max=nteams; max>0; max--)); do
|
||||
for ((i=1; i<max; ++i )); do
|
||||
local team1=${order[$i]} team2=${order[$i + 1]} switch=0
|
||||
|
||||
if (( ${points["$team1"]} < ${points["$team2"]} )) || \
|
||||
( (( ${points["$team1"]} == ${points["$team2"]} )) && \
|
||||
[[ "$team1" > "$team2" ]] ); then
|
||||
order[$i]="$team2"
|
||||
order[$i + 1]="$team1"
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
output() {
|
||||
printf "%-30s |%3s |%3s |%3s |%3s |%3s\n" "${@:1:6}"
|
||||
}
|
||||
|
||||
output_team() {
|
||||
output "$1" "${mp[$1]}" "${win[$1]}" "${draw[$1]}" "${loss[$1]}" "${points[$1]}"
|
||||
}
|
||||
|
||||
# output teams, according to "order" table
|
||||
output_teams() {
|
||||
local i
|
||||
# header
|
||||
output "Team" "MP" "W" "D" "L" "P"
|
||||
for (( i=1; i<= nteams; ++i )); do
|
||||
output_team "${order[$i]}"
|
||||
done
|
||||
}
|
||||
|
||||
load_teams() {
|
||||
# set separator. Note we ignore escaping ';': a\;a;b;win wont work
|
||||
local team1 team2 result
|
||||
local IFS=$';\n'
|
||||
|
||||
while read -r team1 team2 result ; do
|
||||
# should empty result considered as error or ignored? Ignored here.
|
||||
[[ -z "$team1" || -z "$team2" || -z "$result" ]] && continue
|
||||
update_results "$team1" "$team2" "$result"
|
||||
done
|
||||
}
|
||||
|
||||
# we will accept both argument (file name) or stdin input
|
||||
if (( $# == 0 )); then
|
||||
load_teams
|
||||
elif [[ -f "$1" ]]; then
|
||||
load_teams < "$1"
|
||||
else
|
||||
die Invalid "[$1]" file. Exiting.
|
||||
fi
|
||||
|
||||
sort_teams
|
||||
output_teams
|
||||
|
||||
exit 0
|
72
bash/two-fer/README.md
Normal file
72
bash/two-fer/README.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Two Fer
|
||||
|
||||
`Two-fer` or `2-fer` is short for two for one. One for you and one for me.
|
||||
|
||||
Given a name, return a string with the message:
|
||||
|
||||
```text
|
||||
One for X, one for me.
|
||||
```
|
||||
|
||||
Where X is the given name.
|
||||
|
||||
However, if the name is missing, return the string:
|
||||
|
||||
```text
|
||||
One for you, one for me.
|
||||
```
|
||||
|
||||
Here are some examples:
|
||||
|
||||
|Name |String to return
|
||||
|:-------|:------------------
|
||||
|Alice |One for Alice, one for me.
|
||||
|Bob |One for Bob, one for me.
|
||||
| |One for you, one for me.
|
||||
|Zaphod |One for Zaphod, one for me.
|
||||
|
||||
|
||||
Run the tests with:
|
||||
|
||||
```bash
|
||||
bats two_fer_test.sh
|
||||
```
|
||||
|
||||
After the first test(s) pass, continue by commenting out or removing the
|
||||
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
|
||||
annotations prepending other tests.
|
||||
|
||||
To run all tests, including the ones with `skip` annotations, run:
|
||||
|
||||
```bash
|
||||
BATS_RUN_SKIPPED=true bats two_fer_test.sh
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
[https://github.com/exercism/problem-specifications/issues/757](https://github.com/exercism/problem-specifications/issues/757)
|
||||
|
||||
|
||||
## External utilities
|
||||
`Bash` is a language to write "scripts" -- programs that can call
|
||||
external tools, such as
|
||||
[`sed`](https://www.gnu.org/software/sed/),
|
||||
[`awk`](https://www.gnu.org/software/gawk/),
|
||||
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
|
||||
and even programs written in other programming languages,
|
||||
like [`Python`](https://www.python.org/).
|
||||
This track does not restrict the usage of these utilities, and as long
|
||||
as your solution is portable between systems and does not require
|
||||
installation of third party applications, feel free to use them to solve
|
||||
the exercise.
|
||||
|
||||
For an extra challenge, if you would like to have a better understanding
|
||||
of the language, try to re-implement the solution in pure `Bash`,
|
||||
without using any external tools. Note that there are some types of
|
||||
problems that bash cannot solve, such as performing floating point
|
||||
arithmetic and manipulating dates: for those, you must call out to an
|
||||
external tool.
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others
|
||||
have completed the exercise.
|
12
bash/two-fer/two_fer.sh
Executable file
12
bash/two-fer/two_fer.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#str=$1
|
||||
|
||||
# the next two lines would trim leading & trailing blank chars. I believe the exercise
|
||||
# should be amended to avoid "One for , one for me."
|
||||
#str="${str#"${str%%[![:space:]]*}"}" # remove leading blanks
|
||||
#str="${str%"${str##*[![:space:]]}"}" # remove trailing blanks
|
||||
|
||||
#[[ ${#str} = 0 ]] && str="you"
|
||||
|
||||
echo "One for ${1:-you}, one for me."
|
41
c/acronym/GNUmakefile
Normal file
41
c/acronym/GNUmakefile
Normal file
@@ -0,0 +1,41 @@
|
||||
# The original 'makefile' has a flaw:
|
||||
# 1) it overrides CFLAGS
|
||||
# 2) it does not pass extra "FLAGS" to $(CC) that could come from environment
|
||||
#
|
||||
# It means :
|
||||
# - we need to edit 'makefile' for different builds (DEBUG, etc...), which is
|
||||
# not practical at all.
|
||||
# - Also, it does not allow to run all tests without editing the test source
|
||||
# code.
|
||||
#
|
||||
# To use this makefile (GNU make only):
|
||||
# "make": build with all predefined tests (without editing test source code)
|
||||
# "make mem": perform memcheck with all tests enabled
|
||||
# "make unit": build standalone (unit) test
|
||||
# "make debug": build standalone test with debugging code
|
||||
#
|
||||
# Original 'makefile' targets can be used (test, memcheck, clean, ...)
|
||||
|
||||
.PHONY: default all mem unit debug std
|
||||
|
||||
default: all
|
||||
|
||||
# default is to build with all predefined tests
|
||||
BUILD := teststall
|
||||
|
||||
include makefile
|
||||
|
||||
all: CFLAGS+=-DTESTALL -g
|
||||
all: clean test
|
||||
|
||||
mem: CFLAGS+=-DTESTALL
|
||||
mem: clean memcheck
|
||||
|
||||
unit: CFLAGS+=-DUNIT_TEST
|
||||
unit: clean std
|
||||
|
||||
debug: CFLAGS+=-DUNIT_TEST -DDEBUG -g
|
||||
debug: clean std
|
||||
|
||||
std: src/*.c src/*.h
|
||||
$(CC) $(CFLAGS) src/*.c -o test.out
|
46
c/acronym/README.md
Normal file
46
c/acronym/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Acronym
|
||||
|
||||
Convert a phrase to its acronym.
|
||||
|
||||
Techies love their TLA (Three Letter Acronyms)!
|
||||
|
||||
Help generate some jargon by writing a program that converts a long name
|
||||
like Portable Network Graphics to its acronym (PNG).
|
||||
|
||||
## Getting Started
|
||||
|
||||
Make sure you have read the "Guides" section of the
|
||||
[C track][c-track] on the Exercism site. This covers
|
||||
the basic information on setting up the development environment expected
|
||||
by the exercises.
|
||||
|
||||
## Passing the Tests
|
||||
|
||||
Get the first test compiling, linking and passing by following the [three
|
||||
rules of test-driven development][3-tdd-rules].
|
||||
|
||||
The included makefile can be used to create and run the tests using the `test`
|
||||
task.
|
||||
|
||||
make test
|
||||
|
||||
Create just the functions you need to satisfy any compiler errors and get the
|
||||
test to fail. Then write just enough code to get the test to pass. Once you've
|
||||
done that, move onto the next test.
|
||||
|
||||
As you progress through the tests, take the time to refactor your
|
||||
implementation for readability and expressiveness and then go on to the next
|
||||
test.
|
||||
|
||||
Try to use standard C99 facilities in preference to writing your own
|
||||
low-level algorithms or facilities by hand.
|
||||
|
||||
## Source
|
||||
|
||||
Julien Vanier [https://github.com/monkbroc](https://github.com/monkbroc)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
||||
[c-track]: https://exercism.io/my/tracks/c
|
||||
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
|
37
c/acronym/makefile
Normal file
37
c/acronym/makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
### If you wish to use extra libraries (math.h for instance),
|
||||
### add their flags here (-lm in our case) in the "LIBS" variable.
|
||||
|
||||
LIBS = -lm
|
||||
|
||||
###
|
||||
CFLAGS = -std=c99
|
||||
CFLAGS += -g
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -pedantic
|
||||
CFLAGS += -Werror
|
||||
CFLAGS += -Wmissing-declarations
|
||||
CFLAGS += -DUNITY_SUPPORT_64
|
||||
|
||||
ASANFLAGS = -fsanitize=address
|
||||
ASANFLAGS += -fno-common
|
||||
ASANFLAGS += -fno-omit-frame-pointer
|
||||
|
||||
.PHONY: test
|
||||
test: tests.out
|
||||
@./tests.out
|
||||
|
||||
.PHONY: memcheck
|
||||
memcheck: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(ASANFLAGS) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o memcheck.out $(LIBS)
|
||||
@./memcheck.out
|
||||
@echo "Memory check passed"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.o *.out *.out.dSYM
|
||||
|
||||
tests.out: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o tests.out $(LIBS)
|
69
c/acronym/src/acronym.c
Normal file
69
c/acronym/src/acronym.c
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "acronym.h"
|
||||
|
||||
/* See GNUmakefile in following link for explanation
|
||||
* https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7
|
||||
*/
|
||||
#if defined UNIT_TEST || defined DEBUG
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define SKIPWORD(p) { while (*(p) && (isalpha(*(p)) || *p=='\'')) (p)++;}
|
||||
#define NEXTWORD(p) { while (*(p) && !isalpha(*(p))) (p)++;}
|
||||
|
||||
char *abbreviate(const char *phrase)
|
||||
{
|
||||
/* Yet another approach (to avoid scanning phrase twice):
|
||||
* We (re)allocate a ALLOCSIZE buffer when current one is not large
|
||||
* enough to accept next character + 1 ('\0')
|
||||
*
|
||||
* Other solutions would be to scan phrase twice (for example an initial
|
||||
* strlen() to find out a maximum length), or the (bad idea) using a fixed
|
||||
* size buffer.
|
||||
*
|
||||
* The usual choices.
|
||||
*/
|
||||
char *buf=NULL;
|
||||
int c=0, size=0;
|
||||
|
||||
if (!phrase)
|
||||
return NULL;
|
||||
|
||||
while (*phrase) {
|
||||
NEXTWORD(phrase);
|
||||
if (*phrase) {
|
||||
/* buffer too small */
|
||||
if (c>=size-1) {
|
||||
size+=ALLOCSIZE;
|
||||
if (!(buf=realloc(buf, size)))
|
||||
return NULL;
|
||||
}
|
||||
*(buf+c++)=toupper(*phrase++);
|
||||
SKIPWORD(phrase);
|
||||
}
|
||||
}
|
||||
|
||||
/* at least one character */
|
||||
if (c)
|
||||
*(buf+c)=0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int arg=1;
|
||||
char *p;
|
||||
|
||||
for (; arg<ac; ++arg) {
|
||||
p=abbreviate(*(av+arg));
|
||||
printf("acronym(%s)=[%s]\n", *(av+arg), p? p: "NULL");
|
||||
if (p)
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
#endif
|
20
c/acronym/src/acronym.h
Normal file
20
c/acronym/src/acronym.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef ACRONYM_H
|
||||
#define ACRONYM_H
|
||||
|
||||
char *abbreviate(const char *phrase);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ALLOCSIZE 2
|
||||
#else
|
||||
#define ALLOCSIZE 1024
|
||||
#endif
|
||||
|
||||
/* See GNUmakefile in following link for explanation
|
||||
* https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7
|
||||
*/
|
||||
#ifdef TESTALL
|
||||
#undef TEST_IGNORE
|
||||
#define TEST_IGNORE() {}
|
||||
#endif
|
||||
|
||||
#endif
|
21
c/armstrong-numbers/GNUmakefile
Normal file
21
c/armstrong-numbers/GNUmakefile
Normal file
@@ -0,0 +1,21 @@
|
||||
# the original 'makefile' has a flaw:
|
||||
# 1) it overrides CFLAGS
|
||||
# 2) it does not pass extra "FLAGS" to $(CC) that could come from environment
|
||||
#
|
||||
# It means we need to edit 'makefile' for different builds (DEBUG, etc...),
|
||||
# which is not practical at all.
|
||||
#
|
||||
# I hope this will be use-able for next exercises...
|
||||
|
||||
#include gmsl
|
||||
include makefile
|
||||
|
||||
manual=-DUNIT_TEST
|
||||
debug=$(manual) -DDEBUG
|
||||
|
||||
.PHONY: manual debug
|
||||
|
||||
manual debug: src/*.c src/*.h
|
||||
$(CC) $($@) src/*.c -o $@.out
|
||||
#debug: src/*.c src/*.h
|
||||
# $(CC) $(DEBUG) src/*.c -o $@.out
|
50
c/armstrong-numbers/README.md
Normal file
50
c/armstrong-numbers/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Armstrong Numbers
|
||||
|
||||
An [Armstrong number](https://en.wikipedia.org/wiki/Narcissistic_number) is a number that is the sum of its own digits each raised to the power of the number of digits.
|
||||
|
||||
For example:
|
||||
|
||||
- 9 is an Armstrong number, because `9 = 9^1 = 9`
|
||||
- 10 is *not* an Armstrong number, because `10 != 1^2 + 0^2 = 1`
|
||||
- 153 is an Armstrong number, because: `153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153`
|
||||
- 154 is *not* an Armstrong number, because: `154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190`
|
||||
|
||||
Write some code to determine whether a number is an Armstrong number.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Make sure you have read the "Guides" section of the
|
||||
[C track][c-track] on the Exercism site. This covers
|
||||
the basic information on setting up the development environment expected
|
||||
by the exercises.
|
||||
|
||||
## Passing the Tests
|
||||
|
||||
Get the first test compiling, linking and passing by following the [three
|
||||
rules of test-driven development][3-tdd-rules].
|
||||
|
||||
The included makefile can be used to create and run the tests using the `test`
|
||||
task.
|
||||
|
||||
make test
|
||||
|
||||
Create just the functions you need to satisfy any compiler errors and get the
|
||||
test to fail. Then write just enough code to get the test to pass. Once you've
|
||||
done that, move onto the next test.
|
||||
|
||||
As you progress through the tests, take the time to refactor your
|
||||
implementation for readability and expressiveness and then go on to the next
|
||||
test.
|
||||
|
||||
Try to use standard C99 facilities in preference to writing your own
|
||||
low-level algorithms or facilities by hand.
|
||||
|
||||
## Source
|
||||
|
||||
Wikipedia [https://en.wikipedia.org/wiki/Narcissistic_number](https://en.wikipedia.org/wiki/Narcissistic_number)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
||||
[c-track]: https://exercism.io/my/tracks/c
|
||||
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
|
35
c/armstrong-numbers/makefile
Normal file
35
c/armstrong-numbers/makefile
Normal file
@@ -0,0 +1,35 @@
|
||||
### If you wish to use extra libraries (math.h for instance),
|
||||
### add their flags here (-lm in our case) in the "LIBS" variable.
|
||||
|
||||
###
|
||||
CFLAGS = -std=c99
|
||||
CFLAGS += -g
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -pedantic
|
||||
CFLAGS += -Werror
|
||||
CFLAGS += -Wmissing-declarations
|
||||
CFLAGS += -DUNITY_SUPPORT_64
|
||||
|
||||
ASANFLAGS = -fsanitize=address
|
||||
ASANFLAGS += -fno-common
|
||||
ASANFLAGS += -fno-omit-frame-pointer
|
||||
|
||||
.PHONY: test
|
||||
test: tests.out
|
||||
@./tests.out
|
||||
|
||||
.PHONY: memcheck
|
||||
memcheck: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(ASANFLAGS) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o memcheck.out $(LIBS)
|
||||
@./memcheck.out
|
||||
@echo "Memory check passed"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.o *.out *.out.dSYM
|
||||
|
||||
tests.out: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o tests.out $(LIBS)
|
40
c/armstrong-numbers/src/armstrong_numbers.c
Normal file
40
c/armstrong-numbers/src/armstrong_numbers.c
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "armstrong_numbers.h"
|
||||
|
||||
static inline int power(int n, int p) {
|
||||
int res=n;
|
||||
|
||||
/* useless here
|
||||
* if (p==0)
|
||||
* return 1;
|
||||
*/
|
||||
while (--p)
|
||||
res*=n;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool is_armstrong_number(int candidate)
|
||||
{
|
||||
int p=1, r=0, tmp=candidate;
|
||||
|
||||
while (tmp/=10)
|
||||
p++;
|
||||
|
||||
for (tmp=candidate; tmp; tmp /=10)
|
||||
r+=power(tmp%10, p);
|
||||
return r==candidate;
|
||||
}
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int arg=1, n;
|
||||
|
||||
for (; arg<ac; ++arg) {
|
||||
n=atoi(av[arg]);
|
||||
printf("armstrong(%d)=%d\n", n, is_armstrong_number(n));
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
8
c/armstrong-numbers/src/armstrong_numbers.h
Normal file
8
c/armstrong-numbers/src/armstrong_numbers.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef ARMSTRONG_NUMBERS
|
||||
#define ARMSTRONG_NUMBERS
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool is_armstrong_number(int candidate);
|
||||
|
||||
#endif
|
34
c/darts/GNUmakefile
Normal file
34
c/darts/GNUmakefile
Normal file
@@ -0,0 +1,34 @@
|
||||
# the original 'makefile' has a flaw:
|
||||
# 1) it overrides CFLAGS
|
||||
# 2) it does not pass extra "FLAGS" to $(CC) that could come from environment
|
||||
#
|
||||
# It means we need to edit 'makefile' for different builds (DEBUG, etc...),
|
||||
# which is not practical at all.
|
||||
#
|
||||
# To use this makefile:
|
||||
# "make": build with all predefined tests
|
||||
# "make unit": build standalone (unit) test
|
||||
# "make debug": build standalone test with debugging code
|
||||
#
|
||||
# Original 'makefile' targets can be used (make test, etc...)
|
||||
|
||||
.PHONY: default all unit debug std
|
||||
|
||||
default: all
|
||||
|
||||
# default is to build with all predefined tests
|
||||
BUILD := teststall
|
||||
|
||||
include makefile
|
||||
|
||||
all: CFLAGS+=-DTESTALL
|
||||
all: clean test
|
||||
|
||||
unit: CFLAGS+=-DUNIT_TEST
|
||||
unit: clean std
|
||||
|
||||
debug: CFLAGS+=-DUNIT_TEST -DDEBUG
|
||||
debug: clean std
|
||||
|
||||
std: src/*.c src/*.h
|
||||
$(CC) $(CFLAGS) src/*.c -o test.out
|
55
c/darts/README.md
Normal file
55
c/darts/README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Darts
|
||||
|
||||
Write a function that returns the earned points in a single toss of a Darts game.
|
||||
|
||||
[Darts](https://en.wikipedia.org/wiki/Darts) is a game where players
|
||||
throw darts to a [target](https://en.wikipedia.org/wiki/Darts#/media/File:Darts_in_a_dartboard.jpg).
|
||||
|
||||
In our particular instance of the game, the target rewards with 4 different amounts of points, depending on where the dart lands:
|
||||
|
||||
* If the dart lands outside the target, player earns no points (0 points).
|
||||
* If the dart lands in the outer circle of the target, player earns 1 point.
|
||||
* If the dart lands in the middle circle of the target, player earns 5 points.
|
||||
* If the dart lands in the inner circle of the target, player earns 10 points.
|
||||
|
||||
The outer circle has a radius of 10 units (This is equivalent to the total radius for the entire target), the middle circle a radius of 5 units, and the inner circle a radius of 1. Of course, they are all centered to the same point (That is, the circles are [concentric](http://mathworld.wolfram.com/ConcentricCircles.html)) defined by the coordinates (0, 0).
|
||||
|
||||
Write a function that given a point in the target (defined by its `real` cartesian coordinates `x` and `y`), returns the correct amount earned by a dart landing in that point.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Make sure you have read the "Guides" section of the
|
||||
[C track][c-track] on the Exercism site. This covers
|
||||
the basic information on setting up the development environment expected
|
||||
by the exercises.
|
||||
|
||||
## Passing the Tests
|
||||
|
||||
Get the first test compiling, linking and passing by following the [three
|
||||
rules of test-driven development][3-tdd-rules].
|
||||
|
||||
The included makefile can be used to create and run the tests using the `test`
|
||||
task.
|
||||
|
||||
make test
|
||||
|
||||
Create just the functions you need to satisfy any compiler errors and get the
|
||||
test to fail. Then write just enough code to get the test to pass. Once you've
|
||||
done that, move onto the next test.
|
||||
|
||||
As you progress through the tests, take the time to refactor your
|
||||
implementation for readability and expressiveness and then go on to the next
|
||||
test.
|
||||
|
||||
Try to use standard C99 facilities in preference to writing your own
|
||||
low-level algorithms or facilities by hand.
|
||||
|
||||
## Source
|
||||
|
||||
Inspired by an exercise created by a professor Della Paolera in Argentina
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
||||
[c-track]: https://exercism.io/my/tracks/c
|
||||
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
|
37
c/darts/makefile
Normal file
37
c/darts/makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
### If you wish to use extra libraries (math.h for instance),
|
||||
### add their flags here (-lm in our case) in the "LIBS" variable.
|
||||
|
||||
LIBS = -lm
|
||||
|
||||
###
|
||||
CFLAGS = -std=c99
|
||||
CFLAGS += -g
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -pedantic
|
||||
CFLAGS += -Werror
|
||||
CFLAGS += -Wmissing-declarations
|
||||
CFLAGS += -DUNITY_SUPPORT_64
|
||||
|
||||
ASANFLAGS = -fsanitize=address
|
||||
ASANFLAGS += -fno-common
|
||||
ASANFLAGS += -fno-omit-frame-pointer
|
||||
|
||||
.PHONY: test
|
||||
test: tests.out
|
||||
@./tests.out
|
||||
|
||||
.PHONY: memcheck
|
||||
memcheck: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(ASANFLAGS) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o memcheck.out $(LIBS)
|
||||
@./memcheck.out
|
||||
@echo "Memory check passed"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.o *.out *.out.dSYM
|
||||
|
||||
tests.out: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o tests.out $(LIBS)
|
49
c/darts/src/darts.c
Normal file
49
c/darts/src/darts.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "darts.h"
|
||||
|
||||
score_t scores[] ={
|
||||
{ 1.0F, 10 },
|
||||
{ 25.0F, 5 },
|
||||
{ 100.0F, 1 },
|
||||
{ -1.0F, 0 }
|
||||
};
|
||||
|
||||
/* Below function is basically incorrect for general case.
|
||||
* However, it should mostly work here, as we compare relatively small numbers.
|
||||
* see below for better alternatives :
|
||||
* https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
|
||||
*/
|
||||
static inline bool float_almost_equal(float x, float y)
|
||||
{
|
||||
register float f=x-y;
|
||||
return f<MIN_FLOAT_EQUAL && f>-MIN_FLOAT_EQUAL? true: false;
|
||||
}
|
||||
|
||||
unsigned score(coordinate_t c)
|
||||
{
|
||||
float x=c.x, y=c.y, radius=x*x+y*y;
|
||||
int i;
|
||||
|
||||
for (i=0; scores[i].score; ++i) {
|
||||
if (float_almost_equal(radius, scores[i].radius) || radius < scores[i].radius)
|
||||
break;
|
||||
}
|
||||
return scores[i].score;
|
||||
}
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int arg=1;
|
||||
float x, y;
|
||||
|
||||
for (; arg<ac-1; ++arg, ++arg) {
|
||||
x=atof(av[arg]);
|
||||
y=atof(av[arg+1]);
|
||||
printf("equal(%f, %f)=%d\n", x, y, float_almost_equal(x, y));
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
28
c/darts/src/darts.h
Normal file
28
c/darts/src/darts.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef DARTS_H
|
||||
#define DARTS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <float.h>
|
||||
|
||||
typedef struct {
|
||||
float x, y;
|
||||
} coordinate_t;
|
||||
|
||||
typedef struct {
|
||||
float radius;
|
||||
int score;
|
||||
} score_t;
|
||||
|
||||
// to allow float comparisons we consider 2 floats are equal if
|
||||
// their difference is below this value.
|
||||
// Use: avoid the '<' & '>' which may be wrong.
|
||||
#define MIN_FLOAT_EQUAL FLT_EPSILON
|
||||
|
||||
extern unsigned score(coordinate_t);
|
||||
|
||||
#ifdef TESTALL
|
||||
#undef TEST_IGNORE
|
||||
#define TEST_IGNORE() {}
|
||||
#endif
|
||||
|
||||
#endif
|
41
c/difference-of-squares/GNUmakefile
Normal file
41
c/difference-of-squares/GNUmakefile
Normal file
@@ -0,0 +1,41 @@
|
||||
# The original 'makefile' has a flaw:
|
||||
# 1) it overrides CFLAGS
|
||||
# 2) it does not pass extra "FLAGS" to $(CC) that could come from environment
|
||||
#
|
||||
# It means :
|
||||
# - we need to edit 'makefile' for different builds (DEBUG, etc...), which is
|
||||
# not practical at all.
|
||||
# - Also, it does not allow to run all tests without editing the test source
|
||||
# code.
|
||||
#
|
||||
# To use this makefile (GNU make only):
|
||||
# "make": build with all predefined tests (without editing test source code)
|
||||
# "make mem": perform memcheck with all tests enabled
|
||||
# "make unit": build standalone (unit) test
|
||||
# "make debug": build standalone test with debugging code
|
||||
#
|
||||
# Original 'makefile' targets can be used (test, memcheck, clean, ...)
|
||||
|
||||
.PHONY: default all mem unit debug std
|
||||
|
||||
default: all
|
||||
|
||||
# default is to build with all predefined tests
|
||||
BUILD := teststall
|
||||
|
||||
include makefile
|
||||
|
||||
all: CFLAGS+=-DTESTALL
|
||||
all: clean test
|
||||
|
||||
mem: CFLAGS+=-DTESTALL
|
||||
mem: clean memcheck
|
||||
|
||||
unit: CFLAGS+=-DUNIT_TEST
|
||||
unit: clean std
|
||||
|
||||
debug: CFLAGS+=-DUNIT_TEST -DDEBUG
|
||||
debug: clean std
|
||||
|
||||
std: src/*.c src/*.h
|
||||
$(CC) $(CFLAGS) src/*.c -o test.out
|
55
c/difference-of-squares/README.md
Normal file
55
c/difference-of-squares/README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Difference Of Squares
|
||||
|
||||
Find the difference between the square of the sum and the sum of the squares of the first N natural numbers.
|
||||
|
||||
The square of the sum of the first ten natural numbers is
|
||||
(1 + 2 + ... + 10)² = 55² = 3025.
|
||||
|
||||
The sum of the squares of the first ten natural numbers is
|
||||
1² + 2² + ... + 10² = 385.
|
||||
|
||||
Hence the difference between the square of the sum of the first
|
||||
ten natural numbers and the sum of the squares of the first ten
|
||||
natural numbers is 3025 - 385 = 2640.
|
||||
|
||||
You are not expected to discover an efficient solution to this yourself from
|
||||
first principles; research is allowed, indeed, encouraged. Finding the best
|
||||
algorithm for the problem is a key skill in software engineering.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Make sure you have read the "Guides" section of the
|
||||
[C track][c-track] on the Exercism site. This covers
|
||||
the basic information on setting up the development environment expected
|
||||
by the exercises.
|
||||
|
||||
## Passing the Tests
|
||||
|
||||
Get the first test compiling, linking and passing by following the [three
|
||||
rules of test-driven development][3-tdd-rules].
|
||||
|
||||
The included makefile can be used to create and run the tests using the `test`
|
||||
task.
|
||||
|
||||
make test
|
||||
|
||||
Create just the functions you need to satisfy any compiler errors and get the
|
||||
test to fail. Then write just enough code to get the test to pass. Once you've
|
||||
done that, move onto the next test.
|
||||
|
||||
As you progress through the tests, take the time to refactor your
|
||||
implementation for readability and expressiveness and then go on to the next
|
||||
test.
|
||||
|
||||
Try to use standard C99 facilities in preference to writing your own
|
||||
low-level algorithms or facilities by hand.
|
||||
|
||||
## Source
|
||||
|
||||
Problem 6 at Project Euler [http://projecteuler.net/problem=6](http://projecteuler.net/problem=6)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
||||
[c-track]: https://exercism.io/my/tracks/c
|
||||
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
|
37
c/difference-of-squares/makefile
Normal file
37
c/difference-of-squares/makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
### If you wish to use extra libraries (math.h for instance),
|
||||
### add their flags here (-lm in our case) in the "LIBS" variable.
|
||||
|
||||
LIBS = -lm
|
||||
|
||||
###
|
||||
CFLAGS = -std=c99
|
||||
CFLAGS += -g
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -pedantic
|
||||
CFLAGS += -Werror
|
||||
CFLAGS += -Wmissing-declarations
|
||||
CFLAGS += -DUNITY_SUPPORT_64
|
||||
|
||||
ASANFLAGS = -fsanitize=address
|
||||
ASANFLAGS += -fno-common
|
||||
ASANFLAGS += -fno-omit-frame-pointer
|
||||
|
||||
.PHONY: test
|
||||
test: tests.out
|
||||
@./tests.out
|
||||
|
||||
.PHONY: memcheck
|
||||
memcheck: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(ASANFLAGS) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o memcheck.out $(LIBS)
|
||||
@./memcheck.out
|
||||
@echo "Memory check passed"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.o *.out *.out.dSYM
|
||||
|
||||
tests.out: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o tests.out $(LIBS)
|
52
c/difference-of-squares/src/difference_of_squares.c
Normal file
52
c/difference-of-squares/src/difference_of_squares.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "difference_of_squares.h"
|
||||
|
||||
/* See GNUmakefile in following link for explanation
|
||||
* https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7
|
||||
*/
|
||||
#if defined UNIT_TEST || defined DEBUG
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
unsigned int sum_of_squares(unsigned int number)
|
||||
{
|
||||
/* the sum of 1st n integers squares is:
|
||||
* S = 1² + 2² + 3² ..... + (n-1)² + n²
|
||||
* = [ n * (n+1) * (2n+1) ] / 6
|
||||
* some visual explanations on:
|
||||
* http://www.takayaiwamoto.com/Sums_and_Series/sumsqr_1.html
|
||||
*/
|
||||
return number * (number+1) * (2*number + 1) / 6;
|
||||
}
|
||||
|
||||
unsigned int square_of_sum(unsigned int number)
|
||||
{
|
||||
register int res;
|
||||
/* The sum of n 1st integers is:
|
||||
* S = 1 + 2 + 3 ... + (n-1) + n
|
||||
* = [ n * (n+1) ] / 2
|
||||
* demonstration is trivial for this one.
|
||||
*/
|
||||
res=number * (number+1) / 2;
|
||||
return res*res;
|
||||
}
|
||||
|
||||
unsigned int difference_of_squares(unsigned int number)
|
||||
{
|
||||
return square_of_sum(number) - sum_of_squares(number);
|
||||
}
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int arg=1;
|
||||
int i;
|
||||
|
||||
for (; arg<ac; ++arg) {
|
||||
i=atoi(av[arg]);
|
||||
printf("sumsq(%d)=%d\n", i, sum_of_squares(i));
|
||||
printf("sqsum(%d)=%d\n", i, square_of_sum(i));
|
||||
printf("diff(%d)=%d\n", i, difference_of_squares(i));
|
||||
}
|
||||
}
|
||||
#endif
|
16
c/difference-of-squares/src/difference_of_squares.h
Normal file
16
c/difference-of-squares/src/difference_of_squares.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef DIFFERENCE_OF_SQUARES_H
|
||||
#define DIFFERENCE_OF_SQUARES_H
|
||||
|
||||
unsigned int sum_of_squares(unsigned int number);
|
||||
unsigned int square_of_sum(unsigned int number);
|
||||
unsigned int difference_of_squares(unsigned int number);
|
||||
|
||||
/* See GNUmakefile in following link for explanation
|
||||
* https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7
|
||||
*/
|
||||
#ifdef TESTALL
|
||||
#undef TEST_IGNORE
|
||||
#define TEST_IGNORE() {}
|
||||
#endif
|
||||
|
||||
#endif
|
41
c/grains/GNUmakefile
Normal file
41
c/grains/GNUmakefile
Normal file
@@ -0,0 +1,41 @@
|
||||
# The original 'makefile' has a flaw:
|
||||
# 1) it overrides CFLAGS
|
||||
# 2) it does not pass extra "FLAGS" to $(CC) that could come from environment
|
||||
#
|
||||
# It means :
|
||||
# - we need to edit 'makefile' for different builds (DEBUG, etc...), which is
|
||||
# not practical at all.
|
||||
# - Also, it does not allow to run all tests without editing the test source
|
||||
# code.
|
||||
#
|
||||
# To use this makefile (GNU make only):
|
||||
# "make": build with all predefined tests (without editing test source code)
|
||||
# "make mem": perform memcheck with all tests enabled
|
||||
# "make unit": build standalone (unit) test
|
||||
# "make debug": build standalone test with debugging code
|
||||
#
|
||||
# Original 'makefile' targets can be used (test, memcheck, clean, ...)
|
||||
|
||||
.PHONY: default all mem unit debug std
|
||||
|
||||
default: all
|
||||
|
||||
# default is to build with all predefined tests
|
||||
BUILD := teststall
|
||||
|
||||
include makefile
|
||||
|
||||
all: CFLAGS+=-DTESTALL
|
||||
all: clean test
|
||||
|
||||
mem: CFLAGS+=-DTESTALL
|
||||
mem: clean memcheck
|
||||
|
||||
unit: CFLAGS+=-DUNIT_TEST
|
||||
unit: clean std
|
||||
|
||||
debug: CFLAGS+=-DUNIT_TEST -DDEBUG
|
||||
debug: clean std
|
||||
|
||||
std: src/*.c src/*.h
|
||||
$(CC) $(CFLAGS) src/*.c -o test.out
|
65
c/grains/README.md
Normal file
65
c/grains/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Grains
|
||||
|
||||
Calculate the number of grains of wheat on a chessboard given that the number
|
||||
on each square doubles.
|
||||
|
||||
There once was a wise servant who saved the life of a prince. The king
|
||||
promised to pay whatever the servant could dream up. Knowing that the
|
||||
king loved chess, the servant told the king he would like to have grains
|
||||
of wheat. One grain on the first square of a chess board, with the number
|
||||
of grains doubling on each successive square.
|
||||
|
||||
There are 64 squares on a chessboard (where square 1 has one grain, square 2 has two grains, and so on).
|
||||
|
||||
Write code that shows:
|
||||
- how many grains were on a given square, and
|
||||
- the total number of grains on the chessboard
|
||||
|
||||
## For bonus points
|
||||
|
||||
Did you get the tests passing and the code clean? If you want to, these
|
||||
are some additional things you could try:
|
||||
|
||||
- Optimize for speed.
|
||||
- Optimize for readability.
|
||||
|
||||
Then please share your thoughts in a comment on the submission. Did this
|
||||
experiment make the code better? Worse? Did you learn anything from it?
|
||||
|
||||
## Getting Started
|
||||
|
||||
Make sure you have read the "Guides" section of the
|
||||
[C track][c-track] on the Exercism site. This covers
|
||||
the basic information on setting up the development environment expected
|
||||
by the exercises.
|
||||
|
||||
## Passing the Tests
|
||||
|
||||
Get the first test compiling, linking and passing by following the [three
|
||||
rules of test-driven development][3-tdd-rules].
|
||||
|
||||
The included makefile can be used to create and run the tests using the `test`
|
||||
task.
|
||||
|
||||
make test
|
||||
|
||||
Create just the functions you need to satisfy any compiler errors and get the
|
||||
test to fail. Then write just enough code to get the test to pass. Once you've
|
||||
done that, move onto the next test.
|
||||
|
||||
As you progress through the tests, take the time to refactor your
|
||||
implementation for readability and expressiveness and then go on to the next
|
||||
test.
|
||||
|
||||
Try to use standard C99 facilities in preference to writing your own
|
||||
low-level algorithms or facilities by hand.
|
||||
|
||||
## Source
|
||||
|
||||
JavaRanch Cattle Drive, exercise 6 [http://www.javaranch.com/grains.jsp](http://www.javaranch.com/grains.jsp)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
||||
[c-track]: https://exercism.io/my/tracks/c
|
||||
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
|
37
c/grains/makefile
Normal file
37
c/grains/makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
### If you wish to use extra libraries (math.h for instance),
|
||||
### add their flags here (-lm in our case) in the "LIBS" variable.
|
||||
|
||||
LIBS = -lm
|
||||
|
||||
###
|
||||
CFLAGS = -std=c99
|
||||
CFLAGS += -g
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -pedantic
|
||||
CFLAGS += -Werror
|
||||
CFLAGS += -Wmissing-declarations
|
||||
CFLAGS += -DUNITY_SUPPORT_64
|
||||
|
||||
ASANFLAGS = -fsanitize=address
|
||||
ASANFLAGS += -fno-common
|
||||
ASANFLAGS += -fno-omit-frame-pointer
|
||||
|
||||
.PHONY: test
|
||||
test: tests.out
|
||||
@./tests.out
|
||||
|
||||
.PHONY: memcheck
|
||||
memcheck: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(ASANFLAGS) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o memcheck.out $(LIBS)
|
||||
@./memcheck.out
|
||||
@echo "Memory check passed"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.o *.out *.out.dSYM
|
||||
|
||||
tests.out: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o tests.out $(LIBS)
|
45
c/grains/src/grains.c
Normal file
45
c/grains/src/grains.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "grains.h"
|
||||
/* See GNUmakefile in following link for explanation
|
||||
* https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7
|
||||
*/
|
||||
#if defined UNIT_TEST || defined DEBUG
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
uint64_t square(uint8_t index)
|
||||
{
|
||||
return index>0 && index <65 ? (uint64_t)1<<(index-1): 0;
|
||||
}
|
||||
uint64_t total(void)
|
||||
{
|
||||
/* Geometric series sum formula for 64 terms, ratio 2 and first term 1:
|
||||
* S = 2⁰ + 2¹ + 2² + ... + 2⁶³
|
||||
* = (1-2⁶⁴) / (1-2)
|
||||
* = 2⁶⁴ - 1
|
||||
* = 0 - 1 for uint64_t
|
||||
* We should write (2<<64)-1, but gcc won't compile, due to:
|
||||
* -Werror=shift-count-overflow
|
||||
* Then we could avoid it by using:
|
||||
* #pragma GCC diagnostic ignored "-Wshift-count-overflow"
|
||||
* but i think it is out of scope for this exercise (we should also take
|
||||
* care of other compilers).
|
||||
*/
|
||||
return (uint64_t) -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int arg=1;
|
||||
uint64_t i;
|
||||
|
||||
for (; arg<ac; ++arg) {
|
||||
i=atol(av[arg]);
|
||||
printf("value(%lu)=%lu\n", i, square(i));
|
||||
}
|
||||
printf("total()=%lu\n", total());
|
||||
}
|
||||
#endif
|
17
c/grains/src/grains.h
Normal file
17
c/grains/src/grains.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef GRAINS_H
|
||||
#define GRAINS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint64_t square(uint8_t index);
|
||||
extern uint64_t total(void);
|
||||
|
||||
/* See GNUmakefile in following link for explanation
|
||||
* https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7
|
||||
*/
|
||||
#ifdef TESTALL
|
||||
#undef TEST_IGNORE
|
||||
#define TEST_IGNORE() {}
|
||||
#endif
|
||||
|
||||
#endif
|
41
c/hamming/GNUmakefile
Normal file
41
c/hamming/GNUmakefile
Normal file
@@ -0,0 +1,41 @@
|
||||
# The original 'makefile' has a flaw:
|
||||
# 1) it overrides CFLAGS
|
||||
# 2) it does not pass extra "FLAGS" to $(CC) that could come from environment
|
||||
#
|
||||
# It means :
|
||||
# - we need to edit 'makefile' for different builds (DEBUG, etc...), which is
|
||||
# not practical at all.
|
||||
# - Also, it does not allow to run all tests without editing the test source
|
||||
# code.
|
||||
#
|
||||
# To use this makefile (GNU make only):
|
||||
# "make": build with all predefined tests (without editing test source code)
|
||||
# "make mem": perform memcheck with all tests enabled
|
||||
# "make unit": build standalone (unit) test
|
||||
# "make debug": build standalone test with debugging code
|
||||
#
|
||||
# Original 'makefile' targets can be used (test, memcheck, clean, ...)
|
||||
|
||||
.PHONY: default all mem unit debug std
|
||||
|
||||
default: all
|
||||
|
||||
# default is to build with all predefined tests
|
||||
BUILD := teststall
|
||||
|
||||
include makefile
|
||||
|
||||
all: CFLAGS+=-DTESTALL
|
||||
all: clean test
|
||||
|
||||
mem: CFLAGS+=-DTESTALL
|
||||
mem: clean memcheck
|
||||
|
||||
unit: CFLAGS+=-DUNIT_TEST
|
||||
unit: clean std
|
||||
|
||||
debug: CFLAGS+=-DUNIT_TEST -DDEBUG
|
||||
debug: clean std
|
||||
|
||||
std: src/*.c src/*.h
|
||||
$(CC) $(CFLAGS) src/*.c -o test.out
|
62
c/hamming/README.md
Normal file
62
c/hamming/README.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Hamming
|
||||
|
||||
Calculate the Hamming Distance between two DNA strands.
|
||||
|
||||
Your body is made up of cells that contain DNA. Those cells regularly wear out and need replacing, which they achieve by dividing into daughter cells. In fact, the average human body experiences about 10 quadrillion cell divisions in a lifetime!
|
||||
|
||||
When cells divide, their DNA replicates too. Sometimes during this process mistakes happen and single pieces of DNA get encoded with the incorrect information. If we compare two strands of DNA and count the differences between them we can see how many mistakes occurred. This is known as the "Hamming Distance".
|
||||
|
||||
We read DNA using the letters C,A,G and T. Two strands might look like this:
|
||||
|
||||
GAGCCTACTAACGGGAT
|
||||
CATCGTAATGACGGCCT
|
||||
^ ^ ^ ^ ^ ^^
|
||||
|
||||
They have 7 differences, and therefore the Hamming Distance is 7.
|
||||
|
||||
The Hamming Distance is useful for lots of things in science, not just biology, so it's a nice phrase to be familiar with :)
|
||||
|
||||
# Implementation notes
|
||||
|
||||
The Hamming distance is only defined for sequences of equal length, so
|
||||
an attempt to calculate it between sequences of different lengths should
|
||||
not work. The general handling of this situation (e.g., raising an
|
||||
exception vs returning a special value) may differ between languages.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Make sure you have read the "Guides" section of the
|
||||
[C track][c-track] on the Exercism site. This covers
|
||||
the basic information on setting up the development environment expected
|
||||
by the exercises.
|
||||
|
||||
## Passing the Tests
|
||||
|
||||
Get the first test compiling, linking and passing by following the [three
|
||||
rules of test-driven development][3-tdd-rules].
|
||||
|
||||
The included makefile can be used to create and run the tests using the `test`
|
||||
task.
|
||||
|
||||
make test
|
||||
|
||||
Create just the functions you need to satisfy any compiler errors and get the
|
||||
test to fail. Then write just enough code to get the test to pass. Once you've
|
||||
done that, move onto the next test.
|
||||
|
||||
As you progress through the tests, take the time to refactor your
|
||||
implementation for readability and expressiveness and then go on to the next
|
||||
test.
|
||||
|
||||
Try to use standard C99 facilities in preference to writing your own
|
||||
low-level algorithms or facilities by hand.
|
||||
|
||||
## Source
|
||||
|
||||
The Calculating Point Mutations problem at Rosalind [http://rosalind.info/problems/hamm/](http://rosalind.info/problems/hamm/)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
||||
[c-track]: https://exercism.io/my/tracks/c
|
||||
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
|
37
c/hamming/makefile
Normal file
37
c/hamming/makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
### If you wish to use extra libraries (math.h for instance),
|
||||
### add their flags here (-lm in our case) in the "LIBS" variable.
|
||||
|
||||
LIBS = -lm
|
||||
|
||||
###
|
||||
CFLAGS = -std=c99
|
||||
CFLAGS += -g
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -pedantic
|
||||
CFLAGS += -Werror
|
||||
CFLAGS += -Wmissing-declarations
|
||||
CFLAGS += -DUNITY_SUPPORT_64
|
||||
|
||||
ASANFLAGS = -fsanitize=address
|
||||
ASANFLAGS += -fno-common
|
||||
ASANFLAGS += -fno-omit-frame-pointer
|
||||
|
||||
.PHONY: test
|
||||
test: tests.out
|
||||
@./tests.out
|
||||
|
||||
.PHONY: memcheck
|
||||
memcheck: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(ASANFLAGS) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o memcheck.out $(LIBS)
|
||||
@./memcheck.out
|
||||
@echo "Memory check passed"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.o *.out *.out.dSYM
|
||||
|
||||
tests.out: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o tests.out $(LIBS)
|
41
c/hamming/src/hamming.c
Normal file
41
c/hamming/src/hamming.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "hamming.h"
|
||||
|
||||
/* Note: For explanation on section below, see 'GNUfilename' included in
|
||||
* link below :
|
||||
* https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7
|
||||
*/
|
||||
#if defined UNIT_TEST || defined DEBUG
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* test does not include invalid input, but it should, as the subject is
|
||||
* about DNA sequence, not ASCII chars sequence :-)
|
||||
* exercism test needs only:
|
||||
* #define V(p) (*p)
|
||||
*/
|
||||
#define V(p) (*(p)=='A' || *(p)=='C' || *(p)=='G' || *(p)=='T')
|
||||
|
||||
int compute(const char *lhs, const char *rhs)
|
||||
{
|
||||
int res=0;
|
||||
const char *l=lhs, *r=rhs;
|
||||
|
||||
if (!l || !r)
|
||||
return -1;
|
||||
for (; V(l) && V(r); ++l, ++r) {
|
||||
if (*l != *r)
|
||||
res++;
|
||||
}
|
||||
return *r || *l? -1: res;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
if (ac==3) {
|
||||
printf("compute(%s, %s)=%d\n", *(av+1), *(av+2), compute(*(av+1), *(av+2)));
|
||||
}
|
||||
}
|
||||
#endif
|
15
c/hamming/src/hamming.h
Normal file
15
c/hamming/src/hamming.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef HAMMING_H
|
||||
#define HAMMING_H
|
||||
|
||||
int compute(const char *lhs, const char *rhs);
|
||||
|
||||
/* Note: For explanation on section below, see 'GNUfilename' included in
|
||||
* link below :
|
||||
* https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7
|
||||
*/
|
||||
#ifdef TESTALL
|
||||
#undef TEST_IGNORE
|
||||
#define TEST_IGNORE() {}
|
||||
#endif
|
||||
|
||||
#endif
|
53
c/hello-world/README.md
Normal file
53
c/hello-world/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Hello World
|
||||
|
||||
The classical introductory exercise. Just say "Hello, World!".
|
||||
|
||||
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is
|
||||
the traditional first program for beginning programming in a new language
|
||||
or environment.
|
||||
|
||||
The objectives are simple:
|
||||
|
||||
- Write a function that returns the string "Hello, World!".
|
||||
- Run the test suite and make sure that it succeeds.
|
||||
- Submit your solution and check it at the website.
|
||||
|
||||
If everything goes well, you will be ready to fetch your first real exercise.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Make sure you have read the "Guides" section of the
|
||||
[C track][c-track] on the Exercism site. This covers
|
||||
the basic information on setting up the development environment expected
|
||||
by the exercises.
|
||||
|
||||
## Passing the Tests
|
||||
|
||||
Get the first test compiling, linking and passing by following the [three
|
||||
rules of test-driven development][3-tdd-rules].
|
||||
|
||||
The included makefile can be used to create and run the tests using the `test`
|
||||
task.
|
||||
|
||||
make test
|
||||
|
||||
Create just the functions you need to satisfy any compiler errors and get the
|
||||
test to fail. Then write just enough code to get the test to pass. Once you've
|
||||
done that, move onto the next test.
|
||||
|
||||
As you progress through the tests, take the time to refactor your
|
||||
implementation for readability and expressiveness and then go on to the next
|
||||
test.
|
||||
|
||||
Try to use standard C99 facilities in preference to writing your own
|
||||
low-level algorithms or facilities by hand.
|
||||
|
||||
## Source
|
||||
|
||||
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
||||
[c-track]: https://exercism.io/my/tracks/c
|
||||
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
|
37
c/hello-world/makefile
Normal file
37
c/hello-world/makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
### If you wish to use extra libraries (math.h for instance),
|
||||
### add their flags here (-lm in our case) in the "LIBS" variable.
|
||||
|
||||
LIBS = -lm
|
||||
|
||||
###
|
||||
CFLAGS = -std=c99
|
||||
CFLAGS += -g
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -pedantic
|
||||
CFLAGS += -Werror
|
||||
CFLAGS += -Wmissing-declarations
|
||||
CFLAGS += -DUNITY_SUPPORT_64
|
||||
|
||||
ASANFLAGS = -fsanitize=address
|
||||
ASANFLAGS += -fno-common
|
||||
ASANFLAGS += -fno-omit-frame-pointer
|
||||
|
||||
.PHONY: test
|
||||
test: tests.out
|
||||
@./tests.out
|
||||
|
||||
.PHONY: memcheck
|
||||
memcheck: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(ASANFLAGS) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o memcheck.out $(LIBS)
|
||||
@./memcheck.out
|
||||
@echo "Memory check passed"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.o *.out *.out.dSYM
|
||||
|
||||
tests.out: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o tests.out $(LIBS)
|
7
c/hello-world/src/hello_world.c
Normal file
7
c/hello-world/src/hello_world.c
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <stddef.h>
|
||||
#include "hello_world.h"
|
||||
|
||||
const char *hello(void)
|
||||
{
|
||||
return "Hello, World!";
|
||||
}
|
14
c/hello-world/src/hello_world.h
Normal file
14
c/hello-world/src/hello_world.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// This is called an include guard, which ensures that the header is only
|
||||
// included once. You could alternatively use '#pragma once'. See
|
||||
// https://en.wikipedia.org/wiki/Include_guard.
|
||||
#ifndef HELLO_WORLD_H
|
||||
#define HELLO_WORLD_H
|
||||
|
||||
// Declare the 'hello()' function, which takes no arguments and returns a
|
||||
// 'const char *', i.e. a pointer to a character (in this case the first
|
||||
// character in a string). The function itself is defined in the hello_world.c
|
||||
// source file. Ths function is called by the test case(s) in the test source
|
||||
// file test/test_hello_world.c.
|
||||
const char *hello(void);
|
||||
|
||||
#endif
|
39
c/isogram/GNUmakefile
Normal file
39
c/isogram/GNUmakefile
Normal file
@@ -0,0 +1,39 @@
|
||||
# the original 'makefile' has a flaw:
|
||||
# 1) it overrides CFLAGS
|
||||
# 2) it does not pass extra "FLAGS" to $(CC) that could come from environment
|
||||
#
|
||||
# It means we need to edit 'makefile' for different builds (DEBUG, etc...),
|
||||
# which is not practical at all. Also, it does not allow to run all tests without
|
||||
# editing the test source code.
|
||||
#
|
||||
# To use this makefile (GNU make only):
|
||||
# "make": build with all predefined tests (without editing test source code)
|
||||
# "make mem": perform memcheck with all tests enabled
|
||||
# "make unit": build standalone (unit) test
|
||||
# "make debug": build standalone test with debugging code
|
||||
#
|
||||
# Original 'makefile' targets can be used (make test, etc...)
|
||||
|
||||
.PHONY: default all mem unit debug std
|
||||
|
||||
default: all
|
||||
|
||||
# default is to build with all predefined tests
|
||||
BUILD := teststall
|
||||
|
||||
include makefile
|
||||
|
||||
all: CFLAGS+=-DTESTALL
|
||||
all: clean test
|
||||
|
||||
mem: CFLAGS+=-DTESTALL
|
||||
mem: clean memcheck
|
||||
|
||||
unit: CFLAGS+=-DUNIT_TEST
|
||||
unit: clean std
|
||||
|
||||
debug: CFLAGS+=-DUNIT_TEST -DDEBUG
|
||||
debug: clean std
|
||||
|
||||
std: src/*.c src/*.h
|
||||
$(CC) $(CFLAGS) src/*.c -o test.out
|
52
c/isogram/README.md
Normal file
52
c/isogram/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Isogram
|
||||
|
||||
Determine if a word or phrase is an isogram.
|
||||
|
||||
An isogram (also known as a "nonpattern word") is a word or phrase without a repeating letter, however spaces and hyphens are allowed to appear multiple times.
|
||||
|
||||
Examples of isograms:
|
||||
|
||||
- lumberjacks
|
||||
- background
|
||||
- downstream
|
||||
- six-year-old
|
||||
|
||||
The word *isograms*, however, is not an isogram, because the s repeats.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Make sure you have read the "Guides" section of the
|
||||
[C track][c-track] on the Exercism site. This covers
|
||||
the basic information on setting up the development environment expected
|
||||
by the exercises.
|
||||
|
||||
## Passing the Tests
|
||||
|
||||
Get the first test compiling, linking and passing by following the [three
|
||||
rules of test-driven development][3-tdd-rules].
|
||||
|
||||
The included makefile can be used to create and run the tests using the `test`
|
||||
task.
|
||||
|
||||
make test
|
||||
|
||||
Create just the functions you need to satisfy any compiler errors and get the
|
||||
test to fail. Then write just enough code to get the test to pass. Once you've
|
||||
done that, move onto the next test.
|
||||
|
||||
As you progress through the tests, take the time to refactor your
|
||||
implementation for readability and expressiveness and then go on to the next
|
||||
test.
|
||||
|
||||
Try to use standard C99 facilities in preference to writing your own
|
||||
low-level algorithms or facilities by hand.
|
||||
|
||||
## Source
|
||||
|
||||
Wikipedia [https://en.wikipedia.org/wiki/Isogram](https://en.wikipedia.org/wiki/Isogram)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
||||
[c-track]: https://exercism.io/my/tracks/c
|
||||
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
|
37
c/isogram/makefile
Normal file
37
c/isogram/makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
### If you wish to use extra libraries (math.h for instance),
|
||||
### add their flags here (-lm in our case) in the "LIBS" variable.
|
||||
|
||||
LIBS = -lm
|
||||
|
||||
###
|
||||
CFLAGS = -std=c99
|
||||
CFLAGS += -g
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -pedantic
|
||||
CFLAGS += -Werror
|
||||
CFLAGS += -Wmissing-declarations
|
||||
CFLAGS += -DUNITY_SUPPORT_64
|
||||
|
||||
ASANFLAGS = -fsanitize=address
|
||||
ASANFLAGS += -fno-common
|
||||
ASANFLAGS += -fno-omit-frame-pointer
|
||||
|
||||
.PHONY: test
|
||||
test: tests.out
|
||||
@./tests.out
|
||||
|
||||
.PHONY: memcheck
|
||||
memcheck: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(ASANFLAGS) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o memcheck.out $(LIBS)
|
||||
@./memcheck.out
|
||||
@echo "Memory check passed"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.o *.out *.out.dSYM
|
||||
|
||||
tests.out: test/*.c src/*.c src/*.h
|
||||
@echo Compiling $@
|
||||
@$(CC) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o tests.out $(LIBS)
|
34
c/isogram/src/isogram.c
Normal file
34
c/isogram/src/isogram.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "isogram.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define POS(c) (tolower(c)-'a')
|
||||
|
||||
/* This does not work outside English world */
|
||||
bool is_isogram(const char phrase[])
|
||||
{
|
||||
//int map['z'-'a'+1]={0};
|
||||
int map[1000]={0};
|
||||
const char *p=phrase;
|
||||
|
||||
if (!p)
|
||||
return false;
|
||||
for (; *p; ++p) {
|
||||
if (*p==' ' || *p=='-')
|
||||
continue;
|
||||
if (!isalpha((unsigned char)*p) || (++map[POS((unsigned char)*p)])>1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
#include <stdio.h>
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int arg=1;
|
||||
|
||||
for (; arg<ac; ++arg) {
|
||||
printf("isogram[%s]=%d\n", av[arg], is_isogram(av[arg]));
|
||||
}
|
||||
}
|
||||
#endif
|
13
c/isogram/src/isogram.h
Normal file
13
c/isogram/src/isogram.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef ISOGRAM_H
|
||||
#define ISOGRAM_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool is_isogram(const char phrase[]);
|
||||
|
||||
#ifdef TESTALL
|
||||
#undef TEST_IGNORE
|
||||
#define TEST_IGNORE() {}
|
||||
#endif
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user