1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Mars

Beiträge von Mars

  • Autoit Spiel (Logik)

    • Mars
    • 3. Oktober 2016 um 13:04

    Die Kollisionsberechnung für 1000 Rechtecke geht in konstanter Zeit und dauert genausolang wie die Kollisionserkenung von einem einzigen Rechteck. Nimm eine Bitmap in Spielfeldgröße mit der Farbe 0x00000000, anschließend nummerierst du alle Rechtecke mit 0x00000001, usw usw und zeichnest diese in die Bitmap. Dann kann man per Pixelgetcolor (oder per Dllstruct, wenn man es schnell haben will) innerhalb weniger Takte wissen ob in der Nähe des Balls ein Rechteck ist. Anschließend überprüft man die Vektorkollision (Also die Rechnung für die Bewegung des Balls) nur mit den Rechtecken die in der direkten Umgebung des Balls sind (sollten immer unter 8 Stück sein, sonst wirds unlogisch :D).

  • Autoit Spiel (Logik)

    • Mars
    • 2. Oktober 2016 um 17:28

    Das mit den Strahlen hatte ich irgendwo schonmal ausprobiert. Wenn ich mich nicht irre haben 3 Strahlen ausgereicht, nämlich in Flugrichtung mit den Startpunkten Senkrecht links, senkrecht rechts am Kreis und einer in der Mitte. Da man via Vektorrechnung und ohne "feste" Schritte Arbeitet überprüft man nur ob die Strecken (Bewegungsvektoren) andere Strecken schneiden, und das tun sie unabhängig von der Objektgröße.

    Das Vorgehen bei "korrekter" Kollision ist wie folgt: ("Zeit zwischen den Frames" = T = 1)
    - Man hat z.B. 10 Kugeln.
    - Man überprüft ob es im nächsten Frame überhaupt irgendeine Kollision gibt. Wenn nein -> bewegen, fertig. Wenn ja gehts weiter.
    - Man findet die zeitlich gesehen erste Kollision (zum Zeitpunkt t < T) und berechnet diese. Man bewegt alle Kugeln um ihrem Richtungsvektor mit Faktor dt/T.
    - Man führt den vorherigen Schritt solange aus, bis die zeitlich gesehen nächste Kollision bei einem t > T stattfindet. Dann bewegt man die Kugeln noch das kleine Stück (im Normalfall der Faktor 1 - t) bis T voll ist, und hat den zu berechnenden Frame fertig.

    Edit: Das ist hier nur die Weganleitung, wie man die Kollisionen im Konkreten berechnet kann man woanderst nachlesen :P

  • Größte/Kleinste Elemente aus einem Array wählen

    • Mars
    • 27. September 2016 um 13:27

    Mir graut es bei dieser Vorstellung :D

    AutoIt
    Func SortN(ByRef $a)
    	Local $t
    	Switch UBound($a)
    		Case 2
    			If $a[0] < $a[1] Then
    				$t = $a[0]
    				$a[0] = $a[1]
    				$a[1] = $t
    			EndIf
    		Case 3
    			If $a[0] < $a[1] Then
    				$t = $a[0]
    				$a[0] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[1]
    				$a[1] = $a[2]
    				$a[2] = $t
    			EndIf
    			If $a[0] < $a[1] Then
    				$t = $a[0]
    				$a[0] = $a[1]
    				$a[1] = $t
    			EndIf
    		Case 4
    			If $a[0] < $a[1] Then
    				$t = $a[0]
    				$a[0] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[1]
    				$a[1] = $a[2]
    				$a[2] = $t
    			EndIf
    			If $a[2] < $a[3] Then
    				$t = $a[3]
    				$a[3] = $a[2]
    				$a[2] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[1]
    				$a[1] = $a[2]
    				$a[2] = $t
    			EndIf
    			If $a[0] < $a[1] Then
    				$t = $a[0]
    				$a[0] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[1]
    				$a[1] = $a[2]
    				$a[2] = $t
    			EndIf
    		Case 5
    			If $a[0] < $a[1] Then
    				$t = $a[0]
    				$a[0] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[2]
    				$a[2] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[2] < $a[3] Then
    				$t = $a[2]
    				$a[2] = $a[3]
    				$a[3] = $t
    			EndIf
    			If $a[3] < $a[4] Then
    				$t = $a[4]
    				$a[4] = $a[3]
    				$a[3] = $t
    			EndIf
    			If $a[2] < $a[3] Then
    				$t = $a[2]
    				$a[2] = $a[3]
    				$a[3] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[2]
    				$a[2] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[0] < $a[1] Then
    				$t = $a[0]
    				$a[0] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[2]
    				$a[2] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[2] < $a[3] Then
    				$t = $a[2]
    				$a[2] = $a[3]
    				$a[3] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[2]
    				$a[2] = $a[1]
    				$a[1] = $t
    			EndIf
    		Case 6
    			If $a[0] < $a[1] Then
    				$t = $a[0]
    				$a[0] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[2]
    				$a[2] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[2] < $a[3] Then
    				$t = $a[2]
    				$a[2] = $a[3]
    				$a[3] = $t
    			EndIf
    			If $a[3] < $a[4] Then
    				$t = $a[4]
    				$a[4] = $a[3]
    				$a[3] = $t
    			EndIf
    			If $a[4] < $a[5] Then
    				$t = $a[5]
    				$a[5] = $a[4]
    				$a[4] = $t
    			EndIf
    			If $a[3] < $a[4] Then
    				$t = $a[4]
    				$a[4] = $a[3]
    				$a[3] = $t
    			EndIf
    			If $a[2] < $a[3] Then
    				$t = $a[2]
    				$a[2] = $a[3]
    				$a[3] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[2]
    				$a[2] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[0] < $a[1] Then
    				$t = $a[0]
    				$a[0] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[2]
    				$a[2] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[2] < $a[3] Then
    				$t = $a[2]
    				$a[2] = $a[3]
    				$a[3] = $t
    			EndIf
    			If $a[3] < $a[4] Then
    				$t = $a[4]
    				$a[4] = $a[3]
    				$a[3] = $t
    			EndIf
    			If $a[2] < $a[3] Then
    				$t = $a[2]
    				$a[2] = $a[3]
    				$a[3] = $t
    			EndIf
    			If $a[1] < $a[2] Then
    				$t = $a[2]
    				$a[2] = $a[1]
    				$a[1] = $t
    			EndIf
    			If $a[2] < $a[3] Then
    				$t = $a[2]
    				$a[2] = $a[3]
    				$a[3] = $t
    			EndIf
    	EndSwitch
    EndFunc   ;==>SortN
    Alles anzeigen
    AutoIt
    #include <Array.au3>
    
    
    Global Const $N = 50000
    Global $f_DecimalPlaces = 5
    Global $iT, $f_Overhead, $a_Results[0][3]
    
    
    Global $a_Array[5]
    
    
    
    
    ; determine the overhead of loop [and optional other stuff]
    $iT = TimerInit()
    For $i = 1 To $N
    	For $j = 0 To 4
    		$a_Array[$j] = Random(1, 100, 1)
    	Next
    Next
    $f_Overhead = TimerDiff($iT)
    
    
    
    
    ; the first measurement
    ReDim $a_Results[UBound($a_Results) + 1][3]
    $a_Results[UBound($a_Results) - 1][0] = "_5Sort"
    $iT = TimerInit()
    For $i = 1 To $N
    	For $j = 0 To 4
    		$a_Array[$j] = Random(1, 100, 1)
    	Next
    	_5Sort($a_Array[0], $a_Array[1], $a_Array[2], $a_Array[3], $a_Array[4])
    Next
    $iT = TimerDiff($iT)
    $a_Results[UBound($a_Results) - 1][1] = ($iT - $f_Overhead) / $N
    
    
    ; the first measurement
    ReDim $a_Results[UBound($a_Results) + 1][3]
    $a_Results[UBound($a_Results) - 1][0] = "____5Sort"
    $iT = TimerInit()
    For $i = 1 To $N
    	For $j = 0 To 4
    		$a_Array[$j] = Random(1, 100, 1)
    	Next
    	____5Sort($a_Array[0], $a_Array[1], $a_Array[2], $a_Array[3], $a_Array[4])
    Next
    $iT = TimerDiff($iT)
    $a_Results[UBound($a_Results) - 1][1] = ($iT - $f_Overhead) / $N
    
    
    ; the second measurement
    ReDim $a_Results[UBound($a_Results) + 1][3]
    $a_Results[UBound($a_Results) - 1][0] = "__5Sort"
    $iT = TimerInit()
    For $i = 1 To $N
    	For $j = 0 To 4
    		$a_Array[$j] = Random(1, 100, 1)
    	Next
    	__5Sort($a_Array)
    Next
    $iT = TimerDiff($iT)
    $a_Results[UBound($a_Results) - 1][1] = ($iT - $f_Overhead) / $N
    
    
    ; the third measurement
    ReDim $a_Results[UBound($a_Results) + 1][3]
    $a_Results[UBound($a_Results) - 1][0] = "___5Sort"
    $iT = TimerInit()
    For $i = 1 To $N
    	For $j = 0 To 4
    		$a_Array[$j] = Random(1, 100, 1)
    	Next
    	___5Sort($a_Array)
    Next
    $iT = TimerDiff($iT)
    $a_Results[UBound($a_Results) - 1][1] = ($iT - $f_Overhead) / $N
    
    
    ; the fourth measurement
    ReDim $a_Results[UBound($a_Results) + 1][3]
    $a_Results[UBound($a_Results) - 1][0] = "ISort"
    $iT = TimerInit()
    For $i = 1 To $N
    	For $j = 0 To 4
    		$a_Array[$j] = Random(1, 100, 1)
    	Next
    	_ISort($a_Array)
    Next
    $iT = TimerDiff($iT)
    $a_Results[UBound($a_Results) - 1][1] = ($iT - $f_Overhead) / $N
    
    
    
    
    ; calculate results and print them out
    _ArraySort($a_Results, 0, 0, 0, 1)
    For $i = 0 To UBound($a_Results) - 1
    	$a_Results[$i][2] = Round($a_Results[$i][1] / $a_Results[0][1], 2)
    	$a_Results[$i][1] = Round($a_Results[$i][1], $f_DecimalPlaces)
    Next
    _ArrayDisplay($a_Results, "Measurement Results", "", 16 + 64, Default, "name|time [ms]|factor")
    
    
    
    
    Func _ISort(ByRef $A)
    	Local $t1, $t2
    	For $i = 1 To UBound($A) - 1
    		$t1 = $A[$i]
    		For $j = $i - 1 To 0 Step -1
    			$t2 = $A[$j]
    			If $t1 > $t2 Then ExitLoop
    			$A[$j + 1] = $t2
    		Next
    		$A[$j + 1] = $t1
    	Next
    EndFunc   ;==>_ISort
    
    
    Func ___5Sort(ByRef $A) ; Die ganz einfache Version
    	Local $t
    	If $A[0] > $A[1] Then
    		$t = $A[0]
    		$A[0] = $A[1]
    		$A[1] = $t
    	EndIf
    	If $A[1] > $A[2] Then
    		$t = $A[2]
    		$A[2] = $A[1]
    		$A[1] = $t
    	EndIf
    	If $A[2] > $A[3] Then
    		$t = $A[2]
    		$A[2] = $A[3]
    		$A[3] = $t
    	EndIf
    	If $A[3] > $A[4] Then
    		$t = $A[4]
    		$A[4] = $A[3]
    		$A[3] = $t
    	EndIf
    	If $A[2] > $A[3] Then
    		$t = $A[2]
    		$A[2] = $A[3]
    		$A[3] = $t
    	EndIf
    	If $A[1] > $A[2] Then
    		$t = $A[2]
    		$A[2] = $A[1]
    		$A[1] = $t
    	EndIf
    	If $A[0] > $A[1] Then
    		$t = $A[0]
    		$A[0] = $A[1]
    		$A[1] = $t
    	EndIf
    	If $A[1] > $A[2] Then
    		$t = $A[2]
    		$A[2] = $A[1]
    		$A[1] = $t
    	EndIf
    	If $A[2] > $A[3] Then
    		$t = $A[2]
    		$A[2] = $A[3]
    		$A[3] = $t
    	EndIf
    	If $A[1] > $A[2] Then
    		$t = $A[2]
    		$A[2] = $A[1]
    		$A[1] = $t
    	EndIf
    EndFunc
    
    
    Func ____5Sort(ByRef $1, ByRef $2, ByRef $3, ByRef $4, ByRef $5) ; Die ganz einfache Version
    	Local $t
    	If $1 > $2 Then
    		$t = $1
    		$1 = $2
    		$2 = $t
    	EndIf
    	If $2 > $3 Then
    		$t = $3
    		$3 = $2
    		$2 = $t
    	EndIf
    	If $3 > $4 Then
    		$t = $3
    		$3 = $4
    		$4 = $t
    	EndIf
    	If $4 > $5 Then
    		$t = $5
    		$5 = $4
    		$4 = $t
    	EndIf
    	If $3 > $4 Then
    		$t = $3
    		$3 = $4
    		$4 = $t
    	EndIf
    	If $2 > $3 Then
    		$t = $3
    		$3 = $2
    		$2 = $t
    	EndIf
    	If $1 > $2 Then
    		$t = $1
    		$1 = $2
    		$2 = $t
    	EndIf
    	If $2 > $3 Then
    		$t = $3
    		$3 = $2
    		$2 = $t
    	EndIf
    	If $3 > $4 Then
    		$t = $3
    		$3 = $4
    		$4 = $t
    	EndIf
    	If $2 > $3 Then
    		$t = $3
    		$3 = $2
    		$2 = $t
    	EndIf
    EndFunc
    
    
    ;~ Global $B[] = [3, 1, 2, 5, 4]
    ;~ __5Sort($B)
    ;~ _ArrayDisplay($B)
    Func __5Sort(ByRef $A)
        Local $t
    
    
    	If $A[0] < $A[1] Then ; if a < b:      a, b = b, a
    		$t = $A[1]
    		$A[1] = $A[0]
    		$A[0] = $t
    	EndIf
    	If $A[2] < $A[3] Then ; if c < d:      c, d = d, c
    		$t = $A[2]
    		$A[2] = $A[3]
    		$A[3] = $t
    	EndIf
    	If $A[0] < $A[2] Then ; if a < c:      a, b, c, d = c, d, a, b
    		$t = $A[2]
    		$A[2] = $A[0]
    		$A[0] = $t
    		$t = $A[3]
    		$A[3] = $A[1]
    		$A[1] = $t
    	EndIf
    
    
    	If $A[4] < $A[2] Then ;~    if e < c:
    		If $A[4] > $A[3] Then ; if e > d:  d, e = e, d
    			$t = $A[3]
    			$A[3] = $A[4]
    			$A[4] = $t
    		EndIf
    	ElseIf $A[4] < $A[0] Then ; if e < a:  c, d, e = e, c, d
    		$t = $A[2]
    		$A[2] = $A[4]
    		$A[4] = $A[3]
    		$A[3] = $t
    	Else ;~         else:      a, c, d, e = e, a, c, d
    		$t = $A[0]
    		$A[0] = $A[4]
    		$A[4] = $A[3]
    		$A[3] = $A[2]
    		$A[2] = $t
    	EndIf
    
    
    	If $A[1] < $A[3] Then ; if b < d:
    		If $A[1] < $A[4] Then ; if b < e:  return b, e, d, c, a
    			Local $B[5] = [$A[1], $A[4], $A[3], $A[2], $A[0]]
    			$A = $B
    		Else ; else:      return e, b, d, c, a
    			Local $B[5] = [$A[4], $A[1], $A[3], $A[2], $A[0]]
    			$A = $B
    		EndIf
    	Else
    		If $A[1] < $A[2] Then ; if b < c:  return e, d, b, c, a
    			Local $B[5] = [$A[4], $A[3], $A[1], $A[2], $A[0]]
    			$A = $B
    		Else ; else:      return e, d, c, b, a
    			Local $B[5] = [$A[4], $A[3], $A[2], $A[1], $A[0]]
    			$A = $B
    		EndIf
    	EndIf
    EndFunc   ;==>_5Sort
    
    
    
    
    
    
    ;~ Global $X[] = [5, 3, 4, 2, 1]
    ;~ _5Sort($X[0], $X[1], $X[2], $X[3], $X[4])
    ;~ _ArrayDisplay($X)
    Func _5Sort(ByRef $A, ByRef $B, ByRef $C, ByRef $D, ByRef $E)
        Local $t
    
    
    	If $A < $B Then ; if a < b:      a, b = b, a
    		$t = $B
    		$B = $A
    		$A = $t
    	EndIf
    	If $C < $D Then ; if c < d:      c, d = d, c
    		$t = $C
    		$C = $D
    		$D = $t
    	EndIf
    	If $A < $C Then ; if a < c:      a, b, c, d = c, d, a, b
    		$t = $C
    		$C = $A
    		$A = $t
    		$t = $D
    		$D = $B
    		$B = $t
    	EndIf
    
    
    	If $E < $C Then ;~    if e < c:
    		If $E > $D Then ; if e > d:  d, e = e, d
    			$t = $D
    			$D = $E
    			$E = $t
    		EndIf
    	ElseIf $E < $A Then ; if e < a:  c, d, e = e, c, d
    		$t = $C
    		$C = $E
    		$E = $D
    		$D = $t
    	Else ;~         else:      a, c, d, e = e, a, c, d
    		$t = $A
    		$A = $E
    		$E = $D
    		$D = $C
    		$C = $t
    	EndIf
    
    
    If $B < $D Then ; if b < d:
    		If $B < $E Then ; if b < e:  return b, e, d, c, a
    			$t = $A
    			$A = $B
    			$B = $E
    			$E = $t
    			$t = $C
    			$C = $D
    			$D = $t
    		 Else ; else:      return e, b, d, c, a
    			$t = $A
    			$A = $E
    			$E = $t
    			$t = $C
    			$C = $D
    			$D = $t
    		EndIf
    	 Else
    		If $B < $C Then ; if b < c:  return e, d, b, c, a
    			$t = $A
    			$A = $E
    			$E = $t
    			$t = $B
    			$B = $D
    			$D = $C
    			$C = $t
    		 Else ; else:      return e, d, c, b, a
    			$t= $A
    			$A = $E
    			$E = $t
    			$t = $B
    			$B = $D
    			$D = $t
    		EndIf
    	EndIf
     EndFunc   ;==>_5Sort
    Alles anzeigen

    lg
    M

  • Größte/Kleinste Elemente aus einem Array wählen

    • Mars
    • 26. September 2016 um 17:26

    Ich schaffe es einfach nicht deine Methode zu überbieten...
    Hab jetzt folgendes ausprobiert: Das Gesamtarray in Teilarrays (Größe 5) spalten (im Übertragenen Sinn. In Wirklichkeit gibts nur eine Neuanordnung), diese mit Swapsort (Weil man den für kleine Arrays gut hardcoden kann, sodass man keine Schleifen oder ähnliches hat) sortieren, anschließend nicht in 1er Schritten durch das Array laufen, sondern in 5er Schritten (Wenn man hinten angekommen ist wieder von Vorne starten und ein element versetzt weitermachen).
    Resultat:
    - in den ersten n/5 der Elementen hat man jeweils die größten Elemente aus den 5er Teilarrays.
    - in den zweiten n/5 Elementen hat man jeweils die 2t größten Elemente aus den 5er Teilarrays... usw
    Anschließend kann man eine meiner beiden Alten Methoden (Mars03 und Mars04) über das teilweise vorsortierte Array laufen lassen, die nun wesentlich schneller zum Ergebnis kommen. Insgesamt ist die Sache zwar schneller als meine bisherigen Versuche, aber wesentlich langsamer als die Post17 Methode. Hab aber noch ein paar Ideen auf lager, mal schauen ob da noch was geht^^

  • Größte/Kleinste Elemente aus einem Array wählen

    • Mars
    • 26. September 2016 um 13:54

    AspirinJunkie:
    Die spezielle Methode ist eine Ecke schneller, aber aus Gründen die ich nicht genau finden konnte tauchen im unteren Bereich ab und zu falsche Zahlen auf. Habe ein (hoffentlich möglichst kleines) Beispielskript dazu gebastelt das die Unterschiede zu Quicksort zeigt. Der Fehler tritt nicht immer auf, daher muss das Beispielskript ggf. mehrfach gestartet werden damit andere Zufallszahlen genutzt werden.

    AutoIt
    #include <Array.au3>
    
    
    For $i = 0 To 9 Step 1
    	Test()
    Next
    
    
    Func Test()
    	Local $sDump = ''
    	Local $a = RandomNumbers(10)
    	Local $QS = __Quicksort($a, 5)
    	Local $AS = _ArrayGetNBiggestElements($a, 5)
    
    
    	For $i = 0 To UBound($QS) - 1 Step 1
    		If $QS[$i] <> $AS[$i] Then $sDump &= Hex($i, 8) & '|'
    	Next
    	If $sDump Then $sDump = StringTrimRight($sDump, 1)
    
    
    	If $sDump Then
    		ConsoleWrite(@CRLF & '       Array[' & StringFormat('%3d', UBound($a)) & ']' & @CRLF)
    		For $i = 0 To UBound($a) - 1 Step 1
    			ConsoleWrite('! ' & StringFormat('%.17f', $a[$i]) & @CRLF)
    		Next
    		ConsoleWrite(@CRLF & '     Quicksort[' & StringFormat('%3d', UBound($QS)) & ']   |    Aspirin02[' & StringFormat('%3d', UBound($AS)) & ']' & @CRLF)
    		For $i = 0 To UBound($QS) - 1 Step 1
    			ConsoleWrite((StringInStr($sDump, Hex($i, 8), 0, 1) ? '! ' : '+ ') & StringFormat('%.17f', $QS[$i]) & ' | ' & StringFormat('%.17f', $AS[$i]) & @CRLF)
    		Next
    		ConsoleWrite(@CRLF)
    		Exit
    	EndIf
    
    
    EndFunc   ;==>Test
    
    
    ;~ Global $a_Array[] = [2, 6, 8, 1, 1, 5, 8, 9, 31, 41, 163, 13, 67, 12, 74, 17, 646, 16, 74, 12, 35, 98, 12, 43]
    ;~ Global $N = 5
    
    
    ;~ $a_Biggest = _ArrayGetNBiggestElements($a_Array, $N)
    ;~ _ArrayDisplay($a_Biggest, "Die " & $N & " größten Elemente im Array")
    
    
    Func _ArrayGetNBiggestElements($a_A, $d_Nth = 1)
    	; by AspirinJunkie
    	Local $i_Min = 0, $i_Max = UBound($a_A) - 1
    	If $d_Nth = $i_Max + 1 Then
    		_ArraySort($a_A, 1)
    		Return $a_A
    	EndIf
    	Do
    		Local $iMiddle = Floor(($i_Max + $i_Min) / 2)
    		Local $a = $a_A[$i_Min], $b = $a_A[$i_Max], $c = $a_A[$iMiddle]
    
    
    		; calculate the pivot element by median(Array[min], Array[middle], Array[max])
    		Local $p_Value = $a > $b ? $a > $c ? $c > $b ? $c : $b : $a : $a > $c ? $a : $c > $b ? $b : $c ; = Median(a,b,c)
    		Local $p_Index = $p_Value = $a ? $i_Min : $p_Value = $b ? $i_Max : $iMiddle ; = Index(p_Value)
    
    
    		; move the pivot-element to the end of the array
    		If $p_Index < $i_Max Then
    			$a_A[$p_Index] = $a_A[$i_Max]
    			$a_A[$i_Max] = $p_Value
    		EndIf
    
    
    		; Partition with Hoare's algorithm:
    		Local $i = $i_Min - 1
    		Local $j = $i_Max + 1
    		Local $t
    		Do
    			; start from right and go left until the next element which is smaller than pivot:
    			Do
    				$j -= 1
    			Until $a_A[$j] > $p_Value Or $j = $i_Min
    			; start from left and go right until the next element which is greater than pivot:
    			Do
    				$i += 1
    			Until $a_A[$i] < $p_Value Or $i = $i_Max
    
    
    			; swap if elements are on the wrong side of the lists
    			If $i < $j Then
    				$t = $a_A[$j]
    				$a_A[$j] = $a_A[$i]
    				$a_A[$i] = $t
    			EndIf
    		Until $i >= $j
    
    
    		; swap with pivot-element if pivot is at the wrong list-side:
    		If $a_A[$i] > $p_Value Then
    			$a_A[$i_Max] = $a_A[$i]
    			$a_A[$i] = $p_Value
    		EndIf
    
    
    		If $i = $d_Nth Then
    			If $d_Nth > 16 Then
    				_ArraySort($a_A, 1, 0, $d_Nth)
    			Else
    				; sort with insertion sort (faster than Quicksort for small element count)
    				For $i = 1 To $d_Nth
    					$t1 = $a_A[$i]
    					For $j = $i - 1 To 0 Step -1
    						$t2 = $a_A[$j]
    						If $t1 < $t2 Then ExitLoop
    						$a_A[$j + 1] = $t2
    					Next
    					$a_A[$j + 1] = $t1
    				Next
    			EndIf
    			ReDim $a_A[$d_Nth]
    			Return $a_A
    		ElseIf $i > $d_Nth Then
    			$i_Max = $i - 1
    		Else
    			$i_Min = $i + 1
    		EndIf
    	Until 0
    
    
    EndFunc   ;==>_ArrayGetNBiggestElements
    
    
    Func RandomNumbers($iCnt = 1)
    	Local $aArray[$iCnt]
    	For $i = 0 To $iCnt - 1 Step 1
    		$aArray[$i] = Random()
    	Next
    	Return $aArray
    EndFunc   ;==>RandomNumbers
    
    
    Func __Quicksort($aArray, $iSubSetSize = 1)
    	_ArraySort($aArray, 1) ; Rocket Science
    	ReDim $aArray[$iSubSetSize] ; Oberen Teil abschneiden, fertig.
    	Return $aArray
    EndFunc   ;==>__Quicksort
    Alles anzeigen

    lg
    M

  • JavaFX in AutoIt? - Framework

    • Mars
    • 26. September 2016 um 12:51

    Interessant ist die Sache auf jeden Fall, aber ich glaube nicht, dass das eine Person in einem anständigen Zeitraum alleine programmieren kann.

  • Größte/Kleinste Elemente aus einem Array wählen

    • Mars
    • 25. September 2016 um 17:25

    Damit hast du eine Waffe ins Feld geschickt, die so schnell keiner besiegen wird :D
    Villeicht gibt es ja doch eine Funktion die "überall" optimal läuft und nicht nur für bestimmte Fälle.

    Vielen Dank, den Startpost aktualisiere ich gleich.

    Da sieht man mal was alles möglich ist, die Zaubershow ist aber noch nicht vorbei, jetzt wird es erst richtig spannend :D

    lg
    M

  • Größte/Kleinste Elemente aus einem Array wählen

    • Mars
    • 24. September 2016 um 11:37

    Also ich hab nicht nur fleißig geredet, sondern auch schon 2 Methoden zur Lösung gebastelt (Die erste zähle ich mal nicht, denn Quicksort + ReDim ist kein Denkaufwand gewesen^^).

    Xor, du bist am Zug :P

  • Größte/Kleinste Elemente aus einem Array wählen

    • Mars
    • 23. September 2016 um 23:31

    O(n*log(k)) ist drin. Dann wäre der Grenzfall für k -> n = O(n*log(n)) was zufälligerweise genau mit Quicksort zusammenfällt. (Und auch exakt die gleiche Funktionalität wie QS bietet. Aus einer unsortierten Liste eine absteigend/aufsteigend sortierte Liste machen)

  • Größte/Kleinste Elemente aus einem Array wählen

    • Mars
    • 23. September 2016 um 23:00

    Moin,

    Nachdem ich nicht in der Lage war mich in der SB richtig auszudrücken (Deutsche Sprache schwäre Sprache) hier nochmal. (Danke an Xori für seine Geduld mit Personen die so viel verstehen wie ein Ziegelstein :D)

    Problemstellung:
    Es gibt ein Array mit n Elementen welches Zufallszahlen enthält (oder irgendwelche anderen Zahlen, ist im Prinzip egal).
    Aus diesem Array hätte man gerne in möglichst geringer Zeit eine Liste mit den k größten Einträgen in absteigender Reihenfolge. (Also wie z.B. ArrayMax eine "Liste" mit dem größten Eintrag liefert, möchte man eine Liste mit dem größten, dem 2t größten, ... dem k-t größten)

    Dazu kommt man spontan auf die brilliante Idee: Nimm Quicksort und trenne anschließend den oberen Teil des Arrays ab.
    Richtig, genauso kann man es machen. Und wenn man aus einem n = 100 Array die größten 90 Elemente in einer sortierten Rückgabeliste haben will ist das sicherlich der beste Weg. Falls man aus den 100 Elementen aber nur die 5 größten haben will ist es sinnlos das komplette Array zu sortieren.

    Es gibt schon ein paar Lösungen, die aber bestimmt noch nicht perfekt sind. Gesucht ist die schnellste Methode :)

    Was ist schnell ?
    Das ist eine gute Frage. Da es 2 Parameter gibt (n = Arraygröße, k = Anzahl der gesuchten Elemente) ist es unwahrscheinlich, dass eine einzige Funktion auf dem kompletten Spektrum von n und k überall am schnellsten zum Ziel kommt. Wie oben angedeutet kann man QuickSort nicht einfach schlagen, wenn man z.B. von 100 Elementen 90 haben will. Gebraucht werden also funktionen die für Spezialfälle ein besonderst gutes Ergebnis liefern. (z.B. für kleines n, für großes n, für kleines k, für großes k, für k = Wurzel(n), usw usw). Aus diesen Fällen lässt sich im Endeffekt eine Funktion die an vielen Stellen halbwegs optimal läuft zusammenschustern.

    Anbei 2 kleine Testskripte:

    AutoIt: Eigene Funktion einfügen und schauen ob das Ergebnis stimmt
    #include <Array.au3>
    
    
    Global $a = RandomNumbers(15)
    Global $m1 = __ArrayMax2($a, 9)
    Global $m2 = __ArrayMax2($a, 9)
    Global $m3 = __ArrayMax4($a, 9)
    
    
    ConsoleWrite(@CRLF & 'Array: [' & UBound($a) & ']' & @CRLF)
    For $i = 0 To UBound($a) - 1 Step 1
    	ConsoleWrite($a[$i] & ' ')
    Next
    
    
    ConsoleWrite(@CRLF & @CRLF & '__ArrayMax1: [' & UBound($m1) & ']' & @CRLF)
    For $i = 0 To UBound($m1) - 1 Step 1
    	ConsoleWrite($m1[$i] & ' ')
    Next
    
    
    ConsoleWrite(@CRLF & @CRLF & '__ArrayMax2: [' & UBound($m2) & ']' & @CRLF)
    For $i = 0 To UBound($m2) - 1 Step 1
    	ConsoleWrite($m2[$i] & ' ')
    Next
    
    
    ConsoleWrite(@CRLF & @CRLF & '__ArrayMax4: [' & UBound($m3) & ']' & @CRLF)
    For $i = 0 To UBound($m3) - 1 Step 1
    	ConsoleWrite($m3[$i] & ' ')
    Next
    ConsoleWrite(@CRLF & @CRLF)
    
    
    
    
    Func Find(ByRef $aArray, $nValue) ; Findet den Index für ein sortiertes Array
    	Local $l = 0, $r = UBound($aArray) - 1, $m = Int(($l + $r) / 2)
    	While 1
    		If $r - $l = 1 Then Return $r
    		If $aArray[$m] > $nValue Then
    			$l = $m
    		Else
    			$r = $m
    		EndIf
    		$m = Int(($l + $r) / 2)
    	WEnd
    EndFunc   ;==>Find
    
    
    Func __ArrayMax4($aArray, $iSubSetSize = 1)
    	$iSubSetSize += 1 ; Ein intern teilweise mit Startindex 1 gearbeitet wird.
    	Local $aRet[$iSubSetSize], $l, $r, $m, $v
    	For $i = 0 To UBound($aArray) - 1 Step 1 ; Komplettes Array durchlaufen
    		For $e = $iSubSetSize - 1 To 0 Step -1 ; Jedes Element mit der Resultatliste vergleichen.
    			If $aArray[$i] < $aRet[$e] Then ExitLoop ; Falls es kleiner ist als das kleinste Teil der Resultatliste passiert nichts.
    			$v = $aArray[$i] ; Suchmethode die in einer sortierten Liste deutlich schneller ist, als jedes Element einzeln zu überprüfen.
    			$l = 0
    			$r = $iSubSetSize - 1
    			$m = Int(($l + $r) / 2)
    			While 1
    				If $r - $l = 1 Then ExitLoop ; in $r ist der gesuchte Index
    				If $aRet[$m] > $v Then
    					$l = $m
    				Else
    					$r = $m
    				EndIf
    				$m = Int(($l + $r) / 2)
    			WEnd
    			For $q = $iSubSetSize - 2 To $r - 1 Step -1 ; Rückwärtslaufen um Platz zu machen
    				$aRet[$q + 1] = $aRet[$q] ; Verschieben in linearer Laufzeit. Das ist schlecht, in einem Tree wäre die Sache angenehmer, kommt beim nächsten Mal.
    			Next
    			$aRet[$r] = $aArray[$i] ; Positionieren
    			ExitLoop ; Läuft
    		Next
    	Next
    	For $i = 0 To $iSubSetSize - 2 Step 1 ; Weil intern teilweise mit Startindex 1 gearbeitet wird.
    		$aRet[$i] = $aRet[$i + 1]
    	Next
    	ReDim $aRet[$iSubSetSize - 1]
    	Return $aRet
    EndFunc
    
    
    Func __ArrayMax2($aArray, $iSubSetSize = 1)
    	Local $aRet[$iSubSetSize] ; Resultatarray erstellen
    	For $i = 0 To UBound($aArray) - 1 Step 1 ; Komplettes Array durchlaufen
    		For $e = 0 To $iSubSetSize - 1 Step 1 ; Jedes Element mit der Resultatliste vergleichen.
    			If $aArray[$i] >= $aRet[$e] Then ; Dabei wird zuerst das größte, dann das 2te usw verglichen.
    				For $o = $iSubSetSize - 2 To $e Step -1 ; Falls was gefunden wurde: Resultatliste um 1 nach unten verschieben.
    					$aRet[$o + 1] = $aRet[$o] ; Rückwärtslaufen nicht vergessen, sonst knackts im Gebälk.
    				Next
    				$aRet[$e] = $aArray[$i] ; Der freigewordene Platz bekommt nun das neue größte Element.
    				ExitLoop ; Fertig. Jeder Treffer wird nur 1x eingespeichert.
    			EndIf ; Hier wird gezaubert, die Resultatliste ist zu jeder Zeit vollständig sortiert.
    		Next
    	Next
    	Return $aRet
    EndFunc   ;==>__ArrayMax2
    
    
    Func __ArrayMax1($aArray, $iSubSetSize = 1)
    	_ArraySort($aArray, 1) ; Rocket Science
    	ReDim $aArray[$iSubSetSize] ; Obersten Teil abschneiden, fertig.
    	Return $aArray
    EndFunc   ;==>__ArrayMax1
    
    
    Func RandomNumbers($iCnt = 1)
    	Local $aArray[$iCnt]
    	For $i = 0 To $iCnt - 1 Step 1
    		$aArray[$i] = Random(100, 999, 1)
    	Next
    	Return $aArray
    EndFunc   ;==>RandomNumbers
    Alles anzeigen
    AutoIt: Wenn die Funktion läuft hier einbauen und gegen die anderen antreten lassen
    #include <Array.au3>
    
    
    Global $bErrCheck = False ; Nur für "kleine" Runden einschalten, sonst wird die Konsole überflutet falls Fehler auftreten.
    Global $iSmooth = 0 ; Nur falls man die Ergebnisse Plotten will und keine Lust hat so viele Versuche zu machen bis die Kurve halbwegs glatt ist.
    
    
    ;~         Func Test($iStart = 10, $iEnd = 15, $iSubSetSize = 3, $iVersuche = 25)
    Global $aTest = Test(50, 100, 20, 1)
    
    
    For $x = 0 To UBound($aTest) - 1 Step 1
    	For $y = 0 To UBound($aTest, 2) - 1 Step 1
    		$aTest[$x][$y] = StringReplace($aTest[$x][$y], '.', ',', 0, 1)
    	Next
    Next
    _ArrayDisplay($aTest, '', '', 0, @TAB)
    
    
    Func Runde($iArraySize = 100, $iSubSetSize = 5, $iVersuche = 25)
    	; $iArraySize  - Größe des zu untersuchenden Arrays
    	; $iSubSetSize - Anzahl der gesuchten Werte
    	; $iVersuche   - Anzahl durchgänge aus denen der Mittelwert gebildet wird (um die Laufzeit besser analysieren zu können)
    	; Runde() lässt die Funktionen einige Male mit gleichen Einstellungen laufen.
    	; Return       - Array mit der Durchschnittlichen Zeit in Millisekunden für jede Funktion.
    
    
    	Local $aTime[4][2] ; Beim Hinzufügen die Arraygröße anpassen.
    
    
    	$aTime[0][0] = 'Mars 01' ; Arraysort + Redim... easy
    	$aTime[1][0] = 'Platzhalter'
    	$aTime[2][0] = 'Mars 03'
    	$aTime[3][0] = 'Mars 04'
    
    
    	Local $aResult[UBound($aTime)], $aCheck, $t, $s, $aTest
    
    
    	For $i = 1 To $iVersuche Step 1
    
    
    		$aTest = RandomNumbers($iArraySize) ; Die Funktionen dürfen das Originalarray nicht verändern. Daher muss es nur 1x erzeugt werden.
    
    
    		Switch Random(0, 1, 1) ; Da man nie weiß was AutoIt intern betreibt kann es sein, dass Funktionen standardmäßig je nach Position im Code
    			Case 0 ; schneller oder langsamer laufen. Daher ist an dieser Stelle ein Switch um die Reihenfolgen durchzumischen.
    
    
    				$t = TimerInit()
    				$aResult[0] = __Mars01($aTest, $iSubSetSize)
    				$aTime[0][1] += TimerDiff($t)
    
    
    				$t = TimerInit()
    				$aResult[1] = Platzhalter($aTest, $iSubSetSize)
    				$aTime[1][1] += TimerDiff($t)
    
    
    				$t = TimerInit()
    				$aResult[2] = __Mars03($aTest, $iSubSetSize)
    				$aTime[2][1] += TimerDiff($t)
    
    
    				$t = TimerInit()
    				$aResult[3] = __Mars04($aTest, $iSubSetSize)
    				$aTime[3][1] += TimerDiff($t)
    
    
    			Case 1
    
    
    				$t = TimerInit()
    				$aResult[3] = __Mars04($aTest, $iSubSetSize)
    				$aTime[3][1] += TimerDiff($t)
    
    
    				$t = TimerInit()
    				$aResult[2] = __Mars03($aTest, $iSubSetSize)
    				$aTime[2][1] += TimerDiff($t)
    
    
    				$t = TimerInit()
    				$aResult[1] = Platzhalter($aTest, $iSubSetSize)
    				$aTime[1][1] += TimerDiff($t)
    
    
    				$t = TimerInit()
    				$aResult[0] = __Mars01($aTest, $iSubSetSize)
    				$aTime[0][1] += TimerDiff($t)
    
    
    		EndSwitch
    
    
    		; Überprüfen ob alle das gleiche raushaben.
    		If $bErrCheck Then
    			For $e = 0 To UBound($aResult) - 1 Step 1
    				$aCheck = $aResult[$e]
    				$s = 0
    				For $o = 0 To UBound($aCheck) - 1 Step 1
    					$s += $aCheck[$o]
    				Next
    				$aResult[$e] = $s ; $aResult ist nur noch die Summe aller Elemente -> Einfacher zu vergleichen und nahezu genauso aussagekräftig.
    			Next ; Dann wird nicht überprüft ob die Resultatliste Sortiert vorliegt, das ist aber zweitrangig.
    			For $e = 1 To UBound($aResult) - 1 Step 1 ; Wir nehmen mal an, dass Quicksort IMMER richtig liegt (ist immerhin milliardenfach erprobt diese Methode)
    				If $aResult[0] <> $aResult[$e] Then ConsoleWrite('!ERROR: ' & '[' & StringFormat('%5s', $iArraySize) & '|' & StringFormat('%4s', $iSubSetSize) & '] ' & $aTime[$e][0] & (Random(0, 1, 1) ? (Random(0, 1, 1) ? ' hat groben Unfug gebaut.' : ' hat keine Ahnung von Mathe.') : (Random(0, 1, 1) ? ' macht seinen verdammten Job nicht.' : ' steht in der Ecke und weint.')) & @CRLF)
    			Next
    		EndIf
    
    
    	Next
    
    
    	For $i = 0 To UBound($aTime) - 1 Step 1
    		$aTime[$i][1] /= $iVersuche
    	Next
    
    
    	Return $aTime
    
    
    EndFunc   ;==>Runde
    
    
    #Region - Funktionen
    
    
    Func Platzhalter($aArray, $iSubSetSize = 1)
    	ReDim $aArray[$iSubSetSize] ; Obersten Teil abschneiden. Klappt hier nicht weil nicht sortiert wurde.
    	Return $aArray ; Das hier dient nur als Beispiel.
    EndFunc   ;==>Platzhalter
    
    
    Func __Mars04($aArray, $iSubSetSize = 1)
    	$iSubSetSize += 1 ; Weil intern teilweise mit Startindex 1 gearbeitet wird.
    	Local $aRet[$iSubSetSize], $l, $r, $m, $v
    	For $i = 0 To UBound($aArray) - 1 Step 1 ; Komplettes Array durchlaufen
    		For $e = $iSubSetSize - 1 To 0 Step -1 ; Jedes Element mit der Resultatliste vergleichen.
    			If $aArray[$i] < $aRet[$e] Then ExitLoop ; Falls es kleiner ist als das kleinste Teil der Resultatliste passiert nichts.
    			$v = $aArray[$i] ; Suchmethode die in einer sortierten Liste deutlich schneller ist, als jedes Element einzeln zu überprüfen.
    			$l = 0
    			$r = $iSubSetSize - 1
    			$m = Int(($l + $r) / 2)
    			While 1
    				If $r - $l = 1 Then ExitLoop ; in $r ist der gesuchte Index
    				If $aRet[$m] > $v Then
    					$l = $m
    				Else
    					$r = $m
    				EndIf
    				$m = Int(($l + $r) / 2)
    			WEnd
    			For $q = $iSubSetSize - 2 To $r - 1 Step -1 ; Rückwärtslaufen um Platz zu machen
    				$aRet[$q + 1] = $aRet[$q] ; Verschieben in linearer Laufzeit. Das ist schlecht, in einem Tree wäre die Sache angenehmer, kommt beim nächsten Mal.
    			Next
    			$aRet[$r] = $aArray[$i] ; Positionieren
    			ExitLoop ; Läuft
    		Next
    	Next
    	For $i = 0 To $iSubSetSize - 2 Step 1 ; Weil intern teilweise mit Startindex 1 gearbeitet wird.
    		$aRet[$i] = $aRet[$i + 1]
    	Next
    	ReDim $aRet[$iSubSetSize - 1]
    	Return $aRet
    EndFunc   ;==>__Mars04
    
    
    Func __Mars03($aArray, $iSubSetSize = 1)
    	Local $aRet[$iSubSetSize]
    	For $i = 0 To UBound($aArray) - 1 Step 1 ; Komplettes Array durchlaufen
    		For $e = $iSubSetSize - 1 To 0 Step -1 ; Jedes Element mit der Resultatliste vergleichen.
    			If $aArray[$i] < $aRet[$e] Then ExitLoop ; Falls es kleiner ist als das kleinste Teil der Resultatliste passiert nichts.
    			For $o = 0 To $iSubSetSize - 1 Step 1 ; Abwandlung von Insertion Sort verwenden
    				If $aArray[$i] >= $aRet[$o] Then ExitLoop ; um in eine Sortierte Liste ein Element einzufügen.
    			Next
    			For $q = $iSubSetSize - 2 To $o Step -1 ; Rückwärtslaufen um Platz zu machen
    				$aRet[$q + 1] = $aRet[$q]
    			Next
    			$aRet[$o] = $aArray[$i] ; Positionieren
    			ExitLoop ; Läuft
    		Next
    	Next
    	Return $aRet
    EndFunc   ;==>__Mars03
    
    
    Func __Mars02($aArray, $iSubSetSize = 1)
    	Local $aRet[$iSubSetSize]
    	For $i = 0 To UBound($aArray) - 1 Step 1 ; Komplettes Array durchlaufen
    		For $e = 0 To $iSubSetSize - 1 Step 1 ; Jedes Element mit der Resultatliste vergleichen.
    			If $aArray[$i] >= $aRet[$e] Then ; Dabei wird zuerst das größte, dann das 2te usw verglichen.
    				For $o = $iSubSetSize - 2 To $e Step -1 ; Falls was gefunden wurde: Resultatliste um 1 nach unten verschieben.
    					$aRet[$o + 1] = $aRet[$o] ; Rückwärtslaufen nicht vergessen, sonst knackts im Gebälk.
    				Next
    				$aRet[$e] = $aArray[$i] ; Der freigewordene Platz bekommt nun das neue größte Element.
    				ExitLoop ; Fertig. Jeder Treffer wird nur 1x eingespeichert.
    			EndIf ; Hier wird gezaubert, die Resultatliste ist zu jeder Zeit vollständig sortiert.
    		Next
    	Next
    	Return $aRet
    EndFunc   ;==>__Mars02
    
    
    Func __Mars01($aArray, $iSubSetSize = 1)
    	_ArraySort($aArray, 1) ; Rocket Science
    	ReDim $aArray[$iSubSetSize] ; Obersten Teil abschneiden, fertig.
    	Return $aArray
    EndFunc   ;==>__Mars01
    
    
    #EndRegion - Funktionen
    
    
    #Region - Unfug
    
    
    Func RandomNumbers($iCnt = 1)
    	Local $aArray[$iCnt]
    	For $i = 0 To $iCnt - 1 Step 1
    		$aArray[$i] = Random()
    	Next
    	Return $aArray
    EndFunc   ;==>RandomNumbers
    
    
    Func Test($iStart = 10, $iEnd = 15, $iSubSetSize = 3, $iVersuche = 25)
    	; $iStart      - Startwert für die Arraygröße
    	; $iEnd        - Endwert für die Arraygröße
    	; $iSubSetSize - Schau bei ner anderen Beschreibung, sei fleißig
    	; $iVersuche   - Anzahl Durchgänge um den Mittelwert zu bilden.
    
    
    	Local $aRunde = Runde(1, 1, 1) ; Testrunde um das Ergebnisarray bestimmen zu können.
    	Local $aRet[$iEnd - $iStart + 2][UBound($aRunde) + 2] = [['ArraySize', 'SubSetSize']]
    	For $i = 0 To UBound($aRunde) - 1 Step 1
    		$aRet[0][$i + 2] = $aRunde[$i][0]
    	Next
    
    
    	For $v = 1 To $iVersuche Step 1 ; Doch besser die Runden einzeln durchzugeben.
    		For $i = $iStart To $iEnd Step 1
    			$aRunde = Runde($i, $iSubSetSize, 1)
    			$aRet[$i - $iStart + 1][0] = $i
    			$aRet[$i - $iStart + 1][1] = $iSubSetSize
    			For $e = 0 To UBound($aRunde) - 1 Step 1
    				$aRet[$i - $iStart + 1][$e + 2] += $aRunde[$e][1] / $iVersuche
    			Next
    		Next
    	Next
    
    
    	If $iSmooth Then
    		Local $aSmooth[$iEnd - $iStart + 1]
    		For $n = 2 To UBound($aRet, 2) - 1 Step 1
    			For $i = 0 To UBound($aSmooth) - 1 Step 1
    				$aSmooth[$i] = $aRet[$i + 1][$n]
    			Next
    			_ArraySmooth($aSmooth, $iSmooth, False)
    			For $i = 0 To UBound($aSmooth) - 1 Step 1
    				$aRet[$i + 1][$n] = $aSmooth[$i]
    			Next
    		Next
    	EndIf
    
    
    	Return $aRet
    
    
    EndFunc   ;==>Test
    
    
    Func _ArraySmooth(ByRef $aArray, $iSmooth = 1, $bFix = False)
    	If Not IsArray($aArray) Then Return SetError(1, 0, 0)
    	If UBound($aArray, 0) <> 1 Then Return SetError(2, 0, 0)
    	If Not IsInt($iSmooth) Or $iSmooth < 1 Or $iSmooth > 1e9 Then Return SetError(3, 0, 0)
    	For $i = 1 To $iSmooth Step 1
    		$aArray = __ArraySmooth($aArray, $bFix)
    	Next
    EndFunc   ;==>_ArraySmooth
    
    
    Func __ArraySmooth($aArray, $bFix)
    	Local $iUBound = UBound($aArray), $aCopy[$iUBound], $nSum = $bFix ? __ArraySum($aArray, 1, $iUBound - 1) : 0, $nSum2
    	$aCopy[0] = $bFix ? $aArray[0] : 0.75 * $aArray[0] + 0.25 * $aArray[1]
    	For $i = 1 To $iUBound - 2 Step 1
    		$aCopy[$i] = 0.25 * $aArray[$i - 1] + 0.5 * $aArray[$i] + 0.25 * $aArray[$i + 1]
    	Next
    	$aCopy[$iUBound - 1] = $bFix ? $aArray[$iUBound - 1] : 0.75 * $aArray[$iUBound - 1] + 0.25 * $aArray[$iUBound - 2]
    	$nSum2 = $bFix ? __ArraySum($aCopy, 1, $iUBound - 1) : 0
    	If $bFix Then
    		For $i = 1 To $iUBound - 2 Step 1
    			$aCopy[$i] *= $nSum / $nSum2
    		Next
    	EndIf
    	Return $aCopy
    EndFunc   ;==>__ArraySmooth
    
    
    Func __ArraySum(ByRef $aArray, $iStart = 0, $iEnd = -1)
    	If $iEnd = -1 Then $iEnd = UBound($aArray)
    	Local $n
    	For $i = $iStart To $iEnd - 1 Step 1
    		$n += $aArray[$i]
    	Next
    	Return $n
    EndFunc   ;==>__ArraySum
    
    
    #EndRegion - Unfug
    Alles anzeigen

    Edit1: Mars02 ist rausgeflogen, weil die Funtkion in allen Fällen deutlich schlechter als Mars03 ist. Neu hinzugekommen ist Mars04, die in einigen Fällen (vorallem bei mittlerem k) etwas schneller ist.

    Edit2: AspirinJunkie hat eine Funktion beigesteuert die in fast allen Fällen schneller ist, als reines Quicksort. Für die UDF und das Testskript bitte in Post 12 nachschauen.

    Da ich ein Diagrammfan bin gibts hier auch ein paar Bildchen :D (Weniger Millisekunden sind wichtig. Also je niedriger die Kurve ist, desto besser.)
    (Peaks in den Diagrammen kommen daher, dass mein Rechner im Hintergrund am Arbeiten ist)
    unnamed.pngunnamed2.pngunnamed3.png

    lg
    M

  • Battle: Autoit vs. FreeBasic - Runde 1+2+3

    • Mars
    • 22. September 2016 um 17:29

    Ich kann dir sagen, warum du das machst. GDI+ funktioniert, D2D nicht. (zumindest in AutoIt).
    Ich habe viel mit D2D herumprobiert, und es gibt wirklich schöne Sachen die damit möglich sind, die man mit GDI+ direct in die Tonne treten kann. Allerdings funktionieren schon triviale Sachen wie "Lade ein Bild mit Alphakanal aus dem Arbeitsspeicher" nicht einfach so, obwohl es speziell zu diesem Zweck D2D Funktionen gibt. Ich habe Stunden und Tagelang (mit eukalyptus zusammen) herumprobiert, die Funktionen arbeiten in AutoIt nicht so wie sie sollten. Weiterhin ist es schwieriger Fehler zu finden, bei GDI+ gibt es wesentlich weniger "seltsame Einstellungen", Flags, "Versionen eines Elements" usw usw, die einem die Fehlersuche erschweren. Wenn es klemmt schaut man, ob GDI+ Startup aufgerufen wurde, überprüft ein paar Variablen, fertig. Bei D2D kommt es oft vor, dass alles so ist wie es sein sollte und man keine Ahnung hat was hier eigentlich los ist und warum etwas nicht funktioniert.

    In golang habe ich SDL ausprobiert und muss sagen: Das ist ein schöner Wrapper für D2D (sehr einfach gehalten, tut exakt das was es soll, schmiert nicht oft ab wenn man Fehler macht), ist wahrscheinlich auch in AutoIt wesentlich einfacher zu verwenden als D2D. UDFs in der Richtung gibts soweit ich weiß auch.

    lg
    M

  • Fazit: HTC Vive, Samsung Gear VR, Oculus Rift

    • Mars
    • 4. September 2016 um 21:02

    Irgendwann in der Zukunft... wenn man sich nicht mehr Backsteine mit Spanngurten vor das Gesicht presst, sondern ganz entspannt mit einer Brille bedient wird, die sowohl volltransparent, halbtransparent/holografisch, oder komplett opak arbeiten kann (also sowohl AR als auch VR funktioniert)... Dann gönne ich mir sowas auch, aber vorher nicht :D

  • BUG ??? File Read nach Script breaking Changes Version 3.3.14.2

    • Mars
    • 4. September 2016 um 20:54

    Auch wenn das Thema schon gegessen ist muss ich dazu noch was sagen:
    Ich habe es schon unzählige Male gehabt, dass Dateien die irgendwas aus meinen Skripten auslagern um von anderen gelesen zu werden Array->Str und dann FileWrite, beim Einlesen nur Unfug herausgeben, obwohl ALLES nur Asc Zeichen waren. Ohne FileOpen mit explizitem Modus mache ich daher überhaupt nichts mehr.

    lg
    M

  • eingefügte Grafik skalieren oder skaliert einfügen

    • Mars
    • 28. August 2016 um 08:47

    Bei Powerpoint ist es eigentlich sinnvoll die Bilder in Originalgröße (außer es sind 20 Megapixel oder sowas) einzufügen, und nur die Anzeige zu skalieren. Dann hat man in der Präsentation auch auf höheren Bildschirmauflösungen ein scharfes Bild.

  • Theorie: AutoIt3-Compiler

    • Mars
    • 8. August 2016 um 00:54

    Genau die gleiche Idee ist vor einiger Zeit doch schonmal aufgetaucht. Was wir damals festgestellt hatten (und die ich noch im Kopf habe) waren folgende:
    [1] - Native Befehle/Macros (GuiCreate, ConsoleWrite, @DesktopWidth, usw usw) müssten in FB implementiert werden ohne dass wir "hineinschauen" können wie diese Befehle intern funktionieren.
    [2] - Die Grammatik (wie oben schon gesagt) muss bekannt sein, damit man von normaler Au3-Syntax zur FB-Syntax wechseln kann.
    [3] - UDFs, verschiedene Programmierstile, usw sind vollkommen egal. Vor dem Kompilieren werden sowieso alle Daten in einem einzigen Skript zusammengefasst, das nach Punkt 2 Übersetzbar ist.
    [4] - Sollte man den Variant-Typ zuverlässig behandeln wird es große Geschwindigkeitseinbußen geben. (Vor jeder Berechnung prüfen wie die Datentypen sind und ggf. casten)
    [5] - DllStructs können wie ein normales Array (mit vorgegebenem Datentyp) verwendet werden, da das in FB Äquivalent gestaltet werden kann, oder umgekehrt. In AutoIt sind normale Arrays aber auf wundersame Weise überall im Speicher verteilt, sodass es keine Arraypointer oder Direktzugriffe gibt.
    [6] - Für auftretende Einschränkungen (die es auf jeden Fall geben wird, da man nicht 100% der Sprache einfach so übersetzen kann) muss ein Au3Check ähnliches Skript geschrieben werden um zu überprüfen ob das Skript nach FB übersetzbar ist.

    Sachen für das Variantproblem waren:
    [1] - Alle Variablen eindeutig deklarieren (MustDeclareVars zur Pflicht machen reicht aus, damit implizit alle Datentypen festgelegt sind). Damit kann der Übersetzer an vielen Stellen bereits feststellen wo gecastet werden muss, sodass das Überprüfen zur Laufzeit wegfällt.
    [2] - Komplett auf Variant verzichten und in AutoIt manuell "casten" z.B. $a = 5.0, $b = 2. Es wird aus $c = $a + $b ein $c = Int($a) + $b, sodass $c eindeutig ein Integer ist, oder $c = $a + Float($b), sodass $c eindeutig Float ist.
    [3] - Funktionen einen eindeutigen Rückgabewert zuweisen. "Func ... Endfunc ; Typ", z.B. "Endfunc ; Int" gibt immer einen Integer zurück. (Kann etwas Arbeit sparen)
    [4] - Einen "Behälter" (der jeden Datentyp enthalten kann) für Funktionsparameter benutzen, damit Funktionen nicht überladen werden müssen.

    Die Liste ist bei weitem nicht vollständig, das sind nur die Sachen die mir direkt zu dem Thema eingefallen sind. Weiterhin weiß ich, dass minx sich auch schonmal an etwas ähnlichem versucht hat (mit seiner selbst gebastelten kompilierbaren Sprache Perseus), wie weit die Entwicklung dort fortgeschritten war weiß ich nicht.

    lg
    M

  • YouTube Videobearbeitung

    • Mars
    • 6. August 2016 um 14:31

    Manche Leute laufen in MMOs die gleiche Instanz 500x nur um ein bestimmtes Item zu bekommen. Ich denke es ist ein menschenmöglicher Aufwand das von Hand zu machen, muss ja nicht alles am gleichen Tag sein.

    Was Captchas angeht sind wir hier auch im falschen Forum, ein Program welches Captchas ausfüllen kann wird es hier nicht geben. (siehe Forenregeln)

    lg
    M

  • Autoit Objekte

    • Mars
    • 4. August 2016 um 12:42

    Für deinen speziellen Fall kann es sein, dass du hier die Antwort findest: Klick Mich.

    Allgemein sollten auch in AutoIt keine Methoden explizit implementiert werden müssen. Das Objekt liefert eigentlich alles, was es zum funktionieren braucht. Warum es dennoch nicht immer funktioniert weiß ich leider nicht, da muss ein Objektguru ran.

    Edit: Für dein spezielles Beispiel hab ich den Fehler gefunden: Die Methode IndexOf kann mit einem Parameter IndexOf(Objekt, Startposition) verwendet werden. Scheinbar wird die Startposition nicht per Default auf 0 gesetzt, sodass man das manuell machen muss:

    AutoIt
    $AList = ObjCreate("System.Collections.ArrayList")
    ;////Einträge hinzufügen///////////
    $AList.add ("Test1") ; Position 0
    $AList.add ("Test6") ; Position 1
    $AList.add ("Test4") ; Position 2
    $AList.add ("Test2") ; Position 3
    $AList.add ("Test3") ; Position 4
    $AList.add ("Test5") ; Position 5
    ConsoleWrite("indexof: " & $AList.IndexOf("Test4", 0) & @CRLF)

    lg
    M

  • PandaRunner - Ein Autoit Game (#02)

    • Mars
    • 30. Juli 2016 um 18:54

    Ich finde es schön, dass sich Jemand mit Jump&Run Spielen in AutoIt beschäftigt. Die Sprache mag nicht für Spiele geeignet sein, diese Hürde lässt sich aber problemlos stämmen. Allerdings ist das vorliegende Spiel bei mir nicht spielbar (es hackt dermaßen stark, dass es kaum Spielbar ist, sieht mir nach Fehlern beim Buffern und Timen aus). Mach das Spiel trotzdem fertig und versuche so viel wie möglich beim Programmieren daraus zu lernen wie man ein Spiel aufbaut. Irgendwann bist du an einem Punkt wo du über deinen alten Code nur noch den Kopf schütteln kannst. Dann ist die Zeit gekommen wo du das gleiche Spielkonzept nochmal von 0 anfängst und es beim 2ten Mal wesentlich besser programmierst. (Das ist der übliche Lernprozess).

    Das soll dich jetzt nicht runterziehen und ich meine es nicht Böse. Du bist noch ein Anfänger auf dem Gebiet und da ist es Okay wenn man vieles falsch macht. Bleib dran und wachse an deinen Aufgaben.

    lg
    M

  • Hello World, das bin ich.. Paracodeycal

    • Mars
    • 23. Juli 2016 um 23:34

    Hoi

    Edit: Im Forum gibts auch ein paar Tips die bei Spielen weiterhelfen könnten. Ich habe früher auf gerne ein paar kleinigkeiten gebastelt, aber seit ein paar Jahren fehlt mir irgendwie die Lust etwas "großes" anzufangen, und mit etwas kleinem würde ich mich nicht zufrieden geben. Aber eins sei gesagt: AutoIt ist nicht dafür hergestellt um damit Spiele zu programmieren, aber inzwischen kann man via D2D/GDI+ und inlineASM (was sich auch kombinieren lässt) an kritischen Stellen extrem viel herausholen. Falls du etwas planst was auch im Vollbildmodus flüssig laufen soll rate ich dir dringend dazu dich mit D2D auseinanderzusetzen, die Zeichenvorgänge (vorallem Skalierungen, "ins Fenster zeichen", V-Sync, usw) gehen dort wesentlich angenehmer. (via BitBlt kann man zwar auch so sehr gute Zeiten erreichen, dafür fallen aber sehr viele andere Vorteile flach)

    Im Anhang habe ich dir mal ein kleines Testskript von mir (ist inzwischen fast 2 Jahre alt... da werde ich schon wieder sentimental^^) angehängt. Da habe ich einige UDFs die zur Spieleentwicklung geeignet sind (wie z.B. Buttons, Hintergründe, Partikel, D2D, ASM, D2D+ASM, usw) ausprobiert, ob das alles so funktioniert wie ich mir das vorstelle. Es ist leider zu 150% unaufgeräumt (da ich keine Lust hatte den alten Kram nochmal komplett auseinanderzunehmen und zu ordnen).

    Edit2: Wie man am Änderungsdatum der Dateien sieht musste ich aber trotzdem einiges ändern, damit es überhaupt läuft. Was nicht läuft ist eine schlechte Demo^^

    lg
    M

    Dateien

    D2DTest.rar 2,81 MB – 477 Downloads
  • Seltsames Leuchten in den Wolken

    • Mars
    • 15. Juli 2016 um 00:41

    Wird erledigt, Sir. Falls ich jemals Erleuchtung finden sollte (ich glaube nicht daran, aber man weiß ja nie) teile ich sie mit allen :)

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™