Sign in to follow this  
DarkSlayer

Permutations

Recommended Posts

Doing some HW on permutations, and some of it is puzzeling me. SO STL IS NO NO... I understand what in "theory" is happening. I have implemented a recursive system that is ending up rotating numbers around, I think that is quite standard. but: One of the sub-tasks is to NOT display duplicate words, or permutations. So the word ASHES is only displayed once. Normally that word would come out twice (where the S and S is switching place). My first idea is to store away the permutations made ... but that is a quite bad idea. The program has to do permutations on a 15letter string ... and 15! is a freakin high number ... any ideas on how to avoid generate duplicates, when there is 2 or more equal letters? Can't find anything about it here or google ...

Share this post


Link to post
Share on other sites
for loop? don't see how that should work...

in a normal permutations you have these ... outputs

123 ___ sis
132 ___ ssi
213 ___ iss
231 ___ iss
312 ___ sis
321 ___ ssi

the first have 6 different outputs, the other have 3 different, 3 of them are duplicates.

My permutation should only print sis, ssi, iss.

I have the function that output the first thing, but I have really no qlues on how to remove duplicates.

Share this post


Link to post
Share on other sites
If I understand you correctly, you are getting a random string and have to generate all permutations of it with no repetitions. If that is the case, here's the solution in Python code:


word = 'ASHES'

arr = [x for x in word] # make an array out of the string
arr.sort()
print arr


def recursive(arr, curWord):
i = 0
while i < len(arr):
l = arr[i] # take a letter
arrcpy = arr[:] # make a copy
del arrcpy[i]
if arrcpy: # if the array is not empty
recursive(arrcpy, curWord+l)
else:
curWord += l

print curWord

while l in arr[i:]: # the point
i += 1

recursive(arr, '')




and the general idea is to first sort your string using whatever you like that the letters are in groups, like 'ashes' -> 'aehss'
Then in your recursive word-building function after using up a single letter (for recursion), you don't simply iterate to the next index of the letter. Instead, you iterate to the next LETTER, i.e. the index where you get another letter, so in case of 'aadnz' being at index 0, you would goto index 2, to letter 'd' because it is next.
Just invented that in a moment. Not guaranteed to work, though tested and giving satisfactory results :]

edit: the forum formatting treats it badly. that function invocation recursive(...) really has two ' characters

Share this post


Link to post
Share on other sites
If I understand you correctly, I have an array which is going to represent A to Z (26 letters), and then add 1 to each position for each letter?

so I have SIS ... then I add 1 in array[8] (for i), and 2 in array[18] (for s) ??

[Brainstorming]
what if I treat unike letters (SI) as an group, then have S, and rotate them around ... like (SI)S and then S(SI) ... then I rotate (SI) ..to (IS) ... then rotate it around S ... like S(IS) and then rotate to (IS)S ...

...no ... d*#%&¤%&¤%& I had it ...

mmm

[/Brainstorming] ... temporarily off ...

EDIT: didn't see your post h3r3tic, reading it now ...

Share this post


Link to post
Share on other sites
sorry, I don't have a functioning C++ compiler, just discovered my dev-cpp is dead. However I've made a D version that may be easier to read than Python anyway. So, here it comes:


import std.stdio;

void recursive(char[] arr, char[] curWord)
{
int i = 0;
while (i < arr.length)
{
char l = arr[i]; // take a letter
char[] arrcpy = arr[0 .. i] ~ arr[i+1 .. length]; // make a copy without the single letter

if (arrcpy.length) // if the array is not empty
{
char[] newWord = curWord.dup; // copy the current word
newWord ~= l; // and add the letter to it
recursive(arrcpy, newWord); // w00t
}
else
{
curWord ~= l; // add the letter to the word
writefln(curWord); // and output it
}

// skip to the next letter
while (i < arr.length && l == arr[i]) // the point
{
i += 1;
}
}
}

void main()
{
char[] word = "ashes";
word.sort; // sort letters in the word

writefln( word ); // output the sorted word (debug info only)
recursive(word, ""); // do the job

getchar(); // wait for a key and
} // exit ;)





edit: damn tabs vs spaces
edit: added some more comments

Share this post


Link to post
Share on other sites
Quote:
Original post by DarkSlayer
If I understand you correctly, I have an array which is going to represent A to Z (26 letters), and then add 1 to each position for each letter?

so I have SIS ... then I add 1 in array[8] (for i), and 2 in array[18] (for s) ??


That's exactly what I'm saying. Then you choose from all of the elements that have at least one element and come up with all of the possibilities that way.


#include <stdio.h>

#define MAX_LENGTH 256

void StrToUpper(char String[], const unsigned StrLen)
{
for(unsigned K=0; K<StrLen; K++)
if(String[K]>='a' && String[K]<='z')
String[K]-='a'-'A';
}

