···11+import ArrayList from "@code/ArrayList";
22+import { test_list } from "./ListTest";
33+44+test("array-list", function () {
55+ const list = new ArrayList<number>(3);
66+ test_list(list);
77+});
+93
src/day1/ArrayList.ts
···11+export default class ArrayList<T> {
22+ public length: number;
33+ private array: Array<T>;
44+ private capacity: number;
55+66+ constructor(capacity: number = 5) {
77+ this.capacity = capacity;
88+ this.array = [];
99+ this.array.length = this.capacity;
1010+ this.length = 0;
1111+ }
1212+1313+ private grow() {
1414+ const old = this.array;
1515+ this.capacity *= 2;
1616+ this.array = [];
1717+ this.array.length = this.capacity;
1818+1919+ let i = 0;
2020+ for (; i < this.length; ++i) {
2121+ this.array[i] = old[i];
2222+ }
2323+ }
2424+2525+ // ShiftRight manages the size of the array and shifts everything
2626+ // from array[idx] one to the right. Creating free space at array[idx].
2727+ private shiftRight(idx: number) {
2828+ if (this.length == this.capacity) {
2929+ this.grow();
3030+ }
3131+3232+ let i = this.length;
3333+ for (; i > idx; --i) {
3434+ this.array[i] = this.array[i - 1];
3535+ }
3636+ this.length++;
3737+ }
3838+3939+ // ShiftLeft manages the size of the array and shifts everything to the
4040+ // right of array[idx] one to the left. Overwriting array[idx].
4141+ private ShiftLeft(idx: number) {
4242+ this.length--;
4343+ let i = idx;
4444+ for (; i < this.length; ++i) {
4545+ this.array[i] = this.array[i + 1];
4646+ }
4747+ }
4848+4949+ prepend(item: T): void {
5050+ this.shiftRight(0);
5151+ this.array[0] = item;
5252+ }
5353+5454+ insertAt(item: T, idx: number): void {
5555+ this.shiftRight(idx);
5656+ this.array[idx] = item;
5757+ }
5858+5959+ append(item: T): void {
6060+ if (this.length == this.capacity) {
6161+ this.grow();
6262+ }
6363+6464+ this.array[this.length] = item;
6565+ this.length++;
6666+ }
6767+6868+ remove(item: T): T | undefined {
6969+ let i = 0;
7070+ for (; i < this.length; ++i) {
7171+ if (this.array[i] == item) {
7272+ break;
7373+ }
7474+ }
7575+7676+ // item was not found
7777+ if (i == this.length) {
7878+ return undefined;
7979+ }
8080+8181+ return this.removeAt(i);
8282+ }
8383+8484+ get(idx: number): T | undefined {
8585+ return idx >= this.length ? undefined : this.array[idx];
8686+ }
8787+8888+ removeAt(idx: number): T | undefined {
8989+ const item = this.get(idx);
9090+ this.ShiftLeft(idx);
9191+ return item;
9292+ }
9393+}
+8
src/day1/BFSGraphList.test.ts
···11+import bfs from "@code/BFSGraphList";
22+import { list2 } from "./graph";
33+44+test("bfs - graph", function () {
55+ expect(bfs(list2, 0, 6)).toEqual([0, 1, 4, 5, 6]);
66+77+ expect(bfs(list2, 6, 0)).toEqual(null);
88+});
···11+export default function bs_list(haystack: number[], needle: number): boolean {
22+ let lo = 0;
33+ let hi = haystack.length;
44+55+ while (lo < hi) {
66+ const m = Math.floor(lo + (hi - lo) / 2);
77+ const v = haystack[m];
88+99+ if (v === needle) {
1010+ return true;
1111+ } else if (v > needle) {
1212+ hi = m;
1313+ } else {
1414+ lo = m + 1;
1515+ }
1616+ }
1717+1818+ return false;
1919+}
···11+import LinkedList from "@code/DoublyLinkedList";
22+import { test_list } from "./ListTest";
33+44+test("DoublyLinkedList", function () {
55+ const list = new LinkedList<number>();
66+ test_list(list);
77+});
···11+import insertion_sort from "@code/InsertionSort";
22+33+test("insertion-sort", function () {
44+ const arr = [9, 3, 7, 4, 69, 420, 42];
55+ debugger;
66+ // where is my debugger
77+ insertion_sort(arr);
88+ expect(arr).toEqual([3, 4, 7, 9, 42, 69, 420]);
99+});
+13
src/day1/InsertionSort.ts
···11+export default function insertion_sort(arr: number[]): void {
22+ for (let i = 1; i < arr.length; i++) {
33+ const key = arr[i];
44+ let j = i - 1;
55+66+ while (j >= 0 && arr[j] > key) {
77+ arr[j + 1] = arr[j];
88+ j--;
99+ }
1010+1111+ arr[j + 1] = key;
1212+ }
1313+}
+27
src/day1/LRU.test.ts
···11+import LRU from "@code/LRU";
22+33+test("LRU", function () {
44+ const lru = new LRU<string, number>(3) as ILRU<string, number>;
55+66+ expect(lru.get("foo")).toEqual(undefined);
77+ lru.update("foo", 69);
88+ expect(lru.get("foo")).toEqual(69);
99+1010+ lru.update("bar", 420);
1111+ expect(lru.get("bar")).toEqual(420);
1212+1313+ lru.update("baz", 1337);
1414+ expect(lru.get("baz")).toEqual(1337);
1515+1616+ lru.update("ball", 69420);
1717+ expect(lru.get("ball")).toEqual(69420);
1818+ expect(lru.get("foo")).toEqual(undefined);
1919+ expect(lru.get("bar")).toEqual(420);
2020+ lru.update("foo", 69);
2121+ expect(lru.get("bar")).toEqual(420);
2222+ expect(lru.get("foo")).toEqual(69);
2323+2424+ // shouldn't of been deleted, but since bar was get'd, bar was added to the
2525+ // front of the list, so baz became the end
2626+ expect(lru.get("baz")).toEqual(undefined);
2727+});
+105
src/day1/LRU.ts
···11+type Node<T> = {
22+ value: T;
33+ prev?: Node<T>;
44+ next?: Node<T>;
55+};
66+77+function createNode<V>(value: V): Node<V> {
88+ return { value };
99+}
1010+1111+export default class LRU<K, V> {
1212+ private length: number;
1313+ private capacity: number;
1414+ private head?: Node<V>;
1515+ private tail?: Node<V>;
1616+ private lookup: Map<K, Node<V>>;
1717+ private reverseLookup: Map<Node<V>, K>;
1818+1919+ constructor(capacity: number) {
2020+ this.length = 0;
2121+ this.capacity = capacity;
2222+ this.head = this.tail = undefined;
2323+ this.lookup = new Map<K, Node<V>>();
2424+ this.reverseLookup = new Map<Node<V>, K>();
2525+ }
2626+2727+ update(key: K, value: V): void {
2828+ // check the cache for existence
2929+ let node = this.lookup.get(key);
3030+ if (!node) {
3131+ node = createNode(value);
3232+ this.length++;
3333+ this.prepend(node);
3434+ this.trimCache();
3535+3636+ this.lookup.set(key, node);
3737+ this.reverseLookup.set(node, key);
3838+ } else {
3939+ this.detach(node);
4040+ this.prepend(node);
4141+ node.value = value;
4242+ }
4343+ }
4444+4545+ get(key: K): V | undefined {
4646+ // check the cache for existence
4747+ const node = this.lookup.get(key);
4848+ if (!node) {
4949+ return undefined;
5050+ }
5151+5252+ // update the value we found and move it to the front
5353+ this.detach(node);
5454+ this.prepend(node);
5555+5656+ // return out the value found
5757+ return node.value;
5858+ }
5959+6060+ private detach(node: Node<V>): void {
6161+ if (node.prev) {
6262+ node.prev.next = node.next;
6363+ }
6464+6565+ if (node.next) {
6666+ node.next.prev = node.prev;
6767+ }
6868+6969+ if (this.head === node) {
7070+ this.head = this.head.next;
7171+ }
7272+7373+ if (this.tail === node) {
7474+ this.tail = this.tail.prev;
7575+ }
7676+7777+ node.next = undefined;
7878+ node.prev = undefined;
7979+ }
8080+8181+ private prepend(node: Node<V>): void {
8282+ if (!this.head) {
8383+ this.head = this.tail = node;
8484+ return;
8585+ }
8686+8787+ node.next = this.head;
8888+ this.head.prev = node;
8989+ this.head = node;
9090+ }
9191+9292+ private trimCache(): void {
9393+ if (this.length <= this.capacity) {
9494+ return;
9595+ }
9696+9797+ const tail = this.tail as Node<V>;
9898+ this.detach(this.tail as Node<V>);
9999+100100+ const key = this.reverseLookup.get(tail) as K;
101101+ this.lookup.delete(key);
102102+ this.reverseLookup.delete(tail);
103103+ this.length--;
104104+ }
105105+}
···11+export default function prims(
22+ list: WeightedAdjacencyList,
33+): WeightedAdjacencyList | null {
44+ const n = list.length;
55+ if (n === 0) {
66+ return null;
77+ }
88+99+ const inMST = new Array(n).fill(false);
1010+ const mst: WeightedAdjacencyList = Array.from({ length: n }, () => []);
1111+1212+ const minEdge: { to: number; from: number; weight: number }[] = new Array(
1313+ n,
1414+ ).fill(null as any);
1515+ minEdge[0] = { to: 0, from: -1, weight: 0 };
1616+1717+ for (let i = 0; i < n; i++) {
1818+ let u = -1;
1919+2020+ for (let v = 0; v < n; v++) {
2121+ if (
2222+ !inMST[v] &&
2323+ (u === -1 ||
2424+ (minEdge[v] && minEdge[v].weight < minEdge[u].weight))
2525+ ) {
2626+ u = v;
2727+ }
2828+ }
2929+3030+ if (u === -1 || minEdge[u] === null) {
3131+ return null;
3232+ }
3333+3434+ inMST[u] = true;
3535+3636+ const edge = minEdge[u];
3737+ if (edge.from !== -1) {
3838+ mst[edge.from].push({ to: u, weight: edge.weight });
3939+ mst[u].push({ to: edge.from, weight: edge.weight });
4040+ }
4141+4242+ for (const neighbor of list[u]) {
4343+ if (
4444+ !inMST[neighbor.to] &&
4545+ (!minEdge[neighbor.to] ||
4646+ neighbor.weight < minEdge[neighbor.to].weight)
4747+ ) {
4848+ minEdge[neighbor.to] = {
4949+ to: neighbor.to,
5050+ from: u,
5151+ weight: neighbor.weight,
5252+ };
5353+ }
5454+ }
5555+ }
5656+5757+ return mst;
5858+}
+30
src/day1/PrimsList.test.ts
···11+import prims from "@code/PrimsAlgorithm";
22+import { list1 } from "./graph";
33+44+test("PrimsAlgorithm", function () {
55+ // there is only one right answer for this graph
66+ expect(prims(list1)).toEqual([
77+ [
88+ { to: 2, weight: 1 },
99+ { to: 1, weight: 3 },
1010+ ],
1111+ [
1212+ { to: 0, weight: 3 },
1313+ { to: 4, weight: 1 },
1414+ ],
1515+ [{ to: 0, weight: 1 }],
1616+ [{ to: 6, weight: 1 }],
1717+ [
1818+ { to: 1, weight: 1 },
1919+ { to: 5, weight: 2 },
2020+ ],
2121+ [
2222+ { to: 4, weight: 2 },
2323+ { to: 6, weight: 1 },
2424+ ],
2525+ [
2626+ { to: 5, weight: 1 },
2727+ { to: 3, weight: 1 },
2828+ ],
2929+ ]);
3030+});
+31
src/day1/Queue.test.ts
···11+import Queue from "@code/Queue";
22+33+test("queue", function () {
44+ const list = new Queue<number>();
55+66+ list.enqueue(5);
77+ list.enqueue(7);
88+ list.enqueue(9);
99+1010+ expect(list.deque()).toEqual(5);
1111+ expect(list.length).toEqual(2);
1212+1313+ // this must be wrong..?
1414+ debugger;
1515+1616+ // i hate using debuggers
1717+ list.enqueue(11);
1818+ debugger;
1919+ expect(list.deque()).toEqual(7);
2020+ expect(list.deque()).toEqual(9);
2121+ expect(list.peek()).toEqual(11);
2222+ expect(list.deque()).toEqual(11);
2323+ expect(list.deque()).toEqual(undefined);
2424+ expect(list.length).toEqual(0);
2525+2626+ // just wanted to make sure that I could not blow up myself when i remove
2727+ // everything
2828+ list.enqueue(69);
2929+ expect(list.peek()).toEqual(69);
3030+ expect(list.length).toEqual(1);
3131+});
···11+import SinglyLinkedList from "@code/SinglyLinkedList";
22+import { test_list } from "./ListTest";
33+44+test("linked-list", function () {
55+ const list = new SinglyLinkedList<number>();
66+ test_list(list);
77+});
+138
src/day1/SinglyLinkedList.ts
···11+class Node<T> {
22+ public value: T;
33+ public next?: Node<T>;
44+55+ constructor(t: T) {
66+ this.value = t;
77+ }
88+}
99+1010+export default class SinglyLinkedList<T> {
1111+ public length: number;
1212+ public head?: Node<T>;
1313+ public tail?: Node<T>;
1414+1515+ constructor() {
1616+ this.length = 0;
1717+ this.head = undefined;
1818+ }
1919+2020+ prepend(item: T): void {
2121+ let node = new Node<T>(item);
2222+ if (this.head != null) {
2323+ node.next = this.head;
2424+ }
2525+ this.head = node;
2626+ this.length++;
2727+ }
2828+2929+ insertAt(item: T, idx: number): void {
3030+ let current_node = this.head;
3131+ let i = 0;
3232+3333+ while (current_node?.next != null && i < idx) {
3434+ current_node = current_node.next;
3535+ i += 1;
3636+ }
3737+3838+ if (current_node?.next != null) {
3939+ let node = new Node<T>(item);
4040+ node.next = current_node.next;
4141+ current_node.next = node;
4242+ this.length++;
4343+ }
4444+ }
4545+4646+ append(item: T): void {
4747+ if (this.length == 0) {
4848+ let node = new Node<T>(item);
4949+ this.head = node;
5050+ this.length++;
5151+ return;
5252+ }
5353+5454+ let current_node = this.head;
5555+5656+ while (current_node?.next != null) {
5757+ current_node = current_node.next;
5858+ }
5959+6060+ if (current_node != null) {
6161+ let node = new Node<T>(item);
6262+ current_node.next = node;
6363+ this.length++;
6464+ }
6565+ }
6666+6767+ remove(item: T): T | undefined {
6868+ let current_node = this.head;
6969+ let prev_node = this.head;
7070+ let node_to_remove = null;
7171+7272+ while (current_node != null) {
7373+ if (current_node.value === item) {
7474+ node_to_remove = current_node;
7575+ break;
7676+ }
7777+ prev_node = current_node;
7878+ current_node = current_node.next;
7979+ }
8080+8181+ if (node_to_remove == this.head) {
8282+ this.head = node_to_remove.next;
8383+ this.length--;
8484+ } else if (prev_node?.next != null) {
8585+ prev_node.next = node_to_remove?.next;
8686+ this.length--;
8787+ }
8888+8989+ return current_node?.value;
9090+ }
9191+9292+ get(idx: number): T | undefined {
9393+ let current_node = this.head;
9494+ let i = 0;
9595+9696+ while (current_node != null && i < idx) {
9797+ current_node = current_node.next;
9898+ i += 1;
9999+ }
100100+101101+ return current_node?.value;
102102+ }
103103+104104+ removeAt(idx: number): T | undefined {
105105+ let current_node = this.head;
106106+107107+ if (idx == 0 && current_node != null) {
108108+ this.head = current_node.next;
109109+ this.length--;
110110+ return current_node.value;
111111+ }
112112+113113+ let i = 0;
114114+ while (current_node?.next != null && i < idx - 1) {
115115+ current_node = current_node.next;
116116+ i += 1;
117117+ }
118118+119119+ if (current_node?.next != null) {
120120+ let node_to_remove = current_node.next;
121121+ current_node.next = node_to_remove.next;
122122+ this.length--;
123123+ return node_to_remove.value;
124124+ }
125125+126126+ return undefined;
127127+ }
128128+129129+ debug() {
130130+ let current_node = this.head;
131131+ let result = "";
132132+ while (current_node != null) {
133133+ result += ` ${current_node.value},`;
134134+ current_node = current_node.next;
135135+ }
136136+ console.log(result);
137137+ }
138138+}
+25
src/day1/Stack.test.ts
···11+import Stack from "@code/Stack";
22+33+test("stack", function () {
44+ const list = new Stack<number>();
55+66+ list.push(5);
77+ list.push(7);
88+ list.push(9);
99+1010+ expect(list.pop()).toEqual(9);
1111+ expect(list.length).toEqual(2);
1212+1313+ list.push(11);
1414+ expect(list.pop()).toEqual(11);
1515+ expect(list.pop()).toEqual(7);
1616+ expect(list.peek()).toEqual(5);
1717+ expect(list.pop()).toEqual(5);
1818+ expect(list.pop()).toEqual(undefined);
1919+2020+ // just wanted to make sure that I could not blow up myself when i remove
2121+ // everything
2222+ list.push(69);
2323+ expect(list.peek()).toEqual(69);
2424+ expect(list.length).toEqual(1);
2525+});