Jump to content

Some math udf's


Uten
 Share

Recommended Posts

Thanks a lot Uten! I managed to use Notepadd ++ to edit and TCC to compile :P It works, but it's extremely slow. I guess I'll try to avoid using recursive calls... I've never programed in C before, so this is hard as hell ;)

@SkinnyGuy: I replaced int by long and it works. But it's like 10000 slower than the one you did!

Do you mean that you have comparable code in C and AutoIt and the C one is slower??? Or are you comparing two different algorithms?

@weaponx, care to profile your solution and mine and post the result? You find a link to profiling code in my signature. I have not done it myself as I'm out of time at the moment..(

Link to comment
Share on other sites

Do you mean that you have comparable code in C and AutoIt and the C one is slower??? Or are you comparing two different algorithms?

I built a DLL with the source I showed in the previous page and, well kinda obviously, works 1000 times slower than the one SkinnyGuy wrote in AutoIt. I guess this is an expected behaviour, sice i'm not really using a ver efficient algorithm... I don't really get along well with C :">

I'm attempting to graph a comparison of the 2 functions because sometimes mine is faster, sometimes yours is. Very curious.

Yeah, that happens to me too.. the weird thing is that sometimes one is WAY faster than the other one. I suppose this is because every loop doesn't last the same, it must depend on how busy the CPU is and all that jazz... I've been explained this, but I forgot :">

Link to comment
Share on other sites

Alright fellas check this out.

Posted Image

I'm out of attachment space so I'm posting the code here, no udf's or external includes are needed.

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.2.8.1
 Author:        WeaponX

 Script Function:
    Steam style graph generator, this version customized to compare number factoring

#ce ----------------------------------------------------------------------------
#include <array.au3>
#include <GUIConstants.au3>

$theArray = randomStatsToArray()
;_ArrayDisplay($theArray)

GraphX($theArray, "Factor speed comparison")

;Return 2D Array of CPU / RAM usage per process
;[0] = Number to be factored
;[1] = GetFactorsX (in ms)
;[2] = GetFactors (in ms)
Func randomStatsToArray()
    Local $points[1][3]

    ;Poll Frequency in milliseconds
    ;Local $PollFrequency = 100

    ;Number of times to execute poll
    Local $PollCount = 1000

    For $X = 1 to $PollCount
        If $X > 1 Then
            Redim $points[$X][3]
        EndIf
        
        ;Store seconds elapsed
        $points[$X - 1][0] = $X
        
        ;Store elapsed time to find factors of $X using GetFactorsX()
        $timestamp = TimerInit()
        $theArray = GetFactorsX($X)
        $points[$X - 1][1] = TimerDiff($timestamp)
        
        ;Store elapsed time to find factors of $X using GetFactors()
        $timestamp = TimerInit()
        $theArray = GetFactors($X)        
        $points[$X - 1][2] = TimerDiff($timestamp)
    Next
    
    Return $points
EndFunc
    
