diff --git a/awk/README.md b/awk/README.md index 234e1f73..9c2c28b1 100644 --- a/awk/README.md +++ b/awk/README.md @@ -21,3 +21,4 @@ - [darts](./darts/README.md) - [luhn](./luhn/README.md) - [series](./series/README.md) +- [atbash-cipher](./atbash-cipher/README.md) diff --git a/awk/atbash-cipher/README.md b/awk/atbash-cipher/README.md index d2a94b75..91eaedb4 100644 --- a/awk/atbash-cipher/README.md +++ b/awk/atbash-cipher/README.md @@ -39,4 +39,11 @@ All text will be encoded as lowercase letters. ### Based on -Wikipedia - https://en.wikipedia.org/wiki/Atbash \ No newline at end of file +Wikipedia - https://en.wikipedia.org/wiki/Atbash + +### My Solution + +- [my solution](./atbash-cipher.awk) +- [awkunit tests](./atbash-cipher_test.awk) +- [test cases](./test-cases.awk) +- [run-tests](./run-tests-awk.txt) diff --git a/awk/atbash-cipher/atbash-cipher.awk b/awk/atbash-cipher/atbash-cipher.awk index 2980831b..09a76600 100644 --- a/awk/atbash-cipher/atbash-cipher.awk +++ b/awk/atbash-cipher/atbash-cipher.awk @@ -1,7 +1,65 @@ +#!/usr/bin/gawk --lint --file + # These variables are initialized on the command line (using '-v'): -# -direction +# # -direction + +function series(input) { + arg_count = split(input, args, ":") + + if (arg_count != 2) { + return "wrong number of arguments" + } + + span_length = args[1] + number_sequence = args[2] + + number_count = split(number_sequence, numbers, "") + + # could also test to make sure that length(sequence) == count + if (number_count == 0) { + # should be "sequence should have at least one number in it" + return "error: series cannot be empty" + } + + if (span_length <= 0) { + # should be "span length needs to be greater than 0" + return "error: invalid length" + } + + if (span_length > length(number_sequence)) { + # should be "span length can't be larger than sequence length" + return "error: invalid length" + } + + span_sequence = "" + + for (i = 1; i <= (length(input) - span_length - 1); i++) { + span = substr(number_sequence, i, span_length) + + if (length(span_sequence) == 0) { + span_sequence = span + } else { + span_sequence = span_sequence " " span + } + } + + return span_sequence +} BEGIN { - print "Implement this solution" > "/dev/stderr" - exit 1 +} + +{ + result = series(len":"$0) + + if (match(result, /^error: /)) { + _ = split(result, part, ":") + print part[2] + exit 1 + } + + print result +} + +END { } diff --git a/awk/atbash-cipher/atbash-cipher_test.awk b/awk/atbash-cipher/atbash-cipher_test.awk new file mode 100644 index 00000000..5ce07e88 --- /dev/null +++ b/awk/atbash-cipher/atbash-cipher_test.awk @@ -0,0 +1,75 @@ +#!/usr/bin/gawk --lint --file + +@include "awkunit" +@include "test-cases" +@include "atbash-cipher" + +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 testAtbashCipher_zero() { + input = "" + want = "" + + # _ = split(input, a, " ") + + _debugTestPre() + got = atbashCipher(input) + + assertEquals(got, want) + _debugTestPost() +} + +function casesAtbashCipher() { + 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 = atbashCipher(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 + testAtbashCipher_zero() + + # running tests with reduced duplication + casesAtbashCipher() + + print "\n" passed " out of " testCount " tests passed!" + + # add exit here to keep it from looping + exit 0 +} diff --git a/awk/atbash-cipher/awkunit.awk b/awk/atbash-cipher/awkunit.awk new file mode 120000 index 00000000..38a08adf --- /dev/null +++ b/awk/atbash-cipher/awkunit.awk @@ -0,0 +1 @@ +../.lib/awkunit.awk \ No newline at end of file diff --git a/awk/atbash-cipher/test-cases.awk b/awk/atbash-cipher/test-cases.awk new file mode 100644 index 00000000..97fd28b5 --- /dev/null +++ b/awk/atbash-cipher/test-cases.awk @@ -0,0 +1,34 @@ +#!/usr/bin/gawk --lint --file +# test-cases.awk + +# key: input +# value: output + +BEGIN { + encode_cases[""]="" # wow, this works with a warning + encode_cases["abcdefghijklmnopqrstuvwxyz"]="zyxwvutsrqponmlkjihgfedcba" + encode_cases["test"]="gvhg" + encode_cases["x123 yes"]="c123b vh" + encode_cases["yes"]="bvh" + encode_cases["no"]="ml" + encode_cases["OMG"]="lnt" + encode_cases["O M G"]="lnt" + encode_cases["mindblowingly"]="nrmwy oldrm tob" + encode_cases["Testing,1 2 3, testing."]="gvhgr mt123 gvhgr mt" + encode_cases["Truth is fiction."]="gifgs rhurx grlm" + encode_cases["The quick brown fox jumps over"]="gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt" + + decode_cases[""]="" # wow, this works with a warning + decode_cases["zyxwvutsrqponmlkjihgfedcba"]="abcdefghijklmnopqrstuvwxyz" + decode_cases["gvhg"]="test" + decode_cases["c123b vh"]="x123 yes" + decode_cases["vcvix rhn"]="exercism" + decode_cases["zmlyh gzxov rhlug vmzhg vkkrm thglm v"]="anobstacleisoftenasteppingstone" + decode_cases["gvhgr mt123 gvhgr mt"]="testing123testing" + decode_cases["gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt"]="thequickbrownfoxjumpsoverthelazydog" + decode_cases["vc vix r hn"]="exercism" + decode_cases["zmlyhgzxovrhlugvmzhgvkkrmthglmv"]="anobstacleisoftenasteppingstone" + + # add exit here to keep it from waiting for input + exit 0 +}