Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 29
Good morning! Here's your coding interview problem for today.

This problem was asked by Amazon.

Run-length encoding is a fast and simple method of encoding strings. The basic idea is to represent repeated successive characters as a single count and character. For example, the string "AAAABBBCCDAA" would be encoded as "4A3B2C1D2A".

Implement run-length encoding and decoding. You can assume the string to be encoded have no digits and consists solely of alphabetic characters. You can assume the string to be decoded is valid.

Pull request description:
Day29
Resolves #67 

Patch:
diff --git a/README.md b/README.md
index 57c1d48..b465c34 100644
--- a/README.md
+++ b/README.md
@@ -42,3 +42,4 @@ problems from
 * [Day 26](https://github.com/vaskoz/dailycodingproblem-go/issues/61)
 * [Day 27](https://github.com/vaskoz/dailycodingproblem-go/issues/63)
 * [Day 28](https://github.com/vaskoz/dailycodingproblem-go/issues/65)
+* [Day 29](https://github.com/vaskoz/dailycodingproblem-go/issues/67)
diff --git a/day29/problem.go b/day29/problem.go
new file mode 100644
index 0000000..c520166
--- /dev/null
+++ b/day29/problem.go
@@ -0,0 +1,49 @@
+package day29
+
+import (
+	"strconv"
+	"strings"
+)
+
+// RunLengthEncoding takes a string of runes [A-Z] and encodes it using run-length.
+func RunLengthEncoding(str string) string {
+	var sb strings.Builder
+	var count int
+	var last rune
+	for i, r := range str {
+		if i == 0 {
+			count++
+			last = r
+			continue
+		} else if r == last {
+			count++
+		} else {
+			sb.WriteString(strconv.Itoa(count))
+			sb.WriteString(string(last))
+			count = 1
+			last = r
+		}
+	}
+	sb.WriteString(strconv.Itoa(count))
+	sb.WriteString(string(last))
+	return sb.String()
+}
+
+// RunLengthDecoding takes a run-length encoding and returns the original string.
+func RunLengthDecoding(str string) string {
+	var sb strings.Builder
+	var count int
+	for _, r := range str {
+		if r >= 'A' && r <= 'Z' {
+			sb.WriteString(strings.Repeat(string(r), count))
+			count = 0
+		} else {
+			if count != 0 {
+				count *= 10
+			}
+			digit, _ := strconv.Atoi(string(r))
+			count += digit
+		}
+	}
+	return sb.String()
+}


Test patch:
diff --git a/day29/problem_test.go b/day29/problem_test.go
new file mode 100644
index 0000000..f04f100
--- /dev/null
+++ b/day29/problem_test.go
@@ -0,0 +1,30 @@
+package day29
+
+import "testing"
+
+var testcases = []struct {
+	orig, encoded string
+}{
+	{"AAAABBBCCDAA", "4A3B2C1D2A"},
+	{"AAAAAAAAAAA", "11A"},
+}
+
+func TestRunLength(t *testing.T) {
+	for _, tc := range testcases {
+		var enc string
+		if enc = RunLengthEncoding(tc.orig); enc != tc.encoded {
+			t.Errorf("Expected %v but got %v", tc.encoded, enc)
+		}
+		if dec := RunLengthDecoding(enc); dec != tc.orig {
+			t.Errorf("Expected %v but got %v", tc.orig, dec)
+		}
+	}
+}
+
+func BenchmarkRunLength(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			RunLengthDecoding(RunLengthEncoding(tc.orig))
+		}
+	}
+}