UNPKG

agentscape

Version:

Agentscape is a library for creating agent-based simulations. It provides a simple API for defining agents and their behavior, and for defining the environment in which the agents interact. Agentscape is designed to be flexible and extensible, allowing

184 lines (147 loc) 3.9 kB
export class LinkedListNode<T> { constructor( public value: T, public next: LinkedListNode<T> | undefined = undefined, public previous: LinkedListNode<T> | undefined = undefined ) {} } export default class LinkedList<T> { // the element at the start of the list public head: LinkedListNode<T> | undefined = undefined // the element at the end of the list public tail: LinkedListNode<T> | undefined = undefined // the number of elements in the list public size: number = 0 constructor() {} /** * Iterates over the elements of the list */ public *[Symbol.iterator]() { let current = this.head while (current) { yield current current = current.next } } public forEach(callback: (value: LinkedListNode<T>) => void) { let current = this.head while (current) { callback(current) current = current.next } } /** * Inserts an element at the end of the list * @param value */ public append(value: T) { const node = new LinkedListNode(value) if (!this.head) { this.head = node this.tail = node } else { this.tail!.next = node node.previous = this.tail this.tail = node } this.size++ } /** * Inserts an element at the start of the list * @param value */ public prepend(value: T) { const node = new LinkedListNode(value) if (!this.head) { this.head = node this.tail = node } else { this.head.previous = node node.next = this.head this.head = node } this.size++ } /** * Removes the first element from the list */ public dropFirst() { if (!this.head) { return } this.head = this.head.next if (this.head) { this.head.previous = undefined } else { this.tail = undefined } this.size-- } /** * Removes the last element from the list */ public dropLast() { if (!this.tail) { return } this.tail = this.tail.previous if (this.tail) { this.tail.next = undefined } else { this.head = undefined } this.size-- } /** * Inserts an element at a specific location in the list */ public insertAt(index: number, value: T) { if (index < 0 || index > this.size) { throw new Error('Index out of bounds') } if (index === 0) { this.prepend(value) return } if (index === this.size) { this.append(value) return } let current = this.head for (let i = 0; i < index - 1; i++) { current = current!.next } const node = new LinkedListNode(value) node.next = current!.next node.previous = current current!.next!.previous = node current!.next = node this.size++ } public find(value: T) { let current = this.head while (current) { if (current.value === value) { return current } current = current.next } return null } public toArray() { const array: T[] = [] let current = this.head while (current) { array.push(current.value) current = current.next } return array } public static fromArray<T>(array: T[]) { const list = new LinkedList<T>() for (const element of array) { list.append(element) } return list } }