Sorting Structs and Arrays - c++

My task is to read in a file with names and scores for a game (file looks something like)
5
John Doe 200
Chris Brown 340
Chris Brown 320
John Smith 300
John Doe 600
And prints out the names in alphabetical order (last name) with the highest score from that person. So output would look something like:
Chris Brown 340
John Doe 600
John Smith 300
I figured out how to sort and print the scores from highest to lowest, but I'm lost on how to print out just the highest scores from each person... any help would be appreciated!
#include <iostream>
#include <fstream>
using namespace std;
struct playerscore
{
string first, last;
int score;
};
bool score(playerscore a, playerscore b);
void selectionsort(playerscore *A, int n);
int main()
{
string file;
int n;
cin >> file;
ifstream fin(file.c_str());
fin >> n;
// read in the names and the scores in the form of struct playerscore
playerscore *A = new playerscore[n];
for(int i = 0; i < n; i++)
fin >> A[i].first >> A[i].last >> A[i].score;
// sort the data
selectionsort(A, n);
// print in sorted order
for(int i = 0; i < n; i++)
cout << A[i].score << " ";
cout << endl;
return 0;
}
bool before(playerscore a, playerscore b)
{
return a.score > b.score;
}
void selectionsort(playerscore *A, int n)
{
for(int length = n; length > 1; length--)
{
//find imax, index of largest
int imax = 0, i;
for(i = 1; i < length; i++)
if(before(A[imax], A[i]))
imax = i;
// swap A[imax] and the last element
playerscore temp = A[imax];
A[imax] = A[length-1];
A[length-1] = temp;
}
}

Sort to ascending order of the name.
If the names compared are same, element with higher score should be come to earlier position of the array.
Print the first element and elements whose name differs from previous element.
Sample implementation:
#include <iostream>
#include <fstream>
using namespace std;
struct playerscore
{
string first, last;
int score;
};
bool score(playerscore a, playerscore b);
void selectionsort(playerscore *A, int n);
int main()
{
string file;
int n;
#if 0
cin >> file;
ifstream fin(file.c_str());
#else
#define fin cin // to test with online compiler
#endif
fin >> n;
// read in the names and the scores in the form of struct playerscore
playerscore *A = new playerscore[n];
for(int i = 0; i < n; i++)
fin >> A[i].first >> A[i].last >> A[i].score;
// sort the data
selectionsort(A, n);
// print in sorted order
for(int i = 0; i < n; i++)
if (i == 0 || A[i].first != A[i - 1].first || A[i].last != A[i - 1].last)
cout << A[i].first << " " << A[i].last << " " << A[i].score << "\n";
cout << endl;
return 0;
}
bool before(playerscore a, playerscore b)
{
return a.first == b.first ? (a.last == b.last ? a.score > b.score : a.last < b.last) : a.first < b.first;
}
void selectionsort(playerscore *A, int n)
{
for(int length = n; length > 1; length--)
{
//find imax, index of largest
int imax = 0, i;
for(i = 1; i < length; i++)
if(before(A[imax], A[i]))
imax = i;
// swap A[imax] and the last element
playerscore temp = A[imax];
A[imax] = A[length-1];
A[length-1] = temp;
}
}

You've already done the difficult part.
Suppose the ((first, last), score) pairs are already sorted, the highest score for each player is the first record for this player, so just keep the current player's name as curr_name when you visit the array:
If the next name is same as curr_name, you can safely ignore this item.
If not, print this record, and update curr_name.
The code is like blew:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <string>
#include <utility>
using namespace std;
bool mycmp (pair<pair<string, string>, int> a, pair<pair<string, string>, int> b) {
return a.first < b.first || (a.first == b.first && a.second > b.second);
}
int main(int argc, char *argv[])
{
ifstream fin("data.txt");
int n;
fin>>n;
vector<pair<pair<string, string>, int>> A(n);
for(int i = 0; i < n; ++i){
fin>>A[i].first.first>>A[i].first.second>>A[i].second;
}
sort(A.begin(), A.end(), mycmp);
pair<string, string> cur_name;
for(int i = 0; i < n; ++i){
if(cur_name != A[i].first){
cout<<A[i].first.first<<" "<<A[i].first.second<<" "<<A[i].second<<endl;
cur_name = A[i].first;
}
}
return 0;
}

