Uten Posted November 21, 2007 Author Posted November 21, 2007 Thanks a lot Uten! I managed to use Notepadd ++ to edit and TCC to compile 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..( Please keep your sig. small! Use the help file. Search the forum. Then ask unresolved questions :) Script plugin demo, Simple Trace udf, TrayMenuEx udf, IOChatter demo, freebasic multithreaded dll sample, PostMessage, Aspell, Code profiling
weaponx Posted November 22, 2007 Posted November 22, 2007 I'm attempting to graph a comparison of the 2 functions because sometimes mine is faster, sometimes yours is. Very curious.
Nahuel Posted November 22, 2007 Posted November 22, 2007 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 :">
weaponx Posted November 22, 2007 Posted November 22, 2007 (edited) Alright fellas check this out.I'm out of attachment space so I'm posting the code here, no udf's or external includes are needed.expandcollapse popup#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 February 15, 2008 by weaponx
Nahuel Posted November 22, 2007 Posted November 22, 2007 Wow! That's awesome weaponx! I think you should use another color for the second graph, though. Gray is kinda.. confusing
PsaltyDS Posted December 28, 2007 Posted December 28, 2007 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: expandcollapse popup#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
Wus Posted December 28, 2007 Posted December 28, 2007 (edited) 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).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.pdfAlgorithm 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, | CBTW, nice graphing function. Edited December 28, 2007 by Wus
Nutster Posted December 29, 2007 Posted December 29, 2007 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 NuttallNuttall 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...
zxzxzx Posted December 29, 2007 Posted December 29, 2007 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.. expandcollapse popupFunc 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 noobishThank
greggklein Posted April 27, 2008 Posted April 27, 2008 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)
SxyfrG Posted June 12, 2008 Posted June 12, 2008 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
SxyfrG Posted June 12, 2008 Posted June 12, 2008 (edited) 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 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 June 13, 2008 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
James Posted January 30, 2009 Posted January 30, 2009 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 Blog - Seriously epic web hosting - Twitter - GitHub - Cachet HQ
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now