Skip to content

Commit d6c39ae

Browse files
Psytewpatrickwestervelt
and
patrickwestervelt
authored
algorithm: lcm (#68)
Co-authored-by: patrickwestervelt <[email protected]>
1 parent aab3f30 commit d6c39ae

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

Maths/LowestCommonMultiple.ts

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* @function LowestCommonMultiple
3+
* @description Determine the lowest common multiple of a group of numbers.
4+
* @param {Number[]} nums - An array of numbers.
5+
* @return {Number} - The lowest common multiple.
6+
* @see https://www.mathsisfun.com/least-common-multiple.html
7+
* @example LowestCommonMultiple(3, 4) = 12
8+
* @example LowestCommonMultiple(8, 6) = 24
9+
* @example LowestCommonMultiple(5, 8, 3) = 120
10+
*/
11+
12+
import { greatestCommonFactor } from "./GreatestCommonFactor";
13+
14+
//A naive solution which requires no additional mathematical algorithm
15+
16+
export const naiveLCM = (nums: number[]): number => {
17+
if (nums.some((num) => num < 0)) {
18+
throw new Error("numbers must be positive to determine lowest common multiple");
19+
}
20+
21+
if (nums.length === 0) {
22+
throw new Error("at least one number must be passed in");
23+
}
24+
25+
const max_num = Math.max(...nums);
26+
let current_num = max_num;
27+
28+
while (true) {
29+
if (nums.every((num) => current_num % num === 0)){
30+
return current_num;
31+
} else {
32+
current_num += max_num;
33+
}
34+
}
35+
}
36+
37+
//A typically more efficient solution which requires prior knowledge of GCF
38+
//Note that due to utilizing GCF, which requires natural numbers, this method only accepts natural numbers.
39+
40+
export const binaryLCM = (a: number, b: number): number => {
41+
if (a < 0 || b < 0) {
42+
throw new Error("numbers must be positive to determine lowest common multiple");
43+
}
44+
45+
if (!Number.isInteger(a) || !Number.isInteger(b)) {
46+
throw new Error("this method, which utilizes GCF, requires natural numbers.");
47+
}
48+
49+
return a * b / greatestCommonFactor([a, b]);
50+
}
51+
52+
export const lowestCommonMultiple = (nums: number[]): number => {
53+
if (nums.length === 0) {
54+
throw new Error("at least one number must be passed in");
55+
}
56+
57+
return nums.reduce(binaryLCM);
58+
}
+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { binaryLCM, lowestCommonMultiple, naiveLCM } from "../LowestCommonMultiple";
2+
3+
describe("naiveLCM", () => {
4+
test.each([[[3, 4], 12], [[8, 6], 24], [[5, 8, 3], 120], [[0.8, 0.4], 0.8]])(
5+
"of given two numbers is correct",
6+
(nums, expected) => {
7+
expect(naiveLCM(nums)).toBe(expected);
8+
},
9+
);
10+
11+
test("only positive numbers should be accepted", () => {
12+
expect(() => naiveLCM([-2, -3])).toThrowError(
13+
"numbers must be positive to determine lowest common multiple",
14+
);
15+
});
16+
17+
test("at least one number must be passed in", () => {
18+
expect(() => naiveLCM([])).toThrowError(
19+
"at least one number must be passed in",
20+
);
21+
});
22+
});
23+
24+
describe("binaryLCM", () => {
25+
test.each([[3, 4, 12], [8, 6, 24], [8, 16, 16]])(
26+
"of given two numbers is correct",
27+
(numa, numb, expected) => {
28+
expect(binaryLCM(numa, numb)).toBe(expected);
29+
},
30+
);
31+
32+
test("only whole numbers should be accepted", () => {
33+
expect(() => binaryLCM(-2, -3)).toThrowError(
34+
"numbers must be positive to determine lowest common multiple",
35+
);
36+
});
37+
});
38+
39+
describe("lowestCommonMultiple", () => {
40+
test.each([[[3, 4], 12], [[8, 6], 24], [[5, 8, 3], 120], [[8, 16], 16]])(
41+
"of given two numbers is correct",
42+
(nums, expected) => {
43+
expect(lowestCommonMultiple(nums)).toBe(expected);
44+
},
45+
);
46+
47+
test("only positive numbers should be accepted", () => {
48+
expect(() => lowestCommonMultiple([-2, -3])).toThrowError(
49+
"numbers must be positive to determine lowest common multiple",
50+
);
51+
});
52+
53+
test("at least one number must be passed in", () => {
54+
expect(() => lowestCommonMultiple([])).toThrowError(
55+
"at least one number must be passed in",
56+
);
57+
});
58+
});

0 commit comments

Comments
 (0)