Jump to content

I want to find the lowest number in Array


Recommended Posts

Use _ArrayMax to find the highest number.

#include <Array.au3>

Local $aArray[7] = [ -23, -17, 0, 7, 25, 31, 53 ]
Local $iHighestNumber = _ArrayMax($aArray, 1)

ConsoleWrite('Highest Number: ' & $iHighestNumber & @CRLF)

Once you have the highest number, loop through the array and check if each array element is greater than zero and less than the highest number.

#include <Array.au3>

Local $aArray[7] = [ -23, -17, 0, 7, 25, 31, 53 ]
Local $iHighestNumber = _ArrayMax($aArray, 1)
Local $iLowestNumber = $iHighestNumber

For $i = 0 To (UBound($aArray) - 1) Step 1
    If $aArray[$i] > 0 And _
       $aArray[$i] < $iLowestNumber Then
        If $aArray[$i] = 1 Then
            $iLowestNumber = 1
            ExitLoop
        EndIf
        $iLowestNumber = $aArray[$i]
    EndIf
Next

ConsoleWrite('Lowest Number: ' & $iLowestNumber & @CRLF)

You could set $iHighestNumber to a really high number rather than using _ArrayMax, assuming the number you enter will always be higher than any number in $aArray.

Link to post
Share on other sites

As @mikell suggested, you can make it fool-proof by using this (in case you are using very large number or all numbers are negative) :

Local $a[7] = [-23, -17, 0, 7, 25, 31, 53]
$min = -1
For $i = 0 to UBound($a)-1
    If $a[$i] > 0 Then $min = $min < 0 ? $a[$i] : ($a[$i] < $min ? $a[$i] : $min)
Next
Msgbox(0,"", $min < 0 ? "Not found" : $min)

 

Link to post
Share on other sites

A slightly more elegant way (and for large arrays, faster than sorting):

#include <Array.au3>

Global $aArray[7] = [ -23, -17, 0, 7, 25, 31, 53 ]

$structIN=dllstructcreate("align 4; int")
$structOUT=dllstructcreate("uint", DllStructGetPtr($structIN))

For $rc=0 To UBound($aArray)-1
    DllStructSetData($structIN,1,$aArray[$rc] - 1)
    $aArray[$rc]=1 + DllStructGetData($structOUT,1)
Next

ConsoleWrite('Lowest Number: ' &  _ArrayMin($aArray, 1) & @CRLF)

