Maximum bitwise AND of all possible pairs in a given range - algorithm

Given a range [l, r] find the maximum bitwise AND of all the possible pairs present.
What approach should I take in order to to solve it efficiently?

Here is a javascript implementation:
function maxAndInRange2(start, end) {
if (end - start == 0) return 0;
if (end - start == 1) return end & start;
if (end % 2 == 0) return (end - 1) & (end - 2)
return end & (end - 1)
}
If end is odd, then the answer must be end & (end - 1), because end - 1 will have all the same binary digits except the last one, which will be turned into a 0. So the result of this will be end - 1, clearly no other pair can be higher than this.
If end is even, then (end - 1) is odd. With the same logic, (end - 1) & (end - 2) will give us (end - 2). Can there be a higher pair than this? Only end - 1 could be higher, but end & (end - 1) won´t give us end - 1 in this case, so (end - 2) is the highest result

Related

Explanation of formula to count # of iterations in a loop

https://stackoverflow.com/a/66458617/18069660
total iterations = (end - start + incr)/incr; // for <=
total iterations = (end - start + incr - 1)/incr; // for <
I have tested both of these formulas and different versions of each for different kinds of for loops. I understand how they work, what I do not understand is how they were made.
Why does the total number of iterations = (the end value minus the start value + the increment)/(divided by the increment).
Why and how were these values chosen and used in such a manner to count the number of iterations. What is the connection between them? How was the formula derived?
Let's first look at the loop that uses <=:
for (int i = start; i <= end; i += incr)
Let's look at the value of i at each iteration:
Iteration
value of i
1
start
2
start + incr
3
start + 2*incr
4
start + 3*incr
...
...
n
start + (n-1)*incr
Case A. i becomes equal to end
If end happens to be one of the values in the second column, for instance, end == start + k*incr for some k, then we can see the number of iterations is k+1.
So we have now the following rule:
If end can be written as start + k*incr for some integer k, then the number of iterations is k+1 and so we can write:
end == start + (numIterations - 1)*incr
Which is equivalent to saying:
numIterations = (end - start) / incr + 1
Or also:
numIterations = (end - start + incr) / incr
Case B: i never becomes equal to end
In this case there is no integer k such that end == start + k*incr. We can find the greatest k for which end < start + k*incr. In other words, there is a positive remainder < incr such that end == start + k*incr + remainder.
We repeat the logic in the previous point, but with that non-zero remainder:
end == start + (numIterations - 1)*incr + remainder
Which is equivalent to saying:
numIterations = (end - start - remainder) / incr + 1
Or also:
numIterations = (end - start - remainder + incr) / incr
When / represents integer division, we don't have to subtract the remainder in that numerator. The integer division will exclude the fractional part that you would get with a real division. So we can simplify to:
numIterations = (end - start + incr) / incr
I hope this explains the case for a loop with <= end.
Loop with < end
When the loop variable cannot become equal to end, but at the most to end-1, then let's translate this case to a loop where the condition is <= end - 1. It is equivalent.
Then apply the formula above by replacing end with end-1, and we get the second form of the formula you presented.

Finding the Nth number where a given binary digit is set to 0

I am looking for an algorithm which given a target, the Nth number with that target bit at 0 is returned.
For example, for the inputs of n={0,1,2,3} and target=1,
The output would be (in binary)
000,001,100,101
Just write the value N-1 (if enumeration starts from 1) in binary, and then insert a 0 in the required position (target).
For example:
for N=3 and target=1
N-1 = 10bin
inserting 0 in 1-th position gives
R = 100b = 4dec
with bit operations:
NN = N- 1
Mask = (1 << target) - 1 //like 00000111 for target=3
NotMask = ~ Mask //like 11111000 for target=3
R = (NN & Mask) | ((NN & NotMask) << 1)
expression (NN & Mask) selects bits right to target bit (zeroing other bits)
expression (NN & NotMask) << 1 selects left bits, then shifts them to free a place for zero target bit
The target bit oscillates between being unset target**2 times and set target**2 times, as we move up the sequence of natural numbers. So we can directly calculate the nth number where the target bit is unset.
JavaScript code:
function f(n, target){
let block = 1 << target
if (n < block)
return n
let index_in_block = n % block;
let num_set_blocks = (n - index_in_block) / block
return 2 * num_set_blocks * block + index_in_block
}
for (let i=0; i<10; i++)
console.log(i, f(i, 1))

