From 5762dbe643ae91b6feda418fd23155c7e8e3c4bd Mon Sep 17 00:00:00 2001 From: kalrnlo Date: Mon, 5 Aug 2024 13:47:26 -0400 Subject: [PATCH] Somehow I made an oopsies by overwriting the init file for linkedlist to its test file... --- libs/linkedlist/init.luau | 171 ++++++++++++++++++++++++++- libs/linkedlist/linkedlist.test.luau | 8 ++ 2 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 libs/linkedlist/linkedlist.test.luau diff --git a/libs/linkedlist/init.luau b/libs/linkedlist/init.luau index 5f075cf..27a989e 100644 --- a/libs/linkedlist/init.luau +++ b/libs/linkedlist/init.luau @@ -1,8 +1,169 @@ -local testkit = require("../../testkit") -local linkedlist = require("linkedlist") +--!native -local TEST, CASE, CHECK, FINISH = testkit.test() +-- linked list +-- a doubly-linked list impl in luau, easily inserts and deletes arbitrarily without reordering. +-- a reference to the entry to insert or delete at is required. References to the front and back of +-- the list always exist. +-- originally made by last talon, uh heavily modified by me (kalrnlo) because im a nitpicker +-- w a changed up api to directly expose the nodes and also not create a new closure +-- for every node created +-- og: https://github.com/LastTalon/linked-list -TEST("linked list", function() +type NodePrototype = { + __call: (self: Node) -> V, +} -end) +export type Node = typeof(setmetatable({} :: { + next: Node?, + prev: Node?, + value: V, +}, {} :: NodePrototype)) + + +export type LinkedList = { + front: Node?, + back: Node?, + len: number, +} + +local function remove_node(list: LinkedList, node: Node): V + local prev_node = node.prev + local next_node = node.next + + if prev_node then + prev_node.next = next_node + else + list.front = next_node + end + + if next_node then + next_node.prev = prev_node + else + list.back = prev_node + end + list.len -= 1 + return node.value +end + +local node_mt = table.freeze({ + __call = function(node: Node): V + return node.value + end, +}) + +local function create_node(value: V): Node + return setmetatable({ + value = value, + next = nil, + prev = nil + }, node_mt) :: any +end + +local linkedlist = {} + +function linkedlist.push(list: LinkedList, value: V) + local node = create_node(value) + local back = list.back + + node.prev = back + + if back then + back.next = node + else + list.front = node + end + list.back = node + list.len += 1 + + return node +end + +function linkedlist.unshift(list: LinkedList, value: V): Node + local node = create_node(value) + local front = list.front + + node.next = front + + if front then + front.prev = node + else + list.back = node + end + list.front = node + + return node +end + +function linkedlist.shift(list: LinkedList): Node? + local node = list.front + + if node then + remove_node(list, node) + return node + else + return nil + end +end + +function linkedlist.pop(list: LinkedList): Node? + local node = list.back + + if node then + remove_node(list, node) + return node + else + return nil + end +end + +function linkedlist.iter(list: LinkedList): () -> (number, Node) + local node = list.front + local index = 0 + + return function() + if not node then + return nil :: any, nil :: any + end + + local current_node = node + node = node.next + index += 1 + return index, current_node + end +end + +function linkedlist.reverse_iter(list: LinkedList): () -> (number, Node) + local node = list.back + local index = list.len + 1 + + return function() + if not node then + return nil :: any, nil :: any + end + + local current = node + node = node.prev + index -= 1 + return index, current + end +end + +function linkedlist.clear(list: LinkedList) + list.front = nil + list.back = nil + list.len = 0 +end + +linkedlist.remove = remove_node + +local list_mt = { + __call = function(self: S): LinkedList + return { + front = nil, + back = nil, + len = 0, + } + end +} + +return table.freeze(setmetatable(linkedlist, table.freeze(list_mt))) \ No newline at end of file diff --git a/libs/linkedlist/linkedlist.test.luau b/libs/linkedlist/linkedlist.test.luau new file mode 100644 index 0000000..b7b577a --- /dev/null +++ b/libs/linkedlist/linkedlist.test.luau @@ -0,0 +1,8 @@ +local testkit = require("../../testkit") +local linkedlist = require("init") + +local TEST, CASE, CHECK, FINISH = testkit.test() + +TEST("linked list", function() + +end)