From 770bfb1f2eec42d1c0430f0da02df83a4827df47 Mon Sep 17 00:00:00 2001 From: Lyss Date: Sat, 20 Jul 2024 15:10:56 +0200 Subject: [PATCH] Add queue --- package.json | 2 +- src/lib/datastructure.test.ts | 50 +++++++++++++++++++++++++++++++++++ src/lib/datastructure.ts | 42 +++++++++++++++++++++++++++++ src/lib/index.ts | 4 ++- 4 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/lib/datastructure.test.ts create mode 100644 src/lib/datastructure.ts diff --git a/package.json b/package.json index 4f0c0ba..229eaf1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@selenite/commons", - "version": "0.8.5", + "version": "0.9.0", "scripts": { "dev": "npm run wasm && vite dev", "wasm": "wasm-pack build ./selenite-commons-rs --target web", diff --git a/src/lib/datastructure.test.ts b/src/lib/datastructure.test.ts new file mode 100644 index 0000000..85e341a --- /dev/null +++ b/src/lib/datastructure.test.ts @@ -0,0 +1,50 @@ +import { describe, test, expect } from 'vitest'; +import { Queue } from './datastructure'; + +describe('datastructures', () => { + describe('queue', () => { + test('queue sizes should be valid', () => { + const queue = new Queue() + expect(queue.size).toBe(0) + queue.add(1) + expect(queue.size).toBe(1) + queue.add(2) + expect(queue.size).toBe(2) + queue.remove() + expect(queue.size).toBe(1) + queue.remove() + expect(queue.size).toBe(0) + }) + test('should be FIFO', () => { + const queue = new Queue([1, 2, 3]); + let res: number[] = []; + let c = 0 + while (queue.size > 0) { + c++ + if (c > 3) { + throw new Error("Too many iterations.") + } + res.push(queue.remove()); + } + expect(res).toEqual([1, 2, 3]); + }); + test('should error on peek empty queue', () => { + const queue = new Queue(); + expect(() => queue.peek()).toThrowError("Can't peek, queue is empty."); + }); + test('should error on remove empty queue', () => { + const queue = new Queue(); + expect(() => queue.remove()).toThrowError("Can't remove an element, queue is empty."); + }) + test('peek should return first element without changing queue', () => { + const queue = new Queue([1, 2, 3]); + expect(queue.peek()).toBe(1); + expect(queue.size).toBe(3); + }); + test('pop should remove first element and return it', () => { + const queue = new Queue([1, 2, 3]); + expect(queue.remove()).toBe(1); + expect(queue.size).toBe(2); + }); + }); +}); diff --git a/src/lib/datastructure.ts b/src/lib/datastructure.ts new file mode 100644 index 0000000..63c76af --- /dev/null +++ b/src/lib/datastructure.ts @@ -0,0 +1,42 @@ +export class Queue { + #inStack: T[] = []; + #outStack: T[] = []; + + constructor(iterable?: Iterable) { + if (iterable) this.#inStack.push(...iterable); + } + + add(e: T) { + this.#inStack.push(e); + } + + peek(): T { + this.handleEmptyOut("Can't peek, queue is empty.") + return this.#outStack.at(-1)!; + } + + remove(): T { + this.handleEmptyOut("Can't remove an element, queue is empty."); + return this.#outStack.pop()!; + } + + private handleEmptyOut(errMsg: string) { + if (this.#outStack.length === 0) { + this.swapStacks(); + } + if (this.#outStack.length === 0) { + throw new Error(errMsg); + } + } + + get size() { + return this.#inStack.length + this.#outStack.length; + } + + private swapStacks() { + let mem = this.#outStack; + this.#outStack = this.#inStack; + this.#inStack = mem; + this.#outStack.reverse(); + } +} diff --git a/src/lib/index.ts b/src/lib/index.ts index 026a1c3..26615a3 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -25,4 +25,6 @@ export * from './actions/index.js' export * as Utils from './utils' export * from './utils/index.js' export * as Types from './type' -export * from './type' \ No newline at end of file +export * from './type' +export * as DataStructure from './datastructure' +export * from './datastructure' \ No newline at end of file