Created
March 3, 2024 13:07
-
-
Save EmilyGraceSeville7cf/de6eb89986a40a5ccaa2e5d40da6cad4 to your computer and use it in GitHub Desktop.
Linked list based stack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"fmt" | |
"os" | |
"github.com/fatih/color" | |
) | |
type Node[T any] struct { | |
value T | |
next *Node[T] | |
} | |
type Stack[T any] struct { | |
head *Node[T] | |
count int | |
} | |
func nilValueMessage(name string) string { | |
return fmt.Sprintf("not nil %s expected", name) | |
} | |
func emptyDataStructureMessage(name string) string { | |
return fmt.Sprintf("not empty %s expected", name) | |
} | |
func lessThanMessage(limit int, name string) string { | |
return fmt.Sprintf("not less than %d %s expected", limit, name) | |
} | |
func newNode[T any](value T) *Node[T] { | |
return &Node[T]{value: value} | |
} | |
func newNodeWithNext[T any](value T, next *Node[T]) *Node[T] { | |
return &Node[T]{value: value, next: next} | |
} | |
func newStack[T any]() *Stack[T] { | |
return &Stack[T]{count: 0} | |
} | |
func (stack *Stack[T]) push(value T) error { | |
stack.head = newNodeWithNext(value, stack.head) | |
stack.count++ | |
return nil | |
} | |
func Default[T any]() T { | |
return *new(T) | |
} | |
func (stack *Stack[T]) pop() (T, error) { | |
if stack.count == 0 { | |
return Default[T](), errors.New(emptyDataStructureMessage("stack")) | |
} | |
value := stack.head.value | |
stack.head = stack.head.next | |
stack.count-- | |
return value, nil | |
} | |
func (stack *Stack[T]) peek() (T, error) { | |
if stack.count == 0 { | |
return Default[T](), errors.New(emptyDataStructureMessage("stack")) | |
} | |
return stack.head.value, nil | |
} | |
func (stack *Stack[T]) String() string { | |
if stack == nil { | |
return "" | |
} | |
current := stack.head | |
representation := "[" | |
for current != nil { | |
representation += fmt.Sprint(current.value) | |
if current.next != nil { | |
representation += ", " | |
} | |
current = current.next | |
} | |
representation += "]" | |
return representation | |
} | |
type Handler func(*Stack[string], ...string) | |
type Command struct { | |
description string | |
handler Handler | |
argumentCount int | |
} | |
func newCommand(description string, handler Handler) (*Command, error) { | |
if handler == nil { | |
return nil, errors.New(nilValueMessage("handler")) | |
} | |
return &Command{description: description, handler: handler}, nil | |
} | |
func newCommandWithArgumentCount(description string, handler Handler, argumentCount int) (*Command, error) { | |
command, err := newCommand(description, handler) | |
if err != nil { | |
return nil, err | |
} | |
if argumentCount < 0 { | |
return nil, errors.New(lessThanMessage(0, "argumentCount")) | |
} | |
command.argumentCount = argumentCount | |
return command, nil | |
} | |
func handleArguments(args []string) { | |
var stack = newStack[string]() | |
pushCommand, _ := newCommandWithArgumentCount("Push new item", func(stack *Stack[string], args ...string) { | |
stack.push(args[0]) | |
}, 1) | |
popCommand, _ := newCommandWithArgumentCount("Pop the last added item", func(stack *Stack[string], args ...string) { | |
stack.pop() | |
}, 0) | |
peekCommand, _ := newCommandWithArgumentCount("Peek the last added item", func(stack *Stack[string], args ...string) { | |
stack.peek() | |
}, 0) | |
commands := make(map[string]*Command) | |
commands["--push"] = pushCommand | |
commands["--pop"] = popCommand | |
commands["--peek"] = peekCommand | |
for i := 0; i < len(args); i++ { | |
arg := args[i] | |
command, exists := commands[arg] | |
if !exists { | |
color.Red("expected known command %s", arg) | |
os.Exit(1) | |
} | |
var commandArgs []string | |
for j := 0; j < command.argumentCount; j++ { | |
i++ | |
if i >= len(args) { | |
color.Red("expected argument for %s", arg) | |
os.Exit(1) | |
} | |
commandArgs = append(commandArgs, args[i]) | |
} | |
command.handler(stack, commandArgs...) | |
color.Red(command.description) | |
color.Yellow("%s", stack) | |
} | |
} | |
func main() { | |
var args = os.Args[1:] | |
if len(args) > 0 { | |
handleArguments(args) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment