Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Professional Discussion / Finding permutations of a string

Author
Message
Phaelax
DBPro Master
23
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 21st Feb 2013 06:46
Been staring at this for an hour now and still no closer to a solution.

Given a string of characters, I want to find all the permutations of a specified length.

So if you're given "ABCDE" and I want all combinations having 3 characters.

ABC ACB
ABD ADB
ABE ADC
ACD AEB
ACE AEC
ADE AED
(example is only a partial set)

I see the obvious pattern and my brain is telling me this is very simple but I can't seem to put it into code.

I even pulled out the mountain dew and doritos brain power food, but no luck.

"You're all wrong. You're all idiots." ~Fluffy Rabbit
Libervurto
20
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 21st Feb 2013 13:39 Edited at: 21st Feb 2013 23:01
I'm pretty sure it's n^m : where n = possible letters, m = length of string.
If for one letter there are n possibilities then for two letters there are n*n possibilities (or n^2)... three letters = n*n*n or n^3... ad infinitum.

Oops, no they can't have duplicate letters.

Dar13
18
Years of Service
User Offline
Joined: 12th May 2008
Location: Microsoft VisualStudio 2010 Professional
Posted: 21st Feb 2013 15:43 Edited at: 25th Feb 2013 18:33
Here's a brute-force method:


Note: requires Matrix1Utils

EDIT: Removed unused function.

EDIT: Gah! Messed up the checkDuplicates function.

spooky
23
Years of Service
User Offline
Joined: 30th Aug 2002
Location: United Kingdom
Posted: 21st Feb 2013 21:37
Simple way;



Boo!
Libervurto
20
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 22nd Feb 2013 00:25 Edited at: 22nd Feb 2013 02:12
Solved:


I found a formula for calculating factorials and converted it to dbp


So putting it all together:


[edit: added a fail-safe for value over-flow,which happens >13!]

Phaelax
DBPro Master
23
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 22nd Feb 2013 07:54
Spooky, what if my string has 12 characters and I need combinations of 8 instead of just 3?

Obese, your code returns 1 for anything I input.

"You're all wrong. You're all idiots." ~Fluffy Rabbit
Libervurto
20
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 22nd Feb 2013 12:31
Maybe this will help


Phaelax
DBPro Master
23
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 22nd Feb 2013 20:38
Ah I see. I should've figured that out the first time. I was putting in a character string. (still your fault for not having error checking!)

The plan was to find all combinations of a certain length, check those in a binary search against a dictionary file, and display only the words.

With some permutations counting over 7k, even with a binary search, it might take a long time checking all those against a 22k word dictionary. (dictionary files were broken down by word size)

Using the code snippet I posted the other day, I'm currently looping through all the dictionary words and comparing it to the given string to see if it contains the necessary characters. Kind of a backwards approach but appears to work quicker than I'd expect. I built it with php: http://zimnox.com/resources/whatstheword/

"You're all wrong. You're all idiots." ~Fluffy Rabbit
spooky
23
Years of Service
User Offline
Joined: 30th Aug 2002
Location: United Kingdom
Posted: 23rd Feb 2013 20:08
If anyone still interested here is way using recursive function that will work on any string length and any desired word length.



Boo!
Phaelax
DBPro Master
23
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 23rd Feb 2013 23:45 Edited at: 23rd Feb 2013 23:52
Awesome spooky!

Tested it with a 10 character string, with a size of 6. 151,200 combinations! And a 12 char string with a size of 8 (the biggest I would need to do), comes out at..... (still calculating for about 8min) 1,9958,400!

"You're all wrong. You're all idiots." ~Fluffy Rabbit
spooky
23
Years of Service
User Offline
Joined: 30th Aug 2002
Location: United Kingdom
Posted: 24th Feb 2013 19:57
Yeah, once you get into big numbers it's rather slow mainly becuase DBPro has to do lots of work juggling stacks for the recursive function. Sped it up a bit but 8 from 12 still takes a good 22 seconds to populate an array of 22 million rows. Any smaller ranges and selection seem to run almost instantly.

