Jump to content

# I want to find the lowest number in Array

## Recommended Posts

Hello everyone,

i have an array like this:

aArray = -23, -17, 0, 7, 25, 31, 53

I want to find the lowest number except the negative ones an zero (should be 7)

Any good idea?

Thank you so much!!!

##### Share on other sites

Good question. _ArrayMin() is not going to work, so unless there is another function I am not aware of I think you would have to search the array programmatically. I shouldn't need to show you how to do that, it's simple enough.

Phil Seakins

##### Share on other sites

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.

##### Share on other sites
17 minutes ago, Luke94 said:

You could set \$iHighestNumber to a really high number rather than using _ArrayMax

Much simpler indeed

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

##### 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)```

Not much of a signature but working on it...

Spoiler

##### Share on other sites

You could just sort the array in ascending order and then just return the first number >=0

Edited by markyrocks
##### 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

My Contributions and Wrappers

Spoiler
##### 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#)
##### 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
##### 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

Not much of a signature but working on it...

Spoiler

##### 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
##### 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

##### 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.

##### 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.

##### 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```

##### 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
##### 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.

Edited by markyrocks

## 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.

×

• Wiki

• Back

• #### Beta

• Git
• FAQ
×
• Create New...