mIRC Home    About    Download    Register    News    Help

Print Thread
This is hard, combinations! #121543 29/05/05 02:37 AM
Joined: May 2005
Posts: 1
L
Luzifer Offline OP
Mostly harmless
OP Offline
Mostly harmless
L
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 smile cool

Re: This is hard, combinations! #121544 29/05/05 02:42 AM
Joined: Jan 2004
Posts: 509
L
LostShadow Offline
Fjord artisan
Offline
Fjord artisan
L
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).

Re: This is hard, combinations! #121545 29/05/05 03:29 AM
Joined: Aug 2004
Posts: 7,252
R
RusselB Offline
Hoopy frood
Offline
Hoopy frood
R
Joined: Aug 2004
Posts: 7,252
Nicely done...and that would work with any number, doesn't have to be 9.

Re: This is hard, combinations! #121546 29/05/05 06:04 AM
Joined: Sep 2003
Posts: 4,230
D
DaveC Offline
Hoopy frood
Offline
Hoopy frood
D
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

Code:
;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.

Re: This is hard, combinations! #121547 29/05/05 02:32 PM
Joined: Apr 2003
Posts: 701
K
Kelder Offline
Hoopy frood
Offline
Hoopy frood
K
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
}

Re: This is hard, combinations! #121548 29/05/05 11:38 PM
Joined: Sep 2003
Posts: 4,230
D
DaveC Offline
Hoopy frood
Offline
Hoopy frood
D
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.


Code:
;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.