Sign in to follow this  
Followers 0
SxyfrG

_StringReverse revamp

10 posts in this topic

#1 ·  Posted (edited)

This is my alternate _StringReverse function (with added progress bar if you want).

I searched the forums to see if anyone has posted something like this and i didn't see any posts so ... yeah, enjoy :D

;String = String you wish to reverse
;prog   = True: Show progress, False: do not show progress
Func __StringReverse($String,$prog=False)
    Local $Split, $ReturnString, $Progress, $Percent
    
    $Split = StringSplit ( $String , "" )
    If $Prog = 1 Or $Prog = True Then
        $Progress = ProgressOn ( "__StringReverse" , "Reversing String..." , "" , Default , Default , 16  )
    EndIf
    
    $Percent = 0
    For $i = $Split[0] To 1 Step -1
        $Percent += 1
        $ReturnString &= $Split[$i]
        If $Prog = True Then
            ProgressSet ( 100-Abs(($Percent/$Split[0])*100) , "" )
        EndIf
    Next

        If $Prog = True Then ProgressOff()
    
    Return $ReturnString
EndFunc

Tested times on my computer:

100,000 character length string

_StringReverse = 15 seconds

__StringReverse = 1.5 seconds

1,000,000 character length string

_StringReverse = Took too long, i got bored (approx 15*10 = 150 seconds or 2 minutes and 30 seconds)

__StringReverse = 11.2 seconds

(my computer is fairly fast: 2.4ghz Duo-core processor, 3gb RAM etc)

Just thought i'd share this :D

Edited by SxyfrG

My scripts:AppLauncherTRAY - Awesome app launcher that runs from the system tray NEW VERSION! | Run Length Encoding - VERY simple compression in pure autoit | Simple Minesweeper Game - Fun little game :)My website

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

You've two flaws in your code. At first, you don't call progressoff. The second flaw is a bit 'bigger', it makes the program loose speed:

Compare this:

$timer = TimerInit()

$true = True

For $n = 1 to 10000000

If $true Then

Do_Something()

Endif

Do_Something_Else()

Next

ConsoleWrite(TimerDiff($timer))

To this:

$timer = TimerInit()

$true = True

If $true Then

For $n = 1 to 10000000

Do_Something()

Do_Something_Else()

Next

Else

For $n = 1 to 10000000

Do_Something_Else()

Next

EndIf

ConsoleWrite(TimerDiff($timer))

Edited by TomZ

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

I fixed the progressoff() bug just a second before you posted, but i don't get what you're saying about the program losing speed, with and without the extra progress bar option, the time difference was negligible (if that's what you're talking about).

Edited by SxyfrG

My scripts:AppLauncherTRAY - Awesome app launcher that runs from the system tray NEW VERSION! | Run Length Encoding - VERY simple compression in pure autoit | Simple Minesweeper Game - Fun little game :)My website

Share this post


Link to post
Share on other sites

You've two flaws in your code. At first, you don't call progressoff. The second flaw is a bit 'bigger', it makes the program loose speed:

Compare this:

$timer = TimerInit()

$true = True

For $n = 1 to 10000000

If $true Then

Do_Something()

Endif

Do_Something_Else()

Next

ConsoleWrite(TimerDiff($timer))

To this:

$timer = TimerInit()

$true = True

If $true Then

For $n = 1 to 10000000

Do_Something()

Do_Something_Else()

Next

Else

For $n = 1 to 10000000

Do_Something_Else()

Next

EndIf

ConsoleWrite(TimerDiff($timer))

Actually i do get what you're talking about. :D

I re-tested the function and cut the time by more than half by commenting out the progress bar option.


My scripts:AppLauncherTRAY - Awesome app launcher that runs from the system tray NEW VERSION! | Run Length Encoding - VERY simple compression in pure autoit | Simple Minesweeper Game - Fun little game :)My website

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Actually i do get what you're talking about. :D

I re-tested the function and cut the time by more than half by commenting out the progress bar option.

You can split the code if you want to leave the progress functionality in:

Func __StringReverse2($String,$fProg=False)
    Local $Split, $ReturnString, $Progress, $Percent
    
    $Split = StringSplit($String , "")
    If $fProg Then
        $Progress = ProgressOn ( "__StringReverse" , "Reversing String..." , "" , Default , Default , 16  )
        $Percent = 0
        For $i = $Split[0] To 1 Step -1
            $Percent += 1
            $ReturnString &= $Split[$i]
            ProgressSet(100-Abs(($Percent/$Split[0])*100) , "")
        Next
        ProgressOff()       
    Else
        For $i = $Split[0] To 1 Step -1
            $ReturnString &= $Split[$i]
        Next        
    EndIf
    
    Return $ReturnString
EndFunc

It's a very basic optimizing technique.

