Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 288
Good morning! Here's your coding interview problem for today.

This problem was asked by Salesforce.

The number **6174** is known as **Kaprekar's constant**, after the mathematician who discovered an associated property: for all four-digit numbers with at least two distinct digits, repeatedly applying a simple procedure eventually results in this value. The procedure is as follows:

For a given input x, create two new numbers that consist of the digits in x in ascending and descending order.
Subtract the smaller number from the larger number.
For example, this algorithm terminates in three steps when starting from `1234`:
```
4321 - 1234 = 3087
8730 - 0378 = 8352
8532 - 2358 = 6174
```
Write a function that returns how many steps this will take for a given input N.

Pull request:
Day288
Resolves #590.

Patch:
diff --git a/README.md b/README.md
index 1f6b4f7..462f3a6 100644
--- a/README.md
+++ b/README.md
@@ -297,3 +297,4 @@ problems from
 * [Day 285](https://github.com/vaskoz/dailycodingproblem-go/issues/583)
 * [Day 286](https://github.com/vaskoz/dailycodingproblem-go/issues/585)
 * [Day 287](https://github.com/vaskoz/dailycodingproblem-go/issues/587)
+* [Day 288](https://github.com/vaskoz/dailycodingproblem-go/issues/590)
diff --git a/day288/problem.go b/day288/problem.go
new file mode 100644
index 0000000..7143f48
--- /dev/null
+++ b/day288/problem.go
@@ -0,0 +1,62 @@
+package day288
+
+import (
+	"errors"
+	"reflect"
+	"sort"
+)
+
+var errInvalidInput = errors.New("only 4 digit positive numbers allowed")
+
+// ErrInvalidInput returns the error associated with invalid input.
+func ErrInvalidInput() error {
+	return errInvalidInput
+}
+
+// KaprekarConstantIterations returns the number of iterations required to
+// reach Kaprekar's constant using Kaprekar's routine.
+func KaprekarConstantIterations(num int) (int, error) {
+	if num < 1 || num > 9999 {
+		return 0, ErrInvalidInput()
+	}
+	digits := convertIntToSlice(num)
+	iterations := 0
+	kaprekarsConstant := []int{6, 1, 7, 4}
+	last := make([]int, 4)
+	for !reflect.DeepEqual(digits, kaprekarsConstant) {
+		if reflect.DeepEqual(last, digits) {
+			return 0, ErrInvalidInput()
+		}
+		desc := make([]int, 4)
+		asc := make([]int, 4)
+		copy(desc, digits)
+		copy(asc, digits)
+		sort.Sort(sort.Reverse(sort.IntSlice(desc)))
+		sort.Ints(asc)
+		result := convertSliceToInt(desc) - convertSliceToInt(asc)
+		digits = convertIntToSlice(result)
+		iterations++
+	}
+	return iterations, nil
+}
+
+func convertSliceToInt(digits []int) int {
+	pow := 1000
+	var result int
+	for _, digit := range digits {
+		result += digit * pow
+		pow /= 10
+	}
+	return result
+}
+
+func convertIntToSlice(num int) []int {
+	digits := make([]int, 4)
+	pos := 3
+	for num != 0 {
+		digits[pos] = num % 10
+		num /= 10
+		pos--
+	}
+	return digits
+}


Test patch:
diff --git a/day288/problem_test.go b/day288/problem_test.go
new file mode 100644
index 0000000..967b6f3
--- /dev/null
+++ b/day288/problem_test.go
@@ -0,0 +1,36 @@
+package day288
+
+import "testing"
+
+// nolint
+var testcases = []struct {
+	num        int
+	iterations int
+	err        error
+}{
+	{1234, 3, nil},
+	{0, 0, ErrInvalidInput()},
+	{1111, 0, ErrInvalidInput()},
+	{4352, 3, nil},
+	{9999, 0, ErrInvalidInput()},
+	{12, 3, nil},
+	{2111, 5, nil},
+	{104, 7, nil},
+}
+
+func TestKaprekarConstantIterations(t *testing.T) {
+	t.Parallel()
+	for _, tc := range testcases {
+		if iterations, err := KaprekarConstantIterations(tc.num); iterations != tc.iterations || err != tc.err {
+			t.Errorf("Expected (%v,%v), got (%v,%v)", tc.iterations, tc.err, iterations, err)
+		}
+	}
+}
+
+func BenchmarkKaprekarConstantIterations(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			KaprekarConstantIterations(tc.num) // nolint
+		}
+	}
+}