As pointed out before, since it's a task I decided to rewrite the code and it should now look like this.
Sort the array based on the score
Sort the array based on alphabetical order
Print unique entries
#include <iostream>
#include <fstream>
using namespace std;
struct playerscore
{
string first, last;
int score;
};
bool score(playerscore a, playerscore b);
void selectionsort(playerscore *A, int n);
int main()
{
string file;
int n;
cin >> file;
ifstream fin(file.c_str());
fin >> n;
// read in the names and the scores in the form of struct playerscore
playerscore *A = new playerscore[n];
for (int i = 0; i < n; i++)
fin >> A[i].first >> A[i].last >> A[i].score;
// sort the data
selectionsort(A, n);
// sort alphabetically and print unique entries
for (int i=0; i<n-1; i++)
{
for (int j=i+1; j<n; j++)
{
if (A[j].last <= A[i].last && A[j].first < A[i].first)
{
playerscore tmp = A[i];
A[i] = A[j], A[j] = tmp;
}
}
playerscore max;
int j = 0;
for (int i=0; j+i<n; i++)
{
max.score = -1;
while (j+i<n && A[j+i].last == A[i].last && A[j+i].first == A[i].first)
{
if (A[j+i].score >= A[i].score)
max = A[j+i];
j++;
}
j--;
if (max.score >= 0)
cout << max.last << " " << max.first << " " << max.score << endl;
}
cout << endl;
return 0;
}
bool before(playerscore a, playerscore b)
{
return a.score > b.score;
}
void selectionsort(playerscore *A, int n)
{
for(int length = n; length > 1; length--)
{
//find imax, index of largest
int imax = 0, i;
for(i = 1; i < length; i++)
if(before(A[imax], A[i]))
imax = i;
// swap A[imax] and the last element
playerscore temp = A[imax];
A[imax] = A[length-1];
A[length-1] = temp;
}
}

Related

C++ unable to find multiple modes

My assignment asks me to write a function that takes an array and the size of that array as a parameter, and to find the mode. If there are multiple modes, I am to find them all, and place them in a vector and print said vector in an ascending order.
For example, if I input the following integers:
3, 4, 2, 1, 2, 3
Then the output should display
2, 3
If I input the following integers:
1, 2, 3, 4
Then the output should display:
1, 2, 3, 4.
However, my program somehow only finds the first mode and displays it in a really awkward manner.
Here was my input:
3, 4, 2, 3, 2, 1
And this was the output:
3
3
3
3
3
Here is my code. Any help would be greatly appreciated. Thank you all for your time!
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int size; //array size
int* array; //array of ints
int arraycount; //counter for array loop
void findMode(int array[], int size); //function prototype
//intialize array
cout << "Enter number of integers ";
cout << "you wish to input." << endl;
cin >> size;
cout << "Enter the integers." << endl;
array = new int[size];
for (arraycount = 0; arraycount < size;
arraycount++)
cin >> array[arraycount];
//call function
findMode(array, size);
return 0;
}
void findMode(int array[], int size) {
int counter = 1;
int max = 0;
int mode = array[0];
int count;
vector <int> results;
//find modes
for(int pass = 0; pass < size - 1; pass++) {
if(array[pass] == array[pass+1]) {
counter++;
if(counter > max) {
max = counter;
mode = array[pass];
}
}
else {
counter = 1;
}
}
//push results to vector
for (count=0; count < size - 1; count++) {
if(counter == max) {
std::cin >> mode;
results.push_back(mode);
}
}
//sort vector and print
std::sort(results.begin(), results.end());
for (count=0; count < size - 1; count++) {
cout << mode << endl;
}
}
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
int main() {
int size; //array size
int* array; //array of ints
std::vector<int> vecInput;
int arraycount; //counter for array loop
void findMode(std::vector<int> vec); //function prototype
//intialize array
cout << "Enter number of integers ";
cout << "you wish to input." << endl;
cin >> size;
cout << "Enter the integers." << endl;
array = new int[size];
for (arraycount = 0; arraycount < size; arraycount++)
{
int num;
cin >> num;
vecInput.push_back(num);
}
//call function
findMode(vecInput);
return 0;
}
void findMode(std::vector<int> vec)
{
std::sort(vec.begin(), vec.end());
std::map<int, int> modMap;
std::vector<int>::iterator iter = vec.begin();
std::vector<int> results;
int prev = *iter;
int maxCount = 1;
modMap.insert(std::pair <int,int>(*iter, 1));
iter++;
for (; iter!= vec.end(); iter++)
{
if (prev == *iter)
{
std::map<int, int>::iterator mapiter = modMap.find(*iter);
if ( mapiter == modMap.end())
{
modMap.insert(std::pair <int,int>(*iter, 1));
}
else
{
mapiter->second++;
if (mapiter->second > maxCount)
{
maxCount = mapiter->second;
}
}
}
else
{
modMap.insert(std::pair <int,int>(*iter, 1));
}
prev = *iter;
}
std::map<int, int>::iterator mapIter = modMap.begin();
for (; mapIter != modMap.end(); mapIter++)
{
if (mapIter->second == maxCount)
{
results.push_back(mapIter->first);
}
}
cout << "mod values are " <<endl;
std::vector<int>::iterator vecIter = results.begin();
for (; vecIter != results.end(); vecIter++)
cout<<*vecIter<<endl;
}
Thank you all for the help, I was able to get the code to work. Turns out the problem was the cin in my vector portion of the function. Here is my revised code:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <stdlib.h>
#include <vector>
using namespace std;
#define N 100
void findMode(int x[], int size); //function prototype
vector<int> results; //vector
int main(void) {
int* x;
int size=0;
int arraycount;
//intialize array
cout << "Enter number of integers ";
cout << "you wish to input." << endl;
cin >> size;
cout << "Enter the integers." << endl;
x = new int[size];
for (arraycount = 0; arraycount < size;
arraycount++)
cin >> x[arraycount];
//send array and size to function
findMode(x, size);
return 0;
}
//findMode function
void findMode(int x[], int size) {
int y[N]={0};
int i, j, k, m, cnt, count, max=0;
int mode_cnt=0;
int num;
int v;
vector<int> results;
vector<int>::iterator pos;
//loop to count an array from left to right
for(k=0; k<size; k++) {
cnt=0;
num=x[k]; //num will equal the value of x[k]
for(i=k; i<size; i++) {
if(num==x[i])
cnt++;
}
y[k]=cnt; //
}
//find highest number in array
for(j=0; j<size; j++) {
if(y[j]>max)
max=y[j];
}
//find how many modes there are
for(m=0; m<size; m++) {
if(max==y[m])
mode_cnt++;
}
//push results to vector
for (m=0; m < size; m++) {
if(max == y[m]) {
//after taking out this line the code works properly
// std::cin >> x[m];
results.push_back(x[m]);
}
}
//sort vector and print
std::sort(results.begin(), results.end());
cout << "The mode(s) is/are: ";
for (pos=results.begin(); pos!=results.end(); ++pos) {
cout << *pos << " ";
}
}

