# 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 on other sites
well i dont get exactly get what your trying to do here but you could use a for loop and a char array to check and make sure 2 things arnt the same

##### 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 on other sites
Instead of switching letters around, have an unsigned array with 26 elements. For each letter add one to the corresponding element in the array. Then come up with your solutions.

##### 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 stringarr.sort()print arrdef 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 += 1recursive(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 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 ...

##### 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

##### Share on other sites
Quote:
 Original post by DarkSlayerIf 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	256void 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 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 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 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 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 on other sites
Quote:
 Original post by DarkSlayerI 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 on other sites
hehe ... mississippi is going to be reduced to 4600 or so permutations when i am done ... more printable.. hehe

##### Share on other sites
weird, i am getting exactly 34650 permutations and my validator tells me that there are no repetitions

##### Share on other sites
no, but i am going to apply more rules to which words to drop, so don't worry about that.... it is probably correct number

##### Share on other sites
yup, my algorithm is fine:
clicky

Look for "Permutations with Repeated Elements"

##### 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 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 on other sites
Quote:
 Original post by Nathaniel HammenEdit: 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]

##### Share on other sites
Quote:
 Original post by Dmytry26! 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 on other sites
Quote:
 the test case is MISSISSIPPI ... "kkk"

Did this bring to mind images of burning crosses for anyone?

##### Share on other sites
Quote:
Original post by Nathaniel Hammen
Quote:
 Original post by Dmytry26! 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 256char 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 on other sites
Python rocks... I just wish it was a little easier to distribute :-\

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628390
• Total Posts
2982409

• 10
• 9
• 19
• 24
• 11