Skip to content

Commit

Permalink
Add more utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
giraugh committed Apr 19, 2023
1 parent 8390fb0 commit f81c902
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 6 deletions.
1 change: 1 addition & 0 deletions lib/arrays/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './groupArrayBy'
export * from './range'
export * from './zipArrays'
export * from './zipArraysLongest'
export * from './partitionArray'
28 changes: 28 additions & 0 deletions lib/arrays/partitionArray.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Split an array into two subarrays using a predicate function
* @param array the array to partition
* @param predicateFn the boolean predicate to split along
* @returns the two partitions
*
* @example
* const [even, odd] = partitionArray([1, 2, 3, 4], x => x % 2 === 0)
* even === [2, 4]
* odd === [1, 3]
*/
export const partitionArray = <T>(array: T[], predicateFn: (t: T) => boolean): [T[], T[]] => {
let [a, b]: [T[], T[]] = [[], []]
for (let el of array) (predicateFn(el) ? a : b).push(el)
return [a, b]
}


// Tests
if (import.meta.vitest) {
const { expect, it } = import.meta.vitest

it('works for example 1', () => {
const [even, odd] = partitionArray([1, 2, 3, 4], x => x % 2 === 0)
expect(even).toStrictEqual([2, 4])
expect(odd).toStrictEqual([1, 3])
})
}
5 changes: 4 additions & 1 deletion lib/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export const TAU = 6.283185
export const TAU = Math.PI * 2
export const GOLDEN_RATIO = 1.618033988749
export const EARTH_GRAVITY = 9.81 // m/s^2
export const JUPITER_GRAVITY = 24.79 // m/s^2
2 changes: 1 addition & 1 deletion lib/errors/expectOrThrow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* @example expectOrThrow(null) // throws error
* @example expectOrThrow(null, ':(') // throws error w/ message ':('
*/
export const expectOrThrow = <T>(t: T | undefined | null, message='Expected argument to be defined') => {
export const expectOrThrow = <T>(t: T | undefined | null, message='Expected argument to be defined'): T => {
if (t === undefined || t === null)
throw new Error(message)
return t
Expand Down
1 change: 1 addition & 0 deletions lib/interpolation/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './lerp'
31 changes: 31 additions & 0 deletions lib/interpolation/lerp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Get a value linearly interpolated between two endpoints.
* @param a the end point for the interpolation
* @param b the start point for the interpolation
* @param t the amount to interpolate. A value in the range `0<=t<=1`
* @returns the value that is `t%` from `a` to `b`
*
* @example lerp(0, 4, 0) === 0
* @example lerp(0, 4, 0.5) === 2
* @example lerp(0, 4, 1) === 4
*/
export const lerp = (a: number, b: number, t: number) =>
a + ( b - a ) * t


// Tests
if (import.meta.vitest) {
const { expect, it } = import.meta.vitest

it('should work for example 1', () => {
expect(lerp(0, 4, 0)).toEqual(0)
})

it('should work for example 2', () => {
expect(lerp(0, 4, .5)).toEqual(2)
})

it('should work for example 3', () => {
expect(lerp(0, 4, 1)).toEqual(4)
})
}
1 change: 1 addition & 0 deletions lib/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './constants'
export * from './aggregation'
export * from './promises'
export * from './strings'
export * from './interpolation'
8 changes: 4 additions & 4 deletions lib/promises/mapAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
*
* @example await mapAsync([1, 2, 3], x => Promise.resolve(x + 1)) === [2, 3, 4]
*/
export const mapAsync = async <A, B>(
array: A[],
asyncMapFn: (value: A, i: number, arr: A[]) => Promise<B>
): Promise<B[]> =>
export const mapAsync = async <TFrom, TTo>(
array: TFrom[],
asyncMapFn: (value: TFrom, i: number, arr: TFrom[]) => Promise<TTo>
): Promise<TTo[]> =>
Promise.all(array.map((v, i, arr) => asyncMapFn(v, i, arr)))


Expand Down
54 changes: 54 additions & 0 deletions lib/strings/editDistance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Compute the levenshtein edit distance between two strings.
* Equivalent to the the number of edits necessary to get from source to target.
* @param source string to use as source
* @param target target string
* @returns the number of changes to edit source into target
*
* @example editDistance('snail', 'mail') === 2
*/
export const editDistance = (source: string, target: string): number => {
// Create dynamic programming matrix
const dynMat = Array(target.length + 1).fill(-1)
.map((_, i) => Array(source.length + 1).fill(-1)
.map((_, j) => i === 0 ? j : (j === 0 ? i : -1) ))

// Compute the matrix values
for (let j = 1; j <= target.length; j++) {
for (let i = 1; i <= source.length; i++) {
const ind = source[i - 1] === target[j - 1] ? 0 : 1
dynMat[j][i] = Math.min(
dynMat[j][i - 1] + 1, // deletion
dynMat[j - 1][i] + 1, // insertion
dynMat[j - 1][i - 1] + ind, // substitution
)
}
}

// Return resulting value from matrix
return dynMat[target.length][source.length]
}



// Tests
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest

it('works for example 1', () => {
expect(editDistance('snail', 'mail')).toBe(2)
})

it('correctly calculates the distance between different words', () => {
expect(editDistance('cake', 'bake')).toBe(1)
expect(editDistance('telethon', 'melatonin')).toBe(5)
})

it('correctly calculates the distance between identical words', () => {
expect(editDistance('superlative', 'superlative')).toBe(0)
})

it('correctly calculates the distance between a word and an empty string', () => {
expect(editDistance('', 'gracious')).toBe(8)
})
}
1 change: 1 addition & 0 deletions lib/strings/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './capitalize'
export * from './truncateWithEllipsis'
export * from './pluralize'
export * from './editDistance'

0 comments on commit f81c902

Please sign in to comment.