heapsort-code is not working

The following code is not working for heap sort. It looks ok to me. Can someone help me please? I have followed the pseudo code from CLRS, the sorted numbers are not being updated after the algorithm is traversed.
#include <iostream>
using namespace std;
void max_heapify(int *b, int i,int he_size)
{
int l,r,largest;
l=2*i;
r=(2*i+1);
if (l<=he_size && b[l]>b[i])
largest=l;
else largest=i;
if (r<=he_size && b[r]> b[largest])
largest=r;
if (largest!=i)
{
swap(b[i],b[largest]);
max_heapify(b,largest,he_size);
}
}
void build_max_heap(int *c,int h_size,int strlength)
{
for (int q=(strlength)/2;q==1;--q)
{
max_heapify(c,q,h_size);
}
}
void swap(int a, int b)
{
int c=b;
b=a;
a=c;
}
int main()
{
int length;
int heap_size;
cout<<"Enter the number of numbers to be sorted by heap sort"<<endl;
cin>>length;
int* a=NULL;
a=new int[length-1];
int temp;
cout<<"Enter the numbers"<<endl;
for(int i=0;i<length;i++)
{
cin>>temp;
*(a+i)=temp;
}
cout<<"The given numbers are:"<<endl;
for(int j=0;j<length;j++)
cout<<*(a+j)<<" "<<endl;
heap_size= length;
build_max_heap(a,heap_size,length);
for (int l=length;l==2;--l)
{
swap(a[1],a[length]);
heap_size=heap_size-1;
max_heapify(a,1,heap_size);
}
cout<<"The sorted numbers are:"<<endl;
for(int j=0;j<length;j++)
cout<<*(a+j)<<" "<<endl;
system("pause");
return 0;
}
The number of mistakes in your code is enormous. Sorry to say it.
void swap(int a, int b)
{
int c=b;
b=a;
a=c;
}
does nothing - a and b should be passed by link, not by value:
void swap(int &a, int &b)
{
int c=b;
b=a;
a=c;
}
for (int q=(strlength)/2;q==1;--q) is wrong. You meant for (int q=(strlength)/2;q>1;--q). Your loop is running only when q==1.
a=new int[length-1]; The size of array should be length, not length-1. And even though swap(a[1],a[length]); is wrong, because a[length] is out of array.
Also there are some mistakes in algorithm. I tried to rewrite as less code as possible.
Right code is:
#include <iostream>
using namespace std;
void sift_down(int *a, int start, int end) {
int root = start;
while (root * 2 + 1 <= end) {
int child = root * 2 + 1;
int sw = root;
if (a[sw] < a[child])
sw = child;
if (child + 1 <= end and a[sw] < a[child + 1])
sw = child + 1;
if (sw == root)
return;
else
swap(a[root], a[sw]);
root = sw;
}
}
void max_heapify(int *b, int count) {
int start = (count - 2) / 2;
while (start >= 0) {
sift_down(b, start, count - 1);
--start;
}
}
void swap(int &a, int &b) {
int c = b;
b = a;
a = c;
}
int main() {
int length;
int heap_size;
cout << "Enter the number of numbers to be sorted by heap sort" << endl;
cin >> length;
int *a = new int[length];
cout << "Enter the numbers" << endl;
for (int i = 0; i < length; i++) {
cin >> a[i];
}
cout << "The given numbers are:" << endl;
for (int j = 0; j < length; j++)
cout << a[j] << " ";
cout << endl;
heap_size = length;
max_heapify(a, heap_size);
--heap_size;
while (heap_size) {
swap(a[heap_size], a[0]);
--heap_size;
sift_down(a, 0, heap_size);
}
cout << "The sorted numbers are:" << endl;
for (int j = 0; j < length; j++)
cout << a[j] << " ";
cout << endl;
//system("pause");
return 0;
}