VBA permutations of undetermined number of variables

Recently I am trying to get the permutation of undetermined number of variables. For undetermined I mean I was aiming to create an input box for users to put in the number.
Start from simple. Originally I was aiming to get a 4 digits permutations with each digit have different number of variables, i.e. 1st digit can only be A,B,C,D; 2nd digit be E,F; 3rd digit be G, H etc. Code are below:
Sub Permut()
Count = 1
For a = 1 To 4
For b = 1 To 2
For c = 1 To 2
For d = 1 To 2
For e = 1 To 2
'chr(97) is the alphabet "a"
Cells(Count, 1) = Chr(96 + a) & Chr(96 + Len(a) + b) & Chr(96 + Len(a) + Len(b) + c) & _
Chr(96 + Len(a) + Len(b) + Len(c) + d) & Chr(96 + Len(a) + Len(b) + Len(c) + Len(d) + e)
Count = Count + 1
Next
Next
Next
Next
Next
End Sub
This will give you 64 different combinations without repetition.
Just wondering is there a way to generalize this process so that people can choose how many variables in total as well as within each digit?
Thank you.
Here is a solution, where you would pass the Permut function the minimum value for each of the characters (digits) as one string, and the maximum characters also as a string. Both strings should have an equal number of characters of course:
Function Permut(min, max)
Dim str, nxt, count
str = min
count = 1
Do While str < max
Cells(count, 1) = str
count = count + 1
nxt = ""
For i = Len(str) To 1 Step -1
If Mid(str, i, 1) < Mid(max, i, 1) Then
nxt = ChrW(AscW(Mid(str, i, 1))+1) & nxt
Exit For
End If
nxt = Mid(min, i, 1) & nxt
Next
str = Left(str, Len(str) - Len(nxt)) & nxt
Loop
Cells(count, 1) = str
End Sub
You would call it like this:
Permut "abc", "bcf"
That example would produce this list on your sheet:
abc
abd
abe
abf
acc
acd
ace
acf
bbc
bbd
bbe
bbf
bcc
bcd
bce
bcf
How to Execute This with User Input and Button Click
If you want to call this code in response to an event, such as a button click, and want to pass it the contents of two cells where the user would first enter the min and max strings, then follow these steps:
Place an ActiveX command button on your sheet (put it somewhere in D1 to leave room for some other stuff)
Double click it to generate the empty click event handler. If that does not work, go to the code window and select the name of the button from the drop-down at the top of the window, and select Click from the next drop down.
Complete the code of that event handler as follows (I assume the button is called CommandButton1, but don't change the generated name):
Code:
Private Sub CommandButton1_Click()
Permut Range("B1"), Range("C1")
End Sub
This code assumes the user has to enter the min and max digits/characters in cells B1 and C1. The A column is of course reserved for the output of the code.
For a more complete explanation on how to add a command button and attach code to its click event, read "Add a command button (ActiveX control)" in the Office manual.
credit to the answer from trincot above.
I have tried to run the code with a bit modification coz I am not sure how to get set value into cells (0,1). It keeps saying error. But If I change the starting point to Cells(1,1) then I will miss the last permutation. So I just add an additional if statement to get the code work as I want.
Function Permut(min, max)
Dim str, nxt, count
str = min
count = 1
Do While str < max
Cells(count, 1) = str
count = count + 1
nxt = ""
For i = Len(str) To 1 Step -1
If Mid(str, i, 1) < Mid(max, i, 1) Then
'asc("a")=97; chr(97) ="a"
nxt = Chr(AscW(Mid(str, i, 1)) + 1) & nxt
Exit For
End If
nxt = Mid(min, i, 1) & nxt
Next
str = Left(str, Len(str) - Len(nxt)) & nxt
If str = max Then
Cells(count, 1) = str
End If
Loop
End Function

Getting numbers around a number

So, I'm trying to do something similar to a paginator (list of page numbers) where the current number is in the middle or as close as can be
Every way I solve it is hard and weird, just wondering if there is a nice mathy way to do it :)
given:
a: current page number
x: first page number
y: last page number
n: number required
I want to generate a list of numbers where a is as close to the center as can be, while staying within x and y
so f(5, 1, 10, 5) would return [3, 4, 5, 6, 7]
but f(1, 1, 10, 5) would return [1, 2, 3, 4, 5]
and f(9, 1, 10, 5) would return [6, 7, 8, 9, 10]
Can anyone think of a nice way of getting that kind of thing?
Implemented in a probably complicated way in ruby, can it be done simpler?
def numbers_around(current:, total:, required: 5)
required_before = (required - 1) / 2
required_after = (required - 1) / 2
before_x = current - required_before
after_x = current + required_after
if before_x < 1
after_x += before_x.abs + 1
before_x = 1
end
if after_x > total
before_x -= (after_x - total)
after_x = total
end
(before_x..after_x)
end
Here's something kind of mathy that returns the first number in the list (JavaScript code):
function f(a,x,y,n){
var m = n >> 1;
return x * (n > y - x) || a - m
+ Math.max(0,m - a + x)
- Math.max(0,m - y + a);
}
Output:
console.log(f(5,1,10,5)); // 3
console.log(f(1,1,10,5)); // 1
console.log(f(9,1,10,5)); // 6
console.log(f(2,1,10,5)); // 1
console.log(f(11,1,10,5)); // 6
console.log(f(7,3,12,10)); // 3
As you wont be mentioning the language you want this to do, here is some explained code I put together in C++:
std::vector<int> getPageNumbers(int first, int last, int page, int count) {
int begin = page - (count / 2);
if (begin < first) {
begin = first;
}
int cur = 0;
std::vector<int> result;
while (begin + cur <= last && cur < count) {
result.push_back(begin + cur);
++cur;
}
cur = 0;
while (begin - cur >= first && result.size() < count) {
++cur;
result.insert(result.begin(), begin-cur);
}
return result;
}
int main() {
std::vector<int> foo = getPageNumbers(1,10,10,4);
std::vector<int>::iterator it;
for (it = foo.begin(); it != foo.end(); ++it) {
std::cout << *it << " " << std::endl;
}
return 0;
}
What it does is basically:
Start at the Element page - (count/2) (count/2 is fine, you dont need to substract zero, as e.g. 2.5 will get rounded to 2).
If start element is below first, start at first
Keep adding Elements to the Result as long as current page number is smaller or equal the lastpage or until enough elements are inserted
Keep on inserting Elements in the beginning as long as there are less than count elements in the Resultvector or until the current Element is smaller than the first page
That is my basic attempt now. The code is executable.
After writing this, I realized it's very similar to #Nidhoegger's answer but maybe it will help? PHP
<?
//Assume 0 index pages
$current = 2;
$first = 1;
$last = 10;
$limit = 5;
$page_counter = floor($limit / 2); //start at half the limit, so if the limit is 5, start at current -2 (page 0) and move up
$pages = array();
for ($i = 0; $i < $limit) {
$page_to_add = $current + $page_counter;
$page_counter++;
if ($page_to_add > $last)
break;
if ($page_to_add > -1) {
$i++;
$pages[] = $page_to_add;
}
}
?>
I think it's just one of those problems with a lot of annoying corner cases.
start = a - (n / 2);
if (start < x) start = x; // don't go past first page.
end = start + (n - 1); // whereever you start, proceed n pages
if (end > y) { // also don't go past last page.
end = y;
start = end - (n - 1); // if you hit the end, go back n pages
if (start < x) start = x; // but _still_ don't go past first page (fewer than n pages)
}
// make some kind of vector [start..end] inclusive.
or, assuming higher-level primitives, if you prefer:
start = max(x, a - (n / 2)) // (n/2) pages before but don't pass x
end = min(start + (n - 1), y) // n pages long, but don't pass y
start = max(x, end - (n - 1)) // really n pages long, but really don't pass x
// make some kind of vector [start..end] inclusive.
Here's what seems to be the most efficient way to me. Using an array from 1 to n, find the index for the a value. First find the center point of the indexes of the array, then check to see if the number is close to one end or the other, and modify it by the difference. Then fill in the values.
It should be quick since instead of iterating, it uses algorithms to arrive at the index numbers.
Pseudocode:
centerindex = Ceiling(n/2, 1)
If (y-a) < (n - centerindex) Then centerindex = 2 * centerindex - (y - a) - 1
If (a-x) < (n - centerindex) Then centerindex = (a - x) + 1
For i = 1 to n
pages(i) = a - (centerindex - i)
Next i