Btw, I guess this just reinforces something I noticed earlier, that AutoIt string functions take advantage of multicores. (scratch that, it's mainly just because _StringReverse() is horribly outdated, not even using "&=" oparator for concatenation...)

Because on my old P4 the difference between the versions is even more severe:

"official" _StringReverse (uses StringMid approach) takes friggin 63+ secs for 100k char string

your first non-optimal version takes 1.8 secs.

the one above takes 1.1 secs.

Overall, I say, good job on this one. Too bad the devs are perfectly happy with old and slow functions being included in AutoIt core package even when presented an alternative. And it's not a critical or oft used UDF. Honestly I don't know why these functions are part of core package to begin with, if any coder should be able to achieve the same with 1 For...Next loop in 3-4 lines.

Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Okay - it runs fast on a single string.

BUT - does it run fast on multiple small strings back-to-back?

I have a feeling creating an array with StringSplit 8000 times might cause your function do lose this race.

It seems, the bigger the test-string, the more advantage your function has

- but, the more times back-to-back it's ran, the more advantage the original UDF function has

Using the code below, I got:

"

_StringReverse Took 2894.73326917248ms

__StringReverse Took 3022.60566636262ms

__StringReverse2 Took 2255.45816577247ms

"

EDIT: Re-ran with the StringReverse2 posted.

$str="ab"
$times=8000
#include <String.au3>
;-- Put your __StringReverse declaration here --;
;-- Put your __StringReverse2 declaration here --;
$t=TimerInit()
For $i=1 To $times
    _StringReverse($str)
Next
ConsoleWrite("_StringReverse Took "&TimerDiff($t)&"ms"&@CRLF)
$t=TimerInit()
For $i=1 To $times
    __StringReverse($str)
Next
ConsoleWrite("__StringReverse Took "&TimerDiff($t)&"ms"&@CRLF)
$t=TimerInit()
For $i=1 To $times
    __StringReverse2($str)
Next
ConsoleWrite("__StringReverse2 Took "&TimerDiff($t)&"ms"&@CRLF)
Edited by crashdemons

My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

OR, how about this, Complete with "_TestFuncSpeed"

Testing Processing Speeds:

"_StringReverse($str)" Took 2328.59902585384ms

"__StringReverse($str)" Took 770.042840640361ms

"__StringReverse2($str)" Took 520.423685133166ms

Testing Initialization Speeds:

"_StringReverse($str)" Took 2303.33547978863ms

"__StringReverse($str)" Took 3401.60718750568ms

"__StringReverse2($str)" Took 2670.47068831374ms

#include <String.au3>
;-- Put your __StringReverse  declaration here --;
;-- Put your __StringReverse2 declaration here --;


Func _TestFuncSpeed($ExecuteString,$TestLoop=1,$OutputResults=True)
    $t=TimerInit()
    For $i=1 To $TestLoop
        Execute($ExecuteString)
    Next
    $result=TimerDiff($t)
    If $OutputResults Then  ConsoleWrite('"'&$ExecuteString&'" Took '&$result&'ms'&@CRLF)
    Return $result
EndFunc

;Testing here
$str=_StringRepeat('ab',8000)
$times=1
ConsoleWrite("Testing Processing Speeds:"&@CRLF)
_TestFuncSpeed("_StringReverse($str)",$times)
_TestFuncSpeed("__StringReverse($str)",$times)
_TestFuncSpeed("__StringReverse2($str)",$times)

$str='ab'
$times=8000
ConsoleWrite("Testing Initialization Speeds:"&@CRLF)
_TestFuncSpeed("_StringReverse($str)",$times)
_TestFuncSpeed("__StringReverse($str)",$times)
_TestFuncSpeed("__StringReverse2($str)",$times)
Edited by crashdemons

My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

Share this post


Link to post
Share on other sites

Hm, time check this too :D

Func _StringReverseCRT($sString)
    Local $tBuff
    If StringLen($sString) >= 1 Then
        $tBuff = DllStructCreate("wchar[" & StringLen($sString)+1 & "]")
        DllStructSetData($tBuff, 1, $sString)
        DllCall("msvcrt.dll","ptr:cdecl","_wcsrev", "ptr",DllStructGetPtr($tBuff))
        If @error Then Return SetError(@error,0,"")
        Return DllStructGetData($tBuff, 1)  
    Else
        Return SetError(1,0,"")
    EndIf   
EndFunc

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

Hm, time check this too :D

Showing Results :D

Testing Processing Speeds:

"_StringReverse($str)" Took 2684.66997900571ms

"__StringReverse($str)" Took 832.423115228332ms

"__StringReverse2($str)" Took 1012.59461747233ms

"_StringReverseCRT($str)" Took 1.72172720275901ms

Testing Initialization Speeds:

"_StringReverse($str)" Took 2913.20461120059ms

"__StringReverse($str)" Took 3826.90509548001ms

"__StringReverse2($str)" Took 2789.22293196482ms

"_StringReverseCRT($str)" Took 4622.43609173792ms

Back-to-Back speeds weren't great but - holy - the processing speed on a single long string was F.A.S.T.


My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

My time results ...

Testing Processing Speeds: (1)

"_StringReverse($str)" Took 334.153083539561ms

"__StringReverse($str)" Took 89.0102095792947ms

"__StringReverse2($str)" Took 54.7416769780711ms

"__StringReverseCRT($str)" Took 0.0405650649618478ms

Testing Initialization Speeds: (80000)

"_StringReverse($str)" Took 2787.18255825943ms

"__StringReverse($str)" Took 3428.77028124356ms

"__StringReverse2($str)" Took 2773.16764710937ms

"__StringReverseCRT($str)" Took 574.129117687496ms

Great work Siao :D

Edited by SxyfrG

My scripts:AppLauncherTRAY - Awesome app launcher that runs from the system tray NEW VERSION! | Run Length Encoding - VERY simple compression in pure autoit | Simple Minesweeper Game - Fun little game :)My website

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