Hone logo
Hone
Problems

Generic Data Structure: Stack

Generic programming allows us to write code that can operate on different data types without being rewritten for each type. Go 1.18 introduced generics, enabling this powerful feature. This challenge asks you to implement a generic stack data structure in Go, demonstrating your understanding of type parameters and constraints.

Problem Description

You are tasked with creating a generic Stack data structure in Go. The stack should support the following operations:

  • Push(value interface{}): Adds a new element to the top of the stack.
  • Pop(): Removes and returns the element at the top of the stack. Returns nil if the stack is empty.
  • Peek(): Returns the element at the top of the stack without removing it. Returns nil if the stack is empty.
  • IsEmpty(): Returns true if the stack is empty, false otherwise.
  • Size(): Returns the number of elements in the stack.

The stack should be generic, meaning it can hold elements of any type. You'll need to define a Stack type that uses type parameters to achieve this. Consider how to handle potential type assertions when popping or peeking.

Examples

Example 1:

Input:
stack := NewStack[int]()
stack.Push(1)
stack.Push(2)
stack.Push(3)

Output:
3
Explanation:
Peek() returns the top element (3) without removing it.

Example 2:

Input:
stack := NewStack[string]()
stack.Push("hello")
stack.Push("world")

Output:
"world"
Explanation:
Pop() removes and returns the top element ("world").

Example 3:

Input:
stack := NewStack[float64]()
stack.Push(3.14)
stack.Push(2.71)
stack.Pop()
stack.Pop()

Output:
nil
Explanation:
After popping both elements, the stack is empty, so Pop() returns nil.

Constraints

  • The stack should be implemented using a slice.
  • The Push operation should have a time complexity of O(1).
  • The Pop, Peek, IsEmpty, and Size operations should have a time complexity of O(1).
  • The stack should handle empty stack conditions gracefully by returning nil for Pop and Peek.
  • The type parameter T should be constrained to be comparable. This is not strictly required for the basic functionality, but it's a good practice for potential future extensions (e.g., sorting the stack).

Notes

  • You'll need to define a NewStack function that creates a new Stack instance with a specified type parameter.
  • Consider using interfaces to allow the stack to hold any type. However, be mindful of type assertions when retrieving values.
  • Think about how to handle potential panics if you attempt to pop or peek from an empty stack. Returning nil is the preferred approach.
  • While not explicitly required, consider adding a Clear() method to remove all elements from the stack. This can be a useful addition to the data structure.
  • The interface{} type allows for any type to be stored, but you'll need to use type assertions when retrieving values to use them with their original type. This is a key aspect of working with generics in Go.
Loading editor...
go