-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathLargestAndSmallestIntWithSameNumberOfSetBits.cs
More file actions
143 lines (122 loc) · 4.06 KB
/
LargestAndSmallestIntWithSameNumberOfSetBits.cs
File metadata and controls
143 lines (122 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics;
// Find the largest and smallest numbers that have the same number of bits
// as the input number.
namespace LargestAndSmallestNumberWithSameNumberOfSetBits
{
public static class FindLargestAndSmallest
{
public static int Smallest(int num)
{
if (num < 0) { throw new ArgumentOutOfRangeException(); }
if (num == 0) { return 0; }
int bits = CountSetBits(num);
// Construct new number consuming bits from LSB to MSB.
int mask = 1;
int result = 0;
while (bits > 0)
{
result |= mask;
mask <<= 1;
bits--;
}
return result;
}
public static int Largest(int num)
{
if (num < 0) { throw new ArgumentOutOfRangeException(); }
if (num == 0) { return 0; }
int bits = CountSetBits(num);
// Construct new number consuming bits from MSB to LSB.
int mask = unchecked((1 << 31) - 1); // Remember MSB is negative sign
Debug.Assert(mask == Math.Pow(2, 31) - 1, "Expected mask to be 2^31 - 1.");
int result = 0;
while (bits > 0)
{
result |= mask;
mask >>= 1;
bits--;
}
return result;
}
/// <summary>
/// Find number of set bits using Brian Kernighan method
/// </summary>
private static int CountSetBits(int num)
{
int bits;
for (bits = 0; num > 0; bits++)
{
num &= num - 1;
}
return bits;
}
}
[TestClass]
public class FindLargestAndSmallestTests
{
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void Smallest_WhenNegative_ExpectException()
{
FindLargestAndSmallest.Smallest(-1);
}
[TestMethod]
public void Smallest_WhenZero_ExpectZero()
{
Assert.AreEqual(0, FindLargestAndSmallest.Smallest(0));
}
[TestMethod]
public void Smallest_WhenOneBit_ExpectOne()
{
Assert.AreEqual(1, FindLargestAndSmallest.Smallest(2));
}
[TestMethod]
public void Smallest_WhenTwoBits_ExpectThree()
{
Assert.AreEqual(3, FindLargestAndSmallest.Smallest(12));
}
[TestMethod]
public void Smallest_WhenMaxIntBits_ExpectMaxIntBits()
{
// Remember that first bit is negative sign so:
// Negative: 2^31 values
// Zero: 1 value
// Positive: 2^31 - 1 values
Assert.AreEqual(int.MaxValue, FindLargestAndSmallest.Smallest(int.MaxValue));
}
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void Largest_WhenNegative_ExpectException()
{
FindLargestAndSmallest.Largest(-1);
}
[TestMethod]
public void Largest_WhenZero_ExpectZero()
{
Assert.AreEqual(0, FindLargestAndSmallest.Largest(0));
}
[TestMethod]
public void Largest_WhenOneBit_ExpectOne()
{
var expected = unchecked((1 << 31) - 1);
Assert.AreEqual(expected, FindLargestAndSmallest.Largest(2));
}
[TestMethod]
public void Largest_WhenTwoBits_ExpectThree()
{
var expected = unchecked( ((1 << 31) - 1) | (1 << 30));
Assert.AreEqual(expected, FindLargestAndSmallest.Largest(12));
}
[TestMethod]
public void Largest_WhenMaxIntBits_ExpectMaxIntBits()
{
// Remember that first bit is negative sign so:
// Negative: 2^31 values
// Zero: 1 value
// Positive: 2^31 - 1 values
Assert.AreEqual(int.MaxValue, FindLargestAndSmallest.Largest(int.MaxValue));
}
}
}