I need to compute all possible combinations of n things selected r at a time where 0<=r<=n, One method to do so is generating the numbers up to 0 to 2^n-1. But I need to generate these numbers such that the numbers should be sorted on the basis of the number of bits set in that number. for n=3:
0 // numbers with 0 bits set
1 2 4 // numbers with 1 bits set
3 5 6 // numbers with 2 bits set
7 // numbers with 3 bits set
I need to know how to generate the numbers such that they are sorted in increasing/decreasing order of bits set?
Implement regular algorithm to generate the combinations, but also hold an additional array where you store the numbers sorted accoding to the 1-bits set. Then for each combination generated replace the numbers with the numbers sitting in the corresponding position minus one in the array sorted as I described.
Iterating over all combinations of some some number of items is covered nicely by quant_dev here.
Here is a simple way function that counts the number of bits set in a number's representation:
// Counts how many bits are set in the representation of the input number n
int numOfBitsSet(int n)
{
int cnt = 0;
while (n != 0)
{
cnt += (n & 1);
n = n >> 1;
}
return cnt;
}
And here is how you could use it in a (C++11) program that does what you want:
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>
using namespace std;
int main()
{
// For instance...
int n = 3;
// Fill up a vector of 2^n entries (0 .. 2^(n - 1))
vector<int> v(1 << n);
iota(begin(v), end(v), 0);
// For each number of bits...
for (size_t i = 0; i <= n; i++)
{
cout << "Numbers with " << i << " bits set: ";
// Find the first number with i bits set...
auto it = find_if(begin(v), end(v), [i] (int x) {
return (numOfBitsSet(x) == i);
});
while (it != end(v))
{
cout << *it << " ";
// Find the next number with i bits set...
it = find_if(next(it), end(v), [i] (int x) {
return (numOfBitsSet(x) == i);
});
}
cout << endl;
}
}
If C++11 is not an option for you, you will have to use functors instead of lambdas, and replace std::iota with a manual loop:
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>
using namespace std;
struct bit_count_filter
{
bit_count_filter(int i) : _i(i) { }
bool operator () (int x) const { return numOfBitsSet(x) == _i; }
int _i;
};
int main()
{
// For instance...
int n = 3;
// Fill up a vector of 2^n entries (0 .. 2^(n - 1))
vector<int> v(1 << n);
for (size_t i = 0; i < v.size(); i++)
{
v[i] = i;
}
// For each number of bits...
for (size_t i = 0; i <= n; i++)
{
cout << "Numbers with " << i << " bits set: ";
// Find the first number with i bits set...
auto it = find_if(begin(v), end(v), bit_count_filter(i));
while (it != end(v))
{
cout << *it << " ";
// Find the next number with i bits set...
it = find_if(next(it), end(v), bit_count_filter(i));
}
cout << endl;
}
}
You could do it recursively:
void setnbits(unsigned int cur, int n, int toset, int max)
{
if(toset == 0)
{
printf("%d ", cur >> (n + 32 - max) , n);
return;
}
toset--;
for(int i = 1 ; i <= n-toset ; i++)
{
setnbits((cur >> i) | 0x80000000, n-i, toset , max);
}
}
Could be called like:
for(int z = 0 ; z < 4 ; z++)
{
printf("%d bits: ", z);
setnbits(0, 3, z, 3);
printf("\n");
}
prints:
0 bits: 0
1 bits: 1 2 4
2 bits: 3 5 6
3 bits: 7
The numbers are not guaranteed to be in numerical order.
That's pretty easy.
There are two cases:
1) Last 1-bit has 0-bit before:
000111001001 -> 000111001010.
You should just move it to the left
2) There is a chain of 1-bits:
000110111100 -> 000111000111
Then you should move last 1-bit to the nearest 0-bit on the left(before the chain), and move all another bits of that chain to the right.
You'll get this way all needed numbers in increasing order.
Related
can someone help me out? I've been trying to get this program to print and add all prime numbers in the Fibonacci Sequence below 1000. Just typing the regular Fibonacci code works fine and will list the numbers 1 - 987.
However, the moment I put in a prime number checker it all of a sudden stops at 5 (printing "1 1 2 3 5" which is technically correct since they all fall under what a prime is (though 1 doesn't count). However I'm looking to see ALL prime numbers from 1 - 987 in the sequence, and no matter what I do I can't seem to get it to work.
My code's down below, don't mind the lack of a main function, I'm making this function as a part of a bigger program, but it can stand on its own. Currently testing it by just calling it in the main function.
#include <iostream>
using namespace std;
void primethousand() {
int fibo = 1;
int nacci = 1;
int fibonacci = 0;
int fibosum = 0; //used to get the sum of all printed numbers later, once this issue is fixed.
int pchk = 0; /*primecheck, used to check if a number is a prime or not. 1 means not prime, 0 means prime*/
cout << "\nPrime Fibonacci #s under 1000: \n\n";
for (int ctr = 1; fibonacci < 987; ctr++) {
if (ctr == 1) {
cout << fibo << " ";
continue;
} else if (ctr == 2) {
cout << nacci << " ";
continue;
}
fibonacci = fibo + nacci;
fibo = nacci;
nacci = fibonacci;
//cout << fibonacci << " ";
for (int chr = 2; chr < fibonacci; chr++) {
if (fibonacci % chr == 0) {
pchk = 1;
}
}
if (pchk == 0) {
cout << fibonacci << " ";
}
}
}
You should break up the big task into smaller tasks by using functions.
Additionally, the fibonacci sequence is growing strongly exponential. So, there are not so many numbers that can be calculated in C++ standard data types. For example, even the biggest 8 byte unsigned long long or uint64_t can hold only the 94th element of the Fibonacci series.
For Fibonaccis below 1000, it will be just 16 elements.
So, we can easily precalculate all vaues during compile time (so, not during runtime). This will be the fastest possible solution. Also the compile time will be very short. And the memory consumption will be very low.
Please see:
#include <iostream>
#include <array>
#include <cstdint>
// For fibonacci number < 1000, 16 of the series elements will be sufficient
constexpr std::size_t ArraySize{ 16 };
// Calculate all 16 needed fibonacci number during compile time
consteval auto CreateFibonacciNumberArray() {
std::array<std::uint64_t, ArraySize> fs{ 1, 1 };
for (std::size_t i{ 2 }; i < ArraySize; ++i)
fs[i] = fs[i - 1] + fs[i - 2];
return fs;
}
// This is an array with the 16 fibonacci numbers. It is an compile time array
constexpr auto FIB = CreateFibonacciNumberArray();
// Compiletime function to calculate, if fibonacci numbers are prime
constexpr bool isPrime(const std::uint64_t number) {
if (number % 2 == 0 or number <= 2) return false;
for (std::uint64_t i = 3; (i * i) <= number; i += 2)
if (number % i == 0) return false;
return true;
}
// Create a compile time array, to indicate, if a fibnacci number is prinme
consteval auto IsPrime(const std::array<std::uint64_t, ArraySize>& FIB) {
std::array<bool, ArraySize> primeFibonacci{};
for (std::size_t i{}; i < ArraySize; ++i)
primeFibonacci[i] = isPrime(FIB[i]);
return primeFibonacci;
}
// Boolean compile time array that shows, if a fibonacci number is prime
constexpr auto FibIsPrime = IsPrime(FIB);
int main()
{
for (std::size_t i{}; i < ArraySize; ++i) {
std::cout << FIB[i];
if (FibIsPrime[i]) std::cout << "\tis prime";
std::cout << '\n';
}
}
It looks like once pchk is set to 1, you never set it back to zero, so further primes are never noticed..
void decimaltobin()
{
binaryNum = 0;
m = 1;
while (num != 0)
{
rem = num % 2;
num /= 2;
binaryNum += rem * m;
m *= 10;
}
}
Just wondering if there was an easy fix to get this function to print an 8-bit binary number instead of a 4-bit number, e.g. 0000 0101 instead of 0101.
As mentioned in the comments, your code does not print anything yet and the data type of binaryNum is not clear. Here is a working solution.
#include <iostream>
using namespace std;
void decToBinary(int n)
{
// array to store binary number
int binaryNum[32];
// counter for binary array
int i = 0;
while (n > 0) {
// storing remainder in binary array
binaryNum[i] = n % 2;
n = n / 2;
i++;
}
// printing the required number of zeros
int zeros = 8 - i;
for(int m = 0; m < zeros; m++){
cout<<0;
}
// printing binary array in reverse order
for (int j = i - 1; j >= 0; j--)
cout << binaryNum[j];
}
// Driver program to test above function
int main()
{
int n = 17;
decToBinary(n);
return 0;
}
The code implements the following:
Store the remainder when the number is divided by 2 in an array.
Divide the number by 2
Repeat the above two steps until the number is greater than zero.
Print the required number of zeros. That is 8 - length of the binary number. Note that this code will work for numbers that can be expressed in 8 bits only.
Print the array in reverse order now
Ref
Maybe I am missing your reason but why do you want to code from scratch instead of using a standard library?
You may use standard c++ without having to code a conversion from scratch using for instance std::bitset<NB_OF_BITS>.
Here is a simple example:
#include <iostream>
#include <bitset>
std::bitset<8> decimalToBin(int numberToConvert)
{
return std::bitset<8>(numberToConvert);
}
int main() {
int a = 4, b=8, c=12;
std::cout << decimalToBin(a)<< std::endl;
std::cout << decimalToBin(b)<< std::endl;
std::cout << decimalToBin(c)<< std::endl;
}
It outputs:
00000100
00001000
00001100
In my situation, a lorry has a capacity of 30, while a van has a capacity of 10. I need to find the number of vans/lorries needed to transport a given amount of cargo, say 100. I need to find all possible combinations of lorries + vans that will add up to 100.
The basic math calculation would be: (30*lorrycount) + (10*vancount) = n, where n is number of cargo.
Output Example
Cargo to be transported: 100
Number of Lorry: 0 3 2 1
Number of Van: 10 1 4 7
For example, the 2nd combination is 3 lorries, 1 van. Considering that lorries have capacity = 30 and van capacity = 10, (30*3)+(10*1) = 100 = n.
For now, we only have this code, which finds literally all combinations of numbers that add up to given number n, without considering the formula given above.
#include <iostream>
#include <vector>
using namespace std;
void findCombinationsUtil(int arr[], int index,
int num, int reducedNum)
{
int lorry_capacity = 30;
int van_capacity = 10;
// Base condition
if (reducedNum < 0)
return;
// If combination is found, print it
if (reducedNum == 0)
{
for (int i = 0; i < index; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
// Find the previous number stored in arr[]
// It helps in maintaining increasing order
int prev = (index == 0) ? 1 : arr[index - 1];
// note loop starts from previous number
// i.e. at array location index - 1
for (int k = prev; k <= num; k++)
{
// next element of array is k
arr[index] = k;
// call recursively with reduced number
findCombinationsUtil(arr, index + 1, num,
reducedNum - k);
}
}
void findCombinations(int n)
{
// array to store the combinations
// It can contain max n elements
std::vector<int> arr(n); // allocate n elements
//find all combinations
findCombinationsUtil(&*arr.begin(), 0, n, n);
}
int main()
{
int n;
cout << "Enter the amount of cargo you want to transport: ";
cin >> n;
cout << endl;
//const int n = 10;
findCombinations(n);
return 0;
}
Do let me know if you have any solution to this, thank you.
An iterative way of finding all possible combinations
#include <iostream>
#include <vector>
int main()
{
int cw = 100;
int lw = 30, vw = 10;
int maxl = cw/lw; // maximum no. of lorries that can be there
std::vector<std::pair<int,int>> solutions;
// for the inclusive range of 0 to maxl, find the corresponding no. of vans for each variant of no of lorries
for(int l = 0; l<= maxl; ++l){
bool is_integer = (cw - l*lw)%vw == 0; // only if this is true, then there is an integer which satisfies for given l
if(is_integer){
int v = (cw-l*lw)/vw; // no of vans
solutions.push_back(std::make_pair(l,v));
}
}
for( auto& solution : solutions){
std::cout<<solution.first<<" lorries and "<< solution.second<<" vans" <<std::endl;
}
return 0;
}
We will create a recursive function that walks a global capacities array left to right and tries to load cargo into the various vehicle types. We keep track of how much we still have to load and pass that on to any recursive call. If we reach the end of the array, we produce a solution only if the remaining cargo is zero.
std::vector<int> capacities = { 30, 10 };
using Solution = std::vector<int>;
using Solutions = std::vector<Solution>;
void tryLoad(int remaining_cargo, int vehicle_index, Solution so_far, std::back_insert_iterator<Solutions>& solutions) {
if (vehicle_index == capacities.size()) {
if (remaining_cargo == 0) // we have a solution
*solutions++ = so_far;
return;
}
int capacity = capacities[vehicle_index];
for (int vehicles = 0; vehicles <= remaining_cargo / capacity; vehicles++) {
Solution new_solution = so_far;
new_solution.push_back(vehicles);
tryLoad(remaining_cargo - vehicles * capacity, vehicle_index + 1, new_solution, solutions);
}
}
Calling this as follows should produce the desired output in all_solutions:
Solutions all_solutions;
auto inserter = std::back_inserter(all_solutions)
tryLoad(100, 0, Solution{}, inserter);
Let say I've a target number and a list of possibile values that I can pick to create a sequence that, once summed every picked number, will sum to the target:
target = 31
list = 2, 3, 4
possible sequence: 3 2 4 2 2 2 4 2 3 2 3 2
I'd like to:
first decide if there is any sequence that will reach the target
return one of the many (possible) sequence
This is my attempt:
#include <iostream>
#include <random>
#include <chrono>
#include <vector>
inline int GetRandomInt(int min = 0, int max = 1) {
uint64_t timeSeed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
std::seed_seq ss{ uint32_t(timeSeed & 0xffffffff), uint32_t(timeSeed >> 32) };
std::mt19937_64 rng;
rng.seed(ss);
std::uniform_int_distribution<int> unif(min, max);
return unif(rng);
}
void CreateSequence(int target, std::vector<int> &availableNumbers) {
int numAttempts = 1;
int count = 0;
std::vector<int> elements;
while (count != target) {
while (count < target) {
int elem = availableNumbers[GetRandomInt(0, availableNumbers.size() - 1)];
count += elem;
elements.push_back(elem);
}
if (count != target) {
numAttempts++;
count = 0;
elements.clear();
}
}
int size = elements.size();
std::cout << "count: " << count << " | " << "num elements: " << size << " | " << "num attempts: " << numAttempts << std::endl;
for (auto it = elements.begin(); it != elements.end(); it++) {
std::cout << *it << " ";
}
}
int main() {
std::vector<int> availableNumbers = { 2, 3, 4 };
CreateSequence(31, availableNumbers);
}
But it can loop infinitely if the list of number can't be appropriate to reach such sum; example:
std::vector<int> availableNumbers = { 3 };
CreateSequence(8, availableNumbers);
No sequence of 3 will sum to 8. Also, if the list is huge and the target number high, it can lead to a huge amount of processing (cause lots of while check fails).
How would you implement this kind of algorithm?
Your suggested code is possibly very fast, since it is heuristic. But as you said, it gets potentially trapped in a nearly endless loop.
If you want to avoid this situation, you have to search the complete set of possible combinations.
Abstraction
Let's define our algorithm as a function f with a scalar target t and a vector <b> as parameters returning a vector of coefficients <c>, where <b> and <c> have the same dimension:
<c> = f(t, <b>)
First the given set of numbers Sg should be reduced to their reduced set Sr so we reduce the dimension of our solution vector <c>. E.g. {2,3,4,11} can be reduced to {2,3}. We get this by calling our algorithm recursively by splitting Sg into a new target ti with the remaining numbers as the new given set Sgi and ask the algorithm, if it finds any solution (a non-zero vector). If so, remove that target ti from the original given set Sg. Repeat this recursively until no solutions found any more.
Now we can understand this set of numbers as a polynomial, where we are looking for possible coefficients ci to get our target t. Let's call each element in Sb bi with i={1..n}.
Our test sum ts is the sum over all i for ci * bi, where each ci can run from 0 to ni = floor(t/bi).
The number of possible tests N is now the product over all ni+1: N = (n1+1) * (n2+1) * ... * (ni+1).
Iterate now over all possibilities by representing the coefficient vector <c> as an vector of integers and incrementing c1 and carrying over an overrun to the next element in the vector, resetting c1 and so forth.
Example
#include <random>
#include <chrono>
#include <vector>
#include <iostream>
using namespace std;
static int evaluatePolynomial(const vector<int> &base, const vector<int> &coefficients)
{
int v=0;
for(unsigned long i=0; i<base.size(); i++){
v += base[i]*coefficients[i];
}
return v;
}
static bool isZeroVector(vector<int> &v)
{
for (auto it = v.begin(); it != v.end(); it++) {
if(*it != 0){
return false;
}
}
return true;
}
static vector<int> searchCoeffs(int target, vector<int> &set) {
// TODO: reduce given set
vector<int> n = set;
vector<int> c = vector<int>(set.size(), 0);
for(unsigned long int i=0; i<set.size(); i++){
n[i] = target/set[i];
}
c[0] = 1;
bool overflow = false;
while(!overflow){
if(evaluatePolynomial(set, c) == target){
return c;
}
// increment coefficient vector
overflow = true;
for(unsigned long int i=0; i<c.size(); i++){
c[i]++;
if(c[i] > n[i]){
c[i] = 0;
}else{
overflow = false;
break;
}
}
}
return vector<int>(set.size(), 0);
}
static void print(int target, vector<int> &set, vector<int> &c)
{
for(unsigned long i=0; i<set.size(); i++){
for(int j=0; j<c[i]; j++){
cout << set[i] << " ";
}
}
cout << endl;
cout << target << " = ";
for(unsigned long i=0; i<set.size(); i++){
cout << " +" << set[i] << "*" << c[i];
}
cout << endl;
}
int main() {
vector<int> set = {4,3,2};
int target = 31;
auto c = searchCoeffs(target, set);
print(target, set,c);
}
That code prints
4 4 4 4 4 4 4 3
31 = +4*7 +3*1 +2*0
Further Thoughts
productive code should test for zeros in any given values
the search could be improved by incrementing the next coefficient if the evaluated polynomial already exceeded the target value.
further speedup is possible, when calculating the difference of the target value and the evaluated polynomial when c1 is set to zero, and checking if that difference is a multiple of b1. If not, c2 could be incremented straight forward.
Perhaps there exist some shortcuts exploiting the least common multiple
As ihavenoidea proposed, I would also try backtracking. In addition, I will sort the numbers in decreasing order, il order to speed up the process.
Note: a comment would be more appropriate than an answer, but I am not allowed to. Hope it helps. I will suppress this answer if requested.
I have an array of 3 integers {1,2,3}. I need to print combinations in the form of-
1 1+2 1+3 1+2+3
2 2+3
3
for(int i = 0; i < array.size(); ++i)
{
for(int j = 0; (i + j) < array.size(); ++j)
{
sum += my[i + j];
cout << sum << " ";
c++;
}
cout << endl;
}
In above, 1+3 is being skipped.
Please help me with that.
Given a set S the power set P(S) is the set of all subsets of S. What you are trying to do is essentially enumerate all of the non-empty elements of x ∈ P(S). From there, you can iterate over all of the elements of each non-empty x in P(S).
What does this mean for you? Well for starters for a set S containing n elements the number of possible elements of P(S) is 2^n, so the size of the power set scales exponentially with the size of its generating set.
But, where this may be useful for small values of n (in particular n < 64) you can use unsigned long long variables to act as a kind of index. In particular, each bit corresponds to one of your array elements. Bits with a value of 0 exclude its associated element in the sum, while bits with a 1 would include the element. To do something like this try the following:
#include <vector>
#include <iostream>
void print_sum(const std::vector<int>& array, unsigned long long i) {
int sum = 0;
for (int index=0; i > 0; i=i>>1, ++index) {
if (i % 2 == 1) {
std::cout << array[index] << (i>1 ? "+" : "=");
sum += array[index];
}
}
std::cout << sum << std::endl;
}
void printer(const std::vector<int>& array) {
if (array.size() < sizeof(unsigned long long) * 8) {
unsigned long long n = 1 << array.size();
for (unsigned long long i = 1; i < n; ++i) {
print_sum(array, i);
}
}
}
int main(int argc, char** argv) {
std::vector<int> sample {1, 2, 3, 4};
printer(sample);
return 0;
}
This program has output:
1=1
2=2
1+2=3
3=3
1+3=4
2+3=5
1+2+3=6
4=4
1+4=5
2+4=6
1+2+4=7
3+4=7
1+3+4=8
2+3+4=9
1+2+3+4=10