;GraphX
Func GraphX(ByRef $xyArray, $graphTitle = "")
    ;Define colors
    Local $graphBGColor = 0x242529
    Local $graphBorderColor = 0x000000
    Local $graphLabelColor = 0x787878

    Const $graphMinX = 0
    Local $graphMaxX = 0
    
    ;Determine highest X value
    For $X = 0 to Ubound($xyArray) - 1
        If $xyArray[$X][0] > $graphMaxX Then
            $graphMaxX = $xyArray[$X][0]
        EndIf
    Next

    Local $graphMinY = 0
    Local $graphMaxY = 0

    ;Determine highest Y value
    For $X = 0 to Ubound($xyArray) - 1
        If $xyArray[$X][1] > $graphMaxY Then
            $graphMaxY = $xyArray[$X][1]
        EndIf
        
        If $xyArray[$X][2] > $graphMaxY Then
            $graphMaxY = $xyArray[$X][2]
        EndIf
    Next
    
    Const $graphWidth = 400
    Const $graphHeight = 100

    Const $graphLineColor1 = 0xc98d35
    Const $graphLineColor2 = 0x686868
    
    Const $graphGridXInterval = 4
    Const $graphGridYInterval = 4
    
    $graphSumLine1 = 0
    $graphSumLine2 = 0
        
    ;Create Main window
    GUICreate("Graph X: " & $graphTitle, 500, 200, -1)
    GUISetBkColor (0x424242)

    ;GUISetState (@SW_SHOW) 

    ;Create the graphic "sandbox" area
    $graphic = GuiCtrlCreateGraphic(50, 5, $graphWidth,$graphHeight)
    GUICtrlSetBkColor(-1,$graphBGColor)
    GUICtrlSetColor (-1, $graphBorderColor)

    ;Draw grid lines at specified interval (skip first and last): Y
    For $X = 1 to $graphGridYInterval - 1
        GUICtrlSetGraphic(-1,$GUI_GR_MOVE, 0,$graphHeight * ($X / $graphGridYInterval))
        GUICtrlSetGraphic(-1,$GUI_GR_LINE,$graphWidth, $graphHeight * ($X / $graphGridYInterval))
    Next
    
    ;Draw grid lines at specified interval (skip first and last): X
    For $X = 1 to $graphGridXInterval - 1
        GUICtrlSetGraphic(-1,$GUI_GR_MOVE, $graphWidth * ($X / $graphGridXInterval),0)
        GUICtrlSetGraphic(-1,$GUI_GR_LINE,$graphWidth * ($X / $graphGridXInterval), $graphHeight)
    Next

    ;Set line color
    GUICtrlSetGraphic(-1,$GUI_GR_COLOR, $graphLineColor1)

    ;Define starting point
    GUICtrlSetGraphic(-1,$GUI_GR_MOVE, 0,$graphMaxY)

    ;Draw line 1
    For $X = 0 to Ubound($xyArray) - 1
        ;$AsPercent = ($xyArray[$X][1] / $graphMaxY) * 100
                 
        ;Convert input value (relative %) into absolute pixel value
        $tempX = ($graphWidth / $graphMaxX) * $xyArray[$X][0]
        
        ;Reflect Y value
        $tempY = $graphHeight - (($graphHeight / $graphMaxY) * $xyArray[$X][1])
        
        GUICtrlSetGraphic(-1,$GUI_GR_LINE,$tempX,$tempY)
        $graphSumLine1 += $xyArray[$X][1]
    Next

    ;Set line color
    GUICtrlSetGraphic(-1,$GUI_GR_COLOR, $graphLineColor2)

    ;Define starting point
    GUICtrlSetGraphic(-1,$GUI_GR_MOVE, 0,$graphMaxY)
    
    ;Draw line 2
        
    For $X = 0 to Ubound($xyArray) - 1
        ;$AsPercent = ($xyArray[$X][2] / $graphMaxY) * 100
        
        ;Convert input value (relative %) into absolute pixel value
        $tempX = ($graphWidth / $graphMaxX) * $xyArray[$X][0]
        
        ;Reflect Y value
        $tempY = $graphHeight - (($graphHeight / $graphMaxY) * $xyArray[$X][2])
        
        GUICtrlSetGraphic(-1,$GUI_GR_LINE,$tempX,$tempY)
        $graphSumLine2 += $xyArray[$X][2]
    Next
    
    ;Define Y labels (% cpu usage)
    GUICtrlCreateLabel (StringFormat("%.2f", $graphMaxY) & " ms",  3, 3, 45)
    GUICtrlSetColor ( -1, $graphLabelColor)
    GUICtrlSetFont (-1,8, 600)

    GUICtrlCreateLabel (StringFormat("%.2f", $graphMaxY / 2) & " ms",3, 50, 45)
    GUICtrlSetColor ( -1, $graphLabelColor)
    GUICtrlSetFont (-1,8, 600)

    GUICtrlCreateLabel ("0.00 ms",  3, 95, 45)
    GUICtrlSetColor ( -1, $graphLabelColor)
    GUICtrlSetFont (-1,8, 600)

    ;Define X labels (elapsed time)
    GUICtrlCreateLabel ($graphMinX,  50, 107, 20)
    GUICtrlSetColor ( -1, $graphLabelColor)
    GUICtrlSetFont (-1,8, 600)

    GUICtrlCreateLabel (($graphMaxX + $graphMinX) / 2,  240, 107, 30)
    GUICtrlSetColor ( -1, $graphLabelColor)
    GUICtrlSetFont (-1,8, 600)

    GUICtrlCreateLabel ($graphMaxX,  440, 107, 30)
    GUICtrlSetColor ( -1, $graphLabelColor)
    GUICtrlSetFont (-1,8, 600)
    
    ;Draw average Line 1
    GUICtrlCreateLabel ("Avg Time GetFactorsX:", 10, 140, 190)
    GUICtrlSetColor ( -1, $graphLabelColor)
    GUICtrlSetFont (-1,12, 700)

    GUICtrlCreateLabel (StringFormat("%.2f", $graphSumLine1 / Ubound($xyArray)) & "ms", 200, 140, 170)
    GUICtrlSetColor ( -1, $graphLineColor1)
    GUICtrlSetFont (-1,12, 700)
    
    ;Draw average Line 2
    GUICtrlCreateLabel ("Avg Time GetFactors:", 10, 160, 170)
    GUICtrlSetColor ( -1, $graphLabelColor)
    GUICtrlSetFont (-1,12, 700)

    GUICtrlCreateLabel (StringFormat("%.2f", $graphSumLine2 / Ubound($xyArray)) & "ms", 200, 160, 170)
    GUICtrlSetColor ( -1, $graphLineColor2)
    GUICtrlSetFont (-1,12, 700)
    GUISetState (@SW_SHOW)
     
    Do
        $msg = GUIGetMsg()
    Until $msg = $GUI_EVENT_CLOSE
EndFunc

Func GetFactorsX($num)
    Local $factorArray[1][2]
    $count = 1
   
    ;Loop through every number from 1 to requested number
    For $X = 1 to $num
        If Mod($num, $X) = 0 Then
            Redim $factorArray[$count][2]
            $factorArray[$count-1][0] = $X
            $factorArray[$count-1][1] = true
           
            ;Check if prime
            For $Y = 2 to $X - 1
                ;If the number can be divided by anything other than 1 or itself
                If Mod($X, $Y) = 0 AND $X > 1 Then
                    $factorArray[$count-1][1] = false
                    ExitLoop
                EndIf
            Next

            $count += 1
        EndIf
    Next
   
    Return $factorArray
