|
Joined: May 2005
Posts: 1
Mostly harmless
|
OP
Mostly harmless
Joined: May 2005
Posts: 1 |
Well I would gess this is realy hard. I want a script that echoe`s all the possible combinations of a nine letter combination. For example hflprsuos could be solprsfuh and so on. I have no use for this what so ever, but it`s bugging me, that I can`t figure away out to solve this. It`s 362880 possible combinations :P Good luck
|
|
|
|
Joined: Jan 2004
Posts: 509
Fjord artisan
|
Fjord artisan
Joined: Jan 2004
Posts: 509 |
Why not use factorials?
9! = 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2 x 1.
alias factorial { var %i = $1, %res = 1 while (%i) { %res = $calc(%res * %i) .dec %i } return %res }
So, $factorial(N).
|
|
|
|
Joined: Aug 2004
Posts: 7,252
Hoopy frood
|
Hoopy frood
Joined: Aug 2004
Posts: 7,252 |
Nicely done...and that would work with any number, doesn't have to be 9.
|
|
|
|
Joined: Sep 2003
Posts: 4,230
Hoopy frood
|
Hoopy frood
Joined: Sep 2003
Posts: 4,230 |
But it isnt what was asked for, its also not strictly the correct number of results for all a sets of passed characters ABCD = 4x3x2x1 = 24 combos ABCA = 4x3x1 = 12 combos
;Echo all Combos of characters in $2 to -a
;Usage $Combo(,hflprsuos)
;
; $1 = fixed string at start
; $2 = string to still cycle
alias Combos {
if (!$2) { echo -a $1 }
else {
var %all.chars = $2
var %cycle.chars = $2
while ($len(%cycle.chars)) {
var %locked = $left(%cycle.chars,1)
var %pre = $poscs(%all.chars,%locked,1) - 1
var %post = %pre + 2
var %unlocked = $+($left(%all.chars,%pre),$mid(%all.chars,%post))
$Combos.Recurse($+($1,%locked),%unlocked)
var %cycle.chars = $removecs(%cycle.chars,%locked)
}
}
}
alias Combos.Recurse { $Combos($1,$2) }
//.echo -q $combos(,abcd) //.echo -q $combos(,abca) Note the different number of results.
|
|
|
|
Joined: Apr 2003
Posts: 701
Hoopy frood
|
Hoopy frood
Joined: Apr 2003
Posts: 701 |
Might not be what he wanted, but I script it anyway :tongue:
alias numcombos { ; returns the number of different possible combinations with the letters of the parameters ; usage: $numcombos(string) returns 6! $numcombos(aaabb) returns 5! / (3! * 2!) = 10 var %1 = $1-, %num = $fac($len($1-)) while (($left(%1,1) != $null) && ($regsub(%1,$+(/,$v1,/g),,%1))) { echo %1 : %num var %num = $calc(%num / $fac($v1)) } return %num } alias fac { ; usage: $fac(number) gives (number)! == number*(number-1)*...*1 var %n = $iif($1 isnum 1-,$1,0), %r = 1 while (%n) var %r = %r * %n, %n = %n - 1 return %r }
|
|
|
|
Joined: Sep 2003
Posts: 4,230
Hoopy frood
|
Hoopy frood
Joined: Sep 2003
Posts: 4,230 |
I was asked to explain what my routine was doing as some parts were hard to follow so... You initially call the routine $combo( , <string> ) , you pass the string to process as the second parameter, becuase the first one is for a better word the "FIXED" part of the string, this well become clearer as I go.
;Echo all Combos of characters in $2 to -a
;Usage $Combo(,hflprsuos)
;
; $1 = fixed string at start
; $2 = string to still cycle
alias Combos {
if (!$2) { echo -a $1 }
[color:blue];^ If there is NO $2 then everything is now a FIXED string so just display the FIXED string
;[/color]
else {
[color:blue];^ If there is something in $2, then those characters still need to be cycled through, example $combos(ab,CDE) means abcCDE, abCED, abDCE, abDEC, abECDm abEDC still needed
;[/color]
var %all.chars = $2
[color:blue];^ store all characters still to cycle (I just looked and i could have just used $2 later for this but this made it more named thus noticable)
;[/color]
var %cycle.chars = $2
[color:blue];^ This variable is similar to the one above but well be reduced to leave only the remainsing characters to cycle through after each pass, with a extra fixed character
;[/color]
while ($len(%cycle.chars)) {
[color:blue];^ while there are still charcters to cycle through keep looping (this is reduced at the bottom of the while loop)
;[/color]
var %locked = $left(%cycle.chars,1)
[color:blue];^ I take a character from the list to be done, it well be added to the FIXED charcters example $combos(ab,CDE) %locked would be C then D then E for the 3 passes of the while loop
;[/color]
var %pre = $poscs(%all.chars,%locked,1) - 1
[color:blue];^ This locates the string position before the %locked character, in %locked being C from CDE it is 0, D it is 1, E it is 2 (CDE of %all.chars)
;[/color]
var %post = %pre + 2
[color:blue];^ This locates the string position after the %locked character, in %locked being C from CDE it is 2, D it is 3, E it is 4 (4 is beyond the end of the string)
;[/color]
var %unlocked = $+($left(%all.chars,%pre),$mid(%all.chars,%post))
[color:blue];^ I use the above two values to creat a new string minus the charcter in %locked, so if %locked is C, %unlocked is DE, in D its CE, in E its CD
;[/color]
$Combos.Recurse($+($1,%locked),%unlocked)
[color:blue];^ on the first while pass I have 3 values (ab, C, DE) i group them as (abC,DE), next while pass its (abD,CE) then (abE,CD)
;^ This second alias is used becuase you can not recursively call the same alias so I call this second one that simply calls this one using the same parameters
;^ This means the entire process repeats but now the FIXED string is abC and the cycled string is DE, from there it well call this again and again as so
; (ab,CDE)--+--(abC,DE)--+--(abCD,E)----(abCDE,)
; | |
; | +--(abCE,D)----(abCED,)
; |
; +--(abD,CE)--+--(abDC,E)----(abDCE,)
; | |
; | +--(abDE,C)----(abDEC,)
; |
; +--(abE,CD)--+--(abEC,D)----(abECD,)
; |
; +--(abED,C)----(abEDC,)
;^ This a subtree of an original larger tree of (,abCDE), how ever if you removed the "ab" from the above you would be seeing an exact recursion tree for (,CDE)
;[/color]
var %cycle.chars = $removecs(%cycle.chars,%locked)
[color:blue];^ This is the only special feature. Removing ALL the occarances of the %locked character from the characters still to cycle. Why? Well a simple cycling of the next
;^ chracter to use, while on CDE would be acceptable. if instead the $2 was CCE you would do (abC,CE) then next pass would do (abC,CE) then do (abE,CC),
;^ the first two passes would be the same, this of course well produce duplicate results on the tree limbs, so instead ALL occurances of C are removed, not just one.
;^ Here you must remeber that you have removed the character from the list of characters still to cycled through and NOT the list of charcters left to to still pass
;^ ie %cycle.chars=CCE %all.chars=CCE,
; while pass1, %locked=C, %unlocked=CE, $combos(abC,CE), %cycle.char=E (all C's removed)
; while pass2, %locked=E, %unlocked=CC, $combos(abE,CC), %cycle.char=$null (all E's removed)
; while loop ends
;^ This is the only step that makes this alias any different from a simple recursive cycler[/color]
}
}
}
alias Combos.Recurse { $Combos($1,$2) }
[color:blue];^ this as stated above is just becuase i cant recursively call the same alias from itself, so i call this that calls the first alias.[/color]
Dont know how good my explanation was, but man it takes ages to write them.
|
|
|
|
|