NB of course this would fail for values >= 2GB (in which case you'd use int64/uint64 instead.

EDIT: obviously, the above is not speed-optimised, it merely illustrated how the signed/unsigned distinction can be exploited here (so ArrayMin can work), and although the above array operation is reversible, the following snippet is faster than my first example and leaves the array intact (unlike sort):

#include <Math.au3>
Global $aArray[7] = [ -23, -17, 0, 7, 25, 31, 53 ]

$structIN=dllstructcreate("align 4; int")
$structOUT=dllstructcreate("uint", DllStructGetPtr($structIN))

$min=0x7fffffff
For $rc=0 To UBound($aArray)-1
    DllStructSetData($structIN,1,$aArray[$rc] - 1)
    $min = _Min(1 + DllStructGetData($structOUT,1),$min)
Next
ConsoleWrite("Lowest positive value: " & $min)

 

Edited by RTFC
Link to post
Share on other sites
  • Is it homework? Whats the bigger context
  • Can your arrays be bigger?
  • Do you need speed?
  • Is your array precoded or coming from a file or database?

 

  • You could
    • sort first
    • run 1/n the size of the array in steps of n and add more compares in the same loop (probably not faster)
    • ....
  • You cannot run in parallel in AutoIt (you could however embed C#)
Link to post
Share on other sites

 

10 hours ago, RTFC said:

A slightly more elegant way (and for large arrays, faster than sorting):

 

_ArraySort is pretty well optimized.  If speed is the issue it could very easily be found in one pass.  

#include <Array.au3>

Global $aArray[7] = [ -23, -17, 0, 7, 25, 31, 53 ]

$min=0xfffffff

for $i in $aArray
    $min=(($i<$min) and ($i>0)) ? $i : $min
Next

ConsoleWrite($min)

If sort is always too expensive to use then...using autoit is too expensive.  I may have bungled the ternary I don't have a editor in front of me.   

Edited by markyrocks
Link to post
Share on other sites

That is all very cute assumptions.  With and without elegance :

#include <Array.au3>

Global $array[200000]
GenerateArray($array)

Local $hTimer = TimerInit()
Example1()
ConsoleWrite("#1 = " & TimerDiff($hTimer) & @CRLF)
Local $hTimer = TimerInit()
Example2()
ConsoleWrite("#2 = " & TimerDiff($hTimer) & @CRLF)

Func Example1()
  $structIN = DllStructCreate("align 4; int")
  $structOUT = DllStructCreate("uint", DllStructGetPtr($structIN))

  For $rc = 0 To UBound($array) - 1
    DllStructSetData($structIN, 1, $array[$rc] - 1)
    $array[$rc] = 1 + DllStructGetData($structOUT, 1)
  Next

  ConsoleWrite('Lowest #1 = ' & _ArrayMin($array, 1) & @CRLF)
EndFunc   ;==>Example1

Func Example2()
  $min = -1
  For $i = 0 To UBound($array) - 1
    If $array[$i] > 0 Then $min = $min < 0 ? $array[$i] : ($array[$i] < $min ? $array[$i] : $min)
  Next
  ConsoleWrite("Lowest #2 = " & $min & @CRLF)
EndFunc   ;==>Example2

Func GenerateArray(ByRef $a)
  For $i = 0 To UBound($a) - 1
    $a[$i] = Random(-1000000, +1000000, 1)
  Next
EndFunc   ;==>GenerateArray

Guess what would be faster ;)

Link to post
Share on other sites
1 hour ago, Nine said:

That is all very cute assumptions.  With and without elegance :

Guess what would be faster ;)

I like this game its called I win.  gawd I had no idea what a dog these array udf functions were.... maybe your results will vary but as far as i can tell #3 is the winner...  I'm not sure how this array min function can be such a ball and chain .  

#include <Array.au3>

Global $array[200000]
GenerateArray($array)

Local $hTimer = TimerInit()
Example1()
ConsoleWrite("#1 = " & TimerDiff($hTimer) & @CRLF)
Local $hTimer = TimerInit()
Example2()
ConsoleWrite("#2 = " & TimerDiff($hTimer) & @CRLF)
Local $hTimer = TimerInit()
Example3()
ConsoleWrite("#3 = " & TimerDiff($hTimer) & @CRLF)
Local $hTimer = TimerInit()
Example5()
ConsoleWrite("#5 = " & TimerDiff($hTimer) & @CRLF)

Func Example1()
  $structIN = DllStructCreate("align 4; int")
  $structOUT = DllStructCreate("uint", DllStructGetPtr($structIN))

  For $rc = 0 To UBound($array) - 1
    DllStructSetData($structIN, 1, $array[$rc] - 1)
    $array[$rc] = 1 + DllStructGetData($structOUT, 1)
  Next

  ConsoleWrite('Lowest #1 = ' & _ArrayMin($array, 1) & @CRLF)
EndFunc   ;==>Example1

Func Example2()
  $min = -1
  For $i = 0 To UBound($array) - 1
    If $array[$i] > 0 Then $min = $min < 0 ? $array[$i] : ($array[$i] < $min ? $array[$i] : $min)
  Next
  ConsoleWrite("Lowest #2 = " & $min & @CRLF)
EndFunc   ;==>Example2

Func GenerateArray(ByRef $a)
  For $i = 0 To UBound($a) - 1
    $a[$i] = Random(-1000000, +1000000, 1)
  Next
EndFunc   ;==>GenerateArray

Func Example3()

$min=0xfffffff

for $i in $array
    $min=(($i<$min) and ($i>0)) ? $i : $min
