Initial commit
This commit is contained in:
commit
8ae9352aa1
70 changed files with 3898 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
node_modules/
|
||||||
11
README.md
Normal file
11
README.md
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# kata-machine
|
||||||
|
|
||||||
|
Kata machine practice.
|
||||||
|
|
||||||
|
https://frontendmasters.com/courses/algorithms/
|
||||||
|
|
||||||
|
https://github.com/ThePrimeagen/kata-machine
|
||||||
|
|
||||||
|
1. `pnpm install`
|
||||||
|
|
||||||
|
2. `pnpm run test`
|
||||||
20
package.json
Normal file
20
package.json
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"name": "test-kata-machine",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"scripts": {
|
||||||
|
"check": "tsc --noEmit",
|
||||||
|
"test": "vitest",
|
||||||
|
"format": "prettier --write ./src"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"vite": "^7.0.5",
|
||||||
|
"vitest": "^3.2.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"prettier": "^3.6.2",
|
||||||
|
"ts-node": "^10.9.2",
|
||||||
|
"tsconfig-paths": "^4.2.0",
|
||||||
|
"tsconfig-paths-jest": "^0.0.1",
|
||||||
|
"typescript": "^5.8.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
1666
pnpm-lock.yaml
generated
Normal file
1666
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
8
prettier.config.ts
Normal file
8
prettier.config.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
export default {
|
||||||
|
tabWidth: 4,
|
||||||
|
printWidth: 80,
|
||||||
|
proseWrap: "never",
|
||||||
|
trailingComma: "all",
|
||||||
|
singleQuote: false,
|
||||||
|
semi: true,
|
||||||
|
};
|
||||||
101
src/array-test.ts
Normal file
101
src/array-test.ts
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
const a: number[] = [];
|
||||||
|
|
||||||
|
function time(fn: () => void): number {
|
||||||
|
const now = Date.now();
|
||||||
|
fn();
|
||||||
|
return Date.now() - now;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unshift(number: number) {
|
||||||
|
for (let i = 0; i < number; ++i) {
|
||||||
|
a.unshift(Math.random());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function shift(number: number) {
|
||||||
|
for (let i = 0; i < number; ++i) {
|
||||||
|
a.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function push(number: number) {
|
||||||
|
for (let i = 0; i < number; ++i) {
|
||||||
|
a.push(Math.random());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pop(number: number) {
|
||||||
|
for (let i = 0; i < number; ++i) {
|
||||||
|
a.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function get(idx: number) {
|
||||||
|
return function () {
|
||||||
|
return a[idx];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function push_arr(count: number) {
|
||||||
|
return function () {
|
||||||
|
push(count);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function pop_arr(count: number) {
|
||||||
|
return function () {
|
||||||
|
pop(count);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function unshift_arr(count: number) {
|
||||||
|
return function () {
|
||||||
|
unshift(count);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function shift_arr(count: number) {
|
||||||
|
return function () {
|
||||||
|
shift(count);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const tests = [10, 100, 1000, 10000, 100000, 1_000_000, 10_000_000];
|
||||||
|
console.log("Testing get");
|
||||||
|
tests.forEach((t) => {
|
||||||
|
a.length = 0;
|
||||||
|
push(t);
|
||||||
|
console.log(t, time(get(t - 1)));
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("push");
|
||||||
|
tests.forEach((t) => {
|
||||||
|
a.length = 0;
|
||||||
|
push(t);
|
||||||
|
|
||||||
|
console.log(t, time(push_arr(1000)));
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("pop");
|
||||||
|
tests.forEach((t) => {
|
||||||
|
a.length = 0;
|
||||||
|
push(t);
|
||||||
|
|
||||||
|
console.log(t, time(pop_arr(1000)));
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("unshift");
|
||||||
|
tests.forEach((t) => {
|
||||||
|
a.length = 0;
|
||||||
|
push(t);
|
||||||
|
|
||||||
|
console.log(t, time(unshift_arr(1000)));
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("shift");
|
||||||
|
tests.forEach((t) => {
|
||||||
|
a.length = 0;
|
||||||
|
push(t);
|
||||||
|
|
||||||
|
console.log(t, time(shift_arr(1000)));
|
||||||
|
});
|
||||||
7
src/day1/ArrayList.test.ts
Normal file
7
src/day1/ArrayList.test.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import ArrayList from "@code/ArrayList";
|
||||||
|
import { test_list } from "./ListTest";
|
||||||
|
|
||||||
|
test("array-list", function () {
|
||||||
|
const list = new ArrayList<number>(3);
|
||||||
|
test_list(list);
|
||||||
|
});
|
||||||
93
src/day1/ArrayList.ts
Normal file
93
src/day1/ArrayList.ts
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
export default class ArrayList<T> {
|
||||||
|
public length: number;
|
||||||
|
private array: Array<T>;
|
||||||
|
private capacity: number;
|
||||||
|
|
||||||
|
constructor(capacity: number = 5) {
|
||||||
|
this.capacity = capacity;
|
||||||
|
this.array = [];
|
||||||
|
this.array.length = this.capacity;
|
||||||
|
this.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private grow() {
|
||||||
|
const old = this.array;
|
||||||
|
this.capacity *= 2;
|
||||||
|
this.array = [];
|
||||||
|
this.array.length = this.capacity;
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
for (; i < this.length; ++i) {
|
||||||
|
this.array[i] = old[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShiftRight manages the size of the array and shifts everything
|
||||||
|
// from array[idx] one to the right. Creating free space at array[idx].
|
||||||
|
private shiftRight(idx: number) {
|
||||||
|
if (this.length == this.capacity) {
|
||||||
|
this.grow();
|
||||||
|
}
|
||||||
|
|
||||||
|
let i = this.length;
|
||||||
|
for (; i > idx; --i) {
|
||||||
|
this.array[i] = this.array[i - 1];
|
||||||
|
}
|
||||||
|
this.length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShiftLeft manages the size of the array and shifts everything to the
|
||||||
|
// right of array[idx] one to the left. Overwriting array[idx].
|
||||||
|
private ShiftLeft(idx: number) {
|
||||||
|
this.length--;
|
||||||
|
let i = idx;
|
||||||
|
for (; i < this.length; ++i) {
|
||||||
|
this.array[i] = this.array[i + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prepend(item: T): void {
|
||||||
|
this.shiftRight(0);
|
||||||
|
this.array[0] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
insertAt(item: T, idx: number): void {
|
||||||
|
this.shiftRight(idx);
|
||||||
|
this.array[idx] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
append(item: T): void {
|
||||||
|
if (this.length == this.capacity) {
|
||||||
|
this.grow();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.array[this.length] = item;
|
||||||
|
this.length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(item: T): T | undefined {
|
||||||
|
let i = 0;
|
||||||
|
for (; i < this.length; ++i) {
|
||||||
|
if (this.array[i] == item) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// item was not found
|
||||||
|
if (i == this.length) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.removeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(idx: number): T | undefined {
|
||||||
|
return idx >= this.length ? undefined : this.array[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
removeAt(idx: number): T | undefined {
|
||||||
|
const item = this.get(idx);
|
||||||
|
this.ShiftLeft(idx);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/day1/BFSGraphList.test.ts
Normal file
8
src/day1/BFSGraphList.test.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import bfs from "@code/BFSGraphList";
|
||||||
|
import { list2 } from "./graph";
|
||||||
|
|
||||||
|
test("bfs - graph", function () {
|
||||||
|
expect(bfs(list2, 0, 6)).toEqual([0, 1, 4, 5, 6]);
|
||||||
|
|
||||||
|
expect(bfs(list2, 6, 0)).toEqual(null);
|
||||||
|
});
|
||||||
45
src/day1/BFSGraphList.ts
Normal file
45
src/day1/BFSGraphList.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
export default function bfs(
|
||||||
|
graph: WeightedAdjacencyList,
|
||||||
|
source: number,
|
||||||
|
needle: number,
|
||||||
|
): number[] | null {
|
||||||
|
const seen = new Array(graph.length).fill(false);
|
||||||
|
const prev = new Array(graph.length).fill(-1);
|
||||||
|
|
||||||
|
const queue: number[] = [source];
|
||||||
|
seen[source] = true;
|
||||||
|
|
||||||
|
while (queue.length > 0) {
|
||||||
|
const curr = queue.shift() as number;
|
||||||
|
|
||||||
|
if (curr === needle) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const edge of graph[curr]) {
|
||||||
|
const neighbor = edge.to;
|
||||||
|
|
||||||
|
if (seen[neighbor]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
seen[neighbor] = true;
|
||||||
|
prev[neighbor] = curr;
|
||||||
|
queue.push(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!seen[needle]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const path: number[] = [];
|
||||||
|
let curr = needle;
|
||||||
|
|
||||||
|
while (curr !== -1) {
|
||||||
|
path.push(curr);
|
||||||
|
curr = prev[curr];
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.reverse();
|
||||||
|
}
|
||||||
8
src/day1/BFSGraphMatrix.test.ts
Normal file
8
src/day1/BFSGraphMatrix.test.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import bfs from "@code/BFSGraphMatrix";
|
||||||
|
import { matrix2 } from "./graph";
|
||||||
|
|
||||||
|
test("bfs - graph matrix", function () {
|
||||||
|
expect(bfs(matrix2, 0, 6)).toEqual([0, 1, 4, 5, 6]);
|
||||||
|
|
||||||
|
expect(bfs(matrix2, 6, 0)).toEqual(null);
|
||||||
|
});
|
||||||
43
src/day1/BFSGraphMatrix.ts
Normal file
43
src/day1/BFSGraphMatrix.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
export default function bfs(
|
||||||
|
graph: number[][],
|
||||||
|
source: number,
|
||||||
|
needle: number,
|
||||||
|
): number[] | null {
|
||||||
|
const seen = new Array(graph.length).fill(false);
|
||||||
|
const prev = new Array(graph.length).fill(-1);
|
||||||
|
const q: number[] = [source];
|
||||||
|
seen[source] = true;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const curr = q.shift() as number;
|
||||||
|
|
||||||
|
if (curr === needle) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const adjs = graph[curr];
|
||||||
|
for (let i = 0; i < graph.length; i++) {
|
||||||
|
if (adjs[i] === 0 || seen[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
seen[i] = true;
|
||||||
|
prev[i] = curr;
|
||||||
|
q.push(i);
|
||||||
|
}
|
||||||
|
} while (q.length);
|
||||||
|
|
||||||
|
if (prev[needle] === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let curr = needle;
|
||||||
|
const out: number[] = [];
|
||||||
|
|
||||||
|
while (prev[curr] !== -1) {
|
||||||
|
out.push(curr);
|
||||||
|
curr = prev[curr];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [source].concat(out.reverse());
|
||||||
|
}
|
||||||
8
src/day1/BTBFS.test.ts
Normal file
8
src/day1/BTBFS.test.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import bfs from "@code/BTBFS";
|
||||||
|
import { tree } from "./tree";
|
||||||
|
|
||||||
|
test("bt bfs", function () {
|
||||||
|
expect(bfs(tree, 45)).toEqual(true);
|
||||||
|
expect(bfs(tree, 7)).toEqual(true);
|
||||||
|
expect(bfs(tree, 69)).toEqual(false);
|
||||||
|
});
|
||||||
20
src/day1/BTBFS.ts
Normal file
20
src/day1/BTBFS.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
export default function bfs(head: BinaryNode<number>, needle: number): boolean {
|
||||||
|
const q: (BinaryNode<number> | null)[] = [head];
|
||||||
|
|
||||||
|
while (q.length) {
|
||||||
|
const curr = q.shift() as BinaryNode<number> | undefined | null;
|
||||||
|
if (!curr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search
|
||||||
|
if (curr.value === needle) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
q.push(curr.left);
|
||||||
|
q.push(curr.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
6
src/day1/BTInOrder.test.ts
Normal file
6
src/day1/BTInOrder.test.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import bt_in_order from "@code/BTInOrder";
|
||||||
|
import { tree } from "./tree";
|
||||||
|
|
||||||
|
test("In order", function () {
|
||||||
|
expect(bt_in_order(tree)).toEqual([5, 7, 10, 15, 20, 29, 30, 45, 50, 100]);
|
||||||
|
});
|
||||||
17
src/day1/BTInOrder.ts
Normal file
17
src/day1/BTInOrder.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
function walk(curr: BinaryNode<number> | null, path: number[]): number[] {
|
||||||
|
if (!curr) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recurse
|
||||||
|
walk(curr.left, path);
|
||||||
|
path.push(curr.value);
|
||||||
|
walk(curr.right, path);
|
||||||
|
|
||||||
|
// post
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function in_order_search(head: BinaryNode<number>): number[] {
|
||||||
|
return walk(head, []);
|
||||||
|
}
|
||||||
8
src/day1/BTPostOrder.test.ts
Normal file
8
src/day1/BTPostOrder.test.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import bt_post_order from "@code/BTPostOrder";
|
||||||
|
import { tree } from "./tree";
|
||||||
|
|
||||||
|
test("post order", function () {
|
||||||
|
expect(bt_post_order(tree)).toEqual([
|
||||||
|
7, 5, 15, 10, 29, 45, 30, 100, 50, 20,
|
||||||
|
]);
|
||||||
|
});
|
||||||
17
src/day1/BTPostOrder.ts
Normal file
17
src/day1/BTPostOrder.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
function walk(curr: BinaryNode<number> | null, path: number[]): number[] {
|
||||||
|
if (!curr) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recurse
|
||||||
|
walk(curr.left, path);
|
||||||
|
walk(curr.right, path);
|
||||||
|
|
||||||
|
// post
|
||||||
|
path.push(curr.value);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function post_order_search(head: BinaryNode<number>): number[] {
|
||||||
|
return walk(head, []);
|
||||||
|
}
|
||||||
6
src/day1/BTPreOrder.test.ts
Normal file
6
src/day1/BTPreOrder.test.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import bt_pre_order from "@code/BTPreOrder";
|
||||||
|
import { tree } from "./tree";
|
||||||
|
|
||||||
|
test("Pre order", function () {
|
||||||
|
expect(bt_pre_order(tree)).toEqual([20, 10, 5, 7, 15, 50, 30, 29, 45, 100]);
|
||||||
|
});
|
||||||
19
src/day1/BTPreOrder.ts
Normal file
19
src/day1/BTPreOrder.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
function walk(curr: BinaryNode<number> | null, path: number[]): number[] {
|
||||||
|
if (!curr) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pre
|
||||||
|
path.push(curr.value);
|
||||||
|
|
||||||
|
// recurse
|
||||||
|
walk(curr.left, path);
|
||||||
|
walk(curr.right, path);
|
||||||
|
|
||||||
|
// post
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function pre_order_search(head: BinaryNode<number>): number[] {
|
||||||
|
return walk(head, []);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue