Skip to content

Commit 2b3c113

Browse files
committed
✨ feat: implemented '@algorithm.ts/gcd'
1 parent 3c5be84 commit 2b3c113

11 files changed

+310
-0
lines changed

Diff for: README.md

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Package | Description
6060
[@algorithm.ts/dinic][] | Dinic algorithm. #MaxFlow, #NetworkFlow.
6161
[@algorithm.ts/dlx][] | DLX algorithm.
6262
[@algorithm.ts/findset][] | Find set.
63+
[@algorithm.ts/gcd][] | Greatest Common Divisor (GCD) and extended Euclidean algorithm.
6364
[@algorithm.ts/isap][] | ISAP algorithm. #MaxFlow, #NetworkFlow.
6465
[@algorithm.ts/knuth-shuffle][] | Knuth-Shuffle algorithm.
6566
[@algorithm.ts/mcmf][] | MCMF algorithm. #MinCostMaxFlow, #NetworkFlow.
@@ -80,6 +81,7 @@ algorithm.ts is [MIT licensed](https://github.com/guanghechen/algorithm.ts/blob/
8081
[@algorithm.ts/dinic]: ./packages/dinic
8182
[@algorithm.ts/dlx]: ./packages/dlx
8283
[@algorithm.ts/findset]: ./packages/findset
84+
[@algorithm.ts/gcd]: ./packages/gcd
8385
[@algorithm.ts/isap]: ./packages/isap
8486
[@algorithm.ts/knuth-shuffle]: ./packages/knuth-shuffle
8587
[@algorithm.ts/mcmf]: ./packages/mcmf

Diff for: package.json

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"postinstall:dev": "is-ci || husky install",
2929
"postpublish": "pinst --enable",
3030
"rebuild": "run-s clean build",
31+
"run:ts": "node -r ts-node/register -r tsconfig-paths/register",
3132
"test": "lerna exec 'echo && pwd && yarn test' --concurrency 1",
3233
"test:coverage": "lerna exec 'echo && pwd && yarn test --coverage' --concurrency 1",
3334
"test:update": "lerna exec 'echo && pwd && yarn test -u' --concurrency 1",

Diff for: packages/gcd/README.md

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<header>
2+
<h1 align="center">
3+
<a href="https://github.com/guanghechen/algorithm.ts/tree/main/packages/gcd#readme">@algorithm.ts/gcd</a>
4+
</h1>
5+
<div align="center">
6+
<a href="https://www.npmjs.com/package/@algorithm.ts/gcd">
7+
<img
8+
alt="Npm Version"
9+
src="https://img.shields.io/npm/v/@algorithm.ts/gcd.svg"
10+
/>
11+
</a>
12+
<a href="https://www.npmjs.com/package/@algorithm.ts/gcd">
13+
<img
14+
alt="Npm Download"
15+
src="https://img.shields.io/npm/dm/@algorithm.ts/gcd.svg"
16+
/>
17+
</a>
18+
<a href="https://www.npmjs.com/package/@algorithm.ts/gcd">
19+
<img
20+
alt="Npm License"
21+
src="https://img.shields.io/npm/l/@algorithm.ts/gcd.svg"
22+
/>
23+
</a>
24+
<a href="#install">
25+
<img
26+
alt="Module Formats: cjs, esm"
27+
src="https://img.shields.io/badge/module_formats-cjs%2C%20esm-green.svg"
28+
/>
29+
</a>
30+
<a href="https://github.com/nodejs/node">
31+
<img
32+
alt="Node.js Version"
33+
src="https://img.shields.io/node/v/@algorithm.ts/gcd"
34+
/>
35+
</a>
36+
<a href="https://github.com/facebook/jest">
37+
<img
38+
alt="Tested with Jest"
39+
src="https://img.shields.io/badge/tested_with-jest-9c465e.svg"
40+
/>
41+
</a>
42+
<a href="https://github.com/prettier/prettier">
43+
<img
44+
alt="Code Style: prettier"
45+
src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square"
46+
/>
47+
</a>
48+
</div>
49+
</header>
50+
<br/>
51+
52+
53+
A typescript implementation of the **gcd** and **Extended Euclidean** algorithm.
54+
55+
* gcd: The Greatest Common Divisor.
56+
57+
* Extended Euclidean algorithm: For solving the smallest
58+
integer solution (|x| + |y| smallest) of the equation `Ax + By = gcd(x,y)`.
59+
60+
61+
## Install
62+
63+
* npm
64+
65+
```bash
66+
npm install --save @algorithm.ts/gcd
67+
```
68+
69+
* yarn
70+
71+
```bash
72+
yarn add @algorithm.ts/gcd
73+
```
74+
75+
76+
## Usage
77+
78+
79+
* gcd
80+
81+
```typescript
82+
import { gcd, gcdBigint } from '@algorithm.ts/gcd'
83+
84+
gcd(3, 4) // => 1
85+
gcdBigint(3n, 6n) // => 3n
86+
```
87+
88+
* Extended Euclidean algorithm
89+
90+
```typescript
91+
import { euclidean, euclideanBigint } from '@algorithm.ts/gcd'
92+
93+
// 3x + 4y = gcd(3, 4)
94+
euclidean(3, 4) // => [-1, 1, 1]
95+
euclidean(3, 8) // => [3, -1, 1]
96+
euclideanBigint(6, 8) // => [-1n, 1n, 2n]
97+
```
98+
99+
## Related
100+
101+
102+
* [数论基础之模方程初步][gcd]
103+
104+
105+
[homepage]: https://github.com/guanghechen/algorithm.ts/tree/main/packages/gcd#readme
106+
[gcd]: https://me.guanghechen.com/post/math/number-theory/%E6%A8%A1%E6%96%B9%E7%A8%8B/basic/

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

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { euclidean, euclideanBigint, gcd, gcdBigint } from '../src'
2+
3+
test('gcd', function () {
4+
for (let i = 1; i < 50; ++i) {
5+
expect(gcd(i, 0)).toBe(i)
6+
expect(gcd(0, i)).toBe(i)
7+
for (let j = 1; j < 50; ++j) {
8+
const d = gcd(i, j)
9+
expect(i % d).toBe(0)
10+
expect(j % d).toBe(0)
11+
expect(gcd(i / d, j / d)).toBe(1)
12+
}
13+
}
14+
})
15+
16+
test('gcdBigint', function () {
17+
for (let i = 1n; i < 50n; ++i) {
18+
expect(gcdBigint(i, 0n)).toBe(i)
19+
expect(gcdBigint(0n, i)).toBe(i)
20+
for (let j = 1n; j < 50n; ++j) {
21+
const d = gcdBigint(i, j)
22+
expect(i % d).toBe(0n)
23+
expect(j % d).toBe(0n)
24+
expect(gcdBigint(i / d, j / d)).toBe(1n)
25+
}
26+
}
27+
})
28+
29+
test('euclid', function () {
30+
for (let i = 1; i < 50; ++i) {
31+
for (let j = 1; j < 50; ++j) {
32+
const [x, y, d] = euclidean(i, j)
33+
expect(i % d).toBe(0)
34+
expect(j % d).toBe(0)
35+
expect(gcd(i / d, j / d)).toBe(1)
36+
expect(i * x + j * y).toBe(d)
37+
}
38+
}
39+
})
40+
41+
test('euclidBigint', function () {
42+
for (let i = 1n; i < 50n; ++i) {
43+
for (let j = 1n; j < 50n; ++j) {
44+
const [x, y, d] = euclideanBigint(i, j)
45+
expect(i % d).toBe(0n)
46+
expect(j % d).toBe(0n)
47+
expect(gcdBigint(i / d, j / d)).toBe(1n)
48+
expect(i * x + j * y).toBe(d)
49+
}
50+
}
51+
})

Diff for: packages/gcd/package.json

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"name": "@algorithm.ts/gcd",
3+
"version": "1.0.12",
4+
"description": "GCD + Euclidean algorithm",
5+
"author": {
6+
"name": "guanghechen",
7+
"url": "https://github.com/guanghechen/"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/guanghechen/algorithm.ts.git",
12+
"directory": "packages/gcd"
13+
},
14+
"homepage": "https://github.com/guanghechen/algorithm.ts/tree/main/packages/gcd#readme",
15+
"keywords": [
16+
"algorithm",
17+
"gcd",
18+
"extended euclidean algorithm"
19+
],
20+
"main": "lib/cjs/index.js",
21+
"module": "lib/esm/index.js",
22+
"types": "lib/types/index.d.ts",
23+
"source": "src/index.ts",
24+
"license": "MIT",
25+
"engines": {
26+
"node": ">= 14.15.0"
27+
},
28+
"files": [
29+
"lib/",
30+
"!lib/**/*.js.map",
31+
"!lib/**/*.d.ts.map",
32+
"package.json",
33+
"CHANGELOG.md",
34+
"LICENSE",
35+
"README.md"
36+
],
37+
"scripts": {
38+
"build": "cross-env NODE_ENV=production rollup -c ../../rollup.config.js",
39+
"prebuild": "rimraf lib/ && tsc -p tsconfig.src.json --emitDeclarationOnly",
40+
"prepublishOnly": "cross-env ROLLUP_SHOULD_SOURCEMAP=false yarn build",
41+
"test": "cross-env TS_NODE_FILES=true jest --config ../../jest.config.js --rootDir ."
42+
}
43+
}

Diff for: packages/gcd/src/euclidean.ts

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* Extended Euclidean algorithm for solving the smallest
3+
* integer solution (|x| + |y| smallest) of the equation `Ax + By = gcd(x,y)`.
4+
*
5+
* @param a
6+
* @param b
7+
* @returns
8+
* @see https://me.guanghechen.com/post/math/number-theory/%E6%A8%A1%E6%96%B9%E7%A8%8B/basic/
9+
*/
10+
export function euclidean(a: number, b: number): [number, number, number] {
11+
let x: number
12+
let y: number
13+
let d: number
14+
solve(a, b)
15+
return [x!, y!, d!]
16+
17+
function solve(_a: number, _b: number): void {
18+
if (_b === 0) {
19+
x = 1
20+
y = 0
21+
d = _a
22+
} else {
23+
const A = _a % _b
24+
const B = _b
25+
solve(B, A)
26+
27+
const X = y
28+
const Y = x
29+
30+
x = X
31+
y = Y - Math.floor(_a / _b) * X
32+
}
33+
}
34+
}
35+
36+
/**
37+
* Bigint version.
38+
*
39+
* @param a
40+
* @param b
41+
* @returns
42+
* @see https://me.guanghechen.com/post/math/number-theory/%E6%A8%A1%E6%96%B9%E7%A8%8B/basic/
43+
*/
44+
export function euclideanBigint(
45+
a: bigint,
46+
b: bigint,
47+
): [bigint, bigint, bigint] {
48+
let x: bigint
49+
let y: bigint
50+
let d: bigint
51+
solve(a, b)
52+
return [x!, y!, d!]
53+
54+
function solve(_a: bigint, _b: bigint): void {
55+
if (_b === 0n) {
56+
x = 1n
57+
y = 0n
58+
d = _a
59+
} else {
60+
const A = _a % _b
61+
const B = _b
62+
solve(B, A)
63+
64+
const X = y
65+
const Y = x
66+
67+
x = X
68+
y = Y - (_a / _b) * X
69+
}
70+
}
71+
}

Diff for: packages/gcd/src/gcd.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Find the greatest common divisor of x and y
3+
*
4+
* @param x
5+
* @param y
6+
* @returns
7+
*/
8+
export function gcd(x: number, y: number): number {
9+
return y === 0 ? x : gcd(y, x % y)
10+
}
11+
12+
/**
13+
* Bigint version.
14+
*
15+
* @param x
16+
* @param y
17+
* @returns
18+
*/
19+
export function gcdBigint(x: bigint, y: bigint): bigint {
20+
return y === 0n ? x : gcdBigint(y, x % y)
21+
}

Diff for: packages/gcd/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './gcd'
2+
export * from './euclidean'

Diff for: packages/gcd/tsconfig.json

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "../../tsconfig",
3+
"include": ["src", "script", "__test__"]
4+
}

Diff for: packages/gcd/tsconfig.src.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "../../tsconfig.settings",
3+
"compilerOptions": {
4+
"declarationDir": "lib/types",
5+
"rootDir": "src"
6+
},
7+
"include": ["src"]
8+
}

Diff for: tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"@algorithm.ts/dinic": ["packages/dinic/src"],
1212
"@algorithm.ts/dlx": ["packages/dlx/src"],
1313
"@algorithm.ts/findset": ["packages/findset/src"],
14+
"@algorithm.ts/gcd": ["packages/gcd/src"],
1415
"@algorithm.ts/isap": ["packages/isap/src"],
1516
"@algorithm.ts/knuth-shuffle": ["packages/knuth-shuffle/src"],
1617
"@algorithm.ts/mcmf": ["packages/mcmf/src"],

0 commit comments

Comments
 (0)