diff --git a/awk/README.md b/awk/README.md index 9c2c28b1..e79fdc32 100644 --- a/awk/README.md +++ b/awk/README.md @@ -22,3 +22,4 @@ - [luhn](./luhn/README.md) - [series](./series/README.md) - [atbash-cipher](./atbash-cipher/README.md) +- [raindrops](./raindrops/README.md) diff --git a/awk/raindrops/README.md b/awk/raindrops/README.md index e0bf6511..4d5bdf12 100644 --- a/awk/raindrops/README.md +++ b/awk/raindrops/README.md @@ -37,4 +37,11 @@ You'll need to implement the logic inside the `BEGIN` block. ### Based on -A variation on FizzBuzz, a famous technical interview question that is intended to weed out potential candidates. That question is itself derived from Fizz Buzz, a popular children's game for teaching division. - https://en.wikipedia.org/wiki/Fizz_buzz \ No newline at end of file +A variation on FizzBuzz, a famous technical interview question that is intended to weed out potential candidates. That question is itself derived from Fizz Buzz, a popular children's game for teaching division. - https://en.wikipedia.org/wiki/Fizz_buzz + +### My Solution + +- [my solution](./raindrops.awk) +- [awkunit tests](./raindrops_test.awk) +- [test cases](./test-cases.awk) +- [run-tests](./run-tests-awk.txt) diff --git a/awk/raindrops/awkunit.awk b/awk/raindrops/awkunit.awk new file mode 120000 index 00000000..38a08adf --- /dev/null +++ b/awk/raindrops/awkunit.awk @@ -0,0 +1 @@ +../.lib/awkunit.awk \ No newline at end of file diff --git a/awk/raindrops/raindrops.awk b/awk/raindrops/raindrops.awk index 44c3df84..2f091738 100644 --- a/awk/raindrops/raindrops.awk +++ b/awk/raindrops/raindrops.awk @@ -1,7 +1,55 @@ +#!/usr/bin/gawk --lint --file + +@load "ordchr" + # These variables are initialized on the command line (using '-v'): -# - num +# - num -> ^([0-9]+$ + +function raindrops(number) { + sounds = "" + + if (length(number) == 0) { + return "error: nothing has no sound" + } + + if (number == 0) { + return number + } + + if (number % 3 == 0) { + sounds = sounds "Pling" + } + + if (number % 5 == 0) { + sounds = sounds "Plang" + } + + if (number % 7 == 0) { + sounds = sounds "Plong" + } + + if (length(sounds) == 0) { + sounds = number + } + + return sounds +} BEGIN { - print "Implement this solution" > "/dev/stderr" - exit 1 + # let's make sure direction isn't being used to inject code + if (! match(num, /^[0-9]+$/)) { + print "error: invalid number [" num "], the only supported numbers are ^[0-9]+$" + exit 1 + } + + print raindrops(num) + + exit 0 +} + +{ + # using this section got us stuck waiting for input that is only given via variables +} + +END { } diff --git a/awk/raindrops/raindrops_test.awk b/awk/raindrops/raindrops_test.awk new file mode 100644 index 00000000..f8c00c9c --- /dev/null +++ b/awk/raindrops/raindrops_test.awk @@ -0,0 +1,75 @@ +#!/usr/bin/gawk --lint --file + +@include "awkunit" +@include "test-cases" +@include "raindrops" + +passed = 0 +testCount = 0 + +function _debugTestPre() { + printf "Test %s:\n", (passed + 1) + printf " input -> [%s]\n", input +} + +function _debugTestPost() { + passed = passed + 1 + printf " output -> [%s]\n", got + printf " result -> passed\n\n" +} + +function testRaindrops_empty() { + input = "" + want = "error: nothing has no sound" + + # _ = split(input, a, " ") + + _debugTestPre() + got = raindrops(input) + + assertEquals(got, want) + _debugTestPost() +} + +function casesRaindrops() { + printf "Running %d test cases\n\n", length(cases) + caseNum = 0 + + # Associative arrays don't preserve insert order. + for (key in cases) { + input = key + want = cases[key] + + # _ = split(input, a, " ") + + _debugTestPre() + got = raindrops(input) + + assertEquals(got, want) + _debugTestPost() + } +} + +BEGIN { + exit 0 +} + +END { + cmd = "grep --no-filename --count ^function\\ test *_test.awk" + cmd | getline testCount + + printf "\nRunning %d tests...\n\n", testCount + + testCount = testCount + length(cases) + + # running tests with a lot of duplication + testRaindrops_empty() + + # running tests with reduced duplication + casesRaindrops() + + print "\n" passed " out of " testCount " tests passed!" + + # add exit here to keep it from looping + exit 0 +} diff --git a/awk/raindrops/run-tests-awk.txt b/awk/raindrops/run-tests-awk.txt new file mode 100644 index 00000000..9b8f3556 --- /dev/null +++ b/awk/raindrops/run-tests-awk.txt @@ -0,0 +1,275 @@ +Running automated test file(s): + + +=============================================================================== + +AWKLIBPATH=/usr/lib/x86_64-linux-gnu/gawk:../.lib + +/usr/lib/x86_64-linux-gnu/gawk +filefuncs.so +fnmatch.so +fork.so +inplace.so +intdiv.so +ordchr.so +readdir.so +readfile.so +revoutput.so +revtwoway.so +rwarray.so +time.so + +../.lib +awkunit.awk +awkunit.so + +gawk --lint --file=./awkunit.awk < /dev/null > /dev/null +gawk: ./awkunit.awk:3: warning: `load' is a gawk extension +gawk: warning: function `assertEquals' defined but never called directly +gawk: warning: function `assert' defined but never called directly +gawk: ./awkunit.awk:26: warning: reference to uninitialized variable `_assert_exit' + +real 0m0.004s +user 0m0.002s +sys 0m0.002s + +gawk --lint --file=./raindrops.awk < /dev/null > /dev/null +gawk: ./raindrops.awk:3: warning: `load' is a gawk extension +gawk: ./raindrops.awk:40: warning: reference to uninitialized variable `num' +gawk: ./raindrops.awk:41: warning: reference to uninitialized variable `num' + +real 0m0.002s +user 0m0.001s +sys 0m0.001s + +gawk --lint --file=./test-cases.awk < /dev/null > /dev/null + +real 0m0.002s +user 0m0.001s +sys 0m0.001s + +exit 1 + +=============================================================================== + +Running: bats ./test-raindrops.bats +1..18 +ok 1 the sound for 1 is 1 +ok 2 the sound for 3 is Pling +ok 3 the sound for 5 is Plang +ok 4 the sound for 7 is Plong +ok 5 the sound for 6 is Pling as it has a factor 3 +ok 6 2 to the power 3 does not make a raindrop sound as 3 is the exponent not the base +ok 7 the sound for 9 is Pling as it has a factor 3 +ok 8 the sound for 10 is Plang as it has a factor 5 +ok 9 the sound for 14 is Plong as it has a factor of 7 +ok 10 the sound for 15 is PlingPlang as it has factors 3 and 5 +ok 11 the sound for 21 is PlingPlong as it has factors 3 and 7 +ok 12 the sound for 25 is Plang as it has a factor 5 +ok 13 the sound for 27 is Pling as it has a factor 3 +ok 14 the sound for 35 is PlangPlong as it has factors 5 and 7 +ok 15 the sound for 49 is Plong as it has a factor 7 +ok 16 the sound for 52 is 52 +ok 17 the sound for 105 is PlingPlangPlong as it has factors 3, 5 and 7 +ok 18 the sound for 3125 is Plang as it has a factor 5 + +real 0m0.645s +user 0m0.430s +sys 0m0.237s + +exit 0 + +=============================================================================== + +AWKLIBPATH=/usr/lib/x86_64-linux-gnu/gawk:../.lib + +/usr/lib/x86_64-linux-gnu/gawk +filefuncs.so +fnmatch.so +fork.so +inplace.so +intdiv.so +ordchr.so +readdir.so +readfile.so +revoutput.so +revtwoway.so +rwarray.so +time.so + +../.lib +awkunit.awk +awkunit.so + +Running: gawk --file ./raindrops_test.awk && printf \n%s\n Tests Passed! || printf \n%s\n Tests Failed! + +Running 1 tests... + +Test 1: + input -> [] + output -> [error: nothing has no sound] + result -> passed + +Running 28 test cases + +Test 2: + input -> [-1] + output -> [-1] + result -> passed + +Test 3: + input -> [-3] + output -> [Pling] + result -> passed + +Test 4: + input -> [-7] + output -> [Plong] + result -> passed + +Test 5: + input -> [-5] + output -> [Plang] + result -> passed + +Test 6: + input -> [0] + output -> [0] + result -> passed + +Test 7: + input -> [1] + output -> [1] + result -> passed + +Test 8: + input -> [3] + output -> [Pling] + result -> passed + +Test 9: + input -> [5] + output -> [Plang] + result -> passed + +Test 10: + input -> [6] + output -> [Pling] + result -> passed + +Test 11: + input -> [7] + output -> [Plong] + result -> passed + +Test 12: + input -> [8] + output -> [8] + result -> passed + +Test 13: + input -> [9] + output -> [Pling] + result -> passed + +Test 14: + input -> [10] + output -> [Plang] + result -> passed + +Test 15: + input -> [11] + output -> [11] + result -> passed + +Test 16: + input -> [12] + output -> [Pling] + result -> passed + +Test 17: + input -> [14] + output -> [Plong] + result -> passed + +Test 18: + input -> [15] + output -> [PlingPlang] + result -> passed + +Test 19: + input -> [21] + output -> [PlingPlong] + result -> passed + +Test 20: + input -> [25] + output -> [Plang] + result -> passed + +Test 21: + input -> [28] + output -> [Plong] + result -> passed + +Test 22: + input -> [35] + output -> [PlangPlong] + result -> passed + +Test 23: + input -> [49] + output -> [Plong] + result -> passed + +Test 24: + input -> [52] + output -> [52] + result -> passed + +Test 25: + input -> [70] + output -> [PlangPlong] + result -> passed + +Test 26: + input -> [105] + output -> [PlingPlangPlong] + result -> passed + +Test 27: + input -> [210] + output -> [PlingPlangPlong] + result -> passed + +Test 28: + input -> [945] + output -> [PlingPlangPlong] + result -> passed + +Test 29: + input -> [3125] + output -> [Plang] + result -> passed + + +29 out of 29 tests passed! + +real 0m0.009s +user 0m0.002s +sys 0m0.007s + +Tests Passed! + +exit 0 + +=============================================================================== + +Running: misspell . + +real 0m0.026s +user 0m0.028s +sys 0m0.012s + +=============================================================================== + diff --git a/awk/raindrops/test-cases.awk b/awk/raindrops/test-cases.awk new file mode 100644 index 00000000..8a12bdb6 --- /dev/null +++ b/awk/raindrops/test-cases.awk @@ -0,0 +1,46 @@ +#!/usr/bin/gawk --lint --file +# test-cases.awk + +# key: input +# value: output + +BEGIN { + cases["0"]="0" + + cases["-1"]="-1" + cases["-3"]="Pling" + cases["-5"]="Plang" + cases["-7"]="Plong" + + cases["1"]="1" + cases["8"]="8" + cases["11"]="11" + cases["52"]="52" + + cases["3"]="Pling" + cases["6"]="Pling" + cases["9"]="Pling" + cases["12"]="Pling" + + cases["5"]="Plang" + cases["10"]="Plang" + cases["25"]="Plang" + cases["3125"]="Plang" + + cases["7"]="Plong" + cases["14"]="Plong" + cases["28"]="Plong" + cases["49"]="Plong" + + cases["15"]="PlingPlang" + cases["21"]="PlingPlong" + cases["35"]="PlangPlong" + cases["70"]="PlangPlong" + + cases["105"]="PlingPlangPlong" + cases["210"]="PlingPlangPlong" + cases["945"]="PlingPlangPlong" + + # add exit here to keep it from waiting for input + exit 0 +}