From 792f4906df14fc8d193f1b2ad3d405a3646055a9 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Wed, 27 Jun 2018 17:19:20 +0300 Subject: [PATCH] Add bit manipulation section. --- README.md | 1 + src/algorithms/math/bits/README.md | 37 +++++++++++++++++++ .../math/bits/__test__/clearBit.test.js | 15 ++++++++ .../math/bits/__test__/getBit.test.js | 23 ++++++++++++ .../math/bits/__test__/setBit.test.js | 15 ++++++++ .../math/bits/__test__/updateBit.test.js | 19 ++++++++++ src/algorithms/math/bits/clearBit.js | 10 +++++ src/algorithms/math/bits/getBit.js | 8 ++++ src/algorithms/math/bits/setBit.js | 8 ++++ src/algorithms/math/bits/updateBit.js | 16 ++++++++ 10 files changed, 152 insertions(+) create mode 100644 src/algorithms/math/bits/README.md create mode 100644 src/algorithms/math/bits/__test__/clearBit.test.js create mode 100644 src/algorithms/math/bits/__test__/getBit.test.js create mode 100644 src/algorithms/math/bits/__test__/setBit.test.js create mode 100644 src/algorithms/math/bits/__test__/updateBit.test.js create mode 100644 src/algorithms/math/bits/clearBit.js create mode 100644 src/algorithms/math/bits/getBit.js create mode 100644 src/algorithms/math/bits/setBit.js create mode 100644 src/algorithms/math/bits/updateBit.js diff --git a/README.md b/README.md index 088005fe..b46717ec 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ a set of rules that precisely define a sequence of operations. ### Algorithms by Topic * **Math** + * `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits * `B` [Factorial](src/algorithms/math/factorial) * `B` [Fibonacci Number](src/algorithms/math/fibonacci) * `B` [Primality Test](src/algorithms/math/primality-test) (trial division method) diff --git a/src/algorithms/math/bits/README.md b/src/algorithms/math/bits/README.md new file mode 100644 index 00000000..b56b06cb --- /dev/null +++ b/src/algorithms/math/bits/README.md @@ -0,0 +1,37 @@ +# Bit Manipulation + +#### Get Bit + +This method shifts `1` over by `bitPosition` bits, creating a +value that looks like `00100`. Then we perform `AND` operation +that clears all bits from the original number except the +`bitPosition` one. Then we compare the result with zero. If +result is zero that would mean that original number has `0` at +position `bitPosition`. + +> See `getBit` function for further details. + +#### Set Bit + +This method shifts `1` over by `bitPosition` bits, creating a +value that looks like `00100`. Then we perform `OR` operation +that sets specific bit into `1` but it does not affect on +other bits of the number. + +> See `setBit` function for further details. + +#### Clear Bit + +This method shifts `1` over by `bitPosition` bits, creating a +value that looks like `00100`. Than it inverts this mask to get +the number that looks like `11011`. Then `AND` operation is +being applied to both the number and the mask. That operation +unsets the bit. + +> See `clearBit` function for further details. + +#### Update Bit + +This method is a combination of "Clear Bit" and "Set Bit" methods. + +> See `updateBit` function for further details. diff --git a/src/algorithms/math/bits/__test__/clearBit.test.js b/src/algorithms/math/bits/__test__/clearBit.test.js new file mode 100644 index 00000000..2d758779 --- /dev/null +++ b/src/algorithms/math/bits/__test__/clearBit.test.js @@ -0,0 +1,15 @@ +import clearBit from '../clearBit'; + +describe('clearBit', () => { + it('should clear bit at specific position', () => { + // 1 = 0b0001 + expect(clearBit(1, 0)).toBe(0); + expect(clearBit(1, 1)).toBe(1); + expect(clearBit(1, 2)).toBe(1); + + // 10 = 0b1010 + expect(clearBit(10, 0)).toBe(10); + expect(clearBit(10, 1)).toBe(8); + expect(clearBit(10, 3)).toBe(2); + }); +}); diff --git a/src/algorithms/math/bits/__test__/getBit.test.js b/src/algorithms/math/bits/__test__/getBit.test.js new file mode 100644 index 00000000..3a7026f2 --- /dev/null +++ b/src/algorithms/math/bits/__test__/getBit.test.js @@ -0,0 +1,23 @@ +import getBit from '../getBit'; + +describe('getBit', () => { + it('should get bit at specific position', () => { + // 1 = 0b0001 + expect(getBit(1, 0)).toBe(1); + expect(getBit(1, 1)).toBe(0); + + // 2 = 0b0010 + expect(getBit(2, 0)).toBe(0); + expect(getBit(2, 1)).toBe(1); + + // 3 = 0b0011 + expect(getBit(3, 0)).toBe(1); + expect(getBit(3, 1)).toBe(1); + + // 10 = 0b1010 + expect(getBit(10, 0)).toBe(0); + expect(getBit(10, 1)).toBe(1); + expect(getBit(10, 2)).toBe(0); + expect(getBit(10, 3)).toBe(1); + }); +}); diff --git a/src/algorithms/math/bits/__test__/setBit.test.js b/src/algorithms/math/bits/__test__/setBit.test.js new file mode 100644 index 00000000..d53d60c7 --- /dev/null +++ b/src/algorithms/math/bits/__test__/setBit.test.js @@ -0,0 +1,15 @@ +import setBit from '../setBit'; + +describe('setBit', () => { + it('should set bit at specific position', () => { + // 1 = 0b0001 + expect(setBit(1, 0)).toBe(1); + expect(setBit(1, 1)).toBe(3); + expect(setBit(1, 2)).toBe(5); + + // 10 = 0b1010 + expect(setBit(10, 0)).toBe(11); + expect(setBit(10, 1)).toBe(10); + expect(setBit(10, 2)).toBe(14); + }); +}); diff --git a/src/algorithms/math/bits/__test__/updateBit.test.js b/src/algorithms/math/bits/__test__/updateBit.test.js new file mode 100644 index 00000000..e2ac2db0 --- /dev/null +++ b/src/algorithms/math/bits/__test__/updateBit.test.js @@ -0,0 +1,19 @@ +import updateBit from '../updateBit'; + +describe('updateBit', () => { + it('should update bit at specific position', () => { + // 1 = 0b0001 + expect(updateBit(1, 0, 1)).toBe(1); + expect(updateBit(1, 0, 0)).toBe(0); + expect(updateBit(1, 1, 1)).toBe(3); + expect(updateBit(1, 2, 1)).toBe(5); + + // 10 = 0b1010 + expect(updateBit(10, 0, 1)).toBe(11); + expect(updateBit(10, 0, 0)).toBe(10); + expect(updateBit(10, 1, 1)).toBe(10); + expect(updateBit(10, 1, 0)).toBe(8); + expect(updateBit(10, 2, 1)).toBe(14); + expect(updateBit(10, 2, 0)).toBe(10); + }); +}); diff --git a/src/algorithms/math/bits/clearBit.js b/src/algorithms/math/bits/clearBit.js new file mode 100644 index 00000000..0329a047 --- /dev/null +++ b/src/algorithms/math/bits/clearBit.js @@ -0,0 +1,10 @@ +/** + * @param {number} number + * @param {number} bitPosition - zero based. + * @return {number} + */ +export default function clearBit(number, bitPosition) { + const mask = ~(1 << bitPosition); + + return number & mask; +} diff --git a/src/algorithms/math/bits/getBit.js b/src/algorithms/math/bits/getBit.js new file mode 100644 index 00000000..a99ce7d5 --- /dev/null +++ b/src/algorithms/math/bits/getBit.js @@ -0,0 +1,8 @@ +/** + * @param {number} number + * @param {number} bitPosition - zero based. + * @return {number} + */ +export default function getBit(number, bitPosition) { + return (number & (1 << bitPosition)) === 0 ? 0 : 1; +} diff --git a/src/algorithms/math/bits/setBit.js b/src/algorithms/math/bits/setBit.js new file mode 100644 index 00000000..c574ac69 --- /dev/null +++ b/src/algorithms/math/bits/setBit.js @@ -0,0 +1,8 @@ +/** + * @param {number} number + * @param {number} bitPosition - zero based. + * @return {number} + */ +export default function setBit(number, bitPosition) { + return number | (1 << bitPosition); +} diff --git a/src/algorithms/math/bits/updateBit.js b/src/algorithms/math/bits/updateBit.js new file mode 100644 index 00000000..b338cd0e --- /dev/null +++ b/src/algorithms/math/bits/updateBit.js @@ -0,0 +1,16 @@ +/** + * @param {number} number + * @param {number} bitPosition - zero based. + * @param {number} bitValue - 0 or 1. + * @return {number} + */ +export default function updateBit(number, bitPosition, bitValue) { + // Normalized bit value. + const bitValueNormalized = bitValue ? 1 : 0; + + // Init clear mask. + const clearMask = ~(1 << bitPosition); + + // Cleat bit value and then set it up to required value. + return (number & clearMask) | (bitValueNormalized << bitPosition); +}