Next

ConsoleWrite("lowest #3 = " & $min & @CRLF)
    EndFunc

func Example4()
    _ArraySort($array)
    for $i in $array
        if $i>0 then
            ConsoleWrite("lowest #4 = " & $i & @CRLF)
            ExitLoop
        EndIf
    Next
EndFunc

func Example5()
    for $i in $array
        $i = $i < 0 ? not $i : $i
    Next
    ConsoleWrite("lowest #5 = " & _ArrayMin($array) & @CRLF)

EndFunc

 

the difference between these 2 is like 10 seconds.... 

func Example5()
    $min=0xfffffff
    for $i in $array
        $i = $i < 0 ? not $i : $i
    Next
    for $i in $array  ;loops throught TWICE!!
        $min=$i<$min ? $i : $min
    Next
    ConsoleWrite("lowest #5 = " & $min & @CRLF)
EndFunc
func Example6()
    for $i in $array
        $i = $i < 0 ? not $i : $i
    Next
    ConsoleWrite("lowest #6 = " & _ArrayMin($array) & @CRLF)
EndFunc

 

Edited by markyrocks
Link to post
Share on other sites
1 hour ago, markyrocks said:

I like this game its called I win.

I guess you guys must be all bored with nothing better to do over the Xmas break. I deliberately refrained from supplying a solution to OP as this looked much like a homework question and he can't learn if he doesn't apply himself to the problem in hand.  @mikell's solution is even better that what I would have come up with. I often forget that you can use C's "conditional expression" in AutoIt.

Edited by pseakins
Credited wrong member.

Phil Seakins

Link to post
Share on other sites

total insanity.  a million ints vs 200k in 5% of the time? 3 seconds vs 66....the only word that comes to mind is broken... 

i'll report back in a few min and post a python comparison.  In my defense this is why noone else in the modern broader coding community is afraid to use sort.  

Untitled.png

Link to post
Share on other sites

I used an online compiler to test a couple of these I know that can slightly mess with the results, I'm kinda skeptical of the python result but I tested it in c , c#, c++,  and python.  I just don't have it in me to write it in java... I was actually thinking about the way I imagine the qsort algorithm works...  I might have to play around with that.  

 

Untitled.png

Link to post
Share on other sites

Interesting to see 3 and 6 are competing in speed based on arraysize and number 8 is the winner 😉 so far in this christmas break context 😉 

* Added code so only the fastest examples are run

#include <Array.au3>

Global $array[200000]
GenerateArray($array)
Func GenerateArray(ByRef $a)
  For $i = 0 To UBound($a) - 1
    $a[$i] = Random(-1000000, +1000000, 1)
  Next
EndFunc   ;==>GenerateArray

;~ Just run the examples relevant
for $fName in stringsplit("example3,example6,example7,example8",",",2)
    Local $hTimer = TimerInit()
    call($fName)
    If @error = 0xDEAD And @extended = 0xBEEF Then
        consolewrite($fname & " Function does not exist.")
        exitloop
    EndIf
    ConsoleWrite( "#" & $fName & " = " & TimerDiff($hTimer) & @CRLF)
Next

Func Example1()
  $structIN = DllStructCreate("align 4; int")
  $structOUT = DllStructCreate("uint", DllStructGetPtr($structIN))

  For $rc = 0 To UBound($array) - 1
    DllStructSetData($structIN, 1, $array[$rc] - 1)
    $array[$rc] = 1 + DllStructGetData($structOUT, 1)
  Next
  ConsoleWrite('Lowest #1 = ' & _ArrayMin($array, 1) & @CRLF)
EndFunc   ;==>Example1

Func Example2()
  $min = -1
  For $i = 0 To UBound($array) - 1
    If $array[$i] > 0 Then $min = $min < 0 ? $array[$i] : ($array[$i] < $min ? $array[$i] : $min)
  Next
  ConsoleWrite("Lowest #2 = " & $min & @CRLF)
EndFunc   ;==>Example2

