diff --git a/countBitsToflipAToB.js b/countBitsToflipAToB.js new file mode 100644 index 0000000000..cc86883da7 --- /dev/null +++ b/countBitsToflipAToB.js @@ -0,0 +1,11 @@ +import countSetBits from 'countSetBits'; + +/** + * @param {number} number + * @return {number} + */ +export default function countBitsToflipAToB(numberA, numberB) { + + return countSetBits(numberA ^ numberB); + +} diff --git a/src/algorithms/math/bits/README.md b/src/algorithms/math/bits/README.md index 5d25efe578..13d17874fd 100644 --- a/src/algorithms/math/bits/README.md +++ b/src/algorithms/math/bits/README.md @@ -2,10 +2,10 @@ #### Get Bit -This method shifts the relevant bit to the zeroth position. -Then we perform `AND` operation with one which has bit +This method shifts the relevant bit to the zeroth position. +Then we perform `AND` operation with one which has bit pattern like `0001`. This clears all bits from the original -number except the relevant one. If the relevant bit is one, +number except the relevant one. If the relevant bit is one, the result is `1`, otherwise the result is `0`. > See `getBit` function for further details. @@ -24,7 +24,7 @@ other bits of the number. 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 +being applied to both the number and the mask. That operation unsets the bit. > See `clearBit` function for further details. @@ -39,17 +39,17 @@ This method is a combination of "Clear Bit" and "Set Bit" methods. This method shifts original number by one bit to the left. Thus all binary number components (powers of two) are being -multiplying by two and thus the number itself is being +multiplying by two and thus the number itself is being multiplied by two. ``` Before the shift Number: 0b0101 = 5 -Powers of two: 0 + 2^2 + 0 + 2^0 +Powers of two: 0 + 2^2 + 0 + 2^0 After the shift Number: 0b1010 = 10 -Powers of two: 2^3 + 0 + 2^1 + 0 +Powers of two: 2^3 + 0 + 2^1 + 0 ``` > See `multiplyByTwo` function for further details. @@ -58,17 +58,17 @@ Powers of two: 2^3 + 0 + 2^1 + 0 This method shifts original number by one bit to the right. Thus all binary number components (powers of two) are being -divided by two and thus the number itself is being +divided by two and thus the number itself is being divided by two without remainder. ``` Before the shift Number: 0b0101 = 5 -Powers of two: 0 + 2^2 + 0 + 2^0 +Powers of two: 0 + 2^2 + 0 + 2^0 After the shift Number: 0b0010 = 2 -Powers of two: 0 + 0 + 2^1 + 0 +Powers of two: 0 + 0 + 2^1 + 0 ``` > See `divideByTwo` function for further details. @@ -87,10 +87,145 @@ inverting all of the bits of the number and adding 1 to it. 0001 1 0010 2 0011 3 -``` +``` > See `switchSign` function for further details. +#### Count Set Bits + +This method counts the number of set bits in a number using bitwise operators. + +``` +Number: 5 = (0101)_2 +Count Set Bits = 2 +``` + +> See `countSetBits` function for further details. + +#### XOR Output Without Using XOR operator + +This method outputs the XOR of two numbers without using the XOR operator. + +``` +Number A : 5 = (0101)_2 +Number B : 1 = (0001)_2 +A XOR B : 4 = (0100)_2 +``` + +> See `XORWithoutXOR` function for further details. + +#### Count Bits to Flip One Number to Another + +This methods outputs the number of bits required to convert a number to another. This +makes use of property when numbers are XORed and `countSetBits`. + +``` +Number A : 5 = (0101)_2 +Number B : 1 = (0001)_2 +Count Bits to be Flipped: 1 +``` + +> See `countFlipAToB` function for further details. + +#### Multiply By 7 + +This method multiplies a number by 7 using bitwise operator. It uses the property that +`8*n - n` would be `7n` multiplied by the number. + +``` +Muliplier : 5 +Multiplied by 7 : 35 +``` + +> See `multiplyBy7` function for further details. + +#### Power of 2 + +This method checks if a number provided is power of two. It uses the property that when +a power of 2 is `&` with power of 2 minus 1, it would return 0 implying that the provided +number is power of 2. + +``` +Number: 4 +Power of 2: True + +Number: 1 +Power of 2: False +``` + +> See `ifPowerof2` function for further details. + +#### Pandigital Concatenation + +This method checks if pair of strings when concatenation consists of all digits from +(0-9) in any order at least once. Given an array of such numbers it returns the count +of number of possible pandigital concatenation. This uses the propery that when two +masks(all 1's) be i and j with frequencies freq_i and freq_j have + + +i | j = Mask_pandigitalconcatenation + +Then, +Number of pairs = freq_i * freq_j + +Using bitwise operators and with this approach the complexity of the method reduces to +`O(N * |s| + 1023 * 1023)` where `|s|` is the length of strings in the array. + +> See `pandigitalConcatenation` function for further details + +#### Booth's Multiplication + +This is the known algorithm where two signed binary numbers are multplied using 2's +complement notation. This algorithm primarily works on shifting than adding. The alorithm +works as + +Put multiplicant in A and multiplied in B +1. if C_n and C_n+1 are same i.e., 00 or 11 perform arithmetic shift by 1 bit. +2. If C_nC_n+1 = 10 do R += A and perform arithmetic shift by 1 bit. +3. if C_nC_n+1 = 01 do R -= A and peform arithmetic shift by 1 bit. + +``` +Number A : 2 +Number B : 3 + +Output : 6 +``` + +> See `boothsMultiplication` function for further details + +#### Alternating OR and XOR Operations in Segment Tree + +A segment tree can be implemented such that at every level the operations OR and XOR +alternates. This is an extension to the classical segment tree where every node is +represented as an integer and the parent node is built after building left and right +subtrees and then combining the results i.e., bottom up order. + +The number of levels would be `O(log n)` and T.C to update a node would be `O(log n)`. + +``` +Array : [6, 1, 4, 3, 7, 8, 9, 2] +Old Value at Root Node : 3 +New Value at Root Node : 11 + +``` + +> See `orXorSegmentTree` function for futher details. + + +#### Karatsuba Multiplication + +Given two numbers in binary representation, karatsuba algorithm find the multiplication +in O(n^1.59) T.C. + +This uses the fact that + +``` +AB = 22ceil(num / 2) A_1B_1 + 2ceil(num / 2) * [(A_1 + A_r)(B_1 + B_r) - A_1B_1 - A_rB_r] + A_rB_r +``` + +> See `karasubaMultiplication` function for further details. + + ## References - [Bit Manipulation on YouTube](https://www.youtube.com/watch?v=NLKQEOgBAnw&t=0s&index=28&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8) diff --git a/src/algorithms/math/bits/XORWithoutXOR.js b/src/algorithms/math/bits/XORWithoutXOR.js new file mode 100644 index 0000000000..1c4a15a3f2 --- /dev/null +++ b/src/algorithms/math/bits/XORWithoutXOR.js @@ -0,0 +1,7 @@ +/** + * @param {number} number + * @return {number} + */ +export default function XORWithoutXOR(numberA, numberB) { + return ((numberA | numberB) & (~numberA | ~numberB)); +} diff --git a/src/algorithms/math/bits/__test__/XORWithoutXOR.test.js b/src/algorithms/math/bits/__test__/XORWithoutXOR.test.js new file mode 100644 index 0000000000..d3528510db --- /dev/null +++ b/src/algorithms/math/bits/__test__/XORWithoutXOR.test.js @@ -0,0 +1,8 @@ +import XORWithoutXOR from '../XORWithoutXOR'; + +describe('XORWithoutXOR', () => { + it('Should return xor without using xor operator', () => { + expect(XORWithoutXOR(5, 7)).toBe(2); + expect(XORWithoutXOR(1, 2)).toBe(3); + }); +}); diff --git a/src/algorithms/math/bits/__test__/countSetBits.test.js b/src/algorithms/math/bits/__test__/countSetBits.test.js new file mode 100644 index 0000000000..ce897da201 --- /dev/null +++ b/src/algorithms/math/bits/__test__/countSetBits.test.js @@ -0,0 +1,8 @@ +import countSetBits from '../countSetBits'; + +describe('countSetBits', () => { + it('Should return number of set bits', () => { + expect(countSetBits(5)).toBe(2); + expect(countSetBits(1)).toBe(1); + }); +}); diff --git a/src/algorithms/math/bits/__test__/ifPowerOf2.test.js b/src/algorithms/math/bits/__test__/ifPowerOf2.test.js new file mode 100644 index 0000000000..564abc2081 --- /dev/null +++ b/src/algorithms/math/bits/__test__/ifPowerOf2.test.js @@ -0,0 +1,8 @@ +import ifPowerOf2 from '../ifPowerOf2'; + +describe('ifPowerOf2', () => { + it('Should return if the number is power of 2 or not', () => { + expect(ifPowerOf2(5)).toBe(false); + expect(ifPowerOf2(4)).toBe(true); + }); +}); diff --git a/src/algorithms/math/bits/__test__/multiplyBy7.test.js b/src/algorithms/math/bits/__test__/multiplyBy7.test.js new file mode 100644 index 0000000000..5ddf7623ee --- /dev/null +++ b/src/algorithms/math/bits/__test__/multiplyBy7.test.js @@ -0,0 +1,8 @@ +import multiplyBy7 from '../multiplyBy7'; + +describe('multiplyBy7', () => { + it('Should return result multiplied by 7', () => { + expect(multiplyBy7(1)).toBe(7); + expect(multiplyBy7(2)).toBe(14); + }); +}); diff --git a/src/algorithms/math/bits/boothsMultiplication.js b/src/algorithms/math/bits/boothsMultiplication.js new file mode 100644 index 0000000000..1252c2af61 --- /dev/null +++ b/src/algorithms/math/bits/boothsMultiplication.js @@ -0,0 +1,59 @@ +/** + * @param {number} number + * @return bool + */ +export default function boothsMultiplication(A, B) { + return A; +} + +function add(A, B, C) { + let x = 0; + for (let i = 0; i < C; i++) { + A[i] += B[i] + x; + if (A[i] > 1) { + A[i] = A[i] % 2; + c = 1; + } + else { + c = 0; + } +} + +function complement(A, N) { + let B = new Array(8); + B[0] = 1; + for (let i = 0; i < N; ++i) { + A[i] = (A[i] + 1) % 2; + } + add(A, B, N); +} + +function rightShift(A, Cq, Cn) { + for (i = 0; i < Cn - 1; i++) { + A[i] = A[i + 1]; + Cq[i] = Cq[i + 1]; + } +} + +function boothAlgorithm(B, Cr, multiplier, Cn, sc) { + let Cn = 0; + let Cq = new Array(10); + while (sc != 0) { + if ((Cn + Cr[0]) == 1) { + if (temp == 0) { + add(A, multiplier, Cn); + for (let i = Cn - 1; i >= 0; --i) + temp = 1; + else if (temp == 1) { + add(A, B, Cn); + for (let i = Cn - 1; i >= 0; --i) + temp = 0; + } + rightShift(A, Cr, Cn, Cq); + + else if (Cn - Cq[0] == 0) + rightShift(A, Cr, Cn, Cq); + --sc; + } +} + diff --git a/src/algorithms/math/bits/countSetBits.js b/src/algorithms/math/bits/countSetBits.js new file mode 100644 index 0000000000..d06418c6d5 --- /dev/null +++ b/src/algorithms/math/bits/countSetBits.js @@ -0,0 +1,13 @@ +/** + * @param {number} number + * @return {number} + */ +export default function countSetBits(number) { + let count = 0; + let num = number; // eslint error https://eslint.org/docs/rules/no-param-reassign + while (num) { + count += num & 1; + num >>= 1; + } + return count; +} diff --git a/src/algorithms/math/bits/flipAToB.js b/src/algorithms/math/bits/flipAToB.js new file mode 100644 index 0000000000..662bc11f70 --- /dev/null +++ b/src/algorithms/math/bits/flipAToB.js @@ -0,0 +1,11 @@ +import countSetBits from 'countSetBits'; + +/** + * @param {number} number + * @return {number} + */ +export default function countBitsToflipAToB(numberA, numberB) { + + return countSetBits(numberA ^ number B); + +} diff --git a/src/algorithms/math/bits/ifPowerOf2.js b/src/algorithms/math/bits/ifPowerOf2.js new file mode 100644 index 0000000000..dd29f9f21b --- /dev/null +++ b/src/algorithms/math/bits/ifPowerOf2.js @@ -0,0 +1,7 @@ +/** + * @param {number} number + * @return bool + */ +export default function ifPowerOf2(number) { + return number && (!(number & (number - 1))); +} diff --git a/src/algorithms/math/bits/karatsubaMultiplication.js b/src/algorithms/math/bits/karatsubaMultiplication.js new file mode 100644 index 0000000000..5f6ec95e27 --- /dev/null +++ b/src/algorithms/math/bits/karatsubaMultiplication.js @@ -0,0 +1,35 @@ +/** + * @param {number} number + * @return bool + */ +export default function karatsubaMultiplication(A, B) { + let A1, A2, B1, B2, base, multiplier; + base = 10; + + if(( A < base ) || ( B < base )) { + return A * B; + } + + let tempA = A.toString(); + let tempB = B.toString(); + + let num = (tempA.length > tempB.length) ? tempB.length : tempA.length; + multiplier = Math.round(num >> 1); + + var highBits1 = parseInt(tempA.substring(0, tempA.length - multiplier)); + var lowBits1 = parseInt(tempA.substring(tempA.length - multiplier, tempA.length)) ; + + var highBits2 = parseInt(tempB.substring(0, tempB.length - multiplier)); + var lowBits2 = parseInt(tempB.substring(tempB.length - multiplier, tempB.length)); + + + var res0 = karatsubaMultiplication(lowBits1, lowBits2); + var res1 = karatsubaMultiplicationa(lowBits1 + highBits1, lowBits2 + highBits2); + var res2 = karatsubaMultiplication(highBits1, highBits2); + + var res = (res2 * Math.pow(10, multiplier << 1 )) + ((res1 - res2 - res0) * Math.pow(10, multiplier)) + res0; + + return res; + + } + diff --git a/src/algorithms/math/bits/multiplyBy7.js b/src/algorithms/math/bits/multiplyBy7.js new file mode 100644 index 0000000000..78b6bd7926 --- /dev/null +++ b/src/algorithms/math/bits/multiplyBy7.js @@ -0,0 +1,7 @@ +/** + * @param {number} number + * @return {number} + */ +export default function multiplyBy7(number) { + return ((number << 3) - number); +} diff --git a/src/algorithms/math/bits/pandigitalConcatenation.js b/src/algorithms/math/bits/pandigitalConcatenation.js new file mode 100644 index 0000000000..272564bc23 --- /dev/null +++ b/src/algorithms/math/bits/pandigitalConcatenation.js @@ -0,0 +1,50 @@ +/** + * @param {number} number + * @param {number} bitPosition - zero based. + * @return {number} + */ +export default function pandigitalConcatenation(input) { + return countPairs(input); +} + +function pandigitalConcatenation(input, hashMap) { + let res = 0; + + for(let i = 1; i <= 1023; ++i) { + for(let j = 1; j < 1023; ++j) { + if((i | j) == pdMask) { + if(i == j){ + res += (hashMap[i] * (hashMap[i] - 1))'' + } + else { + res += (hashMap[i] * hashMap[j]); + } + } + } + } + return res/2; +} + +function calucateFrequencies(input, hashMap) { + for (let i = 0; i < input.length; ++i) { + let mask = 0; + + let digits = new Set(); + + for(let j = 0; j < input[i].size; ++j) { + digits.add(input[i][j] - '0'); + } + + digits.foreach(callback) => { + mask += (1 << digit); + } + + ++hashMap[mask]; + } +} + +function countPairs(input) { + let hashMap = {}; + calculateFrequencies(input, hashMap); + return pandigitalConcatenation(input); +}