c++ permutations high numbers (convert code)

I am trying to convert this code that works for '0' - '3' strings to integer so that it will work for higher numbers
#include <string>
#include <iostream>
using namespace std;
void permutate(char[], int );
bool recurse(char[], int );
int main()
{
int strLength;
cout << "Enter your desired length: ";
cin >> strLength;
char strArray[strLength];
for (int i = 0; i<strLength; i++)
strArray[i] = '0';
permutate(strArray, sizeof(strArray));
return 0;
}
void permutate(char charArray[], int length)
{
string wait;
length--;
bool done = false;
while(!done)
{
for (int i = 0; i <= length; i++)
cout << charArray[i];
cout << endl;
if (charArray[length] == '3')
done = recurse(charArray, length);
else
charArray[length] = (char)(charArray[length]+1);
}
}
bool recurse(char charArray[], int length)
{
bool done = false;
int temp = length;
if (temp > 1)
{
charArray[temp] = '0';
if (charArray[temp-1] == '3')
{
temp--;
done = recurse(charArray, temp);
}
else
(charArray[temp-1] = (char)(charArray[temp-1] + 1));
}
else
{
charArray[temp] = '0';
if (charArray[temp-1] == '3')
done = true;
else
charArray[temp-1] = (char)(charArray[temp-1]+1);
}
return done;
}
I changed every char to int,
every '0' = 0, '3' = 3
every (charArray[temp-1] = (char)(charArray[temp-1] + 1)); to charArray[temp-1]++;
I tried to debug but I still can`t make it work :(
Manged to fix it( works for high numbers):
#include <string>
#include <iostream>
using namespace std;
void permutate(int[], int, int );
bool recurse(int[], int, int );
int main()
{
int strLength, nrElem;
cout << "Enter your desired length: ";
cin >> strLength;
cout << "Enter nr elem: ";
cin >> nrElem;
int strArray[strLength];
for (int i = 0; i<strLength; i++)
strArray[i] = 0;
permutate(strArray, strLength, nrElem );
cout << "\nSTOP";
return 0;
}
void permutate(int charArray[], int length, int nrElem)
{
// length--;
bool done = false;
while(!done)
{
for (int i = 0; i < length; i++)
cout << charArray[i] << " ";
cout << endl;
if (charArray[length - 1] == nrElem)
//done = true;
done = recurse(charArray, length, nrElem);
else
charArray[length - 1]++;
}
}
bool recurse(int charArray[], int length, int nrElem)
{
bool done = false;
int temp = length ;
if (temp > 1)
{
charArray[temp] = 0;
if (charArray[temp-1] == nrElem)
{
temp--;
done = recurse(charArray, temp, nrElem);
}
else
charArray[temp-1]++;
}
else
{
charArray[temp] = 0;
if (charArray[temp-1] == nrElem)
done = true;
else
charArray[temp-1]++;
}
return done;
}
In your permutate function, you're incrementing charArray[length] but checking to see if charArray[length - 1] is equal to nrElem, so you never end up calling recurse.
Here is a short piece of code to do the same (not an answer, however it did not look right in a comment field), not sure if you need the recursion, if you do not this code may be of interest:
#include <iostream>
#include <sstream>
using namespace std;
string output(int firstIntSize, int secondIntSize)
{
std::ostringstream oss;
for (int i = 0; i<firstIntSize; i++)
{
for (int j = 0; j< secondIntSize; j++)
{
oss << i << j << " ";
}
}
return oss.str();
}
int main()
{
cout << output(2,3);
return 0;
}
hmmm... Why not simply make a Permutations algorithm and then use a generic function to print whatever you are permutating. Here's how I would do it for strings:
#include <iostream>
#include <string>
template<class T>
void print(T * A, unsigned n){ //for printing purposes
for(unsigned i=0;i<n;i++){
std::cout<<A[i]<<" ";
}
std::cout<<std::endl;
}
void generate_permutations(unsigned k, std::string str, char *A, bool *U){
// k is the position that we need to fill, starts from 0 and goes to the end.
if(k<str.size()) //if k==str.size() then we will print it
for(unsigned i=0;i<str.size();i++){
if(U[i]==0){
A[k]=str[i]; U[i]=1;
generate_permutations(k+1, str, A,U);
U[i]=0; //after the recursion is finished and printed, we can release the letter.
}
}
else
print(A,str.size());
}
int main(){
std::string str;
std::cout<<"Enter the string to be permutated: \n";
std::cin>>str;
int n;
n = str.length(); // You don't really need to ask the user the size of the string he/she wants to enter.
bool *U; // we will keep track of the used letters with the help of this boolean vector
char *A; // we will copy the contents of str here, so that we keep the str intact
U = new bool[n];
for (int i=0;i<n;i++) U[i]=false;
A = new char[n];
for (int i=0;i<n;i++) A[i]=str[i];
generate_permutations(0,str,A,U);
return 0;
}
Now if you want to convert to numbers (ints), it's almost the same:
#include <iostream>
template<class T>
void print(T * A, int n){
for(int i=0;i<n;i++){
std::cout<<A[i]<<" ";
}
std::cout<<std::endl;
}
void generate_permutations(int k, int *A, bool *U, int n){
if(k==n)
print(A,n);
else {
for(int i=0;i<n;i++){
if(U[i]==0){
A[k]=i; U[i]=1;
generate_permutations(k+1,A,U,n);
U[i]=0;
}
}
}
}
int main(){
int n;
std::cout<<"Permutations of how many objects? \n";
std::cin>>n;
int * A;
bool *U;
A = new int[n];
U = new bool[n];
for (int i=0;i<n;i++) U[i]=false;
print(U, n);
generate_permutations(0,A,U,n);
return 0;
}

How to generate all permutations of an array in sorted order?

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

print sorted strings of a permutation [duplicate]

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