Skip to content

Add few algos implementation #133

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
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
11 changes: 11 additions & 0 deletions countBitsToflipAToB.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import countSetBits from 'countSetBits';

/**
* @param {number} number
* @return {number}
*/
export default function countBitsToflipAToB(numberA, numberB) {

return countSetBits(numberA ^ numberB);

}
157 changes: 146 additions & 11 deletions src/algorithms/math/bits/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions src/algorithms/math/bits/XORWithoutXOR.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* @param {number} number
* @return {number}
*/
export default function XORWithoutXOR(numberA, numberB) {
return ((numberA | numberB) & (~numberA | ~numberB));
}
8 changes: 8 additions & 0 deletions src/algorithms/math/bits/__test__/XORWithoutXOR.test.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
8 changes: 8 additions & 0 deletions src/algorithms/math/bits/__test__/countSetBits.test.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
8 changes: 8 additions & 0 deletions src/algorithms/math/bits/__test__/ifPowerOf2.test.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
8 changes: 8 additions & 0 deletions src/algorithms/math/bits/__test__/multiplyBy7.test.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
59 changes: 59 additions & 0 deletions src/algorithms/math/bits/boothsMultiplication.js
Original file line number Diff line number Diff line change
@@ -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;
}
}

13 changes: 13 additions & 0 deletions src/algorithms/math/bits/countSetBits.js
Original file line number Diff line number Diff line change
@@ -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;
}
11 changes: 11 additions & 0 deletions src/algorithms/math/bits/flipAToB.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import countSetBits from 'countSetBits';

/**
* @param {number} number
* @return {number}
*/
export default function countBitsToflipAToB(numberA, numberB) {

return countSetBits(numberA ^ number B);

}
7 changes: 7 additions & 0 deletions src/algorithms/math/bits/ifPowerOf2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* @param {number} number
* @return bool
*/
export default function ifPowerOf2(number) {
return number && (!(number & (number - 1)));
}
35 changes: 35 additions & 0 deletions src/algorithms/math/bits/karatsubaMultiplication.js
Original file line number Diff line number Diff line change
@@ -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;

}

Loading