Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 154
Good morning! Here's your coding interview problem for today.

This problem was asked by Amazon.

Implement a stack API using only a heap. A stack implements the following methods:

`push(item)`, which adds an element to the stack
`pop()`, which removes and returns the most recently added element (or throws an error if there is nothing on the stack)
Recall that a heap has the following operations:

`push(item)`, which adds a new key to the heap
`pop()`, which removes and returns the max value of the heap

Pull request description:
Day154
Resolves #320.

Patch:
diff --git a/README.md b/README.md
index 829912a..6c43ed4 100644
--- a/README.md
+++ b/README.md
@@ -163,3 +163,4 @@ problems from
 * [Day 150](https://github.com/vaskoz/dailycodingproblem-go/issues/312)
 * [Day 151](https://github.com/vaskoz/dailycodingproblem-go/issues/313)
 * [Day 153](https://github.com/vaskoz/dailycodingproblem-go/issues/316)
+* [Day 154](https://github.com/vaskoz/dailycodingproblem-go/issues/320)
diff --git a/day154/problem.go b/day154/problem.go
new file mode 100644
index 0000000..a56c2c8
--- /dev/null
+++ b/day154/problem.go
@@ -0,0 +1,45 @@
+package day154
+
+import "container/heap"
+
+// StackHeap is a stack implemented using only a heap.
+// Runs in O(N log N) time.
+// Also contains a flaw with the counter due to overflow.
+type StackHeap struct {
+	heap    maxHeap
+	counter uint64
+}
+
+type item struct {
+	index uint64
+	value interface{}
+}
+
+type maxHeap []item
+
+func (h maxHeap) Len() int           { return len(h) }
+func (h maxHeap) Less(i, j int) bool { return h[i].index > h[j].index }
+func (h maxHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
+
+func (h *maxHeap) Push(x interface{}) {
+	*h = append(*h, x.(item))
+}
+
+func (h *maxHeap) Pop() interface{} {
+	old := *h
+	n := len(old)
+	x := old[n-1].value
+	*h = old[:n-1]
+	return x
+}
+
+// Push adds an element to the stack.
+func (sh *StackHeap) Push(v interface{}) {
+	heap.Push(&sh.heap, item{sh.counter, v})
+	sh.counter++
+}
+
+// Pop removes an element from the stack.
+func (sh *StackHeap) Pop() interface{} {
+	return heap.Pop(&sh.heap)
+}


Test patch:
diff --git a/day154/problem_test.go b/day154/problem_test.go
new file mode 100644
index 0000000..80ea6c1
--- /dev/null
+++ b/day154/problem_test.go
@@ -0,0 +1,39 @@
+package day154
+
+import "testing"
+
+var testcases = []struct {
+	items []interface{}
+}{
+	{[]interface{}{"foo", "bar", 1, 3, 5}},
+	{[]interface{}{10, 20, 30, 15, 30, 55}},
+}
+
+func TestStackHeap(t *testing.T) {
+	t.Parallel()
+	for _, tc := range testcases {
+		var stack StackHeap
+		for i := range tc.items {
+			stack.Push(tc.items[i])
+		}
+		for i := range tc.items {
+			if result := stack.Pop(); result != tc.items[len(tc.items)-1-i] {
+				t.Errorf("Expected %v got %v", tc.items[len(tc.items)-1-i], result)
+			}
+		}
+	}
+}
+
+func BenchmarkStackHeap(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			var stack StackHeap
+			for i := range tc.items {
+				stack.Push(tc.items[i])
+			}
+			for range tc.items {
+				stack.Pop()
+			}
+		}
+	}
+}