Func Example3()
    $min=0xfffffff
    for $i in $array
        $min=(($i<$min) and ($i>0)) ? $i : $min
    Next
    ConsoleWrite("lowest #3 = " & $min & @CRLF)
EndFunc

func Example4()
    _ArraySort($array)
    for $i in $array
        if $i>0 then
            ConsoleWrite("lowest #4 = " & $i & @CRLF)
            ExitLoop
        EndIf
    Next
EndFunc

func Example5()
    for $i in $array
        $i = $i < 0 ? not $i : $i
    Next
    ConsoleWrite("lowest #5 = " & _ArrayMin($array) & @CRLF)
EndFunc

Func Example6()
  $min = -1
  $uBoundArr=UBound($array) - 1
  For $i = 0 To $uBoundArr
        $min = $array[$i] > 0 ? ($min < 0 ? $array[$i] : ($array[$i] < $min ? $array[$i] : $min)) : $min
  Next
  ConsoleWrite("Lowest #6 = " & $min & @CRLF)
EndFunc   ;==>Example6

Func Example7()
  $min = -1
  $uBoundArr=UBound($array) - 1
  For $i = $uBoundArr to 0 step -1
        $min = $array[$i] > 0 ? ($min < 0 ? $array[$i] : ($array[$i] < $min ? $array[$i] : $min)) : $min
  Next
  ConsoleWrite("Lowest #7 = " & $min & @CRLF)
EndFunc   ;==>Example7

Func Example8()
  $min = 0xfffffff
  $uBoundArr=UBound($array) - 1
  For $i = $uBoundArr to 0 step -1
    $min = $array[$i] > 0 ? ($min > $array[$i] ? $array[$i] : $min) : $min
  next

  ConsoleWrite("Lowest #8 = " & $min & @CRLF)
EndFunc   ;==>Example8

 

Link to post
Share on other sites
8 hours ago, junkew said:

Interesting to see 3 and 6 are competing in speed based on arraysize and number 8 is the winner 😉 so far in this christmas break context 😉 

* Added code so only the fastest examples are run

 

HAHA!! 8 was the winner ... until example9 came along... bazinga

Func Example9()

$min=0xfffffff
for $i in $array
    $min= -$i > 0 ? $min : ($i < $min ? $i : $min )
Next
    ConsoleWrite("Lowest #9 = " & $min & @CRLF)
EndFunc   ;==>Example9

 

edit this is actually a hair faster it seems

Func Example10()

$min=0xfffffff
for $i in $array
    $min= $i < 0 ? $min : ($i < $min ? $i : $min )
Next
    ConsoleWrite("Lowest #10 = " & $min & @CRLF)
EndFunc   ;==>Example9

 

Edited by markyrocks
Link to post
Share on other sites

ok so I'm just going to say this rn bc I know you all will think im full of it but.... I decided to give making a little dll for autoit to play with... and the results are just staggering. I'll post the autoit code with my added example 11 under the hidey thing.  edit.  notice how 9 and 10 ate shit on the run i screenshotted. 

Spoiler
#include <Array.au3>
Global $size = 1000000;<==ONE MILLION
Global $array[$size]
GenerateArray($array)
$struct=GenerateDllStruct()
Func GenerateArray(ByRef $a)
  For $i = 0 To UBound($a) - 1
    $a[$i] = Random(-1000000, +1000000, 1)
  Next
EndFunc   ;==>GenerateArray

func GenerateDllStruct()
 $s=DllStructCreate("int[" & $size & "]")
 For $i=1 to $size
    DllStructSetData($s,1,$array[$i-1],$i)
 Next
 return $s
EndFunc

;~ Just run the examples relevant
for $fName in stringsplit("example3,example6,example7,example8,example9,example10,example11",",",2)
    Local $hTimer = TimerInit()
    call($fName)
    If @error = 0xDEAD And @extended = 0xBEEF Then
        consolewrite($fname & " Function does not exist.")
        exitloop
    EndIf
    ConsoleWrite( "#" & $fName & " = " & TimerDiff($hTimer) & @CRLF)
