Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 43
Good morning! Here's your coding interview problem for today.

This problem was asked by Amazon.

Implement a stack that has the following methods:

`push(val)`, which pushes an element onto the stack
`pop()`, which pops off and returns the topmost element of the stack. If there are no elements in the stack, then it should throw an error or return null.
`max()`, which returns the maximum value in the stack currently. If there are no elements in the stack, then it should throw an error or return null.

_Each method should run in constant time._

Pull request:
Day43
Resolves #95 .

Patch:
diff --git a/README.md b/README.md
index 543982e..bdf2a7c 100644
--- a/README.md
+++ b/README.md
@@ -55,3 +55,4 @@ problems from
 * [Day 40](https://github.com/vaskoz/dailycodingproblem-go/issues/87)
 * [Day 41](https://github.com/vaskoz/dailycodingproblem-go/issues/90)
 * [Day 42](https://github.com/vaskoz/dailycodingproblem-go/issues/93)
+* [Day 43](https://github.com/vaskoz/dailycodingproblem-go/issues/95)
diff --git a/day43/problem.go b/day43/problem.go
new file mode 100644
index 0000000..a880e22
--- /dev/null
+++ b/day43/problem.go
@@ -0,0 +1,56 @@
+package day43
+
+import "fmt"
+
+var errStackEmpty = fmt.Errorf("Stack is empty")
+
+// maxIntStack is implemented using O(N) extra memory.
+type maxIntStack struct {
+	stack []int
+}
+
+// MaxIntStack represents that API of a stack of ints that push, pop and find the max value.
+type MaxIntStack interface {
+	Push(val int)
+	Pop() (int, error)
+	Max() (int, error)
+}
+
+// NewMaxIntStack returns a new instance.
+func NewMaxIntStack() MaxIntStack {
+	return &maxIntStack{}
+}
+
+func (mis *maxIntStack) Push(val int) {
+	var max int
+	if len(mis.stack) == 0 {
+		max = val
+	} else {
+		max = mis.stack[len(mis.stack)-2]
+		if val > max {
+			max = val
+		}
+	}
+	mis.stack = append(mis.stack, max, val)
+}
+
+func (mis *maxIntStack) Pop() (int, error) {
+	if len(mis.stack) == 0 {
+		return 0, StackEmptyError()
+	}
+	var result int
+	result, mis.stack = mis.stack[len(mis.stack)-1], mis.stack[:len(mis.stack)-2]
+	return result, nil
+}
+
+func (mis *maxIntStack) Max() (int, error) {
+	if len(mis.stack) == 0 {
+		return 0, StackEmptyError()
+	}
+	return mis.stack[len(mis.stack)-2], nil
+}
+
+// StackEmptyError returns the instance of the error representing an empty stack.
+func StackEmptyError() error {
+	return errStackEmpty
+}


Test patch:
diff --git a/day43/problem_test.go b/day43/problem_test.go
new file mode 100644
index 0000000..bb9f895
--- /dev/null
+++ b/day43/problem_test.go
@@ -0,0 +1,53 @@
+package day43
+
+import "testing"
+
+var testcases = []struct {
+	input []int
+	max   []int
+}{
+	{[]int{1, 2, 3, 4, 5, 6}, []int{1, 2, 3, 4, 5, 6}},
+}
+
+func TestMaxIntStack(t *testing.T) {
+	t.Parallel()
+	for tcid, tc := range testcases {
+		stack := NewMaxIntStack()
+		for i, push := range tc.input {
+			stack.Push(push)
+			if max, err := stack.Max(); err != nil || max != tc.max[i] {
+				t.Errorf("TC%d push expected,got max (%d,%d) error should be nil (%v)",
+					tcid, tc.max[i], max, err)
+			}
+		}
+		for i := range tc.input {
+			if max, err := stack.Max(); err != nil || max != tc.max[len(tc.max)-1-i] {
+				t.Errorf("TC%d pre-pop expected,got max (%d,%d) error should be nil (%v)",
+					tcid, tc.max[len(tc.max)-1-i], max, err)
+			}
+			if val, err := stack.Pop(); err != nil || val != tc.input[len(tc.input)-1-i] {
+				t.Errorf("TC%d pop expected,got val (%d,%d) error should be nil (%v)",
+					tcid, tc.input[len(tc.input)-1-i], val, err)
+			}
+		}
+		if _, err := stack.Pop(); err != StackEmptyError() {
+			t.Errorf("Stack should be empty and return an error on Pop()")
+		}
+		if _, err := stack.Max(); err != StackEmptyError() {
+			t.Errorf("Stack should be empty and return an error on Max()")
+		}
+	}
+}
+
+func BenchmarkMaxIntStack(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			stack := NewMaxIntStack()
+			for _, push := range tc.input {
+				stack.Push(push)
+				stack.Max()
+				stack.Pop()
+			}
+		}
+	}
+}