EndFunc

func GetFactors($num)
    ; Return an array with all factors of a given number.
    ; NOTE: This function will fail (not return the smallest factors) for
    ; numbers that is dividable by primes bigger than 997.
    ; To solve that we could increase the prime table or let the function
    ; calculate the primes needed if it reache a undetermined situation
    ;SOURCE PRIMES: [url="http://en.wikipedia.org/wiki/List_of_prime...0_prime_numbers"]http://en.wikipedia.org/wiki/List_of_prime...0_prime_numbers[/url]
    Local $primes = "2 ,3 ,5, 7 ,11 ,13 ,17 ,19 ,23 ,29 ," & _
    "31 ,37 ,41 ,43 ,47 ,53 ,59 ,61 ,67 ,71 ," & _
    "73 ,79 ,83 ,89 ,97 ,101 ,103 ,107 ,109 ,113 ," & _
    "127 ,131 ,137 ,139 ,149 ,151 ,157 ,163 ,167 ,173 ," & _
    "179 ,181 ,191 ,193 ,197 ,199 ,211 ,223 ,227 ,229 ," & _
    "233 ,239 ,241 ,251 ,257 ,263 ,269 ,271 ,277 ,281 ," & _
    "283 ,293 ,307 ,311 ,313 ,317 ,331 ,337 ,347 ,349 ," & _
    "353 ,359 ,367 ,373 ,379 ,383 ,389 ,397 ,401 ,409 ," & _
    "419 ,421 ,431 ,433 ,439 ,443 ,449 ,457 ,461 ,463 ," & _
    "467 ,479 ,487 ,491 ,499 ,503 ,509 ,521 ,523 ,541 ," & _
    "547 ,557 ,563 ,569 ,571 ,577 ,587 ,593 ,599 ,601 ," & _
    "607 ,613 ,617 ,619 ,631 ,641 ,643 ,647 ,653 ,659 ," & _
    "661 ,673 ,677 ,683 ,691 ,701 ,709 ,719 ,727 ,733 ," & _
    "739 ,743 ,751 ,757 ,761 ,769 ,773 ,787 ,797 ,809 ," & _
    "811 ,821 ,823 ,827 ,829 ,839 ,853 ,857 ,859 ,863 ," & _
    "877 ,881 ,883 ,887 ,907 ,911 ,919 ,929 ,937 ,941 ," & _
    "947 ,953 ,967 ,971 ,977 ,983 ,991 ,997"
    $primes = StringSplit($primes, " ,")

    ;Local $primes = StringSplit("2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113",",")
    ; Calculate the factors in $num
    Local $size = 10
    Local $factors[$size]
    $factors[0] = 0
    Local $pos = 1

    While $pos <=$primes[0] AND $num > 1
        If mod($num, $primes[$pos]) = 0 Then
            $factors[0] += 1
            If $size -1 < $factors[0] Then ReDim $factors[$factors[0] + 10]
            $factors[$factors[0]] = $primes[$pos]
            $num = $num/$primes[$pos]
            ; Do not change $pos as we might want the same prime again!
        Else
            $pos += 1
        EndIf
    WEnd
    If $num > 1 then
            $factors[0] += 1
            If $size -1 < $factors[0] Then ReDim $factors[$factors[0] + 10]
            $factors[$factors[0]] = $num
    EndIf
    Return $factors
endfunc
Edited by weaponx
Link to comment
Share on other sites

  • 1 month later...

Nice stuff, WeaponX. Came across this while looking to see if I should bother to post my _Factor() UDF.

Your cool graphing code tweaked with my _Factor() function:

#cs ----------------------------------------------------------------------------
    
    AutoIt Version: 3.2.8.1
    Author:        WeaponX
    
    Script Function:
    Steam style graph generator, this version customized to compare number factoring
    
    Edited by PsaltyDS to use _Factor() as one of the tested functions
    
#ce ----------------------------------------------------------------------------
#include <array.au3>
#include <GUIConstants.au3>

$theArray = randomStatsToArray()
;_ArrayDisplay($theArray)

GraphX($theArray, "Factor speed comparison")

;Return 2D Array of CPU / RAM usage per process
;[0] = Number to be factored
;[1] = _Factor (in ms) ; from PsaltyDS
;[2] = GetFactors (in ms)
Func randomStatsToArray()
    Local $points[1][3]

    ;Poll Frequency in milliseconds
    ;Local $PollFrequency = 100

    ;Number of times to execute poll
    Local $PollCount = 1000

    For $X = 1 To $PollCount
        If $X > 1 Then
            ReDim $points[$X][3]
        EndIf

        ;Store seconds elapsed
        $points[$X - 1][0] = $X

        ;Store elapsed time to find factors of $X using _Factor() from PsaltyDS
        $timestamp = TimerInit()
        $theArray = _Factor($X)
        $points[$X - 1][1] = TimerDiff($timestamp)

        ;Store elapsed time to find factors of $X using GetFactors()
        $timestamp = TimerInit()
        $theArray = GetFactors($X)
        $points[$X - 1][2] = TimerDiff($timestamp)
    Next

    Return $points
