Sign in to follow this  
Followers 0
xOAT

Split string into all combinations

10 posts in this topic

#1 ·  Posted (edited)

I am trying to split a string with a delimiter into all combinations. If the given string is "autoit" the output should be:

autoit
a-utoit
au-toit
aut-oit
auto-it
autoi-t
a-u-toit
a-ut-oit
a-uto-it
a-utoi-t
au-t-oit
au-to-it
au-toi-t
aut-o-it
aut-oi-t
auto-i-t
a-u-t-oit
a-u-to-it
a-u-toi-t
a-ut-o-it
a-ut-oi-t
a-uto-i-t
au-t-o-it
au-t-oi-t
au-to-i-t
aut-o-i-t
a-u-t-o-it
a-u-t-oi-t
a-u-to-i-t
a-ut-o-i-t
au-t-o-i-t
a-u-t-o-i-t

The problem I am having is making it compatible with strings of different lengths. I am guessing it can be done with recursion or complex loops. Here is what I have so far:

#Include <String.au3>

$prefix = "autoit"
$length = StringLen ( $prefix )
$delimiter = "-"

;NO DELIMITER 
ConsoleWrite( $prefix & @CRLF )

;ONE DELIMITER
For $i = 1 To $length - 1 Step 1
    $string = _StringInsert( $prefix, $delimiter, $i )
    ConsoleWrite( $string & @CRLF )
Next

;TWO DELIMITERS
$count = $length - 3
$inc = 1
$dotcount = 1
Do
    For $i = $length - $count To $length
        $string = _StringInsert( $prefix, $delimiter, $inc )
        $string = _StringInsert( $string, $delimiter, $i )
        ConsoleWrite( $string & @CRLF )
    Next
    $count -= 1
    $inc += 1
Until $count < 0

This only works with a string length of 6. Help please.

Edited by xOAT

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

So, if you are guessing it can be done with recursion, why didn't you try recursion yet? :graduated:

Something like this, perhaps?

#include <String.au3>

$string = "123456"

ConsoleWrite($string&@CRLF)

_interdash("", $string)

Exit

Func _interdash($prefix, $string)
    For $i = 1 To StringLen($string) - 1
        ConsoleWrite($prefix & _StringInsert($string, "-", $i) & @CRLF)
    Next
    If StringLen($string) > 2 Then
        $newPrefix = $prefix & StringMid($string, 1, 1) & "-"
        _interdash($newPrefix, StringMid($string, 2))
    EndIf
EndFunc   ;==>_interdash
Edited by SadBunny

Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites

So, if you are guessing it can be done with recursion, why didn't you try recursion yet? :(

Because it hurts my head... :graduated:

Thanks, that is close to what I'm looking for. The intermediate combos are missing like 12-, 123-, etc. There are 2^(length - 1) combinations.

Mind completing it for me? :D

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Because it hurts my head... :graduated:

Thanks, that is close to what I'm looking for. The intermediate combos are missing like 12-, 123-, etc. There are 2^(length - 1) combinations.

Mind completing it for me? :(

It can be solved by using a binary counter from 0 to 2^NumTokens - 1, where the number of tokens is always one less than the length of the string. I can't believe AutoIt doesn't have built in "Decimal to Binary" conversion functions, because that's precisely what you can use to determine when to insert tokens. I can't claim that this is the most efficient algorithm, but it works:

Local $String = "abcdef"
Local $NumChars = StringLen($String)
Local $NumTokens = $NumChars - 1
Local $OutputString
Local Const $Token = "-"
Local $i, $j

For $i = 0 To 2^$NumTokens - 1
  $TokenMask = _DecToBinary($i, $NumTokens)
  $OutputString = ""

  For $j = 1 To $NumChars - 1
    ; Append jth char from string.
    $OutputString = $OutputString & StringMid($String, $j, 1)

    ; Insert token when jth character of mask is a 1.
    If StringMid($TokenMask, $j, 1) = 1 Then
     $OutputString = $OutputString & $Token
    EndIf
  Next

  ; Append last character in string.
  $OutputString = $OutputString & StringMid($String, $NumChars, 1)

  MsgBox(0, "", $OutputString)
Next

Func _DecToBinary ($DecNum, $NumDigits)
  Local $i, $tmp, $c
  Local $BinNum

  $c = 1

  For $i = 1 To $NumDigits
    $tmp = BitAND ($DecNum, $c)
    If $tmp = 0 Then
      $BinNum = "0" & $BinNum
    Else
      $BinNum = "1" & $BinNum
    EndIf
    $c = BitShift($c, -1) ; Shift left by 1 place
  Next

  Return $BinNum
EndFunc

I found and converted the _DecToBinary algorithm from a completely different programming language.

EDIT: Updated the code with better comments so you can understand how it works.

Gerard J. Pinzone

gpinzone AT yahoo.com

Edited by CPinzone

Gerard J. Pinzonegpinzone AT yahoo.com

Share this post


Link to post
Share on other sites

It can be solved by using a binary counter from 0 to 2^NumTokens - 1, where the number of tokens is always one less than the length of the string. I can't believe AutoIt doesn't have built in "Decimal to Binary" conversion functions, because that's precisely what you can use to determine when to insert tokens. I can't claim that this is the most efficient algorithm, but it works:

-snip-

I found and converted the _DecToBinary function from a completely different language.

Thanks for this! I am not concerned with its efficiency, so its perfect.

Share this post


Link to post
Share on other sites

I've got a similar issue where I have to figure out where to split my string. Below is an example of the field I need to split.

IRC (Chat) 194(IRC (Chat) 194):

As you can see, the string is repeated inside quotes. The field is variable in length and the delimeters are used inside the string as well. How can i strip out the correct pair of parenthesis and compare the strings? If the things are different, I keep the whole string. If they match, I strip out the duplicate data inside the

paraenthesis.

Thanks, Mike

Share this post


Link to post
Share on other sites

Using a generic regexp, depending on the _structure_ of your input string.

If you whish to test if the input is of the form:

X(X) where X is something like IRC (Chat) 194

why not use a regexp pattern like (.+?)\(\1\)

It should be close to working for you, even if it involves some backtracking.


This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites

It can be solved by using a binary counter from 0 to 2^NumTokens - 1, where the number of tokens is always one less than the length of the string. I can't believe AutoIt doesn't have built in "Decimal to Binary" conversion functions, because that's precisely what you can use to determine when to insert tokens. I can't claim that this is the most efficient algorithm, but it works:

Nice one! Yeah I didn't actually manually verify the output of my example :graduated:


Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites

Using a generic regexp, depending on the _structure_ of your input string.

If you whish to test if the input is of the form:

X(X) where X is something like IRC (Chat) 194

why not use a regexp pattern like (.+?)\(\1\)

It should be close to working for you, even if it involves some backtracking.

I'm pretty new to this stuff. I'm looking through the help files but not seeing any references to those special characters (.+?)\(\1\). where should I be looking?

Thanks Mike

Share this post


Link to post
Share on other sites

OK, sorry I've a bit elliptic about that.

Try this:

$mystring = "IRC (Chat) 194(IRC (Chat) 194):"

$match = StringRegExp($mystring, "(.+?)\(\1\):")

;; $match will be = 1 if $mystring is of the form X(X): where X is a more or less arbitrary string

;; I understood the final colon to be part of the input, hence I made it part of the pattern


This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0