Search Apps Documentation Source Content File Folder Download Copy Actions Download

stack.gno

3.56 Kb · 113 lines
  1// Package stack is an educational data-structure playground that keeps BOTH a
  2// LIFO stack and a FIFO queue of ints, so you can compare how the two behave.
  3package stack
  4
  5import (
  6	"chain"
  7	"strconv"
  8	"strings"
  9)
 10
 11// stackData holds the LIFO stack; the last pushed element is the "top".
 12var stackData []int
 13
 14// queueData holds the FIFO queue; the oldest enqueued element is the "front".
 15var queueData []int
 16
 17// Push adds n to the top of the LIFO stack.
 18func Push(cur realm, n int) {
 19	stackData = append(stackData, n)
 20	chain.Emit("Push", "n", strconv.Itoa(n), "size", strconv.Itoa(len(stackData)))
 21}
 22
 23// Pop removes and returns the top element of the LIFO stack.
 24// It panics (a cross-realm abort) if the stack is empty.
 25func Pop(cur realm) int {
 26	if len(stackData) == 0 {
 27		panic("stack is empty: nothing to pop")
 28	}
 29	last := len(stackData) - 1
 30	n := stackData[last]
 31	stackData = stackData[:last]
 32	chain.Emit("Pop", "n", strconv.Itoa(n), "size", strconv.Itoa(len(stackData)))
 33	return n
 34}
 35
 36// Enqueue adds n to the back of the FIFO queue.
 37func Enqueue(cur realm, n int) {
 38	queueData = append(queueData, n)
 39	chain.Emit("Enqueue", "n", strconv.Itoa(n), "size", strconv.Itoa(len(queueData)))
 40}
 41
 42// Dequeue removes and returns the front element of the FIFO queue.
 43// It panics (a cross-realm abort) if the queue is empty.
 44func Dequeue(cur realm) int {
 45	if len(queueData) == 0 {
 46		panic("queue is empty: nothing to dequeue")
 47	}
 48	n := queueData[0]
 49	queueData = queueData[1:]
 50	chain.Emit("Dequeue", "n", strconv.Itoa(n), "size", strconv.Itoa(len(queueData)))
 51	return n
 52}
 53
 54// StackSize returns the number of elements in the LIFO stack.
 55func StackSize() int { return len(stackData) }
 56
 57// QueueSize returns the number of elements in the FIFO queue.
 58func QueueSize() int { return len(queueData) }
 59
 60// renderInts formats a slice of ints as a space-separated list, e.g. "1 2 3".
 61func renderInts(xs []int) string {
 62	if len(xs) == 0 {
 63		return "_(empty)_"
 64	}
 65	parts := make([]string, len(xs))
 66	for i, x := range xs {
 67		parts[i] = strconv.Itoa(x)
 68	}
 69	return "`" + strings.Join(parts, " ") + "`"
 70}
 71
 72// Render returns a Markdown view of both structures with top/front labeled,
 73// their sizes, and a one-line explanation of LIFO vs FIFO.
 74func Render(path string) string {
 75	var b strings.Builder
 76
 77	b.WriteString("# Stack & Queue Playground\n\n")
 78	b.WriteString("A **stack** is LIFO (last in, first out) — the last item pushed is the first popped. ")
 79	b.WriteString("A **queue** is FIFO (first in, first out) — the first item enqueued is the first dequeued.\n\n")
 80
 81	b.WriteString("## Stack (LIFO) — size ")
 82	b.WriteString(strconv.Itoa(len(stackData)))
 83	b.WriteString("\n\n")
 84	b.WriteString("Contents (bottom → top): ")
 85	b.WriteString(renderInts(stackData))
 86	b.WriteString("\n\n")
 87	if len(stackData) > 0 {
 88		b.WriteString("Top: `")
 89		b.WriteString(strconv.Itoa(stackData[len(stackData)-1]))
 90		b.WriteString("` — the next `Pop` returns this.\n\n")
 91	} else {
 92		b.WriteString("Top: _(none)_ — `Pop` would panic.\n\n")
 93	}
 94
 95	b.WriteString("## Queue (FIFO) — size ")
 96	b.WriteString(strconv.Itoa(len(queueData)))
 97	b.WriteString("\n\n")
 98	b.WriteString("Contents (front → back): ")
 99	b.WriteString(renderInts(queueData))
100	b.WriteString("\n\n")
101	if len(queueData) > 0 {
102		b.WriteString("Front: `")
103		b.WriteString(strconv.Itoa(queueData[0]))
104		b.WriteString("` — the next `Dequeue` returns this.\n\n")
105	} else {
106		b.WriteString("Front: _(none)_ — `Dequeue` would panic.\n\n")
107	}
108
109	b.WriteString("---\n\n")
110	b.WriteString("_Tip: push the same sequence into both, then Pop vs Dequeue to see LIFO reverse it while FIFO preserves order._\n")
111
112	return b.String()
113}