EndFunc   ;==>randomStatsToArray

;GraphX
Func GraphX(ByRef $xyArray, $graphTitle = "")
    ;Define colors
    Local $graphBGColor = 0x242529
    Local $graphBorderColor = 0x000000
    Local $graphLabelColor = 0x787878

    Const $graphMinX = 0
    Local $graphMaxX = 0

    ;Determine highest X value
    For $X = 0 To UBound($xyArray) - 1
        If $xyArray[$X][0] > $graphMaxX Then
            $graphMaxX = $xyArray[$X][0]
        EndIf
    Next

    Local $graphMinY = 0
    Local $graphMaxY = 0

    ;Determine highest Y value
    For $X = 0 To UBound($xyArray) - 1
        If $xyArray[$X][1] > $graphMaxY Then
            $graphMaxY = $xyArray[$X][1]
        EndIf

        If $xyArray[$X][2] > $graphMaxY Then
            $graphMaxY = $xyArray[$X][2]
        EndIf
    Next

    Const $graphWidth = 400
    Const $graphHeight = 100

    Const $graphLineColor1 = 0xc98d35
    Const $graphLineColor2 = 0x686868

    Const $graphGridXInterval = 4
    Const $graphGridYInterval = 4

    $graphSumLine1 = 0
    $graphSumLine2 = 0

    ;Create Main window
    GUICreate("Graph X: " & $graphTitle, 500, 200, -1)
    GUISetBkColor(0x424242)

    ;GUISetState (@SW_SHOW)

    ;Create the graphic "sandbox" area
    $graphic = GUICtrlCreateGraphic(50, 5, $graphWidth, $graphHeight)
    GUICtrlSetBkColor(-1, $graphBGColor)
    GUICtrlSetColor(-1, $graphBorderColor)

    ;Draw grid lines at specified interval (skip first and last): Y
    For $X = 1 To $graphGridYInterval - 1
        GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 0, $graphHeight * ($X / $graphGridYInterval))
        GUICtrlSetGraphic(-1, $GUI_GR_LINE, $graphWidth, $graphHeight * ($X / $graphGridYInterval))
    Next

    ;Draw grid lines at specified interval (skip first and last): X
    For $X = 1 To $graphGridXInterval - 1
        GUICtrlSetGraphic(-1, $GUI_GR_MOVE, $graphWidth * ($X / $graphGridXInterval), 0)
        GUICtrlSetGraphic(-1, $GUI_GR_LINE, $graphWidth * ($X / $graphGridXInterval), $graphHeight)
    Next

    ;Set line color
    GUICtrlSetGraphic(-1, $GUI_GR_COLOR, $graphLineColor1)

    ;Define starting point
    GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 0, $graphMaxY)

    ;Draw line 1
    For $X = 0 To UBound($xyArray) - 1
        ;$AsPercent = ($xyArray[$X][1] / $graphMaxY) * 100

        ;Convert input value (relative %) into absolute pixel value
        $tempX = ($graphWidth / $graphMaxX) * $xyArray[$X][0]

        ;Reflect Y value
        $tempY = $graphHeight - (($graphHeight / $graphMaxY) * $xyArray[$X][1])

        GUICtrlSetGraphic(-1, $GUI_GR_LINE, $tempX, $tempY)
        $graphSumLine1 += $xyArray[$X][1]
    Next

    ;Set line color
    GUICtrlSetGraphic(-1, $GUI_GR_COLOR, $graphLineColor2)

    ;Define starting point
    GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 0, $graphMaxY)

    ;Draw line 2

    For $X = 0 To UBound($xyArray) - 1
        ;$AsPercent = ($xyArray[$X][2] / $graphMaxY) * 100

        ;Convert input value (relative %) into absolute pixel value
        $tempX = ($graphWidth / $graphMaxX) * $xyArray[$X][0]

        ;Reflect Y value
        $tempY = $graphHeight - (($graphHeight / $graphMaxY) * $xyArray[$X][2])

        GUICtrlSetGraphic(-1, $GUI_GR_LINE, $tempX, $tempY)
        $graphSumLine2 += $xyArray[$X][2]
    Next

    ;Define Y labels (% cpu usage)
    GUICtrlCreateLabel(StringFormat("%.2f", $graphMaxY) & " ms", 3, 3, 45)
    GUICtrlSetColor(-1, $graphLabelColor)
    GUICtrlSetFont(-1, 8, 600)

    GUICtrlCreateLabel(StringFormat("%.2f", $graphMaxY / 2) & " ms", 3, 50, 45)
    GUICtrlSetColor(-1, $graphLabelColor)
    GUICtrlSetFont(-1, 8, 600)

    GUICtrlCreateLabel("0.00 ms", 3, 95, 45)
    GUICtrlSetColor(-1, $graphLabelColor)
    GUICtrlSetFont(-1, 8, 600)

    ;Define X labels (elapsed time)
    GUICtrlCreateLabel($graphMinX, 50, 107, 20)
    GUICtrlSetColor(-1, $graphLabelColor)
    GUICtrlSetFont(-1, 8, 600)

    GUICtrlCreateLabel(($graphMaxX + $graphMinX) / 2, 240, 107, 30)
    GUICtrlSetColor(-1, $graphLabelColor)
    GUICtrlSetFont(-1, 8, 600)

    GUICtrlCreateLabel($graphMaxX, 440, 107, 30)
    GUICtrlSetColor(-1, $graphLabelColor)
    GUICtrlSetFont(-1, 8, 600)

    ;Draw average Line 1
    GUICtrlCreateLabel("Avg Time PsaltyDS's _Factor:", 10, 140, 290)
    GUICtrlSetColor(-1, $graphLabelColor)
    GUICtrlSetFont(-1, 12, 700)

    GUICtrlCreateLabel(StringFormat("%.2f", $graphSumLine1 / UBound($xyArray)) & "ms", 300, 140, 170)
    GUICtrlSetColor(-1, $graphLineColor1)
    GUICtrlSetFont(-1, 12, 700)

    ;Draw average Line 2
    GUICtrlCreateLabel("Avg Time GetFactors:", 10, 160, 290)
    GUICtrlSetColor(-1, $graphLabelColor)
    GUICtrlSetFont(-1, 12, 700)

    GUICtrlCreateLabel(StringFormat("%.2f", $graphSumLine2 / UBound($xyArray)) & "ms", 300, 160, 170)
    GUICtrlSetColor(-1, $graphLineColor2)
    GUICtrlSetFont(-1, 12, 700)
    GUISetState(@SW_SHOW)

    Do
        $msg = GUIGetMsg()
    Until $msg = $GUI_EVENT_CLOSE
