Permutations

Started by
23 comments, last by daerid 19 years, 7 months ago
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 ...
Advertisement
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
____________________________"This just in, 9 out of 10 americans agree that 1 out of 10 americans will disagree with the other 9"- Colin Mochrie
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.
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.
I am the master of ideas.....If only I could write them down...
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  # take a letter        arrcpy = arr[:]  # make a copy        del arrcpy        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
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 ...
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;  // 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)  // 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
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	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==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]
I am the master of ideas.....If only I could write them down...
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...
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 :]

This topic is closed to new replies.

Advertisement