Skip to content

Commit ab00f01

Browse files
authored
Merge pull request #7 from ZapDos7/feature/binary-hacks
Binary hacks
2 parents 5393038 + 36b981d commit ab00f01

File tree

13 files changed

+257
-16
lines changed

13 files changed

+257
-16
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@
5353
- [x] Hamming Weight implementation (return 1-bits of a binary representation of a number)
5454
- [x] [Binary to Decimal Converter](https://tausiq.wordpress.com/2009/07/27/uab-2005-problem-3-binary-to-decimal-converter/)
5555
- [x] [Reverse bits](https://leetcode.com/problems/reverse-bits/)
56+
- [x] [Bit Hacks — Part 1 (Basic)](http://www.techiedelight.com/bit-hacks-part-1-basic/)
57+
- [x] [Bit Hacks — Part 2 (Playing with k’th bit)](http://www.techiedelight.com/bit-hacks-part-2-playing-kth-bit/)
58+
- [x] [Bit Hacks — Part 3 (Playing with rightmost set bit of a number)](http://www.techiedelight.com/bit-hacks-part-3-playing-rightmost-set-bit-number/)
59+
- [x] [Bit Hacks — Part 4 (Playing with letters of English alphabet)](http://www.techiedelight.com/bit-hacks-part-4-playing-letters-english-alphabet/)
60+
- [x] [Bit Hacks — Part 5 (Find absolute value of an integer without branching)](http://www.techiedelight.com/bit-hacks-part-5-find-absolute-value-integer-without-branching/)
61+
- [x] [Bit Hacks — Part 6 (Random Problems)](http://www.techiedelight.com/bit-hacks-part-6-random-problems/)
5662

5763
## Algorithms
5864

@@ -170,12 +176,6 @@
170176
## To Do
171177

172178
- Bits Manipulation
173-
- [ ] [Bit Hacks — Part 1 (Basic)](http://www.techiedelight.com/bit-hacks-part-1-basic/)
174-
- [ ] [Bit Hacks — Part 2 (Playing with k’th bit)](http://www.techiedelight.com/bit-hacks-part-2-playing-kth-bit/)
175-
- [ ] [Bit Hacks — Part 3 (Playing with rightmost set bit of a number)](http://www.techiedelight.com/bit-hacks-part-3-playing-rightmost-set-bit-number/)
176-
- [ ] [Bit Hacks — Part 4 (Playing with letters of English alphabet)](http://www.techiedelight.com/bit-hacks-part-4-playing-letters-english-alphabet/)
177-
- [ ] [Bit Hacks — Part 5 (Find absolute value of an integer without branching)](http://www.techiedelight.com/bit-hacks-part-5-find-absolute-value-integer-without-branching/)
178-
- [ ] [Bit Hacks — Part 6 (Random Problems)](http://www.techiedelight.com/bit-hacks-part-6-random-problems/)
179179
- [ ] [Brian Kernighan’s Algorithm to count set bits in an integer](http://www.techiedelight.com/brian-kernighans-algorithm-count-set-bits-integer/)
180180
- [ ] [Compute parity of a number using lookup table](http://www.techiedelight.com/compute-parity-number-using-lookup-table/)
181181
- [ ] [Count set bits using lookup table](http://www.techiedelight.com/count-set-bits-using-lookup-table/)

src/binary/BitManipulation.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package binary;
22

3+
/* Also check: https://www.techiedelight.com/bit-hacks-part-2-playing-kth-bit/ */
34
public class BitManipulation {
45
public static void main(String[] args) {
56
int num = 42; // 0b101010
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package binary.absoluteCalculator;
2+
3+
import utils.InputReader;
4+
5+
// Given an integer, compute its absolute value (abs) without branching.
6+
public class AbsolutNumCalculator {
7+
8+
public static void main(String[] args) {
9+
System.out.println("Provide input number: ");
10+
int input = InputReader.readInt();
11+
System.out.println("No branching: " + absoluteNoBranch(input));
12+
System.out.println("Yes branching: " + absoluteYesBranch(input));
13+
}
14+
15+
private static int absoluteNoBranch(int x) {
16+
final int mask = x >> 31; // correct for 32-bit int
17+
return ((x + mask) ^ mask);
18+
// Explanation:
19+
// mask = x >> 31 gives:
20+
// 0 if x ≥ 0
21+
// -1 (all 1s) if x < 0 (in two's complement)
22+
// Then:
23+
// x + mask subtracts 1 from x if mask == -1
24+
// XOR with mask flips bits if mask == -1
25+
// Equivalent to x >= 0 ? x : -x
26+
}
27+
28+
private static int absoluteYesBranch(int n) {
29+
return ((n >> 31) & 1) == 1 ? -n : n; // ((n >> 31) & 1) ? (~n + 1) : n;
30+
// Explanation:
31+
// 1. shift 31 bits: keep sign bit (leftmost)
32+
// that's 0 for even nums and 1 for odd ones
33+
// 2. masking with 1
34+
// (0 for positives, 1s from two's complement for negatives)
35+
// 3. AND 1 to extract the least significant bit
36+
// If n >= 0, (n >> 31) is 0, so (n >> 31) & 1 = 0.
37+
// If n < 0, (n >> 31) is -1 (binary 111...111), so (n >> 31) & 1 = 1.
38+
}
39+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package binary.binCheckOddOrEven;
2+
3+
import utils.InputReader;
4+
5+
// The expression n & 1 returns value 1 or 0 depending upon whether n is odd or even.
6+
public class BinaryCheckOddEvenNum {
7+
public static void main(String[] args) {
8+
System.out.print("Input a number: ");
9+
int n = InputReader.readInt();
10+
if ((n & 1) != 0) {
11+
System.out.println(n + " is odd");
12+
}
13+
else {
14+
System.out.println(n + " is even");
15+
}
16+
}
17+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package binary.compareSigns;
2+
3+
import utils.InputReader;
4+
5+
// x ^ y is negative if x and y have opposite signs
6+
public class IntSignsComparator {
7+
public static void main(String[] args) {
8+
System.out.print("Input a number: ");
9+
int x = InputReader.readInt();
10+
System.out.print("Input another number: ");
11+
int y = InputReader.readInt();
12+
13+
if ((x ^ y) < 0) {
14+
System.out.println("They have opposite signs");
15+
}
16+
else {
17+
System.out.println("They have the same sign");
18+
}
19+
}
20+
}

src/binary/hammingWeight/HammingWeight.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ static int getHammingWeight2(int input) {
2020
return res;
2121
}
2222

23+
// Parity
24+
public static int findParity(int n) {
25+
return getHammingWeight(n) % 2;
26+
}
27+
28+
public static boolean isParityEven(int n) {
29+
return findParity(n) / 2 == 0;
30+
}
31+
2332
// String logic
2433
static int getHammingWeight(int input) {
2534
var toBinary = Integer.toBinaryString(input);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package binary.letters;
2+
3+
public class UpperLowercaseSwapper {
4+
public static void main(String[] args) {
5+
// to lowercase
6+
for (char ch = 'A'; ch <= 'Z'; ch++) {
7+
System.out.print((char) (ch | ' ')); // OR space
8+
}
9+
System.out.println();
10+
// to uppercase
11+
for (char ch = 'a'; ch <= 'z'; ch++) {
12+
System.out.print((char) (ch & '_')); // AND underscore
13+
}
14+
15+
/* Why does this work?
16+
* Character ASCII (Decimal) ASCII (Binary) Changes
17+
'A' 65 01000001
18+
'a' 97 01100001 'A' → 'a' adds 32 → sets bit 5 (counting from 0)
19+
' ' 32 00100000 OR'ing with space sets bit 5, XOR'ing with space flips bit 5 so swaps the case
20+
'_' 95 01011111 AND'ing with underscore clears bit 5
21+
* */
22+
23+
System.out.println();
24+
System.out.println();
25+
// to invert
26+
// lowercase uppercase
27+
for (char ch = 'a'; ch <= 'z'; ch++) {
28+
System.out.print((char) (ch ^ ' ')); // XOR space
29+
}
30+
System.out.println();
31+
// same for uppercase to lowercase
32+
for (char ch = 'A'; ch <= 'Z'; ch++) {
33+
System.out.print((char) (ch ^ ' ')); // XOR space
34+
}
35+
36+
System.out.println();
37+
System.out.println();
38+
// find letter's position in alphabet - AND 31
39+
for (char ch = 'a'; ch <= 'z'; ch++) {
40+
System.out.println(ch + " is in alphabet index " + (ch & 31)); // AND 31 (00011111)
41+
}
42+
}
43+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package binary.rightmostBit;
2+
3+
import utils.InputReader;
4+
5+
public class OnlySetBitFinder {
6+
public static void main(String[] args) {
7+
System.out.print("Input a number: ");
8+
int x = InputReader.readInt();
9+
System.out.print("Position of only set bit: " + positionOfSet(x));
10+
}
11+
12+
public static int positionOfSet(int n) {
13+
// unset the rightmost bit and check if the number is non-zero
14+
if ((n & (n - 1)) != 0)
15+
{
16+
System.out.println("Wrong input");
17+
return 1;
18+
}
19+
// If 0, we can find the position of the only set bit by directly using log2(n) + 1.
20+
return log(n, 2) + 1;
21+
}
22+
23+
public static int log(int x, int base) {
24+
return (int) (Math.log(x) / Math.log(base));
25+
}
26+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package binary.rightmostBit;
2+
3+
import utils.InputReader;
4+
5+
public class RightmostBitPositionFinder {
6+
public static void main(String[] args) {
7+
System.out.print("Input a number: ");
8+
int x = InputReader.readInt();
9+
//unset the rightmost bit of number & XOR the result with number
10+
System.out.print("Result: " + positionOfRightmostSetBit(x));
11+
}
12+
13+
static int positionOfRightmostSetBit(int n)
14+
{
15+
// if the number is odd, return 1
16+
if ((n & 1) != 0) {
17+
return 1;
18+
}
19+
20+
// unset rightmost bit and xor with the number itself
21+
n = n ^ (n & (n - 1));
22+
23+
// find the position of the only set bit in the result;
24+
// we can directly return `log2(n) + 1` from the function
25+
int pos = 0;
26+
while (n != 0)
27+
{
28+
n = n >> 1;
29+
pos++;
30+
}
31+
return pos;
32+
}
33+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package binary.rightmostBit;
2+
3+
import utils.InputReader;
4+
5+
// The expression n & (n-1) will turn off the rightmost set bit of a number n
6+
public class Unsetter {
7+
public static void main(String[] args) {
8+
System.out.print("Input a number: ");
9+
int x = InputReader.readInt();
10+
System.out.print("Unsetting the rightmost bit: " + unset(x));
11+
}
12+
13+
public static int unset(int x) {
14+
return x & (x-1);
15+
}
16+
}

0 commit comments

Comments
 (0)