EndFunc   ;==>GraphX

Func GetFactors($num)
    ; Return an array with all factors of a given number.
    ; NOTE: This function will fail (not return the smallest factors) for
    ; numbers that is dividable by primes bigger than 997.
    ; To solve that we could increase the prime table or let the function
    ; calculate the primes needed if it reache a undetermined situation
    ;SOURCE PRIMES: http://en.wikipedia.org/wiki/List_of_prime...0_prime_numbers
    Local $primes = "2 ,3 ,5, 7 ,11 ,13 ,17 ,19 ,23 ,29 ," & _
            "31 ,37 ,41 ,43 ,47 ,53 ,59 ,61 ,67 ,71 ," & _
            "73 ,79 ,83 ,89 ,97 ,101 ,103 ,107 ,109 ,113 ," & _
            "127 ,131 ,137 ,139 ,149 ,151 ,157 ,163 ,167 ,173 ," & _
            "179 ,181 ,191 ,193 ,197 ,199 ,211 ,223 ,227 ,229 ," & _
            "233 ,239 ,241 ,251 ,257 ,263 ,269 ,271 ,277 ,281 ," & _
            "283 ,293 ,307 ,311 ,313 ,317 ,331 ,337 ,347 ,349 ," & _
            "353 ,359 ,367 ,373 ,379 ,383 ,389 ,397 ,401 ,409 ," & _
            "419 ,421 ,431 ,433 ,439 ,443 ,449 ,457 ,461 ,463 ," & _
            "467 ,479 ,487 ,491 ,499 ,503 ,509 ,521 ,523 ,541 ," & _
            "547 ,557 ,563 ,569 ,571 ,577 ,587 ,593 ,599 ,601 ," & _
            "607 ,613 ,617 ,619 ,631 ,641 ,643 ,647 ,653 ,659 ," & _
            "661 ,673 ,677 ,683 ,691 ,701 ,709 ,719 ,727 ,733 ," & _
            "739 ,743 ,751 ,757 ,761 ,769 ,773 ,787 ,797 ,809 ," & _
            "811 ,821 ,823 ,827 ,829 ,839 ,853 ,857 ,859 ,863 ," & _
            "877 ,881 ,883 ,887 ,907 ,911 ,919 ,929 ,937 ,941 ," & _
            "947 ,953 ,967 ,971 ,977 ,983 ,991 ,997"
    $primes = StringSplit($primes, " ,")

    ;Local $primes = StringSplit("2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113",",")
    ; Calculate the factors in $num
    Local $size = 10
    Local $factors[$size]
    $factors[0] = 0
    Local $pos = 1

    While $pos <= $primes[0] And $num > 1
        If Mod($num, $primes[$pos]) = 0 Then
            $factors[0] += 1
            If $size - 1 < $factors[0] Then ReDim $factors[$factors[0] + 10]
            $factors[$factors[0]] = $primes[$pos]
            $num = $num / $primes[$pos]
            ; Do not change $pos as we might want the same prime again!
        Else
            $pos += 1
        EndIf
    WEnd
    If $num > 1 Then
        $factors[0] += 1
        If $size - 1 < $factors[0] Then ReDim $factors[$factors[0] + 10]
        $factors[$factors[0]] = $num
    EndIf
    Return $factors
EndFunc   ;==>GetFactors

