Skip to content

Commit 75d9be3

Browse files
committed
✅ test: simplify tests
1 parent f3f9841 commit 75d9be3

16 files changed

+189
-178
lines changed

Diff for: jest.setup.ts

+20
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
/* eslint-disable jest/no-export */
12
import fs from 'fs-extra'
23
import path from 'path'
34

45
export const workspaceRootDir = __dirname
56
export const testRootDior = path.resolve()
67

8+
const isPromise = (object: unknown): object is Promise<unknown> => {
9+
return !!(object as any).then
10+
}
11+
712
export interface ITestData<P extends any[] = any[], D = any> {
813
input: P
914
answer: D
@@ -23,6 +28,21 @@ export const loadCommonJsonFixtures = <P extends any[] = any[], D = any>(
2328
...p: string[]
2429
): Array<ITestData<P, D>> => fs.readJSONSync(locateCommonJsonFixtures(...p))
2530

31+
export function testOjCodes<T extends (...input: any[]) => any>(
32+
problem: string,
33+
solution: Promise<{ default: T }> | T,
34+
): void {
35+
// eslint-disable-next-line jest/valid-title
36+
test(problem, async function () {
37+
type IParameters = Parameters<T>
38+
type IAnswer = ReturnType<T>
39+
const data: Array<ITestData<IParameters, IAnswer>> = loadCommonJsonFixtures(problem)
40+
41+
const solve: T = isPromise(solution) ? (await solution).default : solution
42+
for (const { input, answer } of data) expect(solve(...input)).toEqual(answer)
43+
})
44+
}
45+
2646
/**
2747
* Locate fixture filepath.
2848
* @param p

Diff for: packages/bellman-ford/__test__/bellman-ford.spec.ts

+13-90
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type { IEdge, IGraph } from '../src'
1+
import { testOjCodes } from 'jest.setup'
2+
import type { IGraph } from '../src'
23
import bellmanFord from '../src'
34

45
describe('basic', function () {
@@ -38,94 +39,16 @@ describe('basic', function () {
3839
})
3940
})
4041

41-
describe('leetcode', function () {
42+
describe('oj', function () {
4243
// https://leetcode.com/problems/number-of-ways-to-arrive-at-destination/
43-
test('leetcode/number-of-ways-to-arrive-at-destination', function () {
44-
const data: any[] = [
45-
{
46-
input: [
47-
7,
48-
[
49-
[0, 6, 7],
50-
[0, 1, 2],
51-
[1, 2, 3],
52-
[1, 3, 3],
53-
[6, 3, 3],
54-
[3, 5, 1],
55-
[6, 5, 1],
56-
[2, 5, 1],
57-
[0, 4, 5],
58-
[4, 6, 2],
59-
],
60-
],
61-
answer: 4,
62-
},
63-
{
64-
input: [2, [[1, 0, 10]]],
65-
answer: 1,
66-
},
67-
]
68-
69-
const customDist: number[] = []
70-
for (const kase of data) {
71-
const [N, roads] = kase.input
72-
73-
expect(countPaths(N, roads)).toEqual(kase.answer)
74-
expect(countPaths(N, roads, customDist)).toEqual(kase.answer)
75-
}
76-
})
44+
testOjCodes(
45+
'leetcode/number-of-ways-to-arrive-at-destination',
46+
import('./oj/number-of-ways-to-arrive-at-destination'),
47+
)
48+
49+
// https://leetcode.com/problems/maximum-path-quality-of-a-graph/
50+
testOjCodes(
51+
'leetcode/maximum-path-quality-of-a-graph',
52+
import('./oj/maximum-path-quality-of-a-graph'),
53+
)
7754
})
78-
79-
const MOD = 1e9 + 7
80-
function countPaths(N: number, roads: number[][], customDist?: number[]): number {
81-
const edges: IEdge[] = []
82-
const G: number[][] = new Array(N)
83-
for (let i = 0; i < N; ++i) G[i] = []
84-
for (const [from, to, cost] of roads) {
85-
G[from].push(edges.length)
86-
edges.push({ to, cost })
87-
88-
G[to].push(edges.length)
89-
edges.push({ to: from, cost })
90-
}
91-
92-
const source = 0
93-
const target = N - 1
94-
const graph: IGraph = {
95-
N,
96-
source: target,
97-
edges,
98-
G,
99-
dist: customDist ?? [],
100-
}
101-
102-
bellmanFord(graph, { INF: 1e12 })
103-
const { dist } = graph
104-
105-
const dp: number[] = new Array(N).fill(-1)
106-
return dfs(source)
107-
108-
function dfs(o: number): number {
109-
if (o === target) return 1
110-
111-
let answer = dp[o]
112-
if (answer !== -1) return answer
113-
114-
answer = 0
115-
const d = dist[o]
116-
for (const idx of G[o]) {
117-
const e: IEdge = edges[idx]
118-
if (dist[e.to] + e.cost === d) {
119-
const t = dfs(e.to)
120-
answer = modAdd(answer, t)
121-
}
122-
}
123-
dp[o] = answer
124-
return answer
125-
}
126-
}
127-
128-
function modAdd(x: number, y: number): number {
129-
const z: number = x + y
130-
return z < MOD ? z : z - MOD
131-
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import type { IEdge, IGraph } from '../../src'
2+
import { bellmanFord } from '../../src'
3+
4+
export default maximalPathQuality
5+
6+
export function maximalPathQuality(
7+
values: number[],
8+
originalEdges: number[][],
9+
maxTime: number,
10+
): number {
11+
const T: number = maxTime
12+
const N: number = values.length
13+
14+
const edges: IEdge[] = new Array(N)
15+
const G: number[][] = new Array(N)
16+
for (let i = 0; i < N; ++i) G[i] = []
17+
for (const [u, v, w] of originalEdges) {
18+
G[u].push(edges.length)
19+
edges.push({ to: v, cost: w })
20+
21+
G[v].push(edges.length)
22+
edges.push({ to: u, cost: w })
23+
}
24+
const graph: IGraph = {
25+
N,
26+
source: 0,
27+
edges,
28+
G,
29+
dist: [],
30+
}
31+
if (!bellmanFord(graph, { INF: Number.MAX_SAFE_INTEGER })) return -1
32+
33+
const { dist } = graph
34+
35+
const visited: Uint8Array = new Uint8Array(N)
36+
return dfs(0, T, values[0])
37+
38+
function dfs(o: number, t: number, acc: number): number {
39+
const g = G[o]
40+
const s0: number = visited[o]
41+
let result = acc
42+
43+
for (let i = 0; i < g.length; ++i) {
44+
if (s0 & (1 << i)) continue
45+
46+
const e = edges[g[i]]
47+
if (e.cost + dist[e.to] > t) continue
48+
49+
visited[o] = s0 | (1 << i)
50+
result = Math.max(result, dfs(e.to, t - e.cost, acc + (visited[e.to] ? 0 : values[e.to])))
51+
visited[o] = s0
52+
}
53+
return result
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import type { IEdge, IGraph } from '../../src'
2+
import bellmanFord from '../../src'
3+
4+
export default countPaths
5+
6+
const MOD = 1e9 + 7
7+
export function countPaths(N: number, roads: number[][]): number {
8+
const edges: IEdge[] = []
9+
const G: number[][] = new Array(N)
10+
for (let i = 0; i < N; ++i) G[i] = []
11+
for (const [from, to, cost] of roads) {
12+
G[from].push(edges.length)
13+
edges.push({ to, cost })
14+
15+
G[to].push(edges.length)
16+
edges.push({ to: from, cost })
17+
}
18+
19+
const source = 0
20+
const target = N - 1
21+
const graph: IGraph = {
22+
N,
23+
source: target,
24+
edges,
25+
G,
26+
dist: [],
27+
}
28+
29+
bellmanFord(graph, { INF: 1e12 })
30+
const { dist } = graph
31+
32+
const dp: number[] = new Array(N).fill(-1)
33+
return dfs(source)
34+
35+
function dfs(o: number): number {
36+
if (o === target) return 1
37+
38+
let answer = dp[o]
39+
if (answer !== -1) return answer
40+
41+
answer = 0
42+
const d = dist[o]
43+
for (const idx of G[o]) {
44+
const e: IEdge = edges[idx]
45+
if (dist[e.to] + e.cost === d) {
46+
const t = dfs(e.to)
47+
answer = modAdd(answer, t)
48+
}
49+
}
50+
dp[o] = answer
51+
return answer
52+
}
53+
}
54+
55+
function modAdd(x: number, y: number): number {
56+
const z: number = x + y
57+
return z < MOD ? z : z - MOD
58+
}

Diff for: packages/dijkstra-bigint/__test__/dijkstra.spec.ts

+10-23
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import { loadCommonJsonFixtures } from 'jest.setup'
2-
import type { ITestData } from 'jest.setup'
1+
import { testOjCodes } from 'jest.setup'
32
import dijkstra from '../src'
4-
import { maximalPathQuality } from './oj/maximum-path-quality-of-a-graph'
5-
import { countPaths } from './oj/number-of-ways-to-arrive-at-destination'
63

74
describe('basic', function () {
85
test('simple', function () {
@@ -22,26 +19,16 @@ describe('basic', function () {
2219
})
2320
})
2421

25-
describe('leetcode', function () {
22+
describe('oj', function () {
2623
// https://leetcode.com/problems/number-of-ways-to-arrive-at-destination/
27-
test('leetcode/number-of-ways-to-arrive-at-destination', function () {
28-
type IParameters = Parameters<typeof countPaths>
29-
type IAnswer = ReturnType<typeof countPaths>
30-
const data: Array<ITestData<IParameters, IAnswer>> = loadCommonJsonFixtures(
31-
'leetcode/number-of-ways-to-arrive-at-destination',
32-
)
33-
34-
for (const { input, answer } of data) expect(countPaths(...input)).toEqual(answer)
35-
})
24+
testOjCodes(
25+
'leetcode/number-of-ways-to-arrive-at-destination',
26+
import('./oj/number-of-ways-to-arrive-at-destination'),
27+
)
3628

3729
// https://leetcode.com/problems/maximum-path-quality-of-a-graph/
38-
test('leetcode/maximum-path-quality-of-a-graph', function () {
39-
type IParameters = Parameters<typeof maximalPathQuality>
40-
type IAnswer = ReturnType<typeof maximalPathQuality>
41-
const data: Array<ITestData<IParameters, IAnswer>> = loadCommonJsonFixtures(
42-
'leetcode/maximum-path-quality-of-a-graph',
43-
)
44-
45-
for (const { input, answer } of data) expect(maximalPathQuality(...input)).toEqual(answer)
46-
})
30+
testOjCodes(
31+
'leetcode/maximum-path-quality-of-a-graph',
32+
import('./oj/maximum-path-quality-of-a-graph'),
33+
)
4734
})

Diff for: packages/dijkstra-bigint/__test__/oj/maximum-path-quality-of-a-graph.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type { IEdge } from '../../src'
22
import { dijkstra } from '../../src'
33

4+
export default maximalPathQuality
5+
46
export function maximalPathQuality(
57
values: number[],
68
originalEdges: number[][],

Diff for: packages/dijkstra-bigint/__test__/oj/number-of-ways-to-arrive-at-destination.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type { IEdge } from '../../src'
22
import { dijkstra } from '../../src'
33

4+
export default countPaths
5+
46
const MOD = BigInt(1e9 + 7)
57
export function countPaths(N: number, roads: number[][]): number {
68
const edges: IEdge[] = []

Diff for: packages/dijkstra/__test__/dijkstra.spec.ts

+9-22
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import type { ITestData } from 'jest.setup'
2-
import { loadCommonJsonFixtures } from 'jest.setup'
1+
import { testOjCodes } from 'jest.setup'
32
import dijkstra from '../src'
4-
import { maximalPathQuality } from './oj/maximum-path-quality-of-a-graph'
5-
import { countPaths } from './oj/number-of-ways-to-arrive-at-destination'
63

74
describe('basic', function () {
85
test('simple', function () {
@@ -24,24 +21,14 @@ describe('basic', function () {
2421

2522
describe('oj', function () {
2623
// https://leetcode.com/problems/number-of-ways-to-arrive-at-destination/
27-
test('leetcode/number-of-ways-to-arrive-at-destination', function () {
28-
type IParameters = Parameters<typeof countPaths>
29-
type IAnswer = ReturnType<typeof countPaths>
30-
const data: Array<ITestData<IParameters, IAnswer>> = loadCommonJsonFixtures(
31-
'leetcode/number-of-ways-to-arrive-at-destination',
32-
)
33-
34-
for (const { input, answer } of data) expect(countPaths(...input)).toEqual(answer)
35-
})
24+
testOjCodes(
25+
'leetcode/number-of-ways-to-arrive-at-destination',
26+
import('./oj/number-of-ways-to-arrive-at-destination'),
27+
)
3628

3729
// https://leetcode.com/problems/maximum-path-quality-of-a-graph/
38-
test('leetcode/maximum-path-quality-of-a-graph', function () {
39-
type IParameters = Parameters<typeof maximalPathQuality>
40-
type IAnswer = ReturnType<typeof maximalPathQuality>
41-
const data: Array<ITestData<IParameters, IAnswer>> = loadCommonJsonFixtures(
42-
'leetcode/maximum-path-quality-of-a-graph',
43-
)
44-
45-
for (const { input, answer } of data) expect(maximalPathQuality(...input)).toEqual(answer)
46-
})
30+
testOjCodes(
31+
'leetcode/maximum-path-quality-of-a-graph',
32+
import('./oj/maximum-path-quality-of-a-graph'),
33+
)
4734
})

Diff for: packages/dijkstra/__test__/oj/maximum-path-quality-of-a-graph.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type { IEdge } from '../../src'
22
import { dijkstra } from '../../src'
33

4+
export default maximalPathQuality
5+
46
export function maximalPathQuality(
57
values: number[],
68
originalEdges: number[][],

Diff for: packages/dijkstra/__test__/oj/number-of-ways-to-arrive-at-destination.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { IEdge } from '../../src'
22
import { dijkstra } from '../../src'
33

4-
const MOD = 1e9 + 7
4+
export default countPaths
55

6+
const MOD = 1e9 + 7
67
export function countPaths(N: number, roads: number[][]): number {
78
const edges: IEdge[] = []
89
const G: number[][] = new Array(N)

0 commit comments

Comments
 (0)