Related
Given a set of positive integers and value X, find a subset S whose sum is >= X, such that sum(S) is the lowest of all sums of such existing subsets.
Can it be done in polynomial time? What would be the solution?
Checking all subsets is 2^n.
Backtracking is a possibility for this problem.
It allows examining all the possibilities recursively, without the need of a large amount of memory.
It stops as soon as an optimal solution is found: sum = X, up to a given tolerance (for example 10^-10 in the programme below)
It allows to implement a simple procedure of premature abandon:
at a given time, if sum + the sum of all remaining elements is higher than X, then we can give up examining the current path, without examining the remaining elements. This procedure is optimized by sorting the input data in decreasing order
Here is a code, in C++. The code being quite basic, it should be easy to migrate it to another language.
This programme tests the algorithm with random (uniform) elements, and display the number of iterations.
The complexity (i.e. the number of iterations) is really varying with the random elements (of course), but also greatly depends of the tolerance that we accept. With a tolerance of 10^-10 and a size of n=100, the complexity generally stays quite acceptable. It is no longer the case with a smaller tolerance.
With n = 100 and five runs, I obtained for the number of iterations: 6102, 3672, 8479, 2235, 12926. However, it is clear that there is no warranty to have good performances in all cases. For n = 100, the number of candidates (subsets) is huge.
// Find min sum greater than a given number X
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <tuple>
#include <cstdlib>
#include <cmath>
#include <ctime>
std::tuple<double, std::vector<double>> min_sum_greater(std::vector<double> &a, double X) {
int n = a.size();
std::vector<bool> parti (n, false); // current partition studies
std::vector<bool> parti_opt (n, false); // optimal partition
std::vector<double> sum_back (n, 0); // sum of remaining elements
//std::cout << "n = " << n << " \tX = " << X << "\n";
std::sort(a.begin(), a.end(), std::greater<double>());
sum_back[n-1] = a[n-1];
for (int i = n-2; i >= 0; --i) {
sum_back[i] = sum_back[i+1] + a[i];
}
double sum = 0.0; // current sum
int i = 0; // index of the element being examined
double best_sum = sum_back[0] + 1.0;
bool up_down = true;
double eps = 1.0e-10; // error tolerance
long long cpt = 0; // to check the number of iterations
while (true) { // UP
//std::cout << "Start of while loop: i = " << i << "\n";
cpt++;
if (up_down) {
bool abandon = (sum + sum_back[i] < X - eps) || (sum > best_sum);
if (abandon) { //premature abandon
parti[i] = false;
up_down = false;
i--;
continue;
}
parti[i] = true;
sum += a[i];
//std::cout << "UP, i = " << i << " \tsum = " << sum << "\n";
if (fabs(sum - X) < eps) {
best_sum = sum;
parti_opt = parti;
break;
}
if (sum >= X) {
if (sum < best_sum) {
best_sum = sum;
parti_opt = parti;
//std::cout << "i = " << i << " \tbest sum = " << best_sum << "\n";
}
parti[i] = false;
sum -= a[i];
}
if (i == (n-1)) { // leaf
up_down = false;
i--;
continue;
}
i++;
} else { // DOWN
if (i < 0) break;
if (parti[i]) {
sum -= a[i];
parti[i] = false;
i++;
up_down = true;
} else {
i--;
up_down = false;
}
}
}
std::vector<double> answer;
for (int i = 0; i < n; ++i) {
if (parti_opt[i]) answer.push_back (a[i]);
}
std::cout << "number of iterations = " << cpt << " for n = " << n << "\n";
return std::make_tuple (best_sum, answer);
}
int main () {
//std::vector<double> a = {5, 6, 2, 10, 2, 3, 4, 13, 17, 38, 42};
double X = 33.5;
srand (time(NULL));
int n = 100;
double vmax = 100;
X = vmax * n / 4;
std::vector<double> a (n);
for (int i = 0; i < n; ++i) {
a[i] = vmax * double(rand())/RAND_MAX;
}
double sum;
std::vector<double> y;
std::tie (sum, y) = min_sum_greater (a, X);
std::cout << std::setprecision(15) << "sum = " << sum << "\n";
if (n < 20) {
std::cout << "set: ";
for (auto val: y) {
std::cout << val << " ";
}
std::cout << "\n";
}
}
You are given an integer N. You have to find smallest multiple of N which consists of digits 0 and 1 only. Since this multiple could be large, return it in form of a string.
Returned string should not contain leading zeroes.
For example,
For N = 55, 110 is smallest multiple consisting of digits 0 and 1.
For N = 2, 10 is the answer.
I saw several related problems, but I could not find the problem with my code.
Here is my code giving TLE on some cases even after using map instead of set.
#define ll long long
int getMod(string s, int A)
{
int res=0;
for(int i=0;i<s.length();i++)
{
res=res*10+(s[i]-'0');
res%=A;
}
return res;
}
string Solution::multiple(int A) {
if(A<=1)
return to_string(A);
queue<string>q;
q.push("1");
set<int>st;
string s="1";
while(!q.empty())
{
s=q.front();
q.pop();
int mod=getMod(s,A);
if(mod==0)
{
return s;
}
else if(st.find(mod)==st.end())
{
st.insert(mod);
q.push(s+"0");
q.push(s+"1");
}
}
}
Here is an implementation in Raku.
my $n = 55;
(1 .. Inf).map( *.base(2) ).first( * %% $n );
(1 .. Inf) is a lazy list from one to infinity. The "whatever star" * establishes a closure and stands for the current element in the map.
base is a method of Rakus Num type which returns a string representation of a given number in the wanted base, here a binary string.
first returns the current element when the "whatever star" closure holds true for it.
The %% is the divisible by operator, it implicitly casts its left side to Int.
Oh, and to top it off. It's easy to parallelize this, so your code can use multiple cpu cores:
(1 .. Inf).race( :batch(1000), :degree(4) ).map( *.base(2) ).first( * %% $n );
As mentioned in the "math" reference, the result is related to the congruence of the power of 10 modulo A.
If
n = sum_i a[i] 10^i
then
n modulo A = sum_i a[i] b[i]
Where the a[i] are equal to 0 or 1, and the b[i] = (10^i) modulo A
Then the problem is to find the minimum a[i] sequence, such that the sum is equal to 0 modulo A.
From a graph a point of view, we have to find the shortest path to zero modulo A.
A BFS is generally well adapted to find such a path. The issue is the possible exponential increase of the number of nodes to visit. Here, were are sure to get a number of nodes less than A, by rejecting the nodes, the sum of which (modulo A) has already been obtained (see vector used in the program). Note that this rejection is needed in order to get the minimum number at the end.
Here is a program in C++. The solution being quite simple, it should be easy to understand even by those no familiar with C++.
#include <iostream>
#include <string>
#include <vector>
struct node {
int sum = 0;
std::string s;
};
std::string multiple (int A) {
std::vector<std::vector<node>> nodes (2);
std::vector<bool> used (A, false);
int range = 0;
int ten = 10 % A;
int pow_ten = 1;
if (A == 0) return "0";
if (A == 1) return "1";
nodes[range].push_back (node{0, "0"});
nodes[range].push_back (node{1, "1"});
used[1] = true;
while (1) {
int range_new = (range + 1) % 2;
nodes[range_new].resize(0);
pow_ten = (pow_ten * ten) % A;
for (node &x: nodes[range]) {
node y = x;
y.s = "0" + y.s;
nodes[range_new].push_back(y);
y = x;
y.sum = (y.sum + pow_ten) % A;
if (used[y.sum]) continue;
used[y.sum] = true;
y.s = "1" + y.s;
if (y.sum == 0) return y.s;
nodes[range_new].push_back(y);
}
range = range_new;
}
}
int main() {
std::cout << "input number: ";
int n;
std::cin >> n;
std::cout << "Result = " << multiple(n) << "\n";
return 0;
}
EDIT
The above program is using a kind of memoization in order to speed up the process but for large inputs memory becomes too large.
As indicated in a comment for example, it cannot handle the case N = 60000007.
I improved the speed and the range a little bit with the following modifications:
A function (reduction) was created to simplify the search when the input number is divisible by 2 or 5
For the memorization of the nodes (nodes array), only one array is used now instead of two
A kind of meet-in-the middle procedure is used: in a first step, a function mem_gen memorizes all relevant 01 sequences up to N_DIGIT_MEM (=20) digits. Then the main procedure multiple2 generates valid 01 sequences "after the 20 first digits" and then in the memory looks for a "complementary sequence" such that the concatenation of both is a valid sequence
With this new program the case N = 60000007 provides the good result (100101000001001010011110111, 27 digits) in about 600ms on my PC.
EDIT 2
Instead of limiting the number of digits for the memorization in the first step, I now use a threshold on the size of the memory, as this size does not depent only on the number of digits but also of the input number. Note that the optimal value of this threshold would depend of the input number. Here, I selected a thresholf of 50k as a compromise. With a threshold of 20k, for 60000007, I obtain the good result in 36 ms. Besides, with a threshold of 100k, the worst case 99999999 is solved in 5s.
I made different tests with values less than 10^9. In about all tested cases, the result is provided in less that 1s. However, I met a corner case N=99999999, for which the result consists in 72 consecutive "1". In this particular case, the program takes about 6.7s. For 60000007, the good result is obtained in 69ms.
Here is the new program:
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <chrono>
#include <cmath>
#include <algorithm>
std::string reverse (std::string s) {
std::string res {s.rbegin(), s.rend()};
return res;
}
struct node {
int sum = 0;
std::string s;
node (int sum_ = 0, std::string s_ = ""): sum(sum_), s(s_) {};
};
// This function simplifies the search when the input number is divisible by 2 or 5
node reduction (int &X, long long &pow_ten) {
node init {0, ""};
while (1) {
int digit = X % 10;
if (digit == 1 || digit == 3 || digit == 7 || digit == 9) break;
switch (digit) {
case(0):
X /= 10;
break;
case(2):
case(4):
case(6):
case(8):
X = (5*X)/10;
break;
case(5):
X = (2*X)/10;
break;
}
init.s.push_back('0');
pow_ten = (pow_ten * 10) % X;
}
return init;
}
const int N_DIGIT_MEM = 30; // 20
const int threshold_size_mem = 50000;
// This function memorizes all relevant 01 sequences up to N_DIGIT_MEM digits
bool gene_mem (int X, long long &pow_ten, int index_max, std::map<int, std::string> &mem, node &result) {
std::vector<node> nodes;
std::vector<bool> used (X, false);
bool start = true;
for (int index = 0; index < index_max; ++index){
if (start) {
node x = {int(pow_ten), "1"};
nodes.push_back (x);
} else {
for (node &x: nodes) {
x.s.push_back('0');
}
int n = nodes.size();
for (int i = 0; i < n; ++i) {
node y = nodes[i];
y.sum = (y.sum + pow_ten) % X;
y.s.back() = '1';
if (used[y.sum]) continue;
used[y.sum] = true;
if (y.sum == 0) {
result = y;
return true;
}
nodes.push_back(y);
}
}
pow_ten = (10 * pow_ten) % X;
start = false;
int n_mem = nodes.size();
if (n_mem > threshold_size_mem) {
break;
}
}
for (auto &x: nodes) {
mem[x.sum] = x.s;
}
//std::cout << "size mem = " << mem.size() << "\n";
return false;
}
// This function generates valid 01 sequences "after the 20 first digits" and then in the memory
// looks for a "complementary sequence" such that the concatenation of both is a valid sequence
std::string multiple2 (int A) {
std::vector<node> nodes;
std::map<int, std::string> mem;
int ten = 10 % A;
long long pow_ten = 1;
int digit;
if (A == 0) return "0";
int X = A;
node init = reduction (X, pow_ten);
if (X != A) ten = ten % X;
if (X == 1) {
init.s.push_back('1');
return reverse(init.s);
}
std::vector<bool> used (X, false);
node result;
int index_max = N_DIGIT_MEM;
if (gene_mem (X, pow_ten, index_max, mem, result)) {
return reverse(init.s + result.s);
}
node init2 {0, ""};
nodes.push_back(init2);
while (1) {
for (node &x: nodes) {
x.s.push_back('0');
}
int n = nodes.size();
for (int i = 0; i < n; ++i) {
node y = nodes[i];
y.sum = (y.sum + pow_ten) % X;
if (used[y.sum]) continue;
used[y.sum] = true;
y.s.back() = '1';
if (y.sum != 0) {
int target = X - y.sum;
auto search = mem.find(target);
if (search != mem.end()) {
//std::cout << "mem size 2nd step = " << nodes.size() << "\n";
return reverse(init.s + search->second + y.s);
}
}
nodes.push_back(y);
}
pow_ten = (pow_ten * ten) % X;
}
}
int main() {
std::cout << "input number: ";
int n;
std::cin >> n;
std::string res;
auto t1 = std::chrono::high_resolution_clock::now();
res = multiple2(n),
std::cout << "Result = " << res << " ndigit = " << res.size() << std::endl;
auto t2 = std::chrono::high_resolution_clock::now();
auto duration2 = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
std::cout << "time = " << duration2/1000 << " ms" << std::endl;
return 0;
}
For people more familiar with Python, here is a converted version of #Damien's code. Damien's important insight is to strongly reduce the search tree, taking advantage of the fact that each partial sum only needs to be investigated once, namely the first time it is encountered.
The problem is also described at Mathpuzzle, but there they mostly fix on the necessary existence of a solution. There's also code mentioned at the online encyclopedia of integer sequences. The sage version seems to be somewhat similar.
I made a few changes:
Starting with an empty list helps to correctly solve A=1 while simplifying the code. The multiplication by 10 is moved to the end of the loop. Doing the same for 0 seems to be hard, as log10(0) is minus infinity.
Instead of alternating between nodes[range] and nodes[new_range], two different lists are used.
As Python supports integers of arbitrary precision, the partial results could be stored as decimal or binary numbers instead of as strings. This is not yet done in the code below.
from collections import namedtuple
node = namedtuple('node', 'sum str')
def find_multiple_ones_zeros(A):
nodes = [node(0, "")]
used = set()
pow_ten = 1
while True:
new_nodes = []
for x in nodes:
y = node(x.sum, "0" + x.str)
new_nodes.append(y)
next_sum = (x.sum + pow_ten) % A
y = node((x.sum + pow_ten) % A, x.str)
if next_sum in used:
continue
used.add(next_sum)
y = node(next_sum, "1" + x.str)
if next_sum == 0:
return y.str
new_nodes.append(y)
pow_ten = (pow_ten * 10) % A
nodes = new_nodes
I came across this question during an interview -
Convert a number source to target in the minimum number of operations.
Allowed Operations
Multiplied by 2.
Addition by 1.
subtraction by 1.
0 < source, target <= 1000.
I tried going the naive recursive route(O(3^n)) ie. subtract 1, add 1 and multiply by 2 at each level to try and find a solution that I could extend to Dynamic Programming but couldnt because of an infinite loop.
//Naive approach Via Recursion
int minMoves(int source, int target){
if(source <1 || source > target){
return -1;
}
int moves =0;
// Potential infinite loop - consider 3,6-> 2,6- >1,6->(0,6)x (2,6)->1,6->(0,6)x (1,6)->(0,6)x (2,6)->1,6..
int movesLeft = minMoves(source -1, target) ==-1? Integer.MAX_VALUE:minMoves(source -1, target);
int movesRight = minMoves(source +1, target) ==-1? Integer.MAX_VALUE:minMoves(source +1, target);
int moves2X = minMoves(2*source, target) ==-1? Integer.MAX_VALUE:minMoves(2*source, target);
moves = 1+ Math.min(Math.min(movesRight,movesLeft), moves2X);
return moves;
}
Any ideas on how I can tweak my solution? Or possibly a better way to solve it?
If you think about your solution like a graph traversal, where each node is an intermediate value you can produce, your recursive solution is like a depth first search (DFS). You'll have to fully expand until you've tried all solutions from that "branch" of the search space before you can proceed anywhere else. If you have an infinite loop, this means it will never terminate even if a shorter path exists, and even if you don't have an infinite loop, you still have to search the rest of the solution space to make sure its optimal.
Instead, consider an approach similar to breadth first search (BFS). You expand outward uniformly, and will never search a path longer than the optimal solution. Just use FIFO queue to schedule which node to access next. This is the approach I've taken with my solver.
from queue import Queue
def solve(source, target):
queue = Queue()
path = [source]
queue.put(path)
while source != target:
queue.put(path + [source * 2])
queue.put(path + [source + 1])
queue.put(path + [source - 1])
path = queue.get()
source = path[-1]
return path
if __name__ == "__main__":
print(solve(4,79))
One way in which you can speed up(and possibly fix) this code, while maintaining the recursive implementation, is to use memoization.
The issue here is that you are recalculating the same value many times. Instead you can use a map to store the results that you already calculated, and reuse them when you need it again.
This problem can be solved constructively. First, the easy cases. If s=t, the answer is 0. If s > t, the answer is s-t because subtraction by 1 is the only operation that lowers s, and the other two can only increase the number of subtractions required.
Now let's assume s < t. Since s>0 is given, doubling will always be the fastest way to increase (if s is 1, it's tied with incrementing). So if the challenge was to make s >= t, the answer would always be the number of doublings required to do that. This procedure may overshoot t, but the first doubling greater than t and the last doubling not greater than t must be within a factor of 2 of t.
Let's look at the effect of when we do an addition or subtraction. First, look only at addition:
(((s*2) * 2) * 2) + 1 = 8s + 1
vs:
((((s+1)*2) * 2) * 2) = 8s + 8
Putting an addition before n doublings makes the final result 2^n bigger. So consider if s is 3 and t is 8. The last double not bigger than 8 is 6. This is 2 off, so if we put an addition 1 double before the last double, we get what we want: (3+1) * 2. Alternatively we could try overshooting to the first double greater than 8, which is 12. This is 4 off, so we need to put a subtraction two doublings before the last : (3-1)*2*2 = 8
In general if we are x below the target, we need to put a +1 at n doublings before the last if the binary representation of x has a 1 at the nth place.
Similarly, if we are x above the target, we do likewise with -1's.
This procedure won't help for the 1's in x's binary representation that are at a position more than the number of doublings there are. For example, if s = 100, t=207, there is only 1 doubling to do, but x is 7, which is 111. We can knock out the middle one by doing an addition first, the rest we have to do one by one (s+1)*2 + 1 + 1 + 1 + 1 + 1.
Here is an implementation that has a debug flag that also outputs the list of operations when the flag is defined. The run time is O(log(t)):
#include <iostream>
#include <string>
#include <sstream>
#define DEBUG_INFO
int MinMoves(int s, int t)
{
int ans = 0;
if (t <= s)
{
return s - t; //Only subtraction will help
}
int firstDoubleGreater = s;
int lastDoubleNotGreater = s;
int nDouble = 0;
while(firstDoubleGreater <= t)
{
nDouble++;
lastDoubleNotGreater = firstDoubleGreater;
firstDoubleGreater *= 2;
}
int d1 = t - lastDoubleNotGreater;
int d2 = firstDoubleGreater - t;
if (d1 == 0)
return nDouble -1;
int strat1 = nDouble -1; //Double and increment
int strat2 = nDouble; //Double and decrement
#ifdef DEBUG_INFO
std::cout << "nDouble: " << nDouble << "\n";
std::stringstream s1Ops;
std::stringstream s2Ops;
int s1Tmp = s;
int s2Tmp = s;
#endif
int mask = 1<<strat1;
for(int pos = 0; pos < nDouble-1; pos++)
{
#ifdef DEBUG_INFO
if (d1 & mask)
{
s1Ops << s1Tmp << "+1=" << s1Tmp+1 << "\n" << s1Tmp+1 << "*2= " << (s1Tmp+1)*2 << "\n";
s1Tmp = (s1Tmp + 1) * 2;
}
else
{
s1Ops << s1Tmp << "*2= " << s1Tmp*2 << "\n";
s1Tmp = s1Tmp*2;
}
#endif
if(d1 & mask)
strat1++;
d1 = d1 & ~mask;
mask = mask >> 1;
}
strat1 += d1;
#ifdef DEBUG_INFO
if (d1 != 0)
s1Ops << s1Tmp << " +1 " << d1 << " times = " << s1Tmp + d1 << "\n";
#endif
mask = 1<<strat2;
for(int pos = 0; pos < nDouble; pos++)
{
#ifdef DEBUG_INFO
if (d2 & mask)
{
s2Ops << s2Tmp << "-1=" << s2Tmp-1 << "\n" << s2Tmp-1 << "*2= " << (s2Tmp-1)*2 << "\n";
s2Tmp = (s2Tmp-1)*2;
}
else
{
s2Ops << s2Tmp << "*2= " << s2Tmp*2 << "\n";
s2Tmp = s2Tmp*2;
}
#endif
if(d2 & mask)
strat2++;
d2 = d2 & ~mask;
mask = mask >> 1;
}
strat2 += d2;
#ifdef DEBUG_INFO
if (d2 != 0)
s2Ops << s2Tmp << " -1 " << d2 << " times = " << s2Tmp - d2 << "\n";
std::cout << "Strat1: " << strat1 << "\n";
std::cout << s1Ops.str() << "\n";
std::cout << "\n\nStrat2: " << strat2 << "\n";
std::cout << s2Ops.str() << "\n";
#endif
if (strat1 < strat2)
{
return strat1;
}
else
{
std::cout << "Strat2\n";
return strat2;
}
}
int main()
{
int s = 25;
int t = 193;
std::cout << "s = " << s << " t = " << t << "\n";
std::cout << MinMoves(s, t) << std::endl;
}
Short BFS algorithm. It finds the shortest path in graph where every vertex x is connected to x + 1, x - 1 and x * 2; O(n)
#include <bits/stdc++.h>
using namespace std;
const int _MAX_DIS = 2020;
const int _MIN_DIS = 0;
int minMoves(int begin, int end){
queue<int> Q;
int dis[_MAX_DIS];
fill(dis, dis + _MAX_DIS, -1);
dis[begin] = 0;
Q.push(begin);
while(!Q.empty()){
int v = Q.front(); Q.pop();
int tab[] = {v + 1, v - 1, v * 2};
for(int i = 0; i < 3; i++){
int w = tab[i];
if(_MIN_DIS <= w && w <= _MAX_DIS && dis[w] == -1){
Q.push(w);
dis[w] = dis[v] + 1;
}
}
}
return dis[end];
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout << minMoves(1, 1000);
return 0;
}
this is just for fun.
Can you give me a way to determine the greater value of two numbers? You can use other operators except greater than or less than operator.
Use any tool you like (programming language, pencil paper, etc.).
And another thing you cannot do the following:
int main()
{
int num1, num2;
cin >> num1 >> num2;
if( (num1-num2) + abs(num1-num2) )
cout << num1 << " is bigger" << endl;
else
cout << num2 << " is bigger" << endl;
return 0;
}
Well, if you assume two's complement arithmetic:
int highBit = ~INT_MAX;
int rslt = num1 - num2;
if (rslt & highBit)
// num2 > num1
else if (rslt)
// num1 > num2
else
// num1 == num2
This will only work when both numbers are positive. For example, if num1 is positive and num2 is negative, then num1-num2 could overflow, causing the result to be negative, which would erroneously report that num2 > num1. If both numbers are negative, this will report the opposite (i.e. -12 will be reported greater than -1).
Ok, I would transform them to binary code and walk from the left byte-by-byte. Whichever first has 1 when the other one has not (means: has 0), this is greater.
So if you go from left to right and:
both have 0 at the current position: go to the next position,
both have 1 at the current position: go to the next position,
first one has 1 at the current position and the second one has 0: the first one is bigger,
second one has 1 at the current position and the first one has 0: the second one is bigger,
If you determine that 3. or 4. is matched, you have the result. If 1. or 2. is matched, repeat the same for the next position. If you have walked through all the bytes and did not determine that one of them is bigger, then both are equal.
#include <algorithm>
cout << std::max(num1, num2) << " is bigger" << endl;
Logarithm of a negative value is undefined; different languages/frameworks process it differently. This solution is for C#:
using System;
public class Test
{
public static bool gt( double a, double b ) {
return Double.IsNaN(Math.Log(b - a));
}
public static void report_gt( double a, double b) {
if( gt(a,b) )
Console.WriteLine("{0} is greater than {1}", a, b);
else
Console.WriteLine("{0} is less than or equal to {1}", a, b);
}
public static void Main()
{
Test.report_gt(-1, 0);
Test.report_gt(1, 0);
Test.report_gt(1, 2);
Test.report_gt(-1, -2);
}
}
Output:
-1 is less than or equal to 0
1 is greater than 0
1 is less than or equal to 2
-1 is greater than -2
A similar solution for C could use floating point exceptions. Unfortunately, C++ does not throw an exception for a negative argument to log2() for a nice try-catch solution in this fun contest :).
This works for positive integers:
#! /usr/bin/python
import math
def bigger (a, b):
length = int (math.log (a, 2) + math.log (b, 2) + 1)
a = toFixedBitString (a, length)
b = toFixedBitString (b, length)
print a, b
while a:
if a [0] == '1' and b [0] == '0':
print "First number is bigger."
return
if a [0] == '0' and b [0] == '1':
print "Second number is bigger."
return
a = a [1:]
b = b [1:]
print "Numbes are equal."
def toFixedBitString (a, length):
retVal = ''
for x in range (length): retVal = ['0', '1'] [a >> x & 1] + retVal
return retVal
Warning: Untested code.
num2 ~= num2;
++num2;
num1 += num2;
rotate_left(num1, 1);
if (num1 == 0)
std::cout << "num1 == num2";
else if (num1 & 1)
std::cout << "num1 < num2";
else
std::cout << "num1 > num2";
I haven't thought about it a lot, but there are probably combinations that will fail due to overflow.
#include <limits>
int a = -1;
int b = -11;
// true for positive difference
bool dpos = ~(unsigned int)(a - b) >> numeric_limits<int>::digits; // 31 for 32-bit
cout << "Problem : a = " << a << " and b = " << b << endl;
if (a == b)
cout << " a == b " << endl;
else if (dpos)
cout << " a > b " << endl;
else
cout << " a < b " << endl;
SSE 4.1 solution
#include <smmintrin.h>
#include <iostream>
using namespace std;
int main()
{
int num1, num2, test;
__m128i v1, v2, vcmp;
cin >> num1 >> num2;
v1 = _mm_set1_epi32(num1);
v2 = _mm_set1_epi32(num2);
vcmp = _mm_cmpgt_epi32(v1, v2);
test = _mm_testz_si128(vcmp, vcmp);
if (test == 0)
{
cout << "num1 is bigger" << endl;
}
else
{
cout << "num2 is bigger" << endl;
}
return 0;
}
$ g++ -Wall -msse4.1 cmpgt.cpp -o cmpgt
$ ./cmpgt
-10 10
num2 is bigger
$ ./cmpgt
10 -10
num1 is bigger
There is a lot of information on how to find the next power of 2 of a given value (see refs) but I cannot find any to get the previous power of two.
The only way I find so far is to keep a table with all power of two up to 2^64 and make a simple lookup.
Acius' Snippets
gamedev
Bit Twiddling Hacks
Stack Overflow
From Hacker's Delight, a nice branchless solution:
uint32_t flp2 (uint32_t x)
{
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);
return x - (x >> 1);
}
This typically takes 12 instructions. You can do it in fewer if your CPU has a "count leading zeroes" instruction.
uint32_t previous_power_of_two( uint32_t x ) {
if (x == 0) {
return 0;
}
// x--; Uncomment this, if you want a strictly less than 'x' result.
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x - (x >> 1);
}
Thanks for the responses. I will try to sum them up and explain a little bit clearer.
What this algorithm does is changing to 'ones' all bits after the first 'one' bit, cause these are the only bits that can make our 'x' larger than its previous power of two.
After making sure they are 'ones', it just removes them, leaving the first 'one' bit intact. That single bit in its place is our previous power of two.
Here is a one liner for posterity (ruby):
2**Math.log(input, 2).floor(0)
Probably the simplest approach (for positive numbers):
// find next (must be greater) power, and go one back
p = 1; while (p <= n) p <<= 1; p >>= 1;
You can make variations in many ways if you want to optimize.
The g++ compiler provides a builtin function __builtin_clz that counts leading zeros:
So we could do:
int previousPowerOfTwo(unsigned int x) {
return 1 << (sizeof(x)*8 - 1) - __builtin_clz(x);
}
int main () {
std::cout << previousPowerOfTwo(7) << std::endl;
std::cout << previousPowerOfTwo(31) << std::endl;
std::cout << previousPowerOfTwo(33) << std::endl;
std::cout << previousPowerOfTwo(8) << std::endl;
std::cout << previousPowerOfTwo(91) << std::endl;
return 0;
}
Results:
4
16
32
8
64
But note that, for x == 0, __builtin_clz return is undefined.
If you can get the next-higher power of 2, the next-lower power of 2 is either that next-higher or half that. It depends on what you consider to be the "next higher" for any power of 2 (and what you consider to be the next-lower power of 2).
What about
if (tt = v >> 16)
{
r = (t = tt >> 8) ? 0x1000000 * Table256[t] : 0x10000 * Table256[tt];
}
else
{
r = (t = v >> 8) ? 0x100 * Table256[t] : Table256[v];
}
It is just modified method from http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup.
This require like 7 operations and it might be faster to replace multiplications whit shift.
Solution with bit manipulation only:
long FindLargestPowerOf2LowerThanN(long n)
{
Assert.IsTrue(n > 0);
byte digits = 0;
while (n > 0)
{
n >>= 1;
digits++;
}
return 1 << (digits - 1);
}
Example:
FindLargestPowerOf2LowerThanN(6):
Our Goal is to get 4 or 100
1) 6 is 110
2) 110 has 3 digits
3) Since we need to find the largest power of 2 lower than n we subtract 1 from digits
4) 1 << 2 is equal to 100
FindLargestPowerOf2LowerThanN(132):
Our Goal is to get 128 or 10000000
1) 6 is 10000100
2) 10000100 has 8 digits
3) Since we need to find the largest power of 2 lower than n we subtract 1 from digits
4) 1 << 7 is equal to 10000000
I write my answer here just in case I need to reference it in the future.
For C language, this is what I believed to be the "ultimate" solution for the previous power of 2 function. The following code:
is targeted for C language (not C++),
uses compiler built-ins to yield efficient code (CLZ or BSR instruction) if compiler supports any,
is portable (standard C and no assembly) with the exception of built-ins, and
addresses undefined behavior of the compiler built-ins (when x is 0).
If you're writing in C++, you may adjust the code appropriately. Note that C++20 introduces std::bit_floor which does the exact same thing.
#include <limits.h>
#ifdef _MSC_VER
# if _MSC_VER >= 1400
/* _BitScanReverse is introduced in Visual C++ 2005 and requires
<intrin.h> (also introduced in Visual C++ 2005). */
#include <intrin.h>
#pragma intrinsic(_BitScanReverse)
#pragma intrinsic(_BitScanReverse64)
# define HAVE_BITSCANREVERSE 1
# endif
#endif
/* Macro indicating that the compiler supports __builtin_clz().
The name HAVE_BUILTIN_CLZ seems to be the most common, but in some
projects HAVE__BUILTIN_CLZ is used instead. */
#ifdef __has_builtin
# if __has_builtin(__builtin_clz)
# define HAVE_BUILTIN_CLZ 1
# endif
#elif defined(__GNUC__)
# if (__GNUC__ > 3)
# define HAVE_BUILTIN_CLZ 1
# elif defined(__GNUC_MINOR__)
# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
# define HAVE_BUILTIN_CLZ 1
# endif
# endif
#endif
/**
* Returns the largest power of two that is not greater than x. If x
* is 0, returns 0.
*/
unsigned int prev_power_of_2(unsigned int x)
{
#ifdef HAVE_BITSCANREVERSE
if (x <= 0) {
return 0;
} else {
unsigned long int index;
(void) _BitScanReverse(&index, x);
return (1U << index);
}
#elif defined(HAVE_BUILTIN_CLZ)
if (x <= 0) {
return 0;
}
return (1U << (sizeof(x) * CHAR_BIT - 1 - __builtin_clz(x)));
#else
/* Fastest known solution without compiler built-ins or integer
logarithm instructions.
From the book "Hacker's Delight".
Converted to a loop for smaller code size.
("gcc -O3" will unroll this.) */
{
unsigned int shift;
for (shift = 1; shift < sizeof(x) * CHAR_BIT; shift <<= 1) {
x |= (x >> shift);
}
}
return (x - (x >> 1));
#endif
}
unsigned long long prev_power_of_2_long_long(unsigned long long x)
{
#if (defined(HAVE_BITSCANREVERSE) && \
ULLONG_MAX == 18446744073709551615ULL)
if (x <= 0) {
return 0;
} else {
/* assert(sizeof(__int64) == sizeof(long long)); */
unsigned long int index;
(void) _BitScanReverse64(&index, x);
return (1ULL << index);
}
#elif defined(HAVE_BUILTIN_CLZ)
if (x <= 0) {
return 0;
}
return (1ULL << (sizeof(x) * CHAR_BIT - 1 - __builtin_clzll(x)));
#else
{
unsigned int shift;
for (shift = 1; shift < sizeof(x) * CHAR_BIT; shift <<= 1) {
x |= (x >> shift);
}
}
return (x - (x >> 1));
#endif
}
Using a count leading zeros function (a.k.a. bitscan right), determining the next lowest power of 2 is easy:
uint32_t lower_power_of_2(uint32_t x) {
assert(x != 0);
return 1 << (31 - __builtin_clz(x));
}
Here, __builtin_clz is recognized by gcc and clang. Use _BitScanReverse with a Microsoft compiler.
This is my way:
//n is the number you want to find the previus power of 2
long m = 1;
while(n > 1){
n >>= 1;
m <<= 1;
}
//m is the previous power of two
When you work in base 2, you can jump from a power of two to the next one by just adding or removing a digit from the right.
For instance, the previous power of two of the number 8 is the number 4. In binary:
01000 -> 0100 (we remove the trailing zero to get number 4)
So the algorithm to solve the calculus of the previous power of two is:
previousPower := number shr 1
previousPower = number >> 1
(or any other syntax)
This can be done in one line.
int nextLowerPowerOf2 = i <= 0
? 0
: ((i & (~i + 1)) == i)
? i >> 1
: (1 << (int)Math.Log(i, 2));
result
i power_of_2
-2 0
-1 0
0 0
1 0
2 1
3 2
4 2
5 4
6 4
7 4
8 4
9 8
Here's a more readable version in c#, with the <=0 guard clause distributed to the utility methods.
int nextLowerPowerOf2 = IsPowerOfTwo(i)
? i >> 1 // shift it right
: GetPowerOfTwoLessThanOrEqualTo(i);
public static int GetPowerOfTwoLessThanOrEqualTo(int x)
{
return (x <= 0 ? 0 : (1 << (int)Math.Log(x, 2)));
}
public static bool IsPowerOfTwo(int x)
{
return (((x & (~x + 1)) == x) && (x > 0));
}
Below code will find the previous power of 2:
int n = 100;
n /= 2;//commenting this will gives the next power of 2
n |= n>>1;
n |= n>>2;
n |= n>>4;
n |= n>>16;
System.out.println(n+1);
This is my current solution to find the next and previous powers of two of any given positive integer n and also a small function to determine if a number is power of two.
This implementation is for Ruby.
class Integer
def power_of_two?
(self & (self - 1) == 0)
end
def next_power_of_two
return 1 if self <= 0
val = self
val = val - 1
val = (val >> 1) | val
val = (val >> 2) | val
val = (val >> 4) | val
val = (val >> 8) | val
val = (val >> 16) | val
val = (val >> 32) | val if self.class == Bignum
val = val + 1
end
def prev_power_of_two
return 1 if self <= 0
val = self
val = val - 1
val = (val >> 1) | val
val = (val >> 2) | val
val = (val >> 4) | val
val = (val >> 8) | val
val = (val >> 16) | val
val = (val >> 32) | val if self.class == Bignum
val = val - (val >> 1)
end
end
Example use:
10.power_of_two? => false
16.power_of_two? => true
10.next_power_of_two => 16
10.prev_power_of_two => 8
For the previous power of two, finding the next and dividing by two is slightly slower than the method above.
I am not sure how it works with Bignums.