JSR?
This commit is contained in:
25 files changed
+186
-94
No files matched your search
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"discord.enabled": false
|
||||
}
|
||||
+4
-4
@@ -46,7 +46,7 @@ export class EventStream<T> implements AsyncIterable<T> {
|
||||
this.#promise = new Promise(r => this.#resolve = r)
|
||||
}
|
||||
|
||||
async*[Symbol.asyncIterator]() {
|
||||
async*[Symbol.asyncIterator](): AsyncGenerator<Awaited<T>, void, undefined> {
|
||||
while (!this.#done) {
|
||||
await this.#promise
|
||||
yield* this.#events
|
||||
@@ -74,7 +74,7 @@ export class EventStream<T> implements AsyncIterable<T> {
|
||||
* const click = stream.once(ev => ev.type === 'click')
|
||||
* @since 2021-12-22
|
||||
*/
|
||||
once(predicate: (value: T) => boolean) {
|
||||
once(predicate: (value: T) => boolean): Promise<Awaited<T> | undefined> {
|
||||
return once(this, predicate)
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ export class EventStream<T> implements AsyncIterable<T> {
|
||||
* @author MindfulMinun
|
||||
* @since 2024-06-02
|
||||
*/
|
||||
each(callback: (value: T) => void) {
|
||||
each(callback: (value: T) => void): Promise<void> {
|
||||
return each(this, callback)
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,7 @@ export class EventStream<T> implements AsyncIterable<T> {
|
||||
* const click = once(stream, ev => ev.type === 'click')
|
||||
* @since 2021-12-22
|
||||
*/
|
||||
export async function once<T>(source: AsyncIterable<T>, predicate: (value: T) => boolean) {
|
||||
export async function once<T>(source: AsyncIterable<T>, predicate: (value: T) => boolean): Promise<T | undefined> {
|
||||
for await (const value of source) {
|
||||
if (predicate(value)) return value
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/// <reference lib="dom" />
|
||||
// <reference lib="dom" />
|
||||
import { templateNoop, HTML_ESCAPES, xss } from "./string.ts"
|
||||
|
||||
export { HTML_ESCAPES }
|
||||
|
||||
+5
-2
@@ -61,7 +61,7 @@ export function* range(a: number, b?: number, c?: number) {
|
||||
* @author MindfulMinun
|
||||
* @since 2022-07-07
|
||||
*/
|
||||
export function* limit<T>(count: number, iterable: Iterable<T>) {
|
||||
export function* limit<T>(count: number, iterable: Iterable<T>): Generator<T, void, unknown> {
|
||||
let i = 0
|
||||
for (const value of iterable) {
|
||||
if (i < count) {
|
||||
@@ -77,7 +77,10 @@ export function* limit<T>(count: number, iterable: Iterable<T>) {
|
||||
* @author MindfulMinun
|
||||
* @since 2022-07-07
|
||||
*/
|
||||
export async function* limitAsync<T>(count: number, iterable: AsyncIterable<T>) {
|
||||
export async function* limitAsync<T>(
|
||||
count: number,
|
||||
iterable: AsyncIterable<T>
|
||||
): AsyncGenerator<Awaited<T>, void, unknown> {
|
||||
let i = 0
|
||||
for await (const value of iterable) {
|
||||
if (i < count) {
|
||||
|
||||
+5
-7
@@ -3,10 +3,8 @@
|
||||
* @author MindfulMinun <https://benjic.xyz>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
console.error("Hey there, past me! Please don't import `mod.ts`, instead import specific files!")
|
||||
|
||||
// export * from "./array.ts"
|
||||
// export * from "./helpers.ts"
|
||||
// export * from "./math.ts"
|
||||
// export * from "./dom.ts"
|
||||
export * as async from './async.ts'
|
||||
export * as dom from './dom.ts'
|
||||
export * as rng from './rng.ts'
|
||||
export * as shell from './shell.ts'
|
||||
export * as string from './string.ts'
|
||||
+9
-9
@@ -24,7 +24,7 @@ export abstract class RNG implements Iterable<number> {
|
||||
* @author MindfulMinun
|
||||
* @since 2022-07-16
|
||||
*/
|
||||
*[Symbol.iterator]() {
|
||||
*[Symbol.iterator](): Generator<number, void, unknown> {
|
||||
while (true) yield this.float()
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ export abstract class RNG implements Iterable<number> {
|
||||
* @author MindfulMinun
|
||||
* @since 2022-07-16
|
||||
*/
|
||||
float() {
|
||||
float(): number {
|
||||
return this.nextValue()
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ export abstract class RNG implements Iterable<number> {
|
||||
* @author MindfulMinun
|
||||
* @since 2022-07-16
|
||||
*/
|
||||
choose<T>(arr: T[]) {
|
||||
choose<T>(arr: T[]): T {
|
||||
return arr[Math.floor(this.float() * arr.length)]
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ export abstract class RNG implements Iterable<number> {
|
||||
* @author MindfulMinun
|
||||
* @since 2022-07-16
|
||||
*/
|
||||
shuffle<T>(arr: T[]) {
|
||||
shuffle<T>(arr: T[]): T[] {
|
||||
let i, j
|
||||
for (i = arr.length - 1; i > 0; i--) {
|
||||
j = Math.floor(this.float() * (i + 1))
|
||||
@@ -89,7 +89,7 @@ export abstract class RNG implements Iterable<number> {
|
||||
* @author MindfulMinun
|
||||
* @since 2022-07-16
|
||||
*/
|
||||
chooseWithWeights<T>(items: T[], weights: number[]) {
|
||||
chooseWithWeights<T>(items: T[], weights: number[]): T {
|
||||
if (items.length != weights.length) throw Error(`Expected items and weights to have the same number of elements, but items has ${items.length} elements, and weights has ${weights.length}.`)
|
||||
|
||||
const sumOfWeights = weights.reduce((acc, v) => acc + v)
|
||||
@@ -113,7 +113,7 @@ export abstract class RNG implements Iterable<number> {
|
||||
* @since 2022-07-08
|
||||
*/
|
||||
export class Random extends RNG {
|
||||
nextValue() { return Math.random() }
|
||||
nextValue(): number { return Math.random() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,18 +125,18 @@ export class Mulberry32 extends RNG {
|
||||
#seed!: number
|
||||
originalSeed!: number
|
||||
|
||||
constructor(seed = Date.now()) {
|
||||
constructor(seed: number = Date.now()) {
|
||||
super()
|
||||
this.resetSeed(seed)
|
||||
}
|
||||
|
||||
/** Resets the seed */
|
||||
resetSeed(seed = this.#seed) {
|
||||
resetSeed(seed: number = this.#seed) {
|
||||
this.originalSeed = seed
|
||||
this.#seed = seed
|
||||
}
|
||||
|
||||
nextValue() {
|
||||
nextValue(): number {
|
||||
// Mulberry32
|
||||
let a = this.#seed
|
||||
a |= 0
|
||||
|
||||
+9
-9
@@ -38,24 +38,24 @@ export class Troopa implements PromiseLike<Deno.CommandOutput> {
|
||||
* @author MindfulMinun
|
||||
* @since 2023-12-26
|
||||
*/
|
||||
start() { return this.process }
|
||||
start(): Deno.ChildProcess { return this.process }
|
||||
|
||||
get process() {
|
||||
get process(): Deno.ChildProcess {
|
||||
if (this.#process) return this.#process
|
||||
this.#process = this.cmd.spawn()
|
||||
return this.#process
|
||||
}
|
||||
|
||||
get stdin() { return this.process.stdin }
|
||||
get stdout() { return this.process.stdout }
|
||||
get stderr() { return this.process.stderr }
|
||||
get stdin(): WritableStream<Uint8Array> { return this.process.stdin }
|
||||
get stdout(): ReadableStream<Uint8Array> { return this.process.stdout }
|
||||
get stderr(): ReadableStream<Uint8Array> { return this.process.stderr }
|
||||
|
||||
response(src: 'stdout' | 'stderr' = 'stdout') {
|
||||
response(src: 'stdout' | 'stderr' = 'stdout'): Response {
|
||||
const source = this.process[src]
|
||||
return new Response(source)
|
||||
}
|
||||
|
||||
async code() {
|
||||
async code(): Promise<number> {
|
||||
return (await this).code
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ export class Troopa implements PromiseLike<Deno.CommandOutput> {
|
||||
return this
|
||||
}
|
||||
|
||||
async close() {
|
||||
async close(): Promise<this> {
|
||||
await this.writer.close()
|
||||
return this
|
||||
}
|
||||
@@ -119,7 +119,7 @@ export class Troopa implements PromiseLike<Deno.CommandOutput> {
|
||||
* Factory facade to easily interact and run shell scripts
|
||||
* @since 2023-11-25
|
||||
*/
|
||||
export default function koopa(opts: Partial<ShellSpawnerOpts> = {}) {
|
||||
export default function koopa(opts: Partial<ShellSpawnerOpts> = {}): ShellSpawner<Troopa> {
|
||||
const actualOpts: ShellSpawnerOpts = {
|
||||
shell: 'bash',
|
||||
shellArgs: cmd => ['-c', `${opts.prefix || 'set -euo pipefail'}; ${cmd}`],
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "@mindfulminun/pear",
|
||||
"version": "1.5.0",
|
||||
"compilerOptions": {
|
||||
"lib": ["dom.iterable", "esnext", "dom", "deno.ns"]
|
||||
},
|
||||
"exports": {
|
||||
"./core": "./core/mod.ts",
|
||||
"./core/async": "./core/async.ts",
|
||||
// "./core/dom": "./core/dom.ts",
|
||||
"./core/iterable": "./core/iterable.ts",
|
||||
"./core/rng": "./core/rng.ts",
|
||||
"./core/shell": "./core/shell.ts",
|
||||
"./core/string": "./core/string.ts",
|
||||
|
||||
// "./tools": "./tools/",
|
||||
"./tools/graph": "./tools/graph/mod.ts",
|
||||
"./tools/graph-solver": "./tools/graph/graph-solver.ts",
|
||||
"./tools/matrix": "./tools/math/matrix.ts",
|
||||
"./tools/primes": "./tools/math/primes.ts",
|
||||
"./tools/structures": "./tools/structures/mod.ts"
|
||||
},
|
||||
"imports": { "@std/fmt": "jsr:@std/fmt@^0.225.6" }
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"version": "3",
|
||||
"packages": {
|
||||
"specifiers": {
|
||||
"jsr:@std/fmt@^0.225.6": "jsr:@std/[email protected]"
|
||||
},
|
||||
"jsr": {
|
||||
"@std/[email protected]": {
|
||||
"integrity": "aba6aea27f66813cecfd9484e074a9e9845782ab0685c030e453a8a70b37afc8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"redirects": {
|
||||
"https://deno.land/std/testing/asserts.ts": "https://deno.land/[email protected]/testing/asserts.ts"
|
||||
},
|
||||
"remote": {
|
||||
"https://deno.land/[email protected]/fmt/colors.ts": "30455035d6d728394781c10755351742dd731e3db6771b1843f9b9e490104d37",
|
||||
"https://deno.land/[email protected]/testing/_diff.ts": "029a00560b0d534bc0046f1bce4bd36b3b41ada3f2a3178c85686eb2ff5f1413",
|
||||
"https://deno.land/[email protected]/testing/_format.ts": "0d8dc79eab15b67cdc532826213bbe05bccfd276ca473a50a3fc7bbfb7260642",
|
||||
"https://deno.land/[email protected]/testing/asserts.ts": "3eea146ece74b36d4add6243c19c302e47b2b0201fbeceeeb243b06b6b410af7",
|
||||
"https://deno.land/[email protected]/fmt/colors.ts": "ff7dc9c9f33a72bd48bc24b21bbc1b4545d8494a431f17894dbc5fe92a938fc4",
|
||||
"https://deno.land/[email protected]/fmt/colors.ts": "9e36a716611dcd2e4865adea9c4bec916b5c60caad4cdcdc630d4974e6bb8bd4",
|
||||
"https://deno.land/[email protected]/testing/_diff.ts": "a23e7fc2b4d8daa3e158fa06856bedf5334ce2a2831e8bf9e509717f455adb2c",
|
||||
"https://deno.land/[email protected]/testing/_format.ts": "cd11136e1797791045e639e9f0f4640d5b4166148796cad37e6ef75f7d7f3832",
|
||||
"https://deno.land/[email protected]/testing/asserts.ts": "1e340c589853e82e0807629ba31a43c84ebdcdeca910c4a9705715dfdb0f5ce8"
|
||||
},
|
||||
"workspace": {
|
||||
"dependencies": [
|
||||
"jsr:@std/fmt@^0.225.6"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
// TODO: write me!
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
fill, range, limit
|
||||
} from "../core/iterable.ts"
|
||||
} from "../../core/iterable.ts"
|
||||
|
||||
import { assertEquals, assert } from "https://deno.land/[email protected]/testing/asserts.ts"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { g1, g2, g3 } from '../tools/graph/_graph-samples.ts'
|
||||
import { GraphSolver } from '../tools/graph/graph-solver.ts'
|
||||
import { g1, g2, g3 } from '../../tools/graph/_graph-samples.ts'
|
||||
import { GraphSolver } from '../../tools/graph/graph-solver.ts'
|
||||
import { assertEquals } from "https://deno.land/std/testing/asserts.ts"
|
||||
import { Path } from "../tools/graph/graph.ts"
|
||||
import { dedent } from "../core/string.ts"
|
||||
import { Path } from "../../tools/graph/mod.ts"
|
||||
import { dedent } from "../../core/string.ts"
|
||||
|
||||
// TODO: Add more tests!
|
||||
|
||||
@@ -43,7 +43,10 @@ Deno.test('GraphSolver::DFS w/ g1', () => {
|
||||
Deno.test('GraphSolver::bidi Path', () => {
|
||||
const G = g3()
|
||||
const solver = new GraphSolver(G)
|
||||
const path = solver.bidi(G.vertices.get('A')!, G.vertices.get('E')!)
|
||||
const path = solver.bidi({
|
||||
source: G.vertices.get('A')!,
|
||||
sink: G.vertices.get('E')!
|
||||
})
|
||||
|
||||
assertPathsEqual(
|
||||
path,
|
||||
@@ -1,7 +1,7 @@
|
||||
import { range } from "../core/iterable.ts";
|
||||
import { Queue } from "../tools/structures/Queue.ts"
|
||||
import { Stack } from "../tools/structures/Stack.ts"
|
||||
import { BinaryHeap } from "../tools/structures/Heap.ts"
|
||||
import { range } from "../../core/iterable.ts";
|
||||
import { Queue } from "../../tools/structures/Queue.ts"
|
||||
import { Stack } from "../../tools/structures/Stack.ts"
|
||||
import { BinaryHeap } from "../../tools/structures/Heap.ts"
|
||||
|
||||
import { assertEquals } from "https://deno.land/[email protected]/testing/asserts.ts"
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
Implement Dijkstra's, Prim and Kruskal's, Topological sort, maybe like Ford-Fulkerson, maybe Christofides
|
||||
|
||||
export * as YAML from "https://esm.sh/yaml@2.3.4"
|
||||
Use YAML format for storing graphs! Use references or something!
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Graph } from './graph.ts'
|
||||
import { Graph } from './mod.ts'
|
||||
|
||||
// Box drawing characters!
|
||||
// ┌ ┬ ┐ ─│
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Graph, Vertex, VertexType, Edge, EdgeType, Path, PathType } from "./graph.ts"
|
||||
import { Graph, Vertex, VertexType, Edge, EdgeType, Path, PathType } from "./mod.ts"
|
||||
import { Queue } from "../structures/Queue.ts"
|
||||
import { Stack } from "../structures/Stack.ts"
|
||||
import { BinaryHeap } from "../structures/Heap.ts"
|
||||
@@ -89,20 +89,24 @@ export class GraphSolver<vData, eData> {
|
||||
* @author MindfulMinun
|
||||
* @since 2022-11-14
|
||||
*/
|
||||
bidi(left: Vertex<vData, eData>, right: Vertex<vData, eData>): Path<vData, eData> | null {
|
||||
const qL = new Queue([left])
|
||||
const qR = new Queue([right])
|
||||
bidi({ source, sink, skipEdge }: {
|
||||
source: Vertex<vData, eData>
|
||||
sink: Vertex<vData, eData>
|
||||
skipEdge?: <vData, eData>(e: Edge<vData, eData>, v: Vertex<vData, eData>, g: Graph<vData, eData>) => boolean
|
||||
}): Path<vData, eData> | null {
|
||||
const qL = new Queue([source])
|
||||
const qR = new Queue([sink])
|
||||
|
||||
// Map a vertex to the path that led to it. Note that paths from the right
|
||||
// will be reversed so they can be concatenated with the paths from the left.
|
||||
const backL = new Map<Vertex<vData, eData>, Path<vData, eData>>()
|
||||
const backR = new Map<Vertex<vData, eData>, Path<vData, eData>>()
|
||||
|
||||
backL.set(left, this.G.createPath(left))
|
||||
backR.set(right, this.G.createPath(right))
|
||||
backL.set(source, this.G.createPath(source))
|
||||
backR.set(sink, this.G.createPath(sink))
|
||||
|
||||
const seenL = new Set<Vertex<vData, eData>>([left])
|
||||
const seenR = new Set<Vertex<vData, eData>>([right])
|
||||
const seenL = new Set<Vertex<vData, eData>>([source])
|
||||
const seenR = new Set<Vertex<vData, eData>>([sink])
|
||||
|
||||
while (qL.length && qR.length) {
|
||||
const l = qL.pop()!
|
||||
@@ -113,6 +117,7 @@ export class GraphSolver<vData, eData> {
|
||||
for (const E of l.adjacentEdges) {
|
||||
if (E.directed && l !== E.u) continue
|
||||
const w = E.not(l)
|
||||
if (skipEdge?.(E, l, this.G) || false) continue
|
||||
if (!seenL.has(w)) {
|
||||
seenL.add(w)
|
||||
const path = backL.get(l)!.copy()
|
||||
@@ -129,6 +134,7 @@ export class GraphSolver<vData, eData> {
|
||||
// Edge u -> v
|
||||
if (E.directed && r !== E.v) continue
|
||||
const w = E.not(r)
|
||||
if (skipEdge?.(E, w, this.G) || false) continue
|
||||
if (!seenR.has(w)) {
|
||||
seenR.add(w)
|
||||
const path = backR.get(r)!.copy()
|
||||
@@ -166,7 +172,7 @@ export class GraphSolver<vData, eData> {
|
||||
* @author MindfulMinun
|
||||
* @since 2023-03-30
|
||||
*/
|
||||
kruskalWithSort() {
|
||||
kruskalWithSort(): Set<Edge<vData, eData>> {
|
||||
this.sortEdgesByWeight()
|
||||
return this.kruskalPresorted()
|
||||
}
|
||||
@@ -228,4 +234,8 @@ export class GraphSolver<vData, eData> {
|
||||
.map(e => [e.id, e] as const)
|
||||
this.G.edges = new Map(edges)
|
||||
}
|
||||
|
||||
floydWarshall() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as Colors from "https://deno.land/[email protected]/fmt/colors.ts"
|
||||
import * as Colors from "@std/fmt/colors"
|
||||
|
||||
type UUID = string
|
||||
|
||||
@@ -60,7 +60,7 @@ export class Graph<vData, eData> {
|
||||
this.vertices.delete(V.id)
|
||||
}
|
||||
|
||||
createEdge(u: Vertex<vData, eData>, v: Vertex<vData, eData>, data: eData, opts: Partial<EdgeOpts> = {}) {
|
||||
createEdge(u: Vertex<vData, eData>, v: Vertex<vData, eData>, data: eData, opts: Partial<EdgeOpts> = {}): Edge<vData, eData> {
|
||||
const options: EdgeOpts = {
|
||||
directed: this.directed,
|
||||
id: crypto.randomUUID(),
|
||||
@@ -81,14 +81,15 @@ export class Graph<vData, eData> {
|
||||
}
|
||||
|
||||
|
||||
createPath(start: Vertex<vData, eData>) {
|
||||
createPath(start: Vertex<vData, eData>): Path<vData, eData> {
|
||||
return new Path<vData, eData>(this, start)
|
||||
}
|
||||
|
||||
// FIXME: return type
|
||||
toJSON(
|
||||
vertexReplacer: (this: Graph<vData, eData>, data: vData) => unknown = data => data,
|
||||
edgeReplacer: (this: Graph<vData, eData>, data: eData) => unknown = data => data
|
||||
) {
|
||||
): unknown {
|
||||
return {
|
||||
"@graph": Graph.signature,
|
||||
v: Array.from(this.vertices.values()).map(v => v.toJSON(vertexReplacer)),
|
||||
@@ -100,7 +101,7 @@ export class Graph<vData, eData> {
|
||||
json: unknown,
|
||||
vertexReviver: (this: Graph<vData, eData>, json: unknown) => vData = data => data as vData,
|
||||
edgeReviver: (this: Graph<vData, eData>, json: unknown) => eData = data => data as eData
|
||||
) {
|
||||
): Graph<vData, eData> {
|
||||
const G = new Graph<vData, eData>()
|
||||
|
||||
if (!json || typeof json !== 'object') throw Error("Failed to parse: Unexpected object!")
|
||||
@@ -172,15 +173,18 @@ export class Vertex<vData, eData> {
|
||||
*/
|
||||
delete() { this.graph.deleteVertex(this) }
|
||||
|
||||
toJSON(replacer: (this: Graph<vData, eData>, data: vData) => unknown = data => data) {
|
||||
// FIXME: return type as tuple
|
||||
toJSON(
|
||||
replacer: (this: Graph<vData, eData>, data: vData) => unknown = data => data
|
||||
): [unknown, unknown] {
|
||||
return [this.id, replacer.call(this.graph, this.data)]
|
||||
}
|
||||
|
||||
toString() {
|
||||
toString(): string {
|
||||
return Colors.cyan(`<${this.id.slice(0, 8)}>: ${this.data}`)
|
||||
}
|
||||
|
||||
[Symbol.for("Deno.customInspect")]() {
|
||||
[Symbol.for("Deno.customInspect")](): string {
|
||||
return this.toString()
|
||||
}
|
||||
}
|
||||
@@ -225,14 +229,16 @@ export class Edge<vData, eData> {
|
||||
}
|
||||
|
||||
/** Given one vertex, get the opposite vertex of this edge */
|
||||
not(v: typeof this.u | typeof this.v) {
|
||||
not(v: typeof this.u | typeof this.v): Vertex<vData, eData> {
|
||||
return this.v !== v ? this.v : this.u
|
||||
}
|
||||
|
||||
delete() { this.graph.deleteEdge(this) }
|
||||
|
||||
toJSON(replacer: (this: Graph<vData, eData>, data: eData) => unknown = data => data) {
|
||||
// tuple!
|
||||
// FIXME: Type me as a tuple!
|
||||
toJSON(
|
||||
replacer: (this: Graph<vData, eData>, data: eData) => unknown = data => data
|
||||
): [unknown, unknown, unknown, unknown, unknown] {
|
||||
return [
|
||||
this.id,
|
||||
this.u.id,
|
||||
@@ -242,11 +248,11 @@ export class Edge<vData, eData> {
|
||||
]
|
||||
}
|
||||
|
||||
toString() {
|
||||
toString(): string {
|
||||
return Colors.magenta(`<${this.id.slice(0, 8)}>: ${this.u} ${!this.directed ? '<' : ''}--> ${this.v}`)
|
||||
}
|
||||
|
||||
[Symbol.for("Deno.customInspect")]() {
|
||||
[Symbol.for("Deno.customInspect")](): string {
|
||||
return this.toString()
|
||||
}
|
||||
}
|
||||
@@ -276,7 +282,7 @@ export class Path<vData, eData> {
|
||||
}
|
||||
|
||||
/** The vertices belonging to this path */
|
||||
get vertices() {
|
||||
get vertices(): Iterable<Vertex<vData, eData>> {
|
||||
if (this.#vertices) return this.#vertices
|
||||
|
||||
const vertices: Vertex<vData, eData>[] = []
|
||||
@@ -294,7 +300,7 @@ export class Path<vData, eData> {
|
||||
return this.#vertices
|
||||
}
|
||||
|
||||
copy() {
|
||||
copy(): Path<vData, eData> {
|
||||
const path = new Path<vData, eData>(this.graph, this.start ?? undefined)
|
||||
path.edges = this.edges.slice()
|
||||
path.#vertices = this.#vertices?.slice() ?? null
|
||||
+14
-11
@@ -1,6 +1,6 @@
|
||||
import { fill } from "../../core/iterable.ts"
|
||||
import * as Colors from "https://deno.land/[email protected]/fmt/colors.ts"
|
||||
import { Memo } from "../structures.ts"
|
||||
import * as Colors from "@std/fmt/colors"
|
||||
import { Memo } from "../structures/Memo.ts"
|
||||
|
||||
|
||||
const memodDeterminant = new Memo({
|
||||
@@ -26,17 +26,17 @@ export class Matrix<M extends number = number, N extends number = number> {
|
||||
this.entries = entries
|
||||
}
|
||||
|
||||
set(row: number, col: number, value: number) {
|
||||
set(row: number, col: number, value: number): void {
|
||||
const offset = this.#calculateOffset(row, col)
|
||||
this.entries[offset] = value
|
||||
}
|
||||
|
||||
get(row: number, col: number) {
|
||||
get(row: number, col: number): number {
|
||||
const offset = this.#calculateOffset(row, col)
|
||||
return this.entries[offset]
|
||||
}
|
||||
|
||||
copy() {
|
||||
copy(): Matrix<M, N> {
|
||||
return new Matrix(this.m, this.n, this.entries.slice())
|
||||
}
|
||||
|
||||
@@ -44,7 +44,9 @@ export class Matrix<M extends number = number, N extends number = number> {
|
||||
* Performs naive matrix multiplication.
|
||||
* @thorws If the dimensions of the matrices are incompatible.
|
||||
*/
|
||||
rightMultiply<P extends number, Q extends number>(right: Matrix<P, Q>) {
|
||||
rightMultiply<P extends number, Q extends number>(
|
||||
right: Matrix<P, Q>
|
||||
): N & P extends never ? never : Matrix<M, Q> {
|
||||
if (this.n as number !== right.m as number) {
|
||||
throw new Error(`Cannot multiply ${this.m}x${this.n} matrix by ${right.m}x${right.n} matrix.`)
|
||||
}
|
||||
@@ -89,7 +91,8 @@ export class Matrix<M extends number = number, N extends number = number> {
|
||||
/**
|
||||
* Returns the submatrix obtained by removing the given row and column.
|
||||
*/
|
||||
laplaceExpansion(row: number, col: number) {
|
||||
// FIXME: Type this correctly
|
||||
laplaceExpansion(row: number, col: number): Matrix {
|
||||
const matrix = Matrix.null(this.m - 1, this.n - 1)
|
||||
matrix.entries = this.entries.filter((_, i) => {
|
||||
const r = Math.floor(i / this.n)
|
||||
@@ -106,7 +109,7 @@ export class Matrix<M extends number = number, N extends number = number> {
|
||||
* @author MindfulMinun
|
||||
* @since 2023-01-06
|
||||
*/
|
||||
toUpperTriangular() {
|
||||
toUpperTriangular(): Matrix<M, N> | null {
|
||||
const A = this.copy()
|
||||
const { m, n } = A
|
||||
for (let i = 0; i < m; i++) {
|
||||
@@ -171,7 +174,7 @@ export class Matrix<M extends number = number, N extends number = number> {
|
||||
}
|
||||
}
|
||||
|
||||
toString() {
|
||||
toString(): string {
|
||||
let out = ''
|
||||
out += 'Matrix<' + this.m + ', ' + this.n + '>['
|
||||
out += this.entries.map(e => e.toString()).join(', ')
|
||||
@@ -179,7 +182,7 @@ export class Matrix<M extends number = number, N extends number = number> {
|
||||
return out
|
||||
}
|
||||
|
||||
[Symbol.for("Deno.customInspect")]() {
|
||||
[Symbol.for("Deno.customInspect")](): string {
|
||||
const strs = this.entries.map(e => e.toString())
|
||||
const maxLengths = Array.from(fill(0, this.n))
|
||||
|
||||
@@ -215,7 +218,7 @@ export class Matrix<M extends number = number, N extends number = number> {
|
||||
* Creates a new matrix with the given numbers and entries.
|
||||
* All entries are initialized to 0.
|
||||
*/
|
||||
static null<M extends number, N extends number>(m: M, n: N) {
|
||||
static null<M extends number, N extends number>(m: M, n: N): Matrix<M, N> {
|
||||
const zeroes = Array.from(fill(0, m * n))
|
||||
return new Matrix(m, n, zeroes)
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
console.error("Hey there, past me! Please don't import `structures.ts`, instead import the specific structure you need.")
|
||||
|
||||
export * from './structures/Queue.ts'
|
||||
export * from './structures/Stack.ts'
|
||||
@@ -24,7 +24,7 @@ export class BinaryHeap<T> implements Iterable<T> {
|
||||
for (const el of initials) this.push(el)
|
||||
}
|
||||
|
||||
*[Symbol.iterator]() {
|
||||
*[Symbol.iterator](): Generator<NonNullable<T>, void, unknown> {
|
||||
while (this.length !== 0) yield this.pop()!
|
||||
}
|
||||
|
||||
@@ -112,5 +112,5 @@ export class BinaryHeap<T> implements Iterable<T> {
|
||||
}
|
||||
|
||||
/** The number of elements in the heap */
|
||||
get length() { return this.#elements.length }
|
||||
get length(): number { return this.#elements.length }
|
||||
}
|
||||
@@ -69,11 +69,11 @@ export class Memo<A extends unknown[], R extends unknown> {
|
||||
return result
|
||||
}
|
||||
|
||||
get ratio() {
|
||||
get ratio(): number {
|
||||
return this.hits / (this.hits + this.misses)
|
||||
}
|
||||
|
||||
get fn() {
|
||||
get fn(): (...args: A) => R {
|
||||
return this.#memoHandler.bind(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,9 +37,11 @@ export class Queue<T> implements Iterable<T> {
|
||||
}
|
||||
|
||||
/** The number of elements remaining in the queue */
|
||||
get length() { return this.#tail - this.#head }
|
||||
get length(): number {
|
||||
return this.#tail - this.#head
|
||||
}
|
||||
|
||||
*[Symbol.iterator]() {
|
||||
*[Symbol.iterator](): Generator<NonNullable<T>, void, unknown> {
|
||||
while (this.length !== 0) yield this.pop()!
|
||||
}
|
||||
}
|
||||
@@ -35,9 +35,9 @@ export class Stack<T> implements Iterable<T> {
|
||||
}
|
||||
|
||||
/** The number of elements remaining in the stack */
|
||||
get length() { return this.#head }
|
||||
get length(): number { return this.#head }
|
||||
|
||||
*[Symbol.iterator]() {
|
||||
*[Symbol.iterator](): Generator<NonNullable<T>, void, unknown> {
|
||||
while (this.length !== 0) yield this.pop()!
|
||||
}
|
||||
}
|
||||
@@ -25,26 +25,28 @@ export class StateMachine<State extends string | number | symbol = 0, InputAlpha
|
||||
this.reset()
|
||||
}
|
||||
|
||||
runWithInput(elements: Iterable<InputAlphabet>) {
|
||||
runWithInput(elements: Iterable<InputAlphabet>): this {
|
||||
for (const element of elements) {
|
||||
this.transitionWith(element)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
transitionWith(input: InputAlphabet) {
|
||||
transitionWith(input: InputAlphabet): this {
|
||||
const fn = this.#transitionTable[this.currentState]
|
||||
if (!fn) throw new Error(`No transition function for state ${String(this.currentState)}`)
|
||||
fn.call(this, input, this)
|
||||
return this
|
||||
}
|
||||
|
||||
goto(state: State) {
|
||||
goto(state: State): this {
|
||||
this.currentState = state
|
||||
return this
|
||||
}
|
||||
|
||||
accepts(state = this.currentState) { return this.#acceptStates.has(state) }
|
||||
accepts(state = this.currentState): boolean {
|
||||
return this.#acceptStates.has(state)
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.currentState = this.#initialState
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export * as DisjointSet from './DisjointSet.ts'
|
||||
export * as Heap from './Heap.ts'
|
||||
export * as Memo from './Memo.ts'
|
||||
export * as Queue from './Queue.ts'
|
||||
export * as Stack from './Stack.ts'
|
||||
export * as StateMachine from './StateMachine.ts'
|
||||
Reference in new issue
Block a user