; ----------------------------------------------------------------------
; Function:         _Factor()
; Purpose:          Return all factors of a signed integer
; Syntax:           _Factor($i)
;   Where:          $i = signed integer value
; Returns:          A 1D array with [0] = count of factors
;   On success:     [1] = 1 or -1 depending on sign of input $i, [2] thru [n] = prime factors
;   On failure:     [0] = 0 and sets @error
; Notes:            Based on the simplest "naive" prime number test, sped up some by inclusion 
;                   of a short prime number table.
;                   The number 1 is not normally given as a prime factor, but is included so 
;                   the function can handle signed/unsigned numbers in a predictable manner.
;                   Element [1] of the array will be 1 or -1 depending on the sign of the input.
;                   Returns @error for non-integer or 0 inputs.
; Author:           PsaltyDS at www.autoitscript.com/forum
; Version: 1.0.0 dated 28 December, 2007
; ----------------------------------------------------------------------
Func _Factor($i)
    Local $avRET[1] = [0]
    Local $iTest, $iWorking, $iOddNum
    
    ; Test for valid input
    If IsInt($i) = 0 Then
        SetError(1)
        Return $avRET
    ElseIf $i = 0 Then
        SetError(2)
        Return $avRET
    EndIf
    
    ; Check for negative number
    Local $avRET[1024] = [1, 1]
    If $i < 0 Then
        $avRET[1] = -1
        $i = $i * - 1
    EndIf
    $iWorking = $i
    
    ; Quick return for input = 1
    If $iWorking = 1 Then
        ReDim $avRET[2]
        Return $avRET
    EndIf
    
    ; Initial table of primes
    Local $avPrimes[201] = [200, _
            2, 3, 5, 7, 11, 13, 17, 19, 23, 29, _
            31, 37, 41, 43, 47, 53, 59, 61, 67, 71, _
            73, 79, 83, 89, 97, 101, 103, 107, 109, 113, _
            127, 131, 137, 139, 149, 151, 157, 163, 167, 173, _
            179, 181, 191, 193, 197, 199, 211, 223, 227, 229, _
            233, 239, 241, 251, 257, 263, 269, 271, 277, 281, _
            283, 293, 307, 311, 313, 317, 331, 337, 347, 349, _
            353, 359, 367, 373, 379, 383, 389, 397, 401, 409, _
            419, 421, 431, 433, 439, 443, 449, 457, 461, 463, _
            467, 479, 487, 491, 499, 503, 509, 521, 523, 541, _
            547, 557, 563, 569, 571, 577, 587, 593, 599, 601, _
            607, 613, 617, 619, 631, 641, 643, 647, 653, 659, _ 
            661, 673, 677, 683, 691, 701, 709, 719, 727, 733, _
            739, 743, 751, 757, 761, 769, 773, 787, 797, 809, _ 
            811, 821, 823, 827, 829, 839, 853, 857, 859, 863, _ 
            877, 881, 883, 887, 907, 911, 919, 929, 937, 941, _ 
            947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, _ 
            1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, _ 
            1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, _
            1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223] 
    
    ; Use static table of primes to start with
    For $p = 1 To $avPrimes[0]
        While 1
            $iTest = Mod($iWorking, $avPrimes[$p])
            If $iTest = 0 Then
                ; This is a factor
                $avRET[0] += 1
                $avRET[$avRET[0]] = $avPrimes[$p]
                $iWorking = $iWorking / $avPrimes[$p]
                If $iWorking = 1 Then
                    ; Last factor found
                    ExitLoop 2
                Else
                    ; Try same prime again
                    ContinueLoop
                EndIf
            Else
                ; This is not a factor, next prime
                ExitLoop
            EndIf
        WEnd
    Next

    ; Continue if remaining factors are larger than the static primes
    If $iWorking > $avPrimes[$avPrimes[0]] Then
        $iOddNum = $avPrimes[$avPrimes[0]] + 2
        While 1
            While 1
                $iTest = Mod($iWorking, $iOddNum)
                If $iTest = 0 Then
                    ; This is a factor
                    $avRET[0] += 1
                    $avRET[$avRET[0]] = $iOddNum
                    $iWorking = $iWorking / $iOddNum
                    If $iWorking = 1 Then
                        ; Last factor found
                        ExitLoop 2
                    Else
                        ; Try same odd number again
                        ContinueLoop
                    EndIf
                Else
                    ; This not a factor, next odd number
                    ExitLoop
                EndIf
            WEnd
            $iOddNum += 2
            If $iOddNum > Int(Sqrt($i)) Then
                ; Remaining number is prime = last factor
                $avRET[0] += 1
                $avRET[$avRET[0]] = $iWorking
                ExitLoop
            EndIf
        WEnd
    EndIf
    
    ; Resize the array and return
    ReDim $avRET[$avRET[0] + 1]
    Return $avRET
EndFunc   ;==>_Factor

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

The reason that the iterative solution is so much faster is because it only computes the fib numbers once. In the recursive method you calculate the same fib numbers many times over. The structure of the function calls can be seen in the diagram I stole of the net (follow the base url for the original page).

Posted Image

It can be seen that fib(4) is calculated twice, fib(3) is calculated 3 times and fib(2) is calculated 5 times. These redundant calls become increasing more problematic as you attempt to calculate larger fib numbers.

In terms of big-oh notation, the recursive solution has O(2^n) where the iterative solution has O(n).

These are discussed here http://www.ecf.toronto.edu/apsc/courses/ec...-complexity.pdf

Algorithm complexity analysis is a useful and fun (at least I think so) thing to play around with.

If I get around to it I will port some simple number theoretic functions to autoit that I coded for class last semester.

i.e. tau, phi, sigma, mobius functions... along with a solver for Ax+By=C where A,B,C are integers and the GCD(A,B) | C