number which appears more than n/3 times in an array

I have read this problem
Find the most common entry in an array
and the answer from jon skeet is just mind blowing .. :)
Now I am trying to solve this problem find an element which occurs more than n/3 times in an array ..
I am pretty sure that we cannot apply the same method because there can be 2 such elements which will occur more than n/3 times and that gives false alarm of the count ..so is there any way we can tweak around jon skeet's answer to work for this ..?
Or is there any solution that will run in linear time ?
Jan Dvorak's answer is probably best:
Start with two empty candidate slots and two counters set to 0.
for each item:
if it is equal to either candidate, increment the corresponding count
else if there is an empty slot (i.e. a slot with count 0), put it in that slot and set the count to 1
else reduce both counters by 1
At the end, make a second pass over the array to check whether the candidates really do have the required count. This isn't allowed by the question you link to but I don't see how to avoid it for this modified version. If there is a value that occurs more than n/3 times then it will be in a slot, but you don't know which one it is.
If this modified version of the question guaranteed that there were two values with more than n/3 elements (in general, k-1 values with more than n/k) then we wouldn't need the second pass. But when the original question has k=2 and 1 guaranteed majority there's no way to know whether we "should" generalize it as guaranteeing 1 such element or guaranteeing k-1. The stronger the guarantee, the easier the problem.
Using Boyer-Moore Majority Vote Algorithm, we get:
vector<int> majorityElement(vector<int>& nums) {
int cnt1=0, cnt2=0;
int a,b;
for(int n: A){
if (n == a) cnt1++;
else if (n == b) cnt2++;
else if (cnt1 == 0){
cnt1++;
a = n;
}
else if (cnt2 == 0){
cnt2++;
b = n;
}
else{
cnt1--;
cnt2--;
}
}
cnt1=cnt2=0;
for(int n: nums){
if (n==a) cnt1++;
else if (n==b) cnt2++;
}
vector<int> result;
if (cnt1 > nums.size()/3) result.push_back(a);
if (cnt2 > nums.size()/3) result.push_back(b);
return result;
}
Updated, correction from #Vipul Jain
You can use Selection algorithm to find the number in the n/3 place and 2n/3.
n1=Selection(array[],n/3);
n2=Selection(array[],n2/3);
coun1=0;
coun2=0;
for(i=0;i<n;i++)
{
if(array[i]==n1)
count1++;
if(array[i]==n2)
count2++;
}
if(count1>n)
print(n1);
else if(count2>n)
print(n2);
else
print("no found!");
At line number five, the if statement should have one more check:
if(n!=b && (cnt1 == 0 || n == a))
I use the following Python solution to discuss the correctness of the algorithm:
class Solution:
"""
#param: nums: a list of integers
#return: The majority number that occurs more than 1/3
"""
def majorityNumber(self, nums):
if nums is None:
return None
if len(nums) == 0:
return None
num1 = None
num2 = None
count1 = 0
count2 = 0
# Loop 1
for i, val in enumerate(nums):
if count1 == 0:
num1 = val
count1 = 1
elif val == num1:
count1 += 1
elif count2 == 0:
num2 = val
count2 = 1
elif val == num2:
count2 += 1
else:
count1 -= 1
count2 -= 1
count1 = 0
count2 = 0
for val in nums:
if val == num1:
count1 += 1
elif val == num2:
count2 += 1
if count1 > count2:
return num1
return num2
First, we need to prove claim A:
Claim A: Consider a list C which contains a majority number m which occurs more floor(n/3) times. After 3 different numbers are removed from C, we have C'. m is the majority number of C'.
Proof: Use R to denote m's occurrence count in C. We have R > floor(n/3). R > floor(n/3) => R - 1 > floor(n/3) - 1 => R - 1 > floor((n-3)/3). Use R' to denote m's occurrence count in C'. And use n' to denote the length of C'. Since 3 different numbers are removed, we have R' >= R - 1. And n'=n-3 is obvious. We can have R' > floor(n'/3) from R - 1 > floor((n-3)/3). So m is the majority number of C'.
Now let's prove the correctness of the loop 1. Define L as count1 * [num1] + count2 * [num2] + nums[i:]. Use m to denote the majority number.
Invariant
The majority number m is in L.
Initialization
At the start of the first itearation, L is nums[0:]. So the invariant is trivially true.
Maintenance
if count1 == 0 branch: Before the iteration, L is count2 * [num2] + nums[i:]. After the iteration, L is 1 * [nums[i]] + count2 * [num2] + nums[i+1:]. In other words, L is not changed. So the invariant is maintained.
if val == num1 branch: Before the iteration, L is count1 * [nums[i]] + count2 * [num2] + nums[i:]. After the iteration, L is (count1+1) * [num[i]] + count2 * [num2] + nums[i+1:]. In other words, L is not changed. So the invariant is maintained.
f count2 == 0 branch: Similar to condition 1.
elif val == num2 branch: Similar to condition 2.
else branch: nums[i], num1 and num2 are different to each other in this case. After the iteration, L is (count1-1) * [num1] + (count2-1) * [num2] + nums[i+1:]. In other words, three different numbers are moved from count1 * [num1] + count2 * [num2] + nums[i:]. From claim A, we know m is the majority number of L.So the invariant is maintained.
Termination
When the loop terminates, nums[n:] is empty. L is count1 * [num1] + count2 * [num2].
So when the loop terminates, the majority number is either num1 or num2.
If there are n elements in the array , and suppose in the worst case only 1 element is repeated n/3 times , then the probability of choosing one number that is not the one which is repeated n/3 times will be (2n/3)/n that is 1/3 , so if we randomly choose N elements from the array of size ‘n’, then the probability that we end up choosing the n/3 times repeated number will be atleast 1-(2/3)^N . If we eqaute this to say 99.99 percent probability of getting success, we will get N=23 for any value of “n”.
Therefore just choose 23 numbers randomly from the list and count their occurrences , if we get count greater than n/3 , we will return that number and if we didn’t get any solution after checking for 23 numbers randomly , return -1;
The algorithm is essentially O(n) as the value 23 doesn’t depend on n(size of list) , so we have to just traverse array 23 times at worst case of algo.
Accepted Code on interviewbit(C++):
int n=A.size();
int ans,flag=0;
for(int i=0;i<23;i++)
{
int index=rand()%n;
int elem=A[index];
int count=0;
for(int i=0;i<n;i++)
{
if(A[i]==elem)
count++;
}
if(count>n/3)
{
flag=1;
ans=elem;
}
if(flag==1)
break;
}
if(flag==1)
return ans;
else return -1;
}

Resources