unsigned FindPermutations(char String[], const unsigned StrLen)
{
StrToUpper(String, StrLen);

unsigned Letters[26];
{
for(unsigned J=0; J<26; J++)
Letters[J]=0;
for(unsigned K=0; K<StrLen; K++)
Letters[String[K]-'A']++;
}

unsigned * CorrespondingNum;
unsigned NumDifferentLetters=0;
{
for(unsigned J=0; J<26; J++)
if(Letters[J])
NumDifferentLetters++;
CorrespondingNum=new unsigned[NumDifferentLetters];
unsigned L=0;
for(unsigned K=0; K<26; K++)
if(Letters[K])
{
CorrespondingNum[L]=K;
L++;
}
}

unsigned * NumberString=new unsigned[StrLen];
{
unsigned LettersCopy[26];
for(unsigned CopyCounter=0; CopyCounter<26; CopyCounter++)
LettersCopy[CopyCounter]=Letters[CopyCounter];

for(unsigned K=0; K<StrLen; K++)
{
for(unsigned L=0; L<26; L++)
{
if(LettersCopy[L])
{
LettersCopy[L]--;
unsigned Index=0;
for(unsigned I=0; !Index; I++)
{
if(CorrespondingNum[I]==L)
Index=I+1;
}
Index--;
NumberString[K]=Index;
break;
}
}
}
}

// also define some sort of linked list or something //
// that can contain all of the strings //

unsigned NumPermutations=0;
bool Done=false;
while(!Done)
{
bool PermutationWorks=true;

unsigned LettersCopy[26];
for(unsigned CopyCounter=0; CopyCounter<26; CopyCounter++)
LettersCopy[CopyCounter]=Letters[CopyCounter];

char* Permutation=new char[StrLen+1];
for(unsigned K=0; K<StrLen; K++)
{
unsigned Letter=CorrespondingNum[NumberString[K]];
Permutation[K]='A'+Letter;
if(LettersCopy[Letter])
LettersCopy[Letter]--;
else PermutationWorks=false;
}
Permutation[StrLen]='\0';

if(PermutationWorks)
{
printf(Permutation);
printf("\n");
// Add Permutation to the linked list //;
NumPermutations++;
}
delete [] Permutation;

NumberString[StrLen-1]++;
for(unsigned L=StrLen-1; L; L--)
{
if(unsigned NextDigit=(NumberString[L]/NumDifferentLetters))
{
NumberString[L-1]+=NextDigit;
NumberString[L]%=NumDifferentLetters;
}
else goto EndOfLoop;
}
Done=(NumberString[0]/NumDifferentLetters);
EndOfLoop:;
}

delete [] NumberString;
delete [] CorrespondingNum;

return NumPermutations;
}

int main()
{
char String[MAX_LENGTH];
printf("Enter the word: ");
scanf("%s",String);
unsigned StrLen;
for(unsigned K=0; K<MAX_LENGTH; K++)
{
if(String[K]=='\0')
{
StrLen=K;
break;
}
}
printf("There are %d different permutations\n",FindPermutations(String, StrLen));
return 0;
}


This looks right...

Edit: I tested it, and it works now...

[Edited by - Nathaniel Hammen on September 21, 2004 9:05:20 PM]

Share this post


Link to post
Share on other sites
just a fast q ... trying hard to read your pyting code ( not a pytonist myself .. hehe )

how does your code deal with

ttss

just to make sure ... didn't quite understood the last while loop in the recusive ....

the test case is MISSISSIPPI ...

but my assignment have more to it, so there is more to be eliminated ... but those are more simpler to remove ( 3 or more of the same consonant "kkk", etc )

...but if duplicates are removed, the rest is childefood...

Share this post


Link to post
Share on other sites
results for ttss:

sstt
stst
stts
tsst
tsts
ttss

fine ?

oh, the last while loop is the point ;) it moves the i (index) to the next letter (not a duplicate of the current one)

btw, this algorithm should really perform better than the permutations-with-repetitions one :]

Share this post


Link to post
Share on other sites
I am reading/coding as fast as I can....

I feel stupid ... I'm suppost to make an career out of this ..programming, here you guy's pops this stuff out of your head in .... 2sek ....

pls tell me you are over 50, and have been doing with this in more than 30years, and spendt your last 10 years teaching this stuff on school...

Share this post


Link to post
Share on other sites
can i paste the results of running the program on 'mississippi' here ? it's only 439 KB (450,450 bytes). please ?


rotfl. nope, im only 19 atm and ive been playing around with Python for about a year. learn it! it will change your whole outlook @ programming :>

Share this post


Link to post
Share on other sites
Quote:
Original post by DarkSlayer
I am reading/coding as fast as I can....

