feat: implement stack
This commit is contained in:
parent
e3ada19976
commit
7885da4e29
6 changed files with 168 additions and 12 deletions
11
manifest.toml
Normal file
11
manifest.toml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# This file was generated by Gleam
|
||||||
|
# You typically do not need to edit this file
|
||||||
|
|
||||||
|
packages = [
|
||||||
|
{ name = "gleam_stdlib", version = "0.40.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "86606B75A600BBD05E539EB59FABC6E307EEEA7B1E5865AFB6D980A93BCB2181" },
|
||||||
|
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[requirements]
|
||||||
|
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
|
||||||
|
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
|
|
@ -1,5 +0,0 @@
|
||||||
import gleam/io
|
|
||||||
|
|
||||||
pub fn main() {
|
|
||||||
io.println("Hello from fortheck!")
|
|
||||||
}
|
|
4
src/fortheck/error.gleam
Normal file
4
src/fortheck/error.gleam
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
pub type Error {
|
||||||
|
StackOverflow
|
||||||
|
StackUnderflow
|
||||||
|
}
|
61
src/fortheck/stack.gleam
Normal file
61
src/fortheck/stack.gleam
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import fortheck/error.{type Error, StackOverflow, StackUnderflow}
|
||||||
|
import gleam/bool
|
||||||
|
import gleam/list
|
||||||
|
import gleam/result
|
||||||
|
|
||||||
|
pub opaque type Stack(a) {
|
||||||
|
Stack(capacity: Int, length: Int, data: List(a))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() -> Stack(a) {
|
||||||
|
Stack(131_072, 0, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_list(list: List(a)) -> Result(Stack(a), Error) {
|
||||||
|
list.try_fold(over: list, from: new(), with: push)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_list(stack: Stack(a)) -> List(a) {
|
||||||
|
list.reverse(stack.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(onto stack: Stack(a), this item: a) -> Result(Stack(a), Error) {
|
||||||
|
use <- bool.guard(
|
||||||
|
when: stack.length >= stack.capacity,
|
||||||
|
return: Error(StackOverflow),
|
||||||
|
)
|
||||||
|
|
||||||
|
Ok(Stack(..stack, length: stack.length + 1, data: [item, ..stack.data]))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop(from stack: Stack(a)) -> Result(#(a, Stack(a)), Error) {
|
||||||
|
case stack.data {
|
||||||
|
[] -> Error(StackUnderflow)
|
||||||
|
[x, ..xs] -> Ok(#(x, Stack(..stack, length: stack.length - 1, data: xs)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_pop(
|
||||||
|
from stack: Stack(a),
|
||||||
|
apply fun: fn(a, Stack(a)) -> Result(b, Error),
|
||||||
|
) -> Result(b, Error) {
|
||||||
|
use #(item, stack) <- result.try(pop(from: stack))
|
||||||
|
|
||||||
|
fun(item, stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_2(from stack: Stack(a)) -> Result(#(#(a, a), Stack(a)), Error) {
|
||||||
|
use b, stack <- try_pop(from: stack)
|
||||||
|
use a, stack <- try_pop(from: stack)
|
||||||
|
|
||||||
|
Ok(#(#(a, b), stack))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_pop_2(
|
||||||
|
from stack: Stack(a),
|
||||||
|
apply fun: fn(a, a, Stack(a)) -> Result(b, Error),
|
||||||
|
) -> Result(b, Error) {
|
||||||
|
use #(#(a, b), stack) <- result.try(pop_2(from: stack))
|
||||||
|
|
||||||
|
fun(a, b, stack)
|
||||||
|
}
|
|
@ -1,12 +1,5 @@
|
||||||
import gleeunit
|
import gleeunit
|
||||||
import gleeunit/should
|
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
gleeunit.main()
|
gleeunit.main()
|
||||||
}
|
}
|
||||||
|
|
||||||
// gleeunit test functions end in `_test`
|
|
||||||
pub fn hello_world_test() {
|
|
||||||
1
|
|
||||||
|> should.equal(1)
|
|
||||||
}
|
|
||||||
|
|
92
test/stack_test.gleam
Normal file
92
test/stack_test.gleam
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
import fortheck/error
|
||||||
|
import fortheck/stack
|
||||||
|
import gleam/iterator
|
||||||
|
import gleam/pair
|
||||||
|
import gleam/result
|
||||||
|
import gleeunit
|
||||||
|
import gleeunit/should
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
gleeunit.main()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_test() {
|
||||||
|
stack.new()
|
||||||
|
|> stack.to_list
|
||||||
|
|> should.equal([])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_test() {
|
||||||
|
stack.new()
|
||||||
|
|> stack.push(123)
|
||||||
|
|> should.be_ok
|
||||||
|
|> stack.push(456)
|
||||||
|
|> should.be_ok
|
||||||
|
|> stack.to_list
|
||||||
|
|> should.equal([123, 456])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_stack_overflow_test() {
|
||||||
|
iterator.range(1, 131_072)
|
||||||
|
|> iterator.try_fold(stack.new(), stack.push)
|
||||||
|
|> should.be_ok
|
||||||
|
|> stack.push(1)
|
||||||
|
|> should.be_error
|
||||||
|
|> should.equal(error.StackOverflow)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_list_test() {
|
||||||
|
[123, 456]
|
||||||
|
|> stack.from_list
|
||||||
|
|> should.be_ok
|
||||||
|
|> stack.to_list
|
||||||
|
|> should.equal([123, 456])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_stack_underflow_test() {
|
||||||
|
stack.new()
|
||||||
|
|> stack.pop
|
||||||
|
|> should.be_error
|
||||||
|
|> should.equal(error.StackUnderflow)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_test() {
|
||||||
|
let assert Ok(stack) = stack.from_list([1, 2, 3])
|
||||||
|
|
||||||
|
stack
|
||||||
|
|> stack.pop
|
||||||
|
|> should.be_ok
|
||||||
|
|> pair.first
|
||||||
|
|> should.equal(3)
|
||||||
|
|
||||||
|
{
|
||||||
|
use a, _ <- stack.try_pop(stack)
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|> should.be_ok
|
||||||
|
|> should.equal(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_2_test() {
|
||||||
|
let assert Ok(stack) = stack.from_list([1, 2, 3])
|
||||||
|
|
||||||
|
stack
|
||||||
|
|> stack.pop_2
|
||||||
|
|> should.be_ok
|
||||||
|
|> pair.first
|
||||||
|
|> should.equal(#(2, 3))
|
||||||
|
|
||||||
|
{
|
||||||
|
use a, b, _ <- stack.try_pop_2(stack)
|
||||||
|
Ok(#(a, b))
|
||||||
|
}
|
||||||
|
|> should.be_ok
|
||||||
|
|> should.equal(#(2, 3))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_2_stack_underflow_test() {
|
||||||
|
stack.from_list([1])
|
||||||
|
|> result.try(stack.pop_2)
|
||||||
|
|> should.be_error
|
||||||
|
|> should.equal(error.StackUnderflow)
|
||||||
|
}
|
Loading…
Reference in a new issue