Next

Func Example1()
  $structIN = DllStructCreate("align 4; int")
  $structOUT = DllStructCreate("uint", DllStructGetPtr($structIN))

  For $rc = 0 To UBound($array) - 1
    DllStructSetData($structIN, 1, $array[$rc] - 1)
    $array[$rc] = 1 + DllStructGetData($structOUT, 1)
  Next
  ConsoleWrite('Lowest #1 = ' & _ArrayMin($array, 1) & @CRLF)
EndFunc   ;==>Example1

Func Example2()
  $min = -1
  For $i = 0 To UBound($array) - 1
    If $array[$i] > 0 Then $min = $min < 0 ? $array[$i] : ($array[$i] < $min ? $array[$i] : $min)
  Next
  ConsoleWrite("Lowest #2 = " & $min & @CRLF)
EndFunc   ;==>Example2

Func Example3()
    $min=0xfffffff
    for $i in $array
        $min=(($i<$min) and ($i>0)) ? $i : $min
    Next
    ConsoleWrite("lowest #3 = " & $min & @CRLF)
EndFunc

func Example4()
    _ArraySort($array)
    for $i in $array
        if $i>0 then
            ConsoleWrite("lowest #4 = " & $i & @CRLF)
            ExitLoop
        EndIf
    Next
EndFunc

func Example5()
    for $i in $array
        $i = $i < 0 ? not $i : $i
    Next
    ConsoleWrite("lowest #5 = " & _ArrayMin($array) & @CRLF)
EndFunc

Func Example6()
  $min = -1
  $uBoundArr=UBound($array) - 1
  For $i = 0 To $uBoundArr
        $min = $array[$i] > 0 ? ($min < 0 ? $array[$i] : ($array[$i] < $min ? $array[$i] : $min)) : $min
  Next
  ConsoleWrite("Lowest #6 = " & $min & @CRLF)
EndFunc   ;==>Example6

Func Example7()
  $min = -1
  $uBoundArr=UBound($array) - 1
  For $i = $uBoundArr to 0 step -1
        $min = $array[$i] > 0 ? ($min < 0 ? $array[$i] : ($array[$i] < $min ? $array[$i] : $min)) : $min
  Next
  ConsoleWrite("Lowest #7 = " & $min & @CRLF)
EndFunc   ;==>Example7

Func Example8()
  $min = 0xfffffff
  $uBoundArr=UBound($array) - 1
  For $i = $uBoundArr to 0 step -1
    $min = $array[$i] > 0 ? ($min > $array[$i] ? $array[$i] : $min) : $min
  next

  ConsoleWrite("Lowest #8 = " & $min & @CRLF)
EndFunc   ;==>Example8

Func Example9()

$min=0xfffffff
for $i in $array
    $min= -$i > 0 ? $min : ($i < $min ? $i : $min )
Next
    ConsoleWrite("Lowest #9 = " & $min & @CRLF)
EndFunc   ;==>Example9

Func Example10()

$min=0xfffffff
for $i in $array
    $min= $i < 1 ? $min : ($i < $min ? $i : $min )
Next
    ConsoleWrite("Lowest #10 = " & $min & @CRLF)
EndFunc   ;==>Example10

Func Example11()
    $dll=DllOpen(@ScriptDir & "\autoitdll.dll")
    if $dll=-1 then Exit
    $result=DllCall($dll,"int:cdecl","_ArrayMinGreaterThanZero","ptr",DllStructGetPtr($struct),"int",$size)
;~  if IsArray($result) then _ArrayDisplay($result)
    ConsoleWrite("Lowest #11 = " & $result[0] & @CRLF)

    EndFunc

 

This screenshot shows how much of disparity there is and I'm fairly confident that I could pretty easily fix the arraysort buisness.  I've offered to help fix things in the past.  It usually doesn't go well.  Anyways. I guess I'll include the file.  

 

Untitled.png

autoitdll.dll

Edited by markyrocks
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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...