I feel stupid ... I'm suppost to make an career out of this ..programming, here you guy's pops this stuff out of your head in .... 2sek ....

pls tell me you are over 50, and have been doing with this in more than 30years, and spendt your last 10 years teaching this stuff on school...


Not me, but my code was buggy when I first posted it...

Edit: It's fixed now...

[Edited by - Nathaniel Hammen on September 21, 2004 9:29:49 PM]

Share this post


Link to post
Share on other sites
There, made the code work... it is in the middle of the night, listning to metallica ... of all, and in 4 hours ... back to school...

OK. Now I need some explanations .. just to clear it up..

Used h3r3tic code as base for now, I'll look into Nathaniel more closely tomorrow, since it looked like something interesting.

The word is first sorted (so that simmilar lettes are put togheter)
Then we create 2 arrays mainly, where we dump the first array into the last except the last letter .. which we keep??

no... I am silly, but the qlue is "which" letter we take out, and which we skip in this mess ...

I have to run this through the debugger tomorrow to see if I can understand it. Give me a day to present a more clean cpp code ... I had to rewrite to make it fit, but the annoying part is that I don't understand what is really going on ... and thats annoys me, because I like to have controll over things.

...but now ... sleep ... zzzzzzzz
thx for excelent help, couldn't do it without you guys
I'll be back....zzzzzzz
aslfjaslfkjslfjsalkj <- head falling on the keyboard...hehe

Share this post


Link to post
Share on other sites
Well, my code works. I cleaned it up and tested it. Although it pauses every once in a while. It has to test whether it is a valid permutation. Essentially what my code does is add, in the base of however many different letters there are.

Edit: If you copied my code before I posted this, I would re-copy it, because your copy might be from before I fixed it.

Edit: My way of doing it is also EXTREMELY slow when you have a lot of different letters. For example, if you typed in the entire alphabet... it would take a long, long time.

[Edited by - Nathaniel Hammen on September 21, 2004 9:14:54 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Nathaniel Hammen
Edit: My way of doing it is also EXTREMELY slow when you have a lot of different letters. For example, if you typed in the entire alphabet... it would take a long, long time.

Heh.
26! is somewhere about 4*1026 , so, i think , anything will take alot of time... say if it can print 108 permutations per second (it certanly can't, i would be surprised if it can print 1000 per second on windows console!)....

Even if it'll print 108 per second, it will take about 100 billions years(alot longer than existence of universe) to show all permutations, if i'm right.[grin]
(edit:had mistake with orders-of-magnitude, fixed.)

Share this post


Link to post
Share on other sites
Quote:
Original post by Dmytry
26! is somewhere about 4*1026 , so, i think , anything will take alot of time... say if it can print 108 permutations per second (it certanly can't, i would be surprised if it can print 1000 per second on windows console!)....

Even if it'll print 108 per second, it will take about 100 billions years(alot longer than existence of universe) to show all permutations, if i'm right.[grin]
(edit:had mistake with orders-of-magnitude, fixed.)


...OK, bad example, but when I started it just to see what happened, it did a couple hundred or thousand and then paused for at least 20 minutes before I quit it.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Nathaniel Hammen
Quote:
Original post by Dmytry
26! is somewhere about 4*1026 , so, i think , anything will take alot of time... say if it can print 108 permutations per second (it certanly can't, i would be surprised if it can print 1000 per second on windows console!)....

Even if it'll print 108 per second, it will take about 100 billions years(alot longer than existence of universe) to show all permutations, if i'm right.[grin]
(edit:had mistake with orders-of-magnitude, fixed.)


...OK, bad example, but when I started it just to see what happened, it did a couple hundred or thousand and then paused for at least 20 minutes before I quit it.

i looked at your code and understood what you mean - you check every combination and it's slower than other methods (except that, for 26 letters it doesn't matter anyway[grin])

How i'd do it:
make an array of unique letters and counts of 'em
(say,for `mississippi' it will be
m 1
i 4
s 4
p 2
,
then in pseudocode(almost compilable)(i can complete if you need)

struct same_letters{
unsigned char c;
int count;
}
same_letters arr[26];
int arrlength;
#define MAX_STRING_SIZE 256
char str[MAX_STRING_SIZE];
int strlength=0;
void recursive_function(){
for(n=0;n<arrlength;n++)// it's possible to speed-up that piece of code but i don't sure it's reasonable.
if(arr[n].count)
{
str[strlength]=arr[n].c;
strlength++;
if(strlength<length_of_original_string){
arr[n].count--;
recursive_function();
arr[n].count++;
} else { printf(str); }
strlength--;
}//for() if
}
main{
Read input;
prepare arr[] and arrlength, it's trivial;
recursive_function();
};


btw, i hope it's not homework?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this