Elements : a b c
all combinations in such a way:abcabacbcabc
Formula to get total number of combinations of unique elements without repetition = 2^n - 1 (where n is the number of unique elements)
In our case top: 2^3 - 1 = 7
Another formula to get the combinations with specific length = n!/(r! * (n - r)!) (where n= nb of unique items and r=length)
Example for our the above case with r=2 : 3!/(2! * 1!) = 3 which is ab ac bc
Is there any algorithm or function that gets all of the 7 combinations?
I searched a lot but all i can find is one that gets the combinations with specific length only.
UPDATE:
This is what I have so far but it only gets combination with specific length:
void recur(string arr[], string out, int i, int n, int k, bool &flag)
{
flag = 1;
// invalid input
if (k > n)
return;
// base case: combination size is k
if (k == 0) {
flag = 0;
cout << out << endl;
return;
}
// start from next index till last index
for (int j = i; j < n; j++)
{
recur(arr, out + " " + arr[j], j + 1, n, k - 1,flag);
}
}
The best algorithm I've ever find to resolve this problem is to use bitwise operator. You simply need to start counting in binary. 1's in binary number means that you have to show number.
e.g.
in case of string "abc"
number , binary , string
1 , 001 , c
2 , 010 , b
3 , 011 , bc
4 , 100 , a
5 , 101 , ac
6 , 110 , ab
7 , 111 , abc
This is the best solution I've ever find. you can do it simply with loop. there will not be any memory issue.
here is the code
#include <iostream>
#include <string>
#include <math.h>
#include<stdio.h>
#include <cmath>
using namespace std;
int main()
{
string s("abcd");
int condition = pow(2, s.size());
for( int i = 1 ; i < condition ; i++){
int temp = i;
for(int j = 0 ; j < s.size() ; j++){
if (temp & 1){ // this condition will always give you the most right bit of temp.
cout << s[j];
}
temp = temp >> 1; //this statement shifts temp to the right by 1 bit.
}
cout<<endl;
}
return 0;
}
Do a simple exhaustive search.
#include <iostream>
#include <string>
using namespace std;
void exhaustiveSearch(const string& s, int i, string t = "")
{
if (i == s.size())
cout << t << endl;
else
{
exhaustiveSearch(s, i + 1, t);
exhaustiveSearch(s, i + 1, t + s[i]);
}
}
int main()
{
string s("abc");
exhaustiveSearch(s, 0);
}
Complexity: O(2^n)
Here's an answer using recursion, which will take any number of elements as strings:
#include <vector>
#include <string>
#include <iostream>
void make_combos(const std::string& start,
const std::vector<std::string>& input,
std::vector<std::string>& output)
{
for(size_t i = 0; i < input.size(); ++i)
{
auto new_string = start + input[i];
output.push_back(new_string);
if (i + 1 == input.size()) break;
std::vector<std::string> new_input(input.begin() + 1 + i, input.end());
make_combos(new_string, new_input, output);
}
}
Now you can do:
int main()
{
std::string s {};
std::vector<std::string> output {};
std::vector<std::string> input {"a", "b", "c"};
make_combos(s, input, output);
for(auto i : output) std::cout << i << std::endl;
std::cout << "There are " << output.size()
<< " unique combinations for this input." << std::endl;
return 0;
}
This outputs:
a
ab
abc
ac
b
bc
c
There are 7 unique combinations for this input.
Related
I am generating all permutations of a string using bitmask.
void recurse(string s, int mask,int taken){
if(taken == n){
cout << " ";
return;
}
for(int i = 0; i < n; i++){
if(((1 << i) & mask) == 0){
cout << s[i];
recurse(s, (mask|(1 << i)), taken + 1);
}
}
}
In this function n is the length of the string. I am keeping track of how many characters are printed so far using taken variable.
In the main function I am calling
recurse(s,0,0);
But this is not working correctly.
For input
red
Its output is
red
de
erd
dr
dre
er
Where I am going wrong?
UPDATE
// Below code works fine.
void recurse(string s, int mask,int taken, string pref){
if(taken == n){
cout << pref <<endl;
return;
}
for(int i = 0; i < n; i++){
if(((mask >> i) & 1) == 0){
recurse(s,(mask | (1 << i)),taken + 1, pref + s[i]);
}
}
}
Actually, the questioner provided the answer himself. (Congratulation.)
As I already started to fiddle (couldn't resist) I want to present my solution as well:
#include <iostream>
#include <string>
using namespace std;
void recurse(
const string &s, unsigned mask = 0, const string &out = string())
{
size_t n = s.size();
if (out.size() == n) cout << ' ' << out;
for (size_t i = 0; i < n; ++i) {
unsigned bit = 1 << i;
if (mask & bit) continue;
recurse(s, mask | bit, out + s[i]);
}
}
int main()
{
string test = "red";
recurse(test);
cout << endl;
return 0;
}
Compiled and tested:
red rde erd edr dre der
recurse() iterates through all characters of s looking for one which is not already marked in the mask as taken. Each found characters is added to output out. Then, the recursive call repeats it for all untaken characters.
Check out the sample code yourself on ideone.
Permutation tree for 'abc'
Your first code was visiting each node of this tree once and printing a character. So it was giving wrong output.
On a different note, you have used some redundant variables.
Instead of n you should use s.size().
In the second code instead of taken you you should use pref.size().
Here is another version. It's different from the questioner's code in 2 ways:
The parameter taken can be omitted and we can use mask + 1 == (1 << n) instead. It basically checks if bits 1 to n-1 of mask are all 1's. If so, then the recursion depth is n and we print the permutation.
Copying the string pref in each iteration can be slow if the size of the string is large. We can instead use a reference.
#include <iostream>
#include <string>
using namespace std;
void recurse(string s, int mask, string &pref);
int n = 3;
int main()
{
string pref("");
recurse(string("abc"), 0, pref);
return 0;
}
void recurse(string s, int mask, string &pref)
{
if (mask + 1 == (1 << n)) {
cout << pref << endl;
return;
}
for (int i = 0; i < n; i++) {
if (((mask >> i) & 1) == 0) {
pref += s[i];
recurse(s, (mask | (1 << i)), pref);
pref.erase(pref.end() - 1);
}
}
}
where n is the size of the string. The output is
abc
acb
bac
bca
cab
cba
I am obliged to write program that will show minimal quantity of Fibonacci numbers which sum is equal to k number which user write into program.
So for example user writes 1070
And the program will show 987 89 -5 -1 (because all of these numbers are Fibonacci numbers (you can add or substract to get desired sum).
I have problem to think about solution to this problem.
I wrote code to get all Fibonacci numbers from 0 to 46.
#include <iostream>
unsigned long long Fibbo[47];
void preapare()
{
Fibbo[0] = 0;
Fibbo[1] = 1;
i = 2;
while (i<47)
{
Fibbo[i] = Fibbo[i - 1] + Fibbo[i - 2];
i++;
}
}
int main()
{
preapare();
int k=0;
std::cin >> k;
}
I will be glad for any help. You can use Fibonacci Number as many times as you will. For example you can do 1+1+1+1+1
#include <iostream>
#include <vector>
#include <stdlib.h>
using namespace std;
void prepare( vector<int> & fibos ) { ... } // along the lines we see in OPs code
int findClosest( int n, vector<int> & fibos ){ // return Fibonacci number closest to n
int fi = 0;
for( std::vector<int>::iterator it = fibos.begin() ; it != fibos.end(); ++it){
if( abs(*it - n) < abs(fi - n) ){
fi = *it;
}
}
return fi;
}
// The algorithm:
// lookup closest Fi, add "signed" to terms
// reduce n, adjust sign and call recursively
void sum( int n, vector<int> & fibos, vector<int> & terms, int sign = 1 ){
if( n == 0 ) return;
int fi = findClosest( n, fibos );
terms.push_back( sign*fi );
sum( abs(n - fi), fibos, terms, n - fi > 0 ? sign : -sign );
}
int main() {
vector<int> fibos;
prepare( fibos );
vector<int> terms;
int n = 1070;
sum( n, fibos, terms );
cout << n << " =";
for( std::vector<int>::iterator it = terms.begin() ; it != terms.end(); ++it){
cout << " " << *it;
}
cout << endl;
return 0;
}
For user input:
Before the while loop, you need to get the input, save it to a variable, and use that in your while condition. Something like this:
#include <iostream>
...
int k_val = 0;
std::cout << "Enter the value for k: ";
std::cin >> k_val;
...
Your prepare() fixed:
unsigned long long* preapare(const size_t n) {
unsigned long long* Fibbo = new unsigned long long[n];
Fibbo[0] = 0;
Fibbo[1] = 1;
for(size_t i = 2; i < n; ++i) {
Fibbo[i] = Fibbo[i - 1] + Fibbo[i - 2];
}
return Fibbo;
}
then you'll have to memory manage the returned array;
I've done this, the code will solve the grater fibonacci numbers to be add so the result will be the specified number:
fiboMax return a sequence with the fibonacci number less to the input number.
getiboSec return a sequence with the bigger fibonacci numbers that sum the input number.
'''
Created on 15/01/2014
'''
def fiboMax(num):
ret = [0,1]
a = 1
b = 2
while b < num:
ret.append(b)
tmp = a + b
a = b
b = tmp
return ret
def getFiboSec(num):
fiboSec = []
fiboNumbers = fiboMax(num)
i = len(fiboNumbers) - 1
while num > 0 and i > 0:
fiboNum = fiboNumbers[i]
while(fiboNum <= num):
fiboSec.append(fiboNum)
num -= fiboNum
i -= 1
return fiboSec
if __name__ == '__main__':
num = 20
print(fiboMax(num))
print(getFiboSec(num))
output:
figonnaci number to 20 = [0, 1, 2, 3, 5, 8, 13]
fibonacci number that sum 20 = [13, 5, 2]
It doesnt work with negative numbers, anyway its solving the problem but not the efficient way.
You are accessing the indexes -2 and -1 in your loop. Your variable i should start at 2. You also try to add values to pointers. None of your values in Fibbo[] are set.
Given a string, I'm trying to count the occurrence of each letter in the string and then sort their frequency from highest to lowest. Then, for letters that have similar number of occurrences, I have to sort them alphabetically.
Here is what I have been able to do so far:
I created an int array of size 26 corresponding to the 26 letters of the alphabet with individual values representing the number of times it appeared in the sentence
I pushed the contents of this array into a vector of pairs, v, of int and char (int for the frequency, and char for the actual letter)
I sorted this vector of pairs using std::sort(v.begin(), v.end());
In displaying the frequency count, I just used a for loop starting from the last index to display the result from highest to lowest. I am having problems, however, with regard to those letters having similar frequencies, because I need them displayed in alphabetical order. I tried using a nested for loop with the inner loop starting with the lowest index and using a conditional statement to check if its frequency is the same as the outer loop. This seemed to work, but my problem is that I can't seem to figure out how to control these loops so that redundant outputs will be avoided. To understand what I'm saying, please see this example output:
Enter a string: hello world
Pushing the array into a vector pair v:
d = 1
e = 1
h = 1
l = 3
o = 2
r = 1
w = 1
Sorted first according to frequency then alphabetically:
l = 3
o = 2
d = 1
e = 1
h = 1
r = 1
w = 1
d = 1
e = 1
h = 1
r = 1
d = 1
e = 1
h = 1
d = 1
e = 1
d = 1
Press any key to continue . . .
As you can see, it would have been fine if it wasn't for the redundant outputs brought about by the incorrect for loops.
If you can suggest more efficient or better implementations with regard to my concern, then I would highly appreciate it as long as they're not too complicated or too advanced as I am just a C++ beginner.
If you need to see my code, here it is:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
cout<<"Enter a string: ";
string input;
getline(cin, input);
int letters[26]= {0};
for (int x = 0; x < input.length(); x++) {
if (isalpha(input[x])) {
int c = tolower(input[x] - 'a');
letters[c]++;
}
}
cout<<"\nPushing the array into a vector pair v: \n";
vector<pair<int, char> > v;
for (int x = 0; x < 26; x++) {
if (letters[x] > 0) {
char c = x + 'a';
cout << c << " = " << letters[x] << "\n";
v.push_back(std::make_pair(letters[x], c));
}
}
// Sort the vector of pairs.
std::sort(v.begin(), v.end());
// I need help here!
cout<<"\n\nSorted first according to frequency then alphabetically: \n";
for (int x = v.size() - 1 ; x >= 0; x--) {
for (int y = 0; y < x; y++) {
if (v[x].first == v[y].first) {
cout << v[y].second<< " = " << v[y].first<<endl;
}
}
cout << v[x].second<< " = " << v[x].first<<endl;
}
system("pause");
return 0;
}
You could simplify this a lot, in two steps:
First use a map to count the number of occurrences of each character in the string:
std::unordered_map<char, unsigned int> count;
for( char character : string )
count[character]++;
Use the values of that map as comparison criteria:
std::sort( std::begin( string ) , std::end( string ) ,
[&]( char lhs , char rhs )
{
return count[lhs] < count[rhs];
}
);
Here is a working example running at ideone.
If you want highest frequency then lowest letter, an easy way would be to store negative values for frequency, then negate it after you sort. A more efficient way would be to change the function used for sorting, but that is a touch trickier:
struct sort_helper {
bool operator()(std::pair<int,char> lhs, std::pair<int,char> rhs) const{
return std::make_pair(-lhs.first,lhs.second)<std::make_pair(-rhs.first,rhs.second);
}
};
std::sort(vec.begin(),vec.end(),sort_helper());
(Posted on behalf of the OP.)
Thanks to the responses of the awesome people here at Stack Overflow, I was finally able to fix my problem. Here is my final code in case anyone is interested or for future references of people who might be stuck in the same boat:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct Letters
{
Letters() : freq(0){}
Letters(char letter,int freq) {
this->freq = freq;
this->letter = letter;
}
char letter;
int freq;
};
bool Greater(const Letters& a, const Letters& b)
{
if(a.freq == b.freq)
return a.letter < b.letter;
return a.freq > b.freq;
}
int main () {
cout<<"Enter a string: ";
string input;
getline(cin, input);
vector<Letters> count;
int letters[26]= {0};
for (int x = 0; x < input.length(); x++) {
if (isalpha(input[x])) {
int c = tolower(input[x] - 'a');
letters[c]++;
}
}
for (int x = 0; x < 26; x++) {
if (letters[x] > 0) {
char c = x + 'a';
count.push_back(Letters(c, letters[x]));
}
}
cout<<"\nUnsorted list..\n";
for (int x = 0 ; x < count.size(); x++) {
cout<<count[x].letter<< " = "<< count[x].freq<<"\n";
}
std::sort(count.begin(),count.end(),Greater);
cout<<"\nSorted list according to frequency then alphabetically..\n";
for (int x = 0 ; x < count.size(); x++) {
cout<<count[x].letter<< " = "<< count[x].freq<<"\n";
}
system("pause");
return 0;
}
Example output:
Enter a string: hello world
Unsorted list..
d = 1
e = 1
h = 1
l = 3
o = 2
r = 1
w = 1
Sorted list according to frequency then alphabetically..
l = 3
o = 2
d = 1
e = 1
h = 1
r = 1
w = 1
Press any key to continue . . .
I basically just followed the advice of #OliCharlesworth and implemented a custom comparator through the help of this guide: A Function Pointer as Comparison Function.
Although I'm pretty sure that my code can still be made more efficient, I'm still pretty happy with the results.
// CODE BY VIJAY JANGID in C language
// Using arrays, Time complexity - ( O(N) * distinct characters )
// Efficient answer
#include <stdio.h>
int main() {
int iSizeFrequencyArray= 58;
// 122 - 65 = 57 for A to z
int frequencyArray[iSizeFrequencyArray];
int iIndex = 0;
// Initializing frequency to zero for all
for (iIndex = 0; iIndex < iSizeFrequencyArray; iIndex++) {
frequencyArray[iIndex] = 0;
}
int iMyStringLength = 1000;
char chMyString[iMyStringLength];
// take input for the string
scanf("%s", &chMyString);
// calculating length
int iSizeMyString;
while(chMyString[++iSizeMyString]);
// saving each character frequency in the freq. array
for (iIndex = 0; iIndex < iSizeMyString; iIndex++) {
int currentChar = chMyString[iIndex];
frequencyArray[currentChar - 65]++;
}
/* // To print the frequency of each alphabet
for (iIndex = 0; iIndex < iSizeFrequencyArray; iIndex++) {
char currentChar = iIndex + 65;
printf("\n%c - %d", currentChar, frequencyArray[iIndex ]);
}
*/
int lowestDone = 0, lowest = 0, highestSeen = 0;
for( iIndex = 0; iIndex < iSizeFrequencyArray; iIndex++ ) {
if(frequencyArray[iIndex] > highestSeen) {
highestSeen = frequencyArray[iIndex];
}
}
// assigning sorted values to the current array
while (lowest != highestSeen) {
// calculating lowest frequency
for( iIndex = 0; iIndex < iSizeFrequencyArray; iIndex++ ) {
if( frequencyArray[iIndex] > lowestDone &&
frequencyArray[iIndex] < lowest) {
lowest = frequencyArray[iIndex]; // taking lowest value
}
}
// printing that frequency
for( iIndex =0; iIndex < iSizeFrequencyArray; iIndex++ ) {
// print that work for that times
if(frequencyArray[iIndex] == lowest){
char currentChar = iIndex + 65;
int iIndex3;
for(iIndex3 = 0; iIndex3 < lowest; iIndex3++){
printf("%c", currentChar);
}
}
}
// now that is done, move to next lowest
lowestDone = lowest;
// reset to highest value, to get the next lowest one
lowest = highestSeen+1;
}
return 0;
}
Explanation:
First create array to store repetition of size (112 - 65) to store asci characters from A to z.
Store the frequency of each character by incrementing at each occurrence.
Now find the highest frequency.
Run a loop where condition is (lowest != highest) where lowest = 0 initially.
Now in each iteration print character which whose frequency is equal to lowest. They will be alphabetically in order automatically.
At last find the next higher frequency and print then so on.
When lowest reach highest then break loop.
Using an unordered_map for counting characters as suggested by #Manu343726 is a good idea. However, in order to produce your sorted output, another step is required.
My solution is also in C++11 and uses a lambda expression. This way you neither need to define a custom struct nor a comparison function. The code is almost complete, I just skipped reading the input:
#include <unordered_map>
#include <iostream>
#include <set>
int main() {
string input = "hello world";
unordered_map<char, unsigned int> count;
for (char character : input)
if (character >= 'a' && character <= 'z')
count[character]++;
cout << "Unsorted list:" << endl;
for (auto const &kv : count)
cout << kv.first << " = " << kv.second << endl;
using myPair = pair<char, unsigned int>;
auto comp = [](const myPair& a, const myPair& b) {
return (a.second > b.second || a.second == b.second && a.first < b.first);
};
set<myPair, decltype(comp)> sorted(comp);
for(auto const &kv : count)
sorted.insert(kv);
cout << "Sorted list according to frequency then alphabetically:" << endl;
for (auto const &kv : sorted)
cout << kv.first << " = " << kv.second << endl;
return 0;
}
Output:
Unsorted list:
r = 1
h = 1
e = 1
d = 1
o = 2
w = 1
l = 3
Sorted list according to frequency then alphabetically:
l = 3
o = 2
d = 1
e = 1
h = 1
r = 1
w = 1
Note 1: Instead of inserting each element from the unordered_map into the set, it might be more efficient to use the function std::transform or std:copy, but my code is at least short.
Note 2: Instead of using a custom sorted set which maintains the order you want, it might be more efficient to use a vector of pairs and sort it once in the end, but your solution is already similar to this.
Code on Ideone
#include<stdio.h>
// CODE BY AKSHAY BHADERIYA
char iFrequencySort (char iString[]);
void vSort (int arr[], int arr1[], int len);
int
main ()
{
int iLen, iCount;
char iString[100], str[100];
printf ("Enter a string : ");
scanf ("%s", iString);
iFrequencySort (iString);
return 0;
}
char
iFrequencySort (char iString[])
{
int iFreq[100] = { 0 };
int iI, iJ, iK, iAsc, iLen1 = 0, iLen = 0;
while (iString[++iLen]);
int iOccurrence[94];
int iCharacter[94];
for (iI = 0; iI < iLen; iI++)
{ //frequency of the characters
iAsc = (int) iString[iI];
iFreq[iAsc - 32]++;
}
for (iI = 0, iJ = 0; iI < 94; iI++)
{ //the characters and occurrence arrays
if (iFreq[iI] != 0)
{
iCharacter[iJ] = iI;
iOccurrence[iJ] = iFreq[iI];
iJ++;
}
}
iLen1 = iJ;
vSort (iOccurrence, iCharacter, iLen1); //sorting both arrays
/*letter array consists only the index of iFreq array.
Converting it to the ASCII value of corresponding character */
for (iI = 0; iI < iLen1; iI++)
{
iCharacter[iI] += 32;
}
iK = 0;
for (iI = 0; iI < iLen1; iI++)
{ //characters into original string
for (iJ = 0; iJ < iOccurrence[iI]; iJ++)
{
iString[iK++] = (char) iCharacter[iI];
}
}
printf ("%s", iString);
}
void
vSort (int iOccurrence[], int iCharacter[], int len)
{
int iI, iJ, iTemp;
for (iI = 0; iI < len - 1; iI++)
{
for (iJ = iI + 1; iJ < len; iJ++)
{
if (iOccurrence[iI] > iOccurrence[iJ])
{
iTemp = iOccurrence[iI];
iOccurrence[iI] = iOccurrence[iJ];
iOccurrence[iJ] = iTemp;
iTemp = iCharacter[iI];
iCharacter[iI] = iCharacter[iJ];
iCharacter[iJ] = iTemp;
}
}
}
}
Answers are given and one is accepted. I would like to give an additional answer showing the standard approach for this task.
There is often the requirement to first count things and then to get back their rank or some topmost value or other information.
One of the most common solution is to use a so called associative container for that, and, here specifically, a std::map or even better a std::unordered_map. This, because we need a key value, in the above described way a letter and an associted value, here the count for this letter. The key is unique. There cannot be more than one of the same letter in it. This would of course not make any sense.
Associative containers are very efficient by accessing their elements by their key value.
OK, there are 2 of them. The std::map and the std::unordered_map. One uses a tree to store the key in a sorted manner and the other use fast hashing algorithms to access the key values. Since we are later not interested in sorted keys, but in sorted count of occurence, we can choose the std::unordred_map. As a futher benefit, this will use fast the hashing algorithms mentioned to access a key.
The maps have an additional huge advantage. The have an index operator [], that will look very fast for a key value. If found, it will return a reference to the value associated with the key. If not found, it will create a key and initialize its value with the default (0 in our case). And then counting of any key is as simple as map[key]++.
But then, later, we here often hear: But it must be sorted by the count. That does of course not work, because the count my have duplicate values, and the map can only contain unique key values. So, impossible.
The solution is to use a second associative container a std::multiset which can have more of the same keys and a custome sort operator, where we can sort according to the value. In this we store the not a key and a value as 2 elements, but a std::pair with both values. And we sort by the 2nd part of the pair.
We cannot use a std::multi:set in the first place, because we need the unique key (in this case the letter).
The above described approach gives us extreme flexibility and ease of use. We can basically count anything with this algorithm
It could for example look the the below compact code:
#include <iostream>
#include <string>
#include <utility>
#include <set>
#include <unordered_map>
#include <type_traits>
#include <cctype>
// ------------------------------------------------------------
// Create aliases. Save typing work and make code more readable
using Pair = std::pair<char, unsigned int>;
// Standard approach for counter
using Counter = std::unordered_map<Pair::first_type, Pair::second_type>;
// Sorted values will be stored in a multiset
struct Comp { bool operator ()(const Pair& p1, const Pair& p2) const { return (p1.second == p2.second) ? p1.first<p2.first : p1.second>p2.second; } };
using Rank = std::multiset<Pair, Comp>;
// ------------------------------------------------------------
// --------------------------------------------------------------------------------------
// Compact function to calculate the frequency of charcters and then get their rank
Rank getRank(std::string& text) {
// Definition of our counter
Counter counter{};
// Iterate over all charcters in text and count their frequency
for (const char c : text) if (std::isalpha(c)) counter[char(std::tolower(c))]++;
// Return ranks,sorted by frequency and then sorted by character
return { counter.begin(), counter.end() };
}
// --------------------------------------------------------------------------------------
// Test, driver code
int main() {
// Get a string from the user
if (std::string text{}; std::getline(std::cin, text))
// Calculate rank and show result
for (const auto& [letter, count] : getRank(text))
std::cout << letter << " = " << count << '\n';
}
Please see the minimal statements used. Very elegant.
But often we do see that arrays are use as an associted container. They have also an index (a key) and a value. Disadvantage may be a tine space overhead for unsued keys. Additionally the will only work for something wit a know magnitude. For example for 26 letters. Other countries alphabets may have more or less letters. Then this kind of solution would be not that flexible. Anyway it is also often used and OK.
So, your solution maybe a littel bit more complex, but will of course still work.
Let me give you an additional example for getting the topmost value of any container. Here you will see, how flexible such a solution can be.
I am sorry, but it is a little bit advanced. . .
#include <iostream>
#include <utility>
#include <unordered_map>
#include <queue>
#include <vector>
#include <iterator>
#include <type_traits>
#include <string>
// Helper for type trait We want to identify an iterable container ----------------------------------------------------
template <typename Container>
auto isIterableHelper(int) -> decltype (
std::begin(std::declval<Container&>()) != std::end(std::declval<Container&>()), // begin/end and operator !=
++std::declval<decltype(std::begin(std::declval<Container&>()))&>(), // operator ++
void(*std::begin(std::declval<Container&>())), // operator*
void(), // Handle potential operator ,
std::true_type{});
template <typename T>
std::false_type isIterableHelper(...);
// The type trait -----------------------------------------------------------------------------------------------------
template <typename Container>
using is_iterable = decltype(isIterableHelper<Container>(0));
// Some Alias names for later easier reading --------------------------------------------------------------------------
template <typename Container>
using ValueType = std::decay_t<decltype(*std::begin(std::declval<Container&>()))>;
template <typename Container>
using Pair = std::pair<ValueType<Container>, size_t>;
template <typename Container>
using Counter = std::unordered_map<ValueType<Container>, size_t>;
template <typename Container>
using UnderlyingContainer = std::vector<Pair<Container>>;
// Predicate Functor
template <class Container> struct LessForSecondOfPair {
bool operator () (const Pair<Container>& p1, const Pair<Container>& p2) { return p1.second < p2.second; }
};
template <typename Container>
using MaxHeap = std::priority_queue<Pair<Container>, UnderlyingContainer<Container>, LessForSecondOfPair<Container>>;
// Function to get most frequent used number in any Container ---------------------------------------------------------
template <class Container>
auto topFrequent(const Container& data) {
if constexpr (is_iterable<Container>::value) {
// Count all occurences of data
Counter<Container> counter{};
for (const auto& d : data) counter[d]++;
// Build a Max-Heap
MaxHeap<Container> maxHeap(counter.begin(), counter.end());
// Return most frequent number
return maxHeap.top().first;
}
else
return data;
}
// Test
int main() {
std::vector testVector{ 1,2,2,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,6,7 };
std::cout << "Most frequent is: " << topFrequent(testVector) << "\n";
double cStyleArray[] = { 1.1, 2.2, 2.2, 3.3, 3.3, 3.3 };
std::cout << "Most frequent is: " << topFrequent(cStyleArray) << "\n";
std::string s{ "abbcccddddeeeeeffffffggggggg" };
std::cout << "Most frequent is: " << topFrequent(s) << "\n";
double value = 12.34;
std::cout << "Most frequent is: " << topFrequent(value) << "\n";
return 0;
}
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.
I wanted a non recursive approach to the problem of generating combination of certain set of characters or numbers.
So, given a subset k of numbers n, generate all the possible combination n!/k!(n-k)!
The recursive method would give a combination, given the previous one combination.
A non recursive method would generate a combination of a given value of loop index i.
I approached the problem with this code:
Tested with n = 4 and k = 3, and it works, but if I change k to a number > 3 it does not work.
Is it due to the fact that (n-k)! in case of n = 4 and k = 3 is 1. and if k > 3 it will be more than 1?
Thanks.
int facto(int x);
int len,fact,rem=0,pos=0;
int str[7];
int avail[7];
str[0] = 1;
str[1] = 2;
str[2] = 3;
str[3] = 4;
str[4] = 5;
str[5] = 6;
str[6] = 7;
int tot=facto(n) / facto(n-k) / facto(k);
for (int i=0;i<tot;i++)
{
avail[0]=1;
avail[1]=2;
avail[2]=3;
avail[3]=4;
avail[4]=5;
avail[5]=6;
avail[6]=7;
rem = facto(i+1)-1;
cout<<rem+1<<". ";
for(int j=len;j>0;j--)
{
int div = facto(j);
pos = rem / div;
rem = rem % div;
cout<<avail[pos]<<" ";
avail[pos]=avail[j];
}
cout<<endl;
}
int facto(int x)
{
int fact=1;
while(x>0) fact*=x--;
return fact;
}
Err.. why not use std::next_permutation? It does exactly what you're looking for and doesn't require you to write (and debug and maintain) your own.
This is about as fast as it can be calculated - the actual combination function is done using two lines of code.
However, this isn't the most intuitively easy to understand!
The work is done by implementing a Gray code sequence.
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <stdint.h>
using namespace std;
//'Combinations' over a set of n objects with k bins, eg n=3,k=2 = 3
//The combination function.
//It takes a combination and returns the next combination.
//It uses GCC's '__builtin_ctzll' which returns the number of
//trailing 0-bits in v, starting at the least significant bit position.
uint64_t combination(uint64_t v) {
uint64_t t = v | (v - 1ULL); // t gets v's least significant 0 bits set to 1
return (t + 1ULL) | (((~t & -~t) - 1ULL) >> (__builtin_ctzll(v) + 1ULL));
}
//arg 1 is number of bins (n) arg 2 is number of samples (k/r)
int main (int argc, char *argv[]) {
uint64_t n = min(64ULL,argc > 1ULL ? atoi(argv[1]) : 3ULL); //max bins = 63
uint64_t k = min( n,argc > 2 ? atoi(argv[2]) : 2ULL); //max samples = bins.
uint64_t v = (1ULL << k) - 1; //start value;
uint64_t m = n == 64 ? UINT64_MAX: (1ULL << n) - 1ULL; //size of n is used as a mask.
string index = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz+*";
cout << index.substr(0,n) << endl;
do {
cout << bitset<64>(v & m).to_string().substr(64ULL-n) << endl;
v=combination(v);
} while (v < m);
return 0;
}
Consider that your iterator is a number of k digits in base n. In C/C++ you can represent it as an array of ints of size k where every element is in the range from 0 to n-1).
Then, to iterate from one position to the next you only need to increment the number.
That will give you all the permutations. In order to get combinations you have to impose an additional condition that is that digits must be in ascending order.
For instance with k = 3, n = 3: 000 001 002 011 012 022 111 112 122 222
Implementing that constraint in C is also pretty simple, on the increment operation used to iterate, instead of setting the rightmost digits to zero when there is a carry, you have to set them to the same value as the leftmost digit changed.
update: some code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXK 100
int
main(int argc, char *argv[]) {
int digits[MAXK];
int k = atol(argv[1]);
int n = atol(argv[2]);
int i, left;
memset(digits, 0, sizeof(digits));
while(1) {
for (i = k; i--; ) {
printf("%d", digits[i]);
printf((i ? "-" : "\n"));
}
for (i = k; i--; ) {
left = ++digits[i];
if (left < n) {
while (++i < k) digits[i] = left;
break;
}
}
if (i < 0) break;
}
}