I wrote the following code for counting the frequency of names and then printing out the names in lexicographic order with their frequencies.The input here is supposed to be n number of names.So for sorting i wrote qsort function but i guess there is some error in it which i am not able to find bcoz using using other sorting method besides qsort works fine for this code.Please suggest what is the error as i have tried but found no help.below is the code snippet
#include <cstdlib>
#include<stdio.h>
#include<string.h>
struct stu
{
char name[100];
int no;
};
int cmpfunc(const void* p,const void *q){
struct stu *a = *((struct stu**)p);
struct stu *b = *((struct stu**)q);
int str=strcmp(a->name,b->name);
if(str>0) return 1;
if(str<0) return -1;
else return 0;
}
int main(int argc, char** argv) {
int n,k=0;
scanf("%d",&n);
struct stu* data[1000];
for(int i=0 ; i<n ; i++)
{
char nam[100];
scanf("%s",nam);
if(i==0)
{
struct stu* temp=(struct stu*)(malloc(sizeof(struct stu)));
strcpy(temp->name,nam);
temp->no=1;
data[k++]=temp;
}
else
{
int j;
for(j=0 ; j<k ; j++)
{
if(strcmp(data[j]->name,nam)==0)
{
data[j]->no++;
break;
}
}
if(j==k)
{
struct stu* temp=(struct stu*)(malloc(sizeof(struct stu)));
strcpy(temp->name,nam);
temp->no=1;
data[k++]=temp;
}
}
}
qsort(data, k, sizeof(struct stu*),cmpfunc);
for(int i=0 ; i<k ; i++)
{
printf("%s %d\n",data[i]->name,data[i]->no);
}
return 0;
}
if i give input as
5
abcd
abcd
fgh
fgr
fgh
the output is run failed
With the exception of <cstdio>, your code looks much more like C than C++. Perhaps you meant to use <stdio.h>, heed various warnings against casting malloc, check return values and use a C compiler, but this question is tagged C++. In C++ there are far more sensible idioms, for example:
std::string instead of char* / char[].
std::cin/std::cout instead of scanf/printf.
std::vector instead of struct stu* data[1000].
size_t instead of int for array indexes and looping over arrays.
new/delete/unique_ptr instead of malloc/free.
using namespace std;
struct stu {
string name;
int no;
stu() {
}
};
int cmpfunc(const stu *p, const stu *q) {
return p->name < q->name;
}
int main(int argc, char** argv) {
size_t n;
cin >> n;
vector<stu*> data;
for (size_t i = 0; i < n; i++)
{
string nam;
cin >> nam;
if (i == 0)
{
auto* temp = new stu();
temp->name = nam;
temp->no = 1;
data.push_back(temp);
}
else
{
int j;
for (j = 0; j < data.size(); j++)
{
if(data[j]->name == nam)
{
data[j]->no++;
break;
}
}
if (j == data.size())
{
auto* temp= new stu();
temp->name = nam;
temp->no = 1;
data.push_back(temp);
}
}
}
std::sort(data.begin(), data.end(), cmpfunc);
for (int i = 0; i < data.size(); i++)
{
cout << data[i]->name << data[i]->no << endl;
delete data[i];
}
return 0;
}
Related
struct Student
{
char* name;
int balls;
};
void inputdata(Student **s, int *n)
{
int nn;
printf("%s\n", "Input amount of students");
scanf("%i", &nn);
Student* a = new Student[nn];
for (int i = 0; i < nn; ++i)
{
a[i].name = new char[4096];
scanf("%4095s", a[i].name);
scanf("%i", &a[i].balls);
}
*n = nn;
*s = a;
}
void print(Student *s, int n)
{
for (int i = 0; i < n; ++i)
{
printf("%s %i\n", s[i].name, s[i].balls);
}
}
void fixdata(Student *s, int *n)
{
int nn = *n;
for (int i = 0; i < nn; ++i)
{
if (s[i].balls > 100)
s[i].balls = 100;
else if (s[i].balls < 20)
{
for(int j = i; j < nn; ++j)
s[j] = s[j+1];
nn-=1;
}
}
*n = nn;
}
int main(int argc, char const *argv[])
{
Student* s;
int n;
inputdata(&s, &n);
print(s, n);
fixdata(s, &n);
print(s, n);
return 0;
}
I am trying to delete items where balls is less than 20. If so, I am supposed to shift items to the right, but at the same time remove items that are less than 20. I try, but it drastically shifts left 2 of the same records and is not doing the job properly.
UPDATE: Ok, I cleaned up the code a bit, now n decreases, but the problem when it stays at 1 record, that is supposed to be deleted too. I wonder why it does not get removed. Thankfully most of the trouble is fixed. Still, what is the problem deleting one item left when it is less than 20?
The function has a bug because after moving elements of a sub-array to the left in the next iteration of the for loop you will deal with another element instead of the required. Also the function should return the number of actual elements after removing some elements.
Also the function can produce memory leaks then one element of the array is assigned to other element of the array.
The function can look the following way
int fixdata( Student *s, int n )
{
int i = 0;
for ( int j = 0; j < n; ++j )
{
if ( not ( s[j].balls < 20 ) )
{
if ( i != j )
{
delete [] s[i].name;
s[i] = s[j];
s[j].name = nullptr;
}
if ( s[i].balls > 100 ) s[i].balls = 100;
++i;
}
}
return i;
}
And in main you can write
int m = fixdata(s, n);
print(s, m);
Also you should delete the allocated memory when the array is not needed any more.
for ( int i = 0; i < n; i++ )
{
delete [] s[i].name;
}
delete [] s;
In fixdata(), when "removing" an item, you are leaking that item's name, but more importantly your inner loop goes out of bounds of the array if the "last" item is removed.
Try this instead:
void fixdata(Student *s, int *n)
{
int nn = *n;
for (int i = 0; i < nn; ++i)
{
if (s[i].balls > 100)
{
s[i].balls = 100;
}
else if (s[i].balls < 20)
{
for(int j = i + 1; j < nn; ++j)
{
delete[] s[j-1].name;
s[j-1] = s[j];
s[j] = Student{};
}
--nn;
}
}
*n = nn;
}
That being said, your code is more C than C++. The C++ approach would be to use things like std::cin, std::string, and std::vector instead, eg:
#include <iostream>
#include <vector>
#include <string>
struct Student
{
std::string name;
int balls;
};
std::istream& operator>>(std::istream &in, Student &stud)
{
in >> s.name >> s.balls;
return in;
}
std::ostream& operator<<(std::ostream &out, const Student &stud)
{
out << stud.name << " " << stud.balls;
return out;
}
void inputdata(std:vector<Student> &s)
{
int nn;
std::cout << "Input amount of students\n";
std::cin >> nn;
std::vector<Student> a(nn);
for (auto &stud : s) {
std::cin >> stud;
}
s = std:move(a);
}
void print(const std::vector<Student> &s)
{
for (const auto &stud : s) {
std::cout << stud << "\n";
}
}
void fixdata(std::vector<Student> &s)
{
for (size_t i = 0; i < s.size();)
{
auto &stud = s[i];
if (stud.balls < 20) {
s.erase(s.begin()+i);
}
else {
if (stud.balls > 100) {
stud.balls = 100;
}
++i;
}
}
/* alternatively:
s.erase(
std::remove_if(s.begin(), s.end(),
[](const auto &stud){ return (stud.balls < 20); }
),
s.end()
);
std::for_each(s.begin(), s.end(),
[](auto &stud){ stud.balls = std::min(stud.balls, 100); }
);
*/
}
int main()
{
std::vector<Student> s;
inputdata(s);
print(s);
fixdata(s);
print(s);
return 0;
}
It's a practice problem I'm trying to do, but so far I've had no luck. Here's what I tried so far:
#include <iostream>
using namespace std;
string updateList(char arr[],char key, int n);
int main()
{
char usernames[10];
int sizeOf = 2;
usernames[0] = 'a'; usernames[1] = 'b';
string x = updateList(usernames, 'c', sizeOf);
cout << x;
}
string updateList(char arr[],char key, int n)
{
int arrLength = sizeof(arr)/sizeof(char);
int i;
for (i = 0; i < arrLength; i++) {
if (arr[i] == key) {
return "Username already exists";}
else {
arr[n++] = key;
int arrLength = sizeof(arr)/sizeof(char);
for (i = 0; i < arrLength; i++) {
cout << arr[i];
return "\n Username added";
}
} }
}
Any help would be appreciated.
Problem with your approach is that you are not updating the value of n(sizeOf) and you are using n to add element which will create error.instead of that use pass by reference so that n(i,e here sizeOf will updated) will updated Try something like
#include <iostream>
using namespace std;
string updateList(char arr[],char key, int *n);
int main()
{
char usernames[10];
int sizeOf=2;
usernames[0] = 'a'; usernames[1] = 'b';
string x = updateList(usernames, 'c', &sizeOf);
cout << x;
int updateList(char arr[],char key, int n)
{
int i;
for (i = 0; i < arrLength; i++) {
if (arr[i] == key) {
return "Username already exists";}
else {
arr[n++] = key;
for (i = 0; i < arrLength; i++) {
cout << arr[i];
}
return 0; } }
}
You can either use string or vector in order to keep the array of chars dynamic. This is an example of string and it also acts as an array of characters.
#include <iostream>
using namespace std;
int main()
{
string usernames="ab";
char key = 'b';
int i=0;
for(;i<usernames.size();i++)
if(usernames[i]==key)
{
printf("Key exists already");
break;
}
if(i==usernames.size())
{
usernames.push_back(key);
cout << usernames <<endl;
}
return 0;
}
class uid
{
public:
char id[6] = {'0','0','0','0','0','0'};
uid() {}
~uid() {}
inline void recursive(int x)
{
if(':' == id[x])
{
id[x] = '0';
++id[--x];
recursive(x);
}
}
char* operator++()
{
++id[5];
recursive(5);
return id;
}
void write(char* pchar) const
{
for(int i = 0; i < 6; ++i)
pchar[i] = id[i];
}
};
using namespace std;
int main(int argc, char** argv)
{
const int MAX = 5000000;
uid c;
char** arr = new char*[MAX];
//char** it = arr;
//loop 1
for(int i = 0; i < MAX; ++i)
arr[i] = new char[6];
cout << "allocated" << endl;
//loop 2
for(int i = 0; i < MAX; ++i)
{
++c;
c.write(arr[i]);
}
cout << "data written" << endl;
for(int i = 0; i < MAX; ++i)
delete[] arr[i];
cout << "deleting arr" << endl;
delete[] arr;
return 0;
}
Running this will cause a seg fault in loop 2 when i == 999999 -- However, when adding the line:
char** it = arr;
The seg fault disappears -- does anyone have any ideas of why this happens?
Thanks
As soon as you go past 999,999 you are writing to memory not owned by c. Declaring it changes the memory map enough that there is no immediate segfault, but the code is still not correct, and any other small change might bring back the fault.
Here's how to fix it:
inline void recursive(int x)
{
if(':' == id[x])
{
id[x] = '0';
if (x) { // <-- added this
++id[--x];
recursive(x);
}
}
}
Now overflow will wrap around to 000000 instead of creating a 7 digit number in a space not big enough to hold it.
I have an array, and the user can insert a string.
And I have this code:
int main(){
char anagrama[13];
cin >> anagrama;
for(int j = 0; j < strlen(anagrama); j++){
cout << anagrama[j];
for(int k = 0; k < strlen(anagrama); k++){
if(j != k)
cout << anagrama[k];
}
cout << endl;
}
}
The problem is that I need all permutations of the string in sorted order.
For example if the user write: abc, the output must to be:
abc
acb
bac
bca
cab
cba
and my code doesn't show all permutations, and not sorted
Can you help me?
I need do the implementation without a function already implemented.
I think with a recursive function, but I do not know how.
This is an example:
http://www.disfrutalasmatematicas.com/combinatoria/combinaciones-permutaciones-calculadora.html without repetition and sorted
In C++ you can use std::next_permutation to go through permutations one by one. You need to sort the characters alphabetically before calling std::next_permutation for the first time:
cin>>anagrama;
int len = strlen(anagrama);
sort(anagrama, anagrama+len);
do {
cout << anagrama << endl;
} while (next_permutation(anagrama, anagrama+len));
Here is a demo on ideone.
If you must implement permutations yourself, you could borrow the source code of next_permutation, or choose a simpler way of implementing a permutation algorithm recursively.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
void permute(string select, string remain){
if(remain == ""){
cout << select << endl;
return;
}
for(int i=0;remain[i];++i){
string wk(remain);
permute(select + remain[i], wk.erase(i, 1));
}
}
int main(){
string anagrama;
cout << "input character set >";
cin >> anagrama;
sort(anagrama.begin(), anagrama.end());
permute("", anagrama);
}
Another version
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
void permute(string& list, int level, vector<string>& v){
if(level == list.size()){
v.push_back(list);
return;
}
for(int i=level;list[i];++i){
swap(list[level], list[i]);
permute(list, level + 1, v);
swap(list[level], list[i]);
}
}
int main(){
string anagrama;
vector<string> v;
cout << "input character set >";
cin >> anagrama;
permute(anagrama, 0, v);
sort(v.begin(), v.end());
copy(v.begin(), v.end(), ostream_iterator<string>(cout, "\n"));
}
#alexander the output of this programme is in exact order as requested by you:
HERE, is a simplest code for generating all combination/permutations of a given array without including some special libraries (only iostream.h and string are included) and without using some special namespaces than usual ( only namespace std is used).
void shuffle_string_algo( string ark )
{
//generating multi-dimentional array:
char** alpha = new char*[ark.length()];
for (int i = 0; i < ark.length(); i++)
alpha[i] = new char[ark.length()];
//populating given string combinations over multi-dimentional array
for (int i = 0; i < ark.length(); i++)
for (int j = 0; j < ark.length(); j++)
for (int n = 0; n < ark.length(); n++)
if( (j+n) <= 2 * (ark.length() -1) )
if( i == j-n)
alpha[i][j] = ark[n];
else if( (i-n)== j)
alpha[i][j] = ark[ ark.length() - n];
if(ark.length()>=2)
{
for(int i=0; i<ark.length() ; i++)
{
char* shuffle_this_also = new char(ark.length());
int j=0;
//storing first digit in golobal array ma
ma[v] = alpha[i][j];
//getting the remaning string
for (; j < ark.length(); j++)
if( (j+1)<ark.length())
shuffle_this_also[j] = alpha[i][j+1];
else
break;
shuffle_this_also[j]='\0';
//converting to string
string send_this(shuffle_this_also);
//checking if further combinations exist or not
if(send_this.length()>=2)
{
//review the logic to get the working idea of v++ and v--
v++;
shuffle_string_algo( send_this);
v--;
}
else
{
//if, further combinations are not possiable print these combinations
ma[v] = alpha[i][0];
ma[++v] = alpha[i][1];
ma[++v] = '\0';
v=v-2;
string disply(ma);
cout<<++permutaioning<<":\t"<<disply<<endl;
}
}
}
}
and main:
int main()
{
string a;
int ch;
do
{
system("CLS");
cout<<"PERMUNATING BY ARK's ALGORITH"<<endl;
cout<<"Enter string: ";
fflush(stdin);
getline(cin, a);
ma = new char[a.length()];
shuffle_string_algo(a);
cout<<"Do you want another Permutation?? (1/0): ";
cin>>ch;
} while (ch!=0);
return 0;
}
HOPE! it helps you! if you are having problem with understanding logic just comment below and i will edit.
/*Think of this as a tree. The depth of the tree is same as the length of string.
In this code, I am starting from root node " " with level -1. It has as many children as the characters in string. From there onwards, I am pushing all the string characters in stack.
Algo is like this:
1. Put root node in stack.
2. Loop till stack is empty
2.a If backtracking
2.a.1 loop from last of the string character to present depth or level and reconfigure datastruture.
2.b Enter the present char from stack into output char
2.c If this is leaf node, print output and continue with backtracking on.
2.d Else find all the neighbors or children of this node and put it them on stack. */
class StringEnumerator
{
char* m_string;
int m_length;
int m_nextItr;
public:
StringEnumerator(char* str, int length): m_string(new char[length + 1]), m_length(length) , m_Complete(m_length, false)
{
memcpy(m_string, str, length);
m_string[length] = 0;
}
StringEnumerator(const char* str, int length): m_string(new char[length + 1]), m_length(length) , m_Complete(m_length, false)
{
memcpy(m_string, str, length);
m_string[length] = 0;
}
~StringEnumerator()
{
delete []m_string;
}
void Enumerate();
};
const int MAX_STR_LEN = 1024;
const int BEGIN_CHAR = 0;
struct StackElem
{
char Elem;
int Level;
StackElem(): Level(0), Elem(0){}
StackElem(char elem, int level): Elem(elem), Level(level){}
};
struct CharNode
{
int Max;
int Curr;
int Itr;
CharNode(int max = 0): Max(max), Curr(0), Itr(0){}
bool IsAvailable(){return (Max > Curr);}
void Increase()
{
if(Curr < Max)
Curr++;
}
void Decrease()
{
if(Curr > 0)
Curr--;
}
void PrepareItr()
{
Itr = Curr;
}
};
void StringEnumerator::Enumerate()
{
stack<StackElem> CStack;
int count = 0;
CStack.push(StackElem(BEGIN_CHAR,-1));
char answerStr[MAX_STR_LEN];
memset(answerStr, 0, MAX_STR_LEN);
bool forwardPath = true;
typedef std::map<char, CharNode> CharMap;
typedef CharMap::iterator CharItr;
typedef std::pair<char, CharNode> CharPair;
CharMap mCharMap;
CharItr itr;
//Prepare Char Map
for(int i = 0; i < m_length; i++)
{
itr = mCharMap.find(m_string[i]);
if(itr != mCharMap.end())
{
itr->second.Max++;
}
else
{
mCharMap.insert(CharPair(m_string[i], CharNode(1)));
}
}
while(CStack.size() > 0)
{
StackElem elem = CStack.top();
CStack.pop();
if(elem.Level != -1) // No root node
{
int currl = m_length - 1;
if(!forwardPath)
{
while(currl >= elem.Level)
{
itr = mCharMap.find(answerStr[currl]);
if((itr != mCharMap.end()))
{
itr->second.Decrease();
}
currl--;
}
forwardPath = true;
}
answerStr[elem.Level] = elem.Elem;
itr = mCharMap.find(elem.Elem);
if((itr != mCharMap.end()))
{
itr->second.Increase();
}
}
//If leaf node
if(elem.Level == (m_length - 1))
{
count++;
cout<<count<<endl;
cout<<answerStr<<endl;
forwardPath = false;
continue;
}
itr = mCharMap.begin();
while(itr != mCharMap.end())
{
itr->second.PrepareItr();
itr++;
}
//Find neighbors of this elem
for(int i = 0; i < m_length; i++)
{
itr = mCharMap.find(m_string[i]);
if(/*(itr != mCharMap.end()) &&*/ (itr->second.Itr < itr->second.Max))
{
CStack.push(StackElem(m_string[i], elem.Level + 1));
itr->second.Itr++;
}
}
}
}
I wrote one without a function already implemented even any templates and containers. actually it was written in C first, but has been transform to C++.
easy to understand but poor efficiency, and its output is what you want, sorted.
#include <iostream>
#define N 4
using namespace std;
char ch[] = "abcd";
int func(int n) {
int i,j;
char temp;
if(n==0) {
for(j=N-1;j>=0;j--)
cout<<ch[j];
cout<<endl;
return 0;
}
for(i=0;i<n;i++){
temp = ch[i];
for(j=i+1;j<n;j++)
ch[j-1] = ch[j];
ch[n-1] = temp;
//shift
func(n-1);
for(j=n-1;j>i;j--)
ch[j] = ch[j-1];
ch[i] = temp;
//and shift back agian
}
return 1;
}
int main(void)
{
func(N);
return 0;
}
In case you have std::vector of strings then you can 'permute' the vector items as below.
C++14 Code
#include <iostream>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string/join.hpp>
using namespace std;
int main() {
// your code goes here
std::vector<std::string> s;
s.push_back("abc");
s.push_back("def");
s.push_back("ghi");
std::sort(s.begin(), s.end());
do
{
std::cout << boost::algorithm::join(s,"_") << std::endl ;
} while(std::next_permutation(s.begin(), s.end()));
return 0;
}
Output:
abc_def_ghi
abc_ghi_def
def_abc_ghi
def_ghi_abc
ghi_abc_def
ghi_def_abc
I have an array, and the user can insert a string.
And I have this code:
int main(){
char anagrama[13];
cin >> anagrama;
for(int j = 0; j < strlen(anagrama); j++){
cout << anagrama[j];
for(int k = 0; k < strlen(anagrama); k++){
if(j != k)
cout << anagrama[k];
}
cout << endl;
}
}
The problem is that I need all permutations of the string in sorted order.
For example if the user write: abc, the output must to be:
abc
acb
bac
bca
cab
cba
and my code doesn't show all permutations, and not sorted
Can you help me?
I need do the implementation without a function already implemented.
I think with a recursive function, but I do not know how.
This is an example:
http://www.disfrutalasmatematicas.com/combinatoria/combinaciones-permutaciones-calculadora.html without repetition and sorted
In C++ you can use std::next_permutation to go through permutations one by one. You need to sort the characters alphabetically before calling std::next_permutation for the first time:
cin>>anagrama;
int len = strlen(anagrama);
sort(anagrama, anagrama+len);
do {
cout << anagrama << endl;
} while (next_permutation(anagrama, anagrama+len));
Here is a demo on ideone.
If you must implement permutations yourself, you could borrow the source code of next_permutation, or choose a simpler way of implementing a permutation algorithm recursively.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
void permute(string select, string remain){
if(remain == ""){
cout << select << endl;
return;
}
for(int i=0;remain[i];++i){
string wk(remain);
permute(select + remain[i], wk.erase(i, 1));
}
}
int main(){
string anagrama;
cout << "input character set >";
cin >> anagrama;
sort(anagrama.begin(), anagrama.end());
permute("", anagrama);
}
Another version
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
void permute(string& list, int level, vector<string>& v){
if(level == list.size()){
v.push_back(list);
return;
}
for(int i=level;list[i];++i){
swap(list[level], list[i]);
permute(list, level + 1, v);
swap(list[level], list[i]);
}
}
int main(){
string anagrama;
vector<string> v;
cout << "input character set >";
cin >> anagrama;
permute(anagrama, 0, v);
sort(v.begin(), v.end());
copy(v.begin(), v.end(), ostream_iterator<string>(cout, "\n"));
}
#alexander the output of this programme is in exact order as requested by you:
HERE, is a simplest code for generating all combination/permutations of a given array without including some special libraries (only iostream.h and string are included) and without using some special namespaces than usual ( only namespace std is used).
void shuffle_string_algo( string ark )
{
//generating multi-dimentional array:
char** alpha = new char*[ark.length()];
for (int i = 0; i < ark.length(); i++)
alpha[i] = new char[ark.length()];
//populating given string combinations over multi-dimentional array
for (int i = 0; i < ark.length(); i++)
for (int j = 0; j < ark.length(); j++)
for (int n = 0; n < ark.length(); n++)
if( (j+n) <= 2 * (ark.length() -1) )
if( i == j-n)
alpha[i][j] = ark[n];
else if( (i-n)== j)
alpha[i][j] = ark[ ark.length() - n];
if(ark.length()>=2)
{
for(int i=0; i<ark.length() ; i++)
{
char* shuffle_this_also = new char(ark.length());
int j=0;
//storing first digit in golobal array ma
ma[v] = alpha[i][j];
//getting the remaning string
for (; j < ark.length(); j++)
if( (j+1)<ark.length())
shuffle_this_also[j] = alpha[i][j+1];
else
break;
shuffle_this_also[j]='\0';
//converting to string
string send_this(shuffle_this_also);
//checking if further combinations exist or not
if(send_this.length()>=2)
{
//review the logic to get the working idea of v++ and v--
v++;
shuffle_string_algo( send_this);
v--;
}
else
{
//if, further combinations are not possiable print these combinations
ma[v] = alpha[i][0];
ma[++v] = alpha[i][1];
ma[++v] = '\0';
v=v-2;
string disply(ma);
cout<<++permutaioning<<":\t"<<disply<<endl;
}
}
}
}
and main:
int main()
{
string a;
int ch;
do
{
system("CLS");
cout<<"PERMUNATING BY ARK's ALGORITH"<<endl;
cout<<"Enter string: ";
fflush(stdin);
getline(cin, a);
ma = new char[a.length()];
shuffle_string_algo(a);
cout<<"Do you want another Permutation?? (1/0): ";
cin>>ch;
} while (ch!=0);
return 0;
}
HOPE! it helps you! if you are having problem with understanding logic just comment below and i will edit.
/*Think of this as a tree. The depth of the tree is same as the length of string.
In this code, I am starting from root node " " with level -1. It has as many children as the characters in string. From there onwards, I am pushing all the string characters in stack.
Algo is like this:
1. Put root node in stack.
2. Loop till stack is empty
2.a If backtracking
2.a.1 loop from last of the string character to present depth or level and reconfigure datastruture.
2.b Enter the present char from stack into output char
2.c If this is leaf node, print output and continue with backtracking on.
2.d Else find all the neighbors or children of this node and put it them on stack. */
class StringEnumerator
{
char* m_string;
int m_length;
int m_nextItr;
public:
StringEnumerator(char* str, int length): m_string(new char[length + 1]), m_length(length) , m_Complete(m_length, false)
{
memcpy(m_string, str, length);
m_string[length] = 0;
}
StringEnumerator(const char* str, int length): m_string(new char[length + 1]), m_length(length) , m_Complete(m_length, false)
{
memcpy(m_string, str, length);
m_string[length] = 0;
}
~StringEnumerator()
{
delete []m_string;
}
void Enumerate();
};
const int MAX_STR_LEN = 1024;
const int BEGIN_CHAR = 0;
struct StackElem
{
char Elem;
int Level;
StackElem(): Level(0), Elem(0){}
StackElem(char elem, int level): Elem(elem), Level(level){}
};
struct CharNode
{
int Max;
int Curr;
int Itr;
CharNode(int max = 0): Max(max), Curr(0), Itr(0){}
bool IsAvailable(){return (Max > Curr);}
void Increase()
{
if(Curr < Max)
Curr++;
}
void Decrease()
{
if(Curr > 0)
Curr--;
}
void PrepareItr()
{
Itr = Curr;
}
};
void StringEnumerator::Enumerate()
{
stack<StackElem> CStack;
int count = 0;
CStack.push(StackElem(BEGIN_CHAR,-1));
char answerStr[MAX_STR_LEN];
memset(answerStr, 0, MAX_STR_LEN);
bool forwardPath = true;
typedef std::map<char, CharNode> CharMap;
typedef CharMap::iterator CharItr;
typedef std::pair<char, CharNode> CharPair;
CharMap mCharMap;
CharItr itr;
//Prepare Char Map
for(int i = 0; i < m_length; i++)
{
itr = mCharMap.find(m_string[i]);
if(itr != mCharMap.end())
{
itr->second.Max++;
}
else
{
mCharMap.insert(CharPair(m_string[i], CharNode(1)));
}
}
while(CStack.size() > 0)
{
StackElem elem = CStack.top();
CStack.pop();
if(elem.Level != -1) // No root node
{
int currl = m_length - 1;
if(!forwardPath)
{
while(currl >= elem.Level)
{
itr = mCharMap.find(answerStr[currl]);
if((itr != mCharMap.end()))
{
itr->second.Decrease();
}
currl--;
}
forwardPath = true;
}
answerStr[elem.Level] = elem.Elem;
itr = mCharMap.find(elem.Elem);
if((itr != mCharMap.end()))
{
itr->second.Increase();
}
}
//If leaf node
if(elem.Level == (m_length - 1))
{
count++;
cout<<count<<endl;
cout<<answerStr<<endl;
forwardPath = false;
continue;
}
itr = mCharMap.begin();
while(itr != mCharMap.end())
{
itr->second.PrepareItr();
itr++;
}
//Find neighbors of this elem
for(int i = 0; i < m_length; i++)
{
itr = mCharMap.find(m_string[i]);
if(/*(itr != mCharMap.end()) &&*/ (itr->second.Itr < itr->second.Max))
{
CStack.push(StackElem(m_string[i], elem.Level + 1));
itr->second.Itr++;
}
}
}
}
I wrote one without a function already implemented even any templates and containers. actually it was written in C first, but has been transform to C++.
easy to understand but poor efficiency, and its output is what you want, sorted.
#include <iostream>
#define N 4
using namespace std;
char ch[] = "abcd";
int func(int n) {
int i,j;
char temp;
if(n==0) {
for(j=N-1;j>=0;j--)
cout<<ch[j];
cout<<endl;
return 0;
}
for(i=0;i<n;i++){
temp = ch[i];
for(j=i+1;j<n;j++)
ch[j-1] = ch[j];
ch[n-1] = temp;
//shift
func(n-1);
for(j=n-1;j>i;j--)
ch[j] = ch[j-1];
ch[i] = temp;
//and shift back agian
}
return 1;
}
int main(void)
{
func(N);
return 0;
}
In case you have std::vector of strings then you can 'permute' the vector items as below.
C++14 Code
#include <iostream>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string/join.hpp>
using namespace std;
int main() {
// your code goes here
std::vector<std::string> s;
s.push_back("abc");
s.push_back("def");
s.push_back("ghi");
std::sort(s.begin(), s.end());
do
{
std::cout << boost::algorithm::join(s,"_") << std::endl ;
} while(std::next_permutation(s.begin(), s.end()));
return 0;
}
Output:
abc_def_ghi
abc_ghi_def
def_abc_ghi
def_ghi_abc
ghi_abc_def
ghi_def_abc