Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 374
Good morning! Here's your coding interview problem for today.

This problem was asked by Amazon.

Given a sorted array `arr` of distinct integers, return the lowest index `i` for which `arr[i] == i`. Return `null` if there is no such index.

For example, given the array `[-5, -3, 2, 3]`, return `2` since `arr[2] == 2`. Even though `arr[3] == 3`, we return `2` since it's the lowest index.

Pull request description:
Day374
Resolves #754.

Patch:
diff --git a/README.md b/README.md
index 1f0990d..c615aea 100644
--- a/README.md
+++ b/README.md
@@ -369,4 +369,5 @@ problems from
 * [Day 371](https://github.com/vaskoz/dailycodingproblem-go/issues/750)
 * [Day 372](https://github.com/vaskoz/dailycodingproblem-go/issues/748)
 * [Day 373](https://github.com/vaskoz/dailycodingproblem-go/issues/752)
+* [Day 374](https://github.com/vaskoz/dailycodingproblem-go/issues/754)
 
diff --git a/day374/problem.go b/day374/problem.go
new file mode 100644
index 0000000..b97c1b1
--- /dev/null
+++ b/day374/problem.go
@@ -0,0 +1,38 @@
+package day374
+
+import (
+	"errors"
+	"sort"
+)
+
+var (
+	errNoSuchIndex    = errors.New("no index is a fixed point")
+	errInputNotSorted = errors.New("input is not sorted and must be")
+)
+
+// LowestFixedPoint returns the lowest fixed point index.
+// If no such index exists, it returns an error.
+// Also returns an error if input is not sorted.
+// Runs in O(log N) worst case time thanks to binary search.
+func LowestFixedPoint(sorted []int) (int, error) {
+	if !sort.IntsAreSorted(sorted) {
+		return 0, errInputNotSorted
+	}
+
+	for lo, hi := 0, len(sorted); lo <= hi; {
+		switch mid := (lo + hi) / 2; {
+		case sorted[mid] == mid:
+			if hi-lo == 0 {
+				return mid, nil
+			}
+
+			hi = mid
+		case sorted[mid] < mid:
+			lo = mid + 1
+		default:
+			hi = mid - 1
+		}
+	}
+
+	return 0, errNoSuchIndex
+}


Test patch:
diff --git a/day374/problem_test.go b/day374/problem_test.go
new file mode 100644
index 0000000..b8462cb
--- /dev/null
+++ b/day374/problem_test.go
@@ -0,0 +1,34 @@
+package day374
+
+import "testing"
+
+// nolint
+var testcases = []struct {
+	input       []int
+	expected    int
+	expectedErr error
+}{
+	{[]int{-5, -3, 2, 3}, 2, nil},
+	{[]int{2, 3, -3}, 0, errInputNotSorted},
+	{[]int{-5, -3, 5, 13}, 0, errNoSuchIndex},
+	{[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, 0, nil},
+	{[]int{-15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, 1, 15}, 15, nil},
+}
+
+func TestLowestFixedPoint(t *testing.T) {
+	t.Parallel()
+
+	for _, tc := range testcases {
+		if res, err := LowestFixedPoint(tc.input); res != tc.expected || err != tc.expectedErr {
+			t.Errorf("Expected (%v,%v), got (%v,%v)", tc.expected, tc.expectedErr, res, err)
+		}
+	}
+}
+
+func BenchmarkLowestFixedPoint(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			LowestFixedPoint(tc.input) // nolint
+		}
+	}
+}