From 93052abe7ca69d2adb4ed66bbe77b193f92ba12d Mon Sep 17 00:00:00 2001 From: Patrick Marabeas Date: Thu, 4 Jul 2019 15:05:26 +1000 Subject: [PATCH] Add numeronyms functionality Implemented numeronym functionality in a executable Go program which returns a slice of numeronyms given an input of n strings Closes Lab 04 (#419) --- 04_numeronym/patrickmarabeas/main.go | 33 +++++++++ 04_numeronym/patrickmarabeas/main_test.go | 84 +++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 04_numeronym/patrickmarabeas/main.go create mode 100644 04_numeronym/patrickmarabeas/main_test.go diff --git a/04_numeronym/patrickmarabeas/main.go b/04_numeronym/patrickmarabeas/main.go new file mode 100644 index 000000000..07cf62e71 --- /dev/null +++ b/04_numeronym/patrickmarabeas/main.go @@ -0,0 +1,33 @@ +package main + +import ( + "fmt" + "io" + "os" +) + +var out io.Writer = os.Stdout + +// GenerateNumeronym creates a numeronym from the given string. +func generateNumeronym(s string) string { + // Convert to runes to handle multi byte characters + runes := []rune(s) + length := len(runes) + if length < 4 { + return string(runes) + } + return fmt.Sprintf("%c%d%c", runes[0], length-2, runes[length-1]) +} + +// Numeronyms takes an input of n strings and returns a slice containing each string's numeronym. +func numeronyms(vals ...string) []string { + result := make([]string, len(vals)) + for i, numeronym := range vals { + result[i] = generateNumeronym(numeronym) + } + return result +} + +func main() { + fmt.Fprint(out, numeronyms("accessibility", "Kubernetes", "abc")) +} diff --git a/04_numeronym/patrickmarabeas/main_test.go b/04_numeronym/patrickmarabeas/main_test.go new file mode 100644 index 000000000..bc4ae1274 --- /dev/null +++ b/04_numeronym/patrickmarabeas/main_test.go @@ -0,0 +1,84 @@ +package main + +import ( + "bytes" + "fmt" + "testing" +) + +func TestMainOutput(t *testing.T) { + var buf bytes.Buffer + out = &buf + + main() + + expected := "[a11y K8s abc]" + got := buf.String() + + t.Run("Main function", func(t *testing.T) { + if expected != got { + t.Errorf("\nExpected: %s\nGot: %s", expected, got) + } + }) +} + +func TestGenerateNumeronym(t *testing.T) { + var cases = map[string]struct { + input string + expected string + }{ + "Lowercase": { + input: "lowercase", + expected: "l7e", + }, + "Uppercase": { + input: "Uppercase", + expected: "U7e", + }, + "Three letters": { + input: "abc", + expected: "abc", + }, + "Two letters": { + input: "ab", + expected: "ab", + }, + "Single letter": { + input: "a", + expected: "a", + }, + "": { + input: "😚😚😚😚😚😚", + expected: "😚4😚", + }, + "Empty": { + input: "", + expected: "", + }, + } + + for name, c := range cases { + got, expected := generateNumeronym(c.input), c.expected + t.Run(name, func(t *testing.T) { + if got != expected { + t.Errorf("\nExpected: %s\nGot: %s", expected, got) + } + }) + } +} + +func TestNumeronyms(t *testing.T) { + test := numeronyms("lowercase", "Uppercase") + expected := []string{"l7e", "U7e"} + + for i, got := range test { + // Lint error: Using the variable on range scope `got` / `i` in function literal + i := i + got := got + t.Run(fmt.Sprintf("String of index %d", i), func(t *testing.T) { + if got != expected[i] { + t.Errorf("\nExpected: %s\nGot: %s", expected[i], got) + } + }) + } +}