I'm sure I've done a similar bit of code in other languages by not doing recursion as that runs a lot quicker. If I get bored over next day or so I'll have a play.



Boo!
spooky
23
Years of Service
User Offline
Joined: 30th Aug 2002
Location: United Kingdom
Posted: 24th Feb 2013 22:08
Got bored watching Top Gear (although the old people car was quite amusing!). Here's an attempt at using a non recursive method and for smallish numbers works as good as or faster than recursion, but for the 8 from 12 test it takes around 27 seconds. Oh well, worth a try anyway. If matched to a fast method of testing for dictionary words as you run the permutation function, then it should be pretty quick.

For example whilst running perm routine using the letters ABCDEZQW, then if currently down to DEA, then you should easily be able to tell there's no english words starting DEAZ so no need to explode that part of the tree.



Boo!
Phaelax
DBPro Master
23
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 25th Feb 2013 03:18
Quote: "Got bored watching Top Gear (although the old people car was quite amusing!)"

I forgot it was Sunday!

I wonder how the memory usage differs between this one and the recursive method.

"You're all wrong. You're all idiots." ~Fluffy Rabbit
Libervurto
20
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 25th Feb 2013 17:17 Edited at: 25th Feb 2013 17:33
Now that I realised you actually want the strings not just a number, this problem bugs me! I'm sure there's a way to simply manipulate the string into all its possible permutations.

I can't find any algorithm that wont loop before all the permutations have been found. You can get the first n!/(n-2)! permutations with this simple method:
Quote: "n$ = a$
i = 2 to len(a$)
swap 1st and ith characters of n$
when i = len(a$) : if n$ =/= a$ then repeat"

Example:

My Code:

It's very quick. If we can work out what "meta-manipulation" of the string is required to produce many groups like this that are all unique, then we'll have a very fast solution.


Libervurto
20
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 25th Feb 2013 22:59 Edited at: 25th Feb 2013 22:59
Damn I thought I had it this time, but I'm getting duplicates.

There just has to be a simple solution to this.


spooky
23
Years of Service
User Offline
Joined: 30th Aug 2002
Location: United Kingdom
Posted: 25th Feb 2013 23:29
I agree. I'm sure there is a simple way that works quicker than my feeble attempts. I read about the swapping method on some other forums late last night but then I thought I'd better go to bed as I had to be at work early this morning.

Will have a good old browse around the net over next few days to see what I can dig up.

At least Phaelax has a quick workaround by doing the reverse and going through the dictionary and seeing which ones match letters you have, specially as most word lists only go up to around 200,000 words.

Boo!
Phaelax
DBPro Master
23
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 26th Feb 2013 03:16
Yea, the puzzle doesn't need to calculate anything in realtime. And I have my dictionary broken down into separate files to contain only words of the specified lengths. It's simpler, and apparently faster checking maybe 100k words versus a possible million. Although, checking the combinations against the dictionary file would be a binary search and that would be faster than my current matching scheme. I may have to try out Spooky's method and compare the two.

"You're all wrong. You're all idiots." ~Fluffy Rabbit
Libervurto
20
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 26th Feb 2013 05:59
How about storing a second version of each word, in which the letters are sorted alphabetically? Then simply compare equivalence. You could even use those strings to sort your dictionary so that all the words that use the same letters are together.


Libervurto
20
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 27th Feb 2013 05:55 Edited at: 27th Feb 2013 06:42
I've found a really elegant mechanical solution, so mechanical that I'm going to make an animation for it so you can watch it working its way through all the permutations.


Damn I just found out it doesn't work for length 4
Here is the algorithm working on a string of length 5 (it also works for 6, 3 and 2):



Login to post a reply

Server time is: 2026-07-07 14:23:55
Your offset time is: 2026-07-07 14:23:55