Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended Euclidean Algorithm #200

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -58,6 +58,8 @@ a set of rules that precisely define a sequence of operations.
* **Math**
* `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits, multiplication/division by two, make negative etc.
* `B` [Factorial](src/algorithms/math/factorial)
* `B` [nth Root](src/algorithms/math/nth-root)
* `B` [Extended Euclidean Algorithm](src/algorithms/math/extended-euclidean-algorithm)
* `B` [Fibonacci Number](src/algorithms/math/fibonacci)
* `B` [Primality Test](src/algorithms/math/primality-test) (trial division method)
* `B` [Euclidean Algorithm](src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD)
19 changes: 19 additions & 0 deletions src/algorithms/math/bits/__test__/isEven.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import isEven from '../isEven';

describe('isEven', () => {
it('should get if number is even', () => {
expect(isEven(2)).toBe(true);
expect(isEven(6)).toBe(true);
expect(isEven(8)).toBe(true);
expect(isEven(10)).toBe(true);
expect(isEven(12)).toBe(true);
});

it('should get if number is odd', () => {
expect(isEven(3)).toBe(false);
expect(isEven(5)).toBe(false);
expect(isEven(7)).toBe(false);
expect(isEven(9)).toBe(false);
expect(isEven(11)).toBe(false);
});
});
7 changes: 3 additions & 4 deletions src/algorithms/math/bits/countSetBits.js
Original file line number Diff line number Diff line change
@@ -7,11 +7,10 @@ export default function countSetBits(originalNumber) {
let number = originalNumber;

while (number) {
// Add last bit of the number to the sum of set bits.
setBitsCount += number & 1;
// Using And operation on number with previous number.
number &= (number - 1);

// Shift number right by one bit to investigate other bits.
number >>= 1;
setBitsCount += 1;
}

return setBitsCount;
7 changes: 7 additions & 0 deletions src/algorithms/math/bits/isEven.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* @param {number} number
* @return {Boolean}
*/
export default function isEven(number) {
return ((number & 1) === 0);
}
14 changes: 14 additions & 0 deletions src/algorithms/math/extended-euclidean-algorithm/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Extended Euclidean algorithm

In arithmetic and computer programming, the extended Euclidean algorithm is an extension to the Euclidean algorithm,
and computes, in addition to the greatest common divisor of integers a and b, also the coefficients of Bézout's
identity, which are integers x and y such that `ax + by = gcd(a,b)`.
This is a certifying algorithm, because the gcd is the only number that can simultaneously satisfy this equation and
divide the inputs. It allows one to compute also, with almost no extra cost, the quotients of a and b by their
greatest common divisor.

![Extended](https://i.stack.imgur.com/UiQ2m.png)

## References

[Wikipedia](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm)
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import extendedEuclid from '../extendedEuclid';

describe('extendedEuclideanAlgorithm', () => {
it('should calculate coefficients', () => {
expect(extendedEuclid(30, 20)).toEqual({
gcd: 10,
x: 1,
y: -1,
});

expect(extendedEuclid(30, 50)).toEqual({
gcd: 10,
x: 2,
y: -1,
});

expect(extendedEuclid(65, 40)).toEqual({
gcd: 5,
x: -3,
y: 5,
});
});
});
21 changes: 21 additions & 0 deletions src/algorithms/math/extended-euclidean-algorithm/extendedEuclid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @param {number} Coefficient A
* @param {number} Coefficient B
* @return {Object} {gcd, x, y}
*/

export default function extendedEuclid(coeffA, coeffB) {
if (coeffA === 0) {
return {
gcd: coeffB,
x: 0,
y: 1,
};
}
const variables = extendedEuclid(coeffB % coeffA, coeffA);
return {
gcd: variables.gcd,
x: (variables.y - Math.floor(coeffB / coeffA) * variables.x),
y: variables.x,
};
}
8 changes: 8 additions & 0 deletions src/algorithms/math/nth-root/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Nth Power using Binary Search

In computer science, `binary search`, also known as `half-interval search`, `logarithmic search`, or `binary chop`,is a search algorithm that finds the position of a target value within a range or sorted array. Binary search compares the target value to the middle element of the range or array. If they are not equal, the half in which the target cannot lie is eliminated and the search continues on the remaining half, again taking the middle element to compare to the target value, and repeating this until the target value is found. If the search ends with the remaining half being empty, the target is not in the array. Even though the idea is simple, implementing binary search correctly requires attention to some subtleties about its exit conditions and midpoint calculation.

![Nth Root](https://upload.wikimedia.org/wikipedia/commons/8/83/Binary_Search_Depiction.svg)

## References
- [Wikipedia](https://en.wikipedia.org/wiki/Binary_search_algorithm)
12 changes: 12 additions & 0 deletions src/algorithms/math/nth-root/__test__/nthRoot.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import nthRoot from '../nthRoot';

describe('nth Root', () => {
it('should nth root of number', () => {
expect(nthRoot(2, 2)).toBeCloseTo(1.414213562373095);
expect(nthRoot(2, 3)).toBeCloseTo(1.259921049894873);
expect(nthRoot(2, 4)).toBeCloseTo(1.189207115);
expect(nthRoot(2, 5)).toBeCloseTo(1.148698354997035);
expect(nthRoot(2, 6)).toBeCloseTo(1.122462048309373);
expect(nthRoot(2, 7)).toBeCloseTo(1.104089513673812);
});
});
32 changes: 32 additions & 0 deletions src/algorithms/math/nth-root/nthRoot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* @param {number} num
* @param {number} power
* @return {number}
*/

export default function nthRoot(num, power) {
const E = 0.000000001;
const roundToMargin = (x) => {
return Math.round(x / E) * E;
};

let guess;
const calculateError = () => Math.abs(num - (guess ** power));

let start = 0;
let end = num;
let error = 1;

while (error > E) {
guess = (start + end) / 2;
error = calculateError();

if (guess ** power > num) {
end = guess;
} else {
start = guess;
}
}

return roundToMargin(guess);
}