BTW, nice graphing function.

Edited by Wus
Link to comment
Share on other sites

I made some math UDF's too. I never shared because I think they are not really useful. Still, fun making.

Func Fibonacci($n)
   Dim $array[3] = [0,0,1]
   If Not IsInt($n) Then Return -1
   If $n < 0 Then Return -1
   If $n < 2 Then Return $n
   For $i = 1 To $n
      $array[0] = $array[1] + $array[2]
      $array[2] = $array[1]
      $array[1] = $array[0]
   Next
   Return $array[0]
EndFuncoÝ÷ Ø¢aj÷­¶¨¶«²Û|ý½ëzr%G¢)à²Û~X¤zØb³ú®¢×+¢é]mç¯zwڲ׫Â+a¢ëmæ«­¬«y÷«zw°Z+{¦¦WºÚ"µÍ[ÈXÛXØÚJ ÌÍÛB[H   ÌÍÛ][L   ÌÍÛOL    ÌÍÛLK    ÌÍÒBYÝÒ[
    ÌÍÛH[]LB[ÙRY    ÌÍÛ  È[]LB[ÙRY ÌÍÛ  È[ÈHÈÈHHÈK]    ÌÍÛ[ÙBÜ    ÌÍÒHHÈ  ÌÍÛ  ÌÍÛ][H   ÌÍÛH
È  ÌÍÛ  ÌÍÛHH    ÌÍÛ  ÌÍÛH ÌÍÛ][^[Y]    ÌÍÛ][[[

The performance hit here just switching from arrays to regular variables will probably not be noticed on a modern computer (speed in excess of 2 GHz) until the numbers are quite large.

David Nuttall
Nuttall Computer Consulting

An Aquarius born during the Age of Aquarius

AutoIt allows me to re-invent the wheel so much faster.

I'm off to write a wizard, a wonderful wizard of odd...

Link to comment
Share on other sites

Autoit is rather lame (slow) for this kind of algorithms. And my implementation is probably (certainly) not optimized. The C versions are like 1000 times faster, so now you are warned..:P

Func GetProperPositiveDivisors($num)
    Local $a[10]
    $a[0] = 0
    For $i = 1 to Floor($num/2)
        If mod($num, $i) = 0 Then 
            $a[0] += 1
            If $a[0] > Ubound($a) -1 Then ReDim $a[$a[0] + 10]
            $a[$a[0]] = $i
        EndIf
    next
    $a[0] += 1
    If $a[0] > Ubound($a) -1 Then ReDim $a[$a[0] + 10]
    $a[$a[0]] = $num
    ReDim $a[$a[0] + 1]
    Return $a
EndFunc
Func IsPerfectNumber($num)
    Local $res
    Local $a = GetProperPositiveDivisors($num)
    For $i = 1 to $a[0]
        If $a[$i] < $num Then $res += $a[$i]
    next
    ;ConsoleWrite("IsPerfectNumber[$num:=" & $num & ", $res:=" & $res & "]:=" & ($num = $res) & @crlf)
    return ($num = $res)
EndFunc
func factorsDump(ByRef $a, $head="", $tail= "")
    if $head = "" Then 
        ConsoleWrite("Factors( count:=" & $a[0] & ") : ")
    Else
        ConsoleWrite($head)
    EndIf
    for $i = 1 to $a[0]
        ConsoleWrite($a[$i] & ", ")
    Next
    ConsoleWrite(@CRLF)
EndFunc

func GetFactors($num)
    ; Return an array with all factors of a given number.
    ; NOTE: This function will fail (not return the smallest factors) for 
    ; numbers that is dividable by primes bigger than 997.
    ; To solve that we could increase the prime table or let the function 
    ; calculate the primes needed if it reache a undetermined situation
    ;SOURCE PRIMES: http://en.wikipedia.org/wiki/List_of_prime_numbers#The_first_500_prime_numbers
    Local $primes = "2 ,3 ,5, 7 ,11 ,13 ,17 ,19 ,23 ,29 ," & _
    "31 ,37 ,41 ,43 ,47 ,53 ,59 ,61 ,67 ,71 ," & _
    "73 ,79 ,83 ,89 ,97 ,101 ,103 ,107 ,109 ,113 ," & _
    "127 ,131 ,137 ,139 ,149 ,151 ,157 ,163 ,167 ,173 ," & _
    "179 ,181 ,191 ,193 ,197 ,199 ,211 ,223 ,227 ,229 ," & _
    "233 ,239 ,241 ,251 ,257 ,263 ,269 ,271 ,277 ,281 ," & _
    "283 ,293 ,307 ,311 ,313 ,317 ,331 ,337 ,347 ,349 ," & _
    "353 ,359 ,367 ,373 ,379 ,383 ,389 ,397 ,401 ,409 ," & _
    "419 ,421 ,431 ,433 ,439 ,443 ,449 ,457 ,461 ,463 ," & _
    "467 ,479 ,487 ,491 ,499 ,503 ,509 ,521 ,523 ,541 ," & _
    "547 ,557 ,563 ,569 ,571 ,577 ,587 ,593 ,599 ,601 ," & _
    "607 ,613 ,617 ,619 ,631 ,641 ,643 ,647 ,653 ,659 ," & _
    "661 ,673 ,677 ,683 ,691 ,701 ,709 ,719 ,727 ,733 ," & _
    "739 ,743 ,751 ,757 ,761 ,769 ,773 ,787 ,797 ,809 ," & _
    "811 ,821 ,823 ,827 ,829 ,839 ,853 ,857 ,859 ,863 ," & _
    "877 ,881 ,883 ,887 ,907 ,911 ,919 ,929 ,937 ,941 ," & _
    "947 ,953 ,967 ,971 ,977 ,983 ,991 ,997"
    $primes = StringSplit($primes, " ,")

    ;Local $primes = StringSplit("2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113",",")
    ; Calculate the factors in $num
    Local $size = 10
    Local $factors[$size]
    $factors[0] = 0
    Local $pos = 1

    While $pos <=$primes[0] AND $num > 1
        If mod($num, $primes[$pos]) = 0 Then 
            $factors[0] += 1
            If $size -1 < $factors[0] Then ReDim $factors[$factors[0] + 10]
            $factors[$factors[0]] = $primes[$pos]
            $num = $num/$primes[$pos]
            ; Do not change $pos as we might want the same prime again!
        Else
            $pos += 1
        EndIf
    WEnd
    If $num > 1 then 
            $factors[0] += 1
            If $size -1 < $factors[0] Then ReDim $factors[$factors[0] + 10]
            $factors[$factors[0]] = $num
    EndIf
    Return $factors
endfunc

EDIT: Something funny was inserted at the bottom of my code. Looked like binary stuff? Thanks to nahuel for pointing it out..:)

oks o ive posted my code!... its not very good scripting tho.. very noobish

Thank
Link to comment
Share on other sites

  • 3 months later...

Here is my first attemp:

greatest common factor of 2 random numbers

Do

$x = Random(1,500,1)

$y = Random(1,500,1)

Until $x < $y

While $y/$x > Floor($y/$x)

$newx = $x

$x = $y-$x*Floor($y/$x)

$y = $newx

WEnd

$gcf = $x

MsgBox("","GCF","The GCF of "&$x& " and "& $y& " is "&$x)

Link to comment
Share on other sites

  • 1 month later...

What about some BaseX -> BaseX converters?

i.e. Base10 to Base6

I've got BaseX to Base10 working ...

Func _BaseXToBase10($dNum, $X)
    If IsNumber($dNum) <> 1 Then Return $dNum
    If $X < 1 Or $X > 10 Then Return $dNum
    
    $dNum = __StringReverse($dNum)
    Local $nNum, $Split = StringSplit($dNum, ''), $b = 0
    
    For $i = 1 To $Split[0]
        $nNum += $Split[$i] * ($X^$B)
        $b += 1
    Next
    
    Return $nNum
EndFunc

Func __StringReverse($String, $fProg = False) ;Optimised by Siao
    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(Abs(($Percent / $Split[0]) * 100), "")
        Next
        ProgressOff()
    Else
        For $i = $Split[0] To 1 Step -1
            $ReturnString &= $Split[$i]
        Next
    EndIf

    Return $ReturnString
EndFunc   ;==>__StringReverseoÝ÷ Ø   Ýfëmx¶¶Ø§¬{]- ¬y|(®H§;¬¶wu©b¶Ù^éi~,b­ºz«y¦èº×(÷«¶)à~º&«×Kh«æØ^¦¸§r*ez+-ëçè­©em«²éÝz½tº¹

And a BaseX -> BaseX function could utilise both of these functions (once Base10 -> BaseX is fixed)

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

Link to comment
Share on other sites

Tried to edit my old post, weird characters kept on popping up :|

Ok, this is the fixed _Base10ToBaseX func

Func _Base10ToBaseX($dNum, $X)
    If IsNumber($dNum) <> 1 Then Return $dNum
    If $X < 2 Or $X > 9 Then Return $dNum
    
    Local $_Num = $dNum, $nNum, $Remainder, $Dump
    
    While $_Num > 0
        $Remainder = Mod($_Num, $X)
        $_Num = Int($_Num/$X)
        $nNum &= $Remainder
    WEnd
    
    Return __StringReverse($nNum)
EndFunc

p.s. You need the __StringReverse function from the prior post :)

*EDIT*

Oh, i suppose you guys need some examples and an explanation :P

basically, what these functions do is convert any number from BaseX To Base10 and vice versa (provided that X is not less than 2, nor more than 9)

Examples:

ConsoleWrite(_Base10ToBaseX(83, 5) & @TAB & _BaseXToBase10(313, 5) & @LF)

*SECOND EDIT*

By BaseX, i'm referring to any base between 2 (binary) and 10 (counting system used currently)

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

Link to comment
Share on other sites

  • 7 months later...

Sorry for an old topic, but I think it's good to add more functions :)

nth Term for an array of numbers:

Local $terms[3] = [10, 20, 30]

ConsoleWrite(nthTerm($terms, 10) & @CRLF)

Func nthTerm($mix, $term)
    If Not IsArray($mix) Then
        SetError(1)
    Else
        Return $mix[0] + ($term - 1) * ($mix[1] - $mix[0])
    EndIf
EndFunc
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...