Das passiert, wenn man <Array.au3> nach _Check() included.
Beiträge von Mars
-
-
Hinweis: Das ist die Lösung für die heruntergeladene Datei (die nur 14 Zeichen erfordert).
AutoIt
Alles anzeigenFunc _CreateID($aUserdata) Local $Return $Return = StringLeft($aUserdata[2] & '99999', 5) $Return &= StringLeft(StringRight(StringSplit($aUserdata[3], '.', 2)[2], 2), 1) $Return &= StringRight('0' & StringSplit($aUserdata[3], '.', 2)[1] + 50 * ($aUserdata[4] = 'W'), 2) $Return &= StringSplit($aUserdata[3], '.', 2)[0] $Return &= StringRight(StringSplit($aUserdata[3], '.', 2)[2], 1) $Return &= StringLeft($aUserdata[0], 1) & ($aUserdata[1] ? StringLeft($aUserdata[1], 1) : '9') Local $q = 0, $a = StringSplit($Return, '', 2) For $i = 0 To UBound($a) - 1 Step 1 $a[$i] = Asc($a[$i]) Next While UBound($a) > 1 For $i = 0 To UBound($a) - 1 Step 1 $q += $a[$i] Next $a = StringSplit($q, '', 2) $q = 0 WEnd $Return &= $a[0] Return $Return EndFunc
-
Moin,
das folgende ist eine mini UDF um Integerzahlen zusammenzupacken. Die Rechnung ist analog zur Umrechnung zwischen "Uhrzeit und Sekunden", sodass genau dieser Spezialfall auch als Beispiel im Code enthalten ist. Eine Einschränkung ist leider, dass AutoIt intern maximal uint63 unterstützt (also eigentlich int64). Mit einer BigInt-UDF (die es ja gibt, ich wollte aber keine Abhängigkeiten hier) könnte man also "sehr viel mehr" Zahlen zusammenfassen.
Mein persönlicher Anwendungsfall ist (mal wieder) irgendwo einzelne Bits beim Speichern von Daten mit bekannten Intervallen herauszuholen. Ob es dafür andere (sinnvolle) Anwendungsfälle gibt weiß ich leider nicht.
Falls Fehler auftauchen, bitte hier melden. Ich habe die Sache nur kurz getestet und bin froh korrigiert zu werden.
AutoIt: PackedIntegers.au3
Alles anzeigen__PI_Test() Func __PI_Test() ; Uhrzeit Beispiel (Hier spart man keine Bits. Schade) Local $structure = [[0,23],[0,59],[0,59]] Local $values = [1, 30, 15] ; Uhrzeit Beispiel mit Tag und Millisekunden (1 Bit gespart) ;~ Local $structure = [[1,365],[0,23],[0,59],[0,59],[0,999]] ;~ Local $values = [234, 1, 30, 15, 789] ; Anderes Beispiel (2 Bit gespart) ;~ Local $structure = [[0, 3], [7, 16], [1000, 1500], [55, 88], [0, 2], [0, 1]] ;~ Local $values = [3, 16, 1500, 88, 1, 1] ; Klassenarbeitsergebnisse von 24 Personen (9 Bit gespart, ist aber auch absichtlich ein Extremfall) ;~ Local $structure = [[1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6]] ;~ Local $values = [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6] Local $packed = _PI_Create($structure) _PI_SetValue($packed, $values) ; Set all values (can set single ones too via ($packed, $i, $iValue) Local $iInt = _PI_GetInt($packed) ; Das ist der resultierende uint _PI_Debug($packed) ; Nochmal reinschauen ConsoleWrite(@CRLF) Local $otherPacked = _PI_Create($structure) _PI_SetInt($otherPacked, $iInt) ; Alle einzelnen Zahlen aus dem uint laden. _PI_Debug($otherPacked) Local $values = _PI_GetValue($otherPacked) For $i = 0 To UBound($values) - 1 Step 1 ConsoleWrite(($i = 0 ? 'Values as array: [' : '') & $values[$i] & ($i < UBound($values) - 1 ? ', ' : ']' & @CRLF)) Next EndFunc ; e.g. $structure = [[0, 3], [7, 16], [1000, 1500], [55, 88]] ; -> 4 Integers ; -> 1st can be 0, 1, 2 or 3. Ränder inklusive! Func _PI_Create($aStructure) Local $x[], $_[] For $i = 0 To UBound($aStructure) - 1 Step 1 $x[$i] = $_ $x[$i][0] = $aStructure[$i][0] $x[$i][1] = $aStructure[$i][1] $x[$i][2] = 0 ; Default = min value Next Return $x EndFunc ; Output the contents + bonus info Func _PI_Debug($x) Local $iSumBits = 0, $iSumBitsNaive = 0, $iValue, $iRange, $iMaxIntLen = 0, $sPadding = ' ' For $i = 0 To UBound($x) - 1 Step 1 $iValue = $x[$i][0] + $x[$i][2] If StringLen($x[$i][0]) > $iMaxIntLen Then $iMaxIntLen = StringLen($x[$i][0]) If StringLen($x[$i][1]) > $iMaxIntLen Then $iMaxIntLen = StringLen($x[$i][1]) If StringLen($iValue) > $iMaxIntLen Then $iMaxIntLen = StringLen($iValue) Next ConsoleWrite('Debug packed integers in $x[' & UBound($x) & '][2]' & @CRLF) For $i = 0 To UBound($x) - 1 Step 1 $iValue = $x[$i][0] + $x[$i][2] $iRange = $x[$i][1] - $x[$i][0] + 1 ConsoleWrite('[' & StringRight($sPadding & $x[$i][0], $iMaxIntLen) & ', ' & StringRight($sPadding & $x[$i][1], $iMaxIntLen) & '] (Bit: ' & StringFormat('%5.2f', (Log($iRange) / Log(2))) & _ ') -> $x[' & $i & '][2] = ' & StringRight($sPadding & $iValue, $iMaxIntLen) & ' (raw: ' & StringRight($sPadding & $x[$i][2], $iMaxIntLen) & ')' & @CRLF) $iSumBits += Log($iRange) / Log(2) $iSumBitsNaive += Ceiling(Log($iRange) / Log(2)) Next ConsoleWrite('Overall bits needed: ' & StringFormat('%.2f', $iSumBits) & ' (' & Ceiling($iSumBits) & ' instead of '&$iSumBitsNaive&') for Integer ' & _PI_GetInt($x) & @CRLF) EndFunc ; set a value with _PI_SetValue($x, $i, $iValue), where $i is the index and $iValue is the value ; set all values with _PI_SetValue($x, $i), where $i = Array of values [1, 2, 3, ...] Func _PI_SetValue(ByRef $x, $i, $iValue = 0) If IsArray($i) Then If UBound($i) <> UBound($x) Then Return SetError(1, 0, 0 * ConsoleWrite('Num Values ('&UBound($i)&') does not match the size of $x (' & UBound($x) & ')' & @CRLF)) For $j = 0 To UBound($i) - 1 Step 1 _PI_SetValue($x, $j, $i[$j]) Next Return EndIf If $iValue < $x[$i][0] Or $iValue > $x[$i][1] Then Return SetError(1, 0, 0 * ConsoleWrite('Value "'&$iValue&'" is outside the allowed range [' & $x[$i][0] & ', ' & $x[$i][1] & ']' & @CRLF)) If Not IsInt($iValue) Then SetError(2, 0, 0 * ConsoleWrite('Value "'&$iValue&'" is no integer but "'&VarGetType($iValue)&'"' & @CRLF)) $x[$i][2] = $iValue - $x[$i][0] EndFunc ; get a value with _PI_GetValue($x, $i), where $i is the index ; get all values with _PI_GetValue($x) Func _PI_GetValue(ByRef $x, $i = -1) If $i = -1 Then Local $aRet[UBound($x)] For $j = 0 To UBound($x) - 1 Step 1 $aRet[$j] = _PI_GetValue($x, $j) Next Return $aRet EndIf Return $x[$i][0] + $x[$i][2] EndFunc ; get the uint value Func _PI_GetInt(ByRef $x) Local $iInt = 0, $mul = 1 For $i = UBound($x) - 1 To 0 Step -1 $iInt += $x[$i][2] * $mul $mul *= $x[$i][1] - $x[$i][0] + 1 Next Return $iInt EndFunc ; set the uint value. This automatically sets all internal values Func _PI_SetInt(ByRef $x, $iInt) Local $prefixMul[], $mul = 1 For $i = UBound($x) - 1 To 1 Step -1 $mul *= $x[$i][1] - $x[$i][0] + 1 $prefixMul[$i - 1] = $mul Next For $i = 0 To UBound($prefixMul) - 1 Step 1 $x[$i][2] = Int($iInt / $prefixMul[$i]) $iInt -= $x[$i][2] * $prefixMul[$i] Next $x[$i][2] = $iInt EndFunc
lg
M
-
Wer online testen möchte: https://gc.de/gc/brainfuck/
Hat mich jetzt knappe 3 Stunden gekostet, das zu entwerfen.
Das erste Element auf dem Stack ist nebenbei die gesamte Baumhöhe. Heißt kurz gesagt, für jedes + was man der Baumspitze hinzufügt, wird der generierte Baum eine Ebene höher.
Hat er nicht gemacht.... Das ist ja der Wahnsinn
-
Die Idee mit der Animation ist gar nicht mal so schlecht. Hoffentlich vergesse ich das nicht bis nächstes Jahr
-
Neues Jahr, neuer Weihnachtsbaum!
(Entspricht nicht den Vorgaben, aber ich wollte einfach Basteln)
AutoIt
Alles anzeigenP(15) Func P($h, $_ = Default) If $_ <> Default Then If $_ > 0 Then Local $1 = $h = '.' ? '' : $h, $a = ['.', '.', ' ', '*', 'O'], $o = False For $i = 0 To $_ - 2 Step 1 $h &= $1 ? $1 : $a[Random(0, UBound($a)-1-(StringInStr($h, 'O', 0, 1)?1:0), 1)] Next Return $h Else Return '' EndIf EndIf Local $w = Int($h / 2) * 2 + 1, $r = 1, $s = '', $l = False, $k, $p For $y = 0 To $h - 1 Step 1 $s &= ($y = 0 ? (P(' ', Int($w / 2 + 1)) & '*') : ($y < $h - 1) ? (P(' ', Int(($w - $r)/2) - 0) & '/' & P('.', $r) & '\') : ((($p/2 < $r/2 ? ' ' : '') & P('^', $p/2) & '[_]' & P('^', $p/2)))) & @CRLF If Not ($y < $h - 1 And $y > 0) Then ContinueLoop $p = $r $k = ($h - $y - 2) > (($w - $r) / 2) And Not $l $l = $k ? Random() > 0.5 : False $r += $k ? (Not ($l And $y > 2) ? ((Random() > 0.5 ? 2 : ($r < $w / 2 ? 2 : ($y > 3 ? -2 : 2)))) : 0) : 2 $r = $r - 2 * ($r > $w) Next ConsoleWrite($s & @CRLF) EndFunc
lg
M
-
1. Meine Weiterbildung erfolgt meistens privat durch "irgendwelche Sachen die ich sehe" und durch "herumbasteln". Das macht sich natürlich auf dem Papier nicht gut, daher bekomme ich alle Halbjahr irgendeine Weiterbildung gesponsort (ist immer Themenbezogen).
Trends sind mir persönlich vollkommen egal, ich mache was ich für richtig halte. Da ich aktuell am C++ lernen bin (bzw. es seit ~5 Jahren aktiv nutze, aber man lernt ja nie aus), will ich das erst "perfektionieren" bevor irgendwas anderes um die Ecke kommt. Sowas wie z.B. Rust gefällt mir überhaupt nicht, da es sich anfühlt als würde man mit angezogener Handbremse programmieren. Den "Mit Rust konnte ich meine alten Projekte 3x so schnell neu implementieren" Bias halte ich ebenfalls für lächerlich. Ja, wenn ich ein altes Projekt erneut programmiere, dann bin ich 3x so schnell, selbst wenn ich die Sprache nicht wechsele. Aber gut, das ist Ansichtssache. Jeder soll machen was er für richtig hält.
2. Ich habe noch keine dollen Papers geschrieben, bin aber gerade dabei. Das scheint wohl gern gesehen zu sein, und da ich soweiso eine Quatschtüte bin ist das kein Problem auch mal ein paar "ordentliche" Sachen zu schreiben. Insgesamt halte ich aber das publizieren für gnadenlos überbewertet. Ja, es ist wichtig neuen Kram für die Welt zugänglich aufzuschreiben, sodass sich das Wissen verbreiten kann. Finde den Fehler im vorherigen Satz. "Für die Welt zugänglich", war der Fehler, da alles was ich "ordentlich" schreibe hinter einer Paywall landen wird (außer auf den sieben Weltmeeren, die ich in diesem Bezug tatsächlich empfehlen kann).
Wenn es nach mir ginge, gäbe es ein weltweites community moderiertes "Wissenschafts Wikipedia" bei dem eben nur Profs bzw. "Leute aus der Forschung an einer Bildungs/Forschungseinrichtung" Schreibrechte, aber jeder auf der ganzen Welt Leserechte besitzt. Möchte man etwas veröffentlichen muss man sich an jemanden vom Fach wenden. Damit wird direkt 90% Unfug (der sich auch in aktuellen Veröffentlichungen wiederfindet) herausgefiltert. Außerdem kann man "in diesem Wiki" eine Analyse machen ob das eigene Thema dort schon vorhanden ist. (Such mal 50 Journals/Konferenzen weltweit über die letzten 50 Jahre nach etwas durch was du erfunden/gefunden hast. Viel Spaß. Die Wahrscheinlichkeit ist 95%, dass du es nicht findest, selbst wenn es schonmal irgendwo aufgetaucht ist. Vielleicht falsche Keywords? Vielleicht falsche Sprache? etc.). Falls ja (Thema existiert bereits), dann bekommt man schreibrechte für den dazugehörigen Artikel für eventuelle Ergänzungen, falls nein (Thema ist neu bzw. transformativ), dann bekommt man einen eigenen Artikel. Ein super Nebeneffekt sind "Verlinkungen" die es zwar auch jetzt schon gibt [Mar24], mit der unfassbar altertümlichen Methode ([...] verweist auf einen Text der im Anhang steht, den ich googeln muss um das dazugehörige Paper zu finden was ich dann lesen muss um herauszufinden welche Stelle überhaupt zitiert wurde) bin ich aber auf Kriegsfuß. Wie schön wäre es, wenn ich [Mar24] anklicke und in einer Sekunde bin ich im richtigen Artikel in der richtigen Zeile um nachzulesen wo etwas herkommt... Das wird es leider niemals geben, zumindest nicht mehr in meiner Lebenszeit.Aber gut, damit kann niemand Geld verdienen, und Wissen wäre ein Grundrecht. So eine Welt haben wir halt nicht.
Over and Out
M
-
Es bringt halt leider auch Granaten wie das Folgende:
Halbe Seite Text
Dauert also noch etwas bis wir ersetzt werden
(Bei der Frage habe ich implizit gehofft, dass mein Thread aus dem PU-Bereich gelesen wurde. Da ist ein Beispiel wie man die Pointer von (Globalen) AutoIt-Variablen durch ein paar Tricks herausbekommen kann)
lg
M
-
Einfach aus Jux habe ich die Frage mal in die KI gefüttert, und siehe da, der Code ist technisch gesehen korrigiert worden.
Irgendwann werden wir als Supporter überflüssig, es ist nur noch eine Frage der Zeit
Edit: Habe noch nachgefragt, ob man an dem Code noch etwas ändern könnte, und tatsächlich, das zweimalige Verwenden von "left" wurde als potenzieller Fehler markiert.
lg
M
-
Moin,
wer kennt es nicht. Man hat eine Funktion die irgendetwas stochastisch berechnet (Monte-Carlo) und relativ lange braucht.
Diese Funktion möchte man aber im Idealfall "oft" aufrufen (ggf. in einer anderen Funktion, die ebenfalls stochastisch arbeitet, usw usw). Im Endeffekt resultiert das in Abermillionen von Funktionsaufrufen, die sehr schnell sehr viel Zeit in Anspruch nehmen.
Aber es gibt Abhilfe: Ein sich selbst füllender Puffer der Funktionswerte an einigen Stützstellen speichert und dann linear interpoliert (mit Unsicherheitsangabe).
Vermutlich habe ich darin noch ein Paar Bugs versteckt, aber für meine bisherigen Anwendungsfälle hat es funktioniert, daher gibts jetzt ne "mini-UDF". Wie bei allen Methoden ist es wichtig "sinnvolle" Parameter zu wählen, ansonsten läuft sich der Algorithmus tot (mit Failsave -> MaxIter) oder produziert vollkommen falsche Ergebnisse (z.B. wenn man nur 10 Stützstellen verwendet, obwohl man eigentlich mindestens 100 braucht, oder wenn man eine Genauigkeit von 0.01 haben möchte, obwohl die Funktionswerte die Größenordnung 100 und eine große Streuung haben). Was die Ungenauigkeitsangabe im Returnwert angeht möchte ich meine Hand nicht ins Feuer legen. Da sich der Mittelwert ja mit jedem neuen Sample ändert und die vorherigen Varianzen nicht angepasst werden können (man will ja nicht "alles" speichern) ist dieser Wert nur "ungefähr richtig".
Die Verwendung ist glaube ich intuitiv ersichtlich wenn man das Beispiel anschaut. FFB heißt "FuzzyFunctionBuffer"
AutoIt
Alles anzeigenGlobal Const $__FFB_MIN_SAMPLES = 17 ; Beispielfunktion mit langer Rechenzeit die "nicht genau" arbeitet: ; Stochastisches abschätzen vom Volumen einer Kugel mir Radius $r Func myFunc($r) Local Const $k = 1000 Local $n = 0, $r2 = $r ^ 2 For $i = 0 To $k - 1 Step 1 $n += Random(-$r, $r) ^ 2 + Random(-$r, $r) ^ 2 + Random(-$r, $r) ^ 2 < $r2 Next Return $n / $k * (2 * $r) ^ 3 EndFunc ;==>myFunc ; Naiver Ansatz: ; Einfach Mittelwert bilden über N Versuche (hier mit N = 100) ; Probleme: ; - Wie genau ist das denn jetzt? ; - Wenn ich die Funktionswerte mehrfach brauche muss ich mich selbst um das Puffern kümmern. ; - Wenn ich "ähnliche" Funktionswerte brauche muss die Funktion komplett neu ausgewertet werden. Local $t = TimerInit() For $i = 80 To 90 Step 1 Local $v = 0 For $j = 0 To 99 Step 1 $v += myFunc($i / 100) Next $v /= 100 ConsoleWrite('r = ' & StringFormat('% 5.3f', $i / 100) & ' -> Vol = ' & StringFormat('% 6.4f', $v) & ' err = ' & StringFormat('% 6.4f', $v-4/3*(($i/100)^3)*3.141592654) & @CRLF) Next ConsoleWrite('Time: ' & TimerDiff($t) & @CRLF) ConsoleWrite(@CRLF) ;~ ; Ansatz mit Lookup-Table & linearer Interpolation Local $FFB = _FFB_Create1D(myFunc, 0, 5, 100) Local $t = TimerInit() For $i = 80 To 90 Step 1 Local $v = _FFB_Call1D($FFB, $i / 100, 0.01) ConsoleWrite('r = ' & StringFormat('% 5.3f', $i / 100) & ' -> Vol = ' & StringFormat('% 6.4f +- % 6.4f', $v[0], $v[1]) & ' err = ' & StringFormat('% 6.4f', $v[0] - 4 / 3 * (($i / 100) ^ 3) * 3.141592654) & @CRLF) Next ConsoleWrite('Time: ' & TimerDiff($t) & @CRLF) ConsoleWrite(@CRLF) ; Der Trick ist jetzt, dass der LUT jetzt aufgebaut ist. Braucht man die Funktionswerte erneut ist das relativ schnell ; Auch für Funktionswerte die nicht "exakt" da liegen wo man schonmal gesampled hat. Je mehr sich der LUT füllt, desto schneller wird er. Local $t = TimerInit() For $i = 80 To 90 Step 1 Local $x = $i / 100 + Random(-0.05, 0.05) Local $v = _FFB_Call1D($FFB, $x, 0.01) ConsoleWrite('r = ' & StringFormat('% 5.3f', $x) & ' -> Vol = ' & StringFormat('% 6.4f +- % 6.4f', $v[0], $v[1]) & ' err = ' & StringFormat('% 6.4f', $v[0] - 4 / 3 * ($x ^ 3) * 3.141592654) & @CRLF) Next ConsoleWrite('Time: ' & TimerDiff($t) & @CRLF) ConsoleWrite(@CRLF) Func _FFB_Call1D(ByRef $FFB, $x, $nAccuracy = 0.01, $iIterMax = 100) Local $iSteps = UBound($FFB) - 1 Local $k = ($x - $FFB[$iSteps][1]) / $FFB[$iSteps][2] * ($iSteps - 1) Local $i = Int($k), $ix = ($i / ($iSteps - 1) * $FFB[$iSteps][2] + $FFB[$iSteps][1]) ; Unterer Slot Local $j = $i + 1, $jx = ($j / ($iSteps - 1) * $FFB[$iSteps][2] + $FFB[$iSteps][1]) ; Oberer Slot Local $alpha = $k - $i ; $alpha = Prozentsatz vom darüberliegenden Slot Local $f = $FFB[$iSteps][0], $v = 0, $t = 0 If $i >= 0 And $i < $iSteps Then If $FFB[$i][2] < $__FFB_MIN_SAMPLES Then Local $p[] For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1 $p[$_] = $f($ix) $FFB[$i][0] += $p[$_] Next $FFB[$i][0] /= $__FFB_MIN_SAMPLES For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1 $FFB[$i][1] += ($p[$_] - $FFB[$i][0]) ^ 2 Next $FFB[$i][2] = $__FFB_MIN_SAMPLES EndIf $t = 0 While Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1) > $nAccuracy $v = $f($ix) $FFB[$i][0] = ($FFB[$i][0] * $FFB[$i][2] + $v) / ($FFB[$i][2] + 1) $FFB[$i][1] += ($v - $FFB[$i][0]) ^ 2 $FFB[$i][2] += 1 $t += 1 If $t >= $iIterMax Then ExitLoop WEnd EndIf If $j >= 0 And $j < $iSteps Then If $FFB[$j][2] < $__FFB_MIN_SAMPLES Then Local $p[] For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1 $p[$_] = $f($jx) $FFB[$j][0] += $p[$_] Next $FFB[$j][0] /= $__FFB_MIN_SAMPLES For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1 $FFB[$j][1] += ($p[$_] - $FFB[$j][0]) ^ 2 Next $FFB[$j][2] = $__FFB_MIN_SAMPLES EndIf $t = 0 While Sqrt($FFB[$j][1]) / ($FFB[$j][2] - 1) > $nAccuracy $v = $f($jx) $FFB[$j][0] = ($FFB[$j][0] * $FFB[$j][2] + $v) / ($FFB[$j][2] + 1) $FFB[$j][1] += ($v - $FFB[$j][0]) ^ 2 $FFB[$j][2] += 1 $t += 1 If $t >= $iIterMax Then ExitLoop WEnd EndIf Local $Ret[] If Abs($alpha) < 1E-3 Then $Ret[0] = $FFB[$i][0] $Ret[1] = Sqrt($FFB[$i][1] / ($FFB[$i][2] - 1)) ElseIf Abs($alpha - 1) < 1E-3 Then $Ret[0] = $FFB[$j][0] $Ret[1] = Sqrt($FFB[$j][1] / ($FFB[$j][2] - 1)) Else $Ret[0] = $FFB[$i][0] * (1 - $alpha) + $FFB[$j][0] * $alpha $Ret[1] = (Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1)) * (1 - $alpha) + (Sqrt($FFB[$j][1]) / ($FFB[$j][2] - 1)) * $alpha EndIf Return $Ret ; [0] = Wert, [1] = Unsicherheit EndFunc ;==>_FFB_Call1D Func _FFB_Create1D($xFunc, $fMinInclusive = 0, $fMaxInclusive = 1, $iSteps = 100) Local $_[$iSteps + 1][3] $_[$iSteps][0] = $xFunc $_[$iSteps][1] = $fMinInclusive $_[$iSteps][2] = $fMaxInclusive - $fMinInclusive ; [0] = Mittelwert ; [1] = VarianzSumme ; [2] = NumSamples Return $_ EndFunc ;==>_FFB_Create1D
Edit: Hier noch eine Überarbeitung mit quadratischer Interpolation (so kann man den LUT etwas kleiner wählen, oder man möchte eine sehr weiche Kurve. Die gab es bei der linearen Version nicht).
AutoIt
Alles anzeigen#include <Array.au3> Global Const $__FFB_MIN_SAMPLES = 17 Global Const $__FFB_NUM_MAXITER = 100 ; Anwendungsfall: Funktionswerte entstören Func myFunc($r) Return Sin($r) + Random() / 3 ; sin ist im Bereich -1 bis 1, mit 1/3 plusminus rauschen ist das schon ziemlich viel. EndFunc ;==>myFunc Local $FFB = _FFB_Create1D(myFunc, -10, 10, 100) ; Hat 100 Slots zwischen -10 und 10 For $i In __FFB_Range('[', -3.141, 3.141, ']', 200) ; Die 200 Samples brauchen nur ca. 33 Slots. Durch die quadratische Interpolation kommt trotzdem eine gute Kurve heraus. Local $v = _FFB_Call1D($FFB, $i[1], 0.0005, 1e9, 100000) ; Wenn man es wirklich ganz genau haben will. (0.0005 Sigma, da will man schon 3 richtige Nachkommastellen haben) ConsoleWrite(StringFormat('% 5.3f', $i[1]) & ', ' & StringFormat('% 6.4f', $v[0]) & @CRLF) Next _ArrayDisplay($FFB) ; Nachschauen was im LUT eigentlich drin steht. Func _FFB_Train1D(ByRef $FFB, $nAbsAccuracy = 1e9, $nRelAccuracy = 1e9) Local $iSteps = UBound($FFB) - 1 Local $fMin = $FFB[$iSteps][1] Local $fMax = $FFB[$iSteps][2] + $FFB[$iSteps][1] Local $bTargetMet = True, $v = 0 Do $bTargetMet = True For $i In __FFB_Range('[', $fMin, $fMax, ']', $iSteps) $v = _FFB_Call1D($FFB, $i[1], $nAbsAccuracy, $nRelAccuracy) If $v[1] > $nAbsAccuracy Then $bTargetMet = False If $v[0] > 1E-9 And $v[1] / $v[0] > $nRelAccuracy Then $bTargetMet = False Next Until $bTargetMet EndFunc ;==>_FFB_Train1D Func _FFB_Call1D(ByRef $FFB, $x, $nAbsAccuracy = 1e9, $nRelAccuracy = 1e9, $iIterMax = $__FFB_NUM_MAXITER, $bQuadraticInterpolation = True) Local $iSteps = UBound($FFB) - 1, $s5 = $iSteps - 5, $s5d = $s5 / $FFB[$iSteps][2] Local $k = ($x - $FFB[$iSteps][1]) * $s5d + 2, $ik = Int($k) ; Slots: [ik-1, ik, ik+1, ik+2] <- diese 4 sind immer vorhanden. Local $alpha = $k - $ik ; $alpha = Prozentsatz vom darüberliegenden Slot Local $f = $FFB[$iSteps][0], $v = 0, $t = 0 For $i = $ik - 1 To $ik + 2 Step 1 ; from -1 to 2 -> Für 4 Slots. Local $ix = ($i - 2) / $s5d + $FFB[$iSteps][1] If $FFB[$i][2] < $__FFB_MIN_SAMPLES Then Local $p[] For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1 $p[$_] = $f($ix) $FFB[$i][0] += $p[$_] Next $FFB[$i][0] /= $__FFB_MIN_SAMPLES For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1 $FFB[$i][1] += ($p[$_] - $FFB[$i][0]) ^ 2 Next $FFB[$i][2] = $__FFB_MIN_SAMPLES EndIf $t = 0 While Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1) > $nAbsAccuracy Or ($FFB[$i][0] > 1E-9 And Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1) / $FFB[$i][0] > $nRelAccuracy) $v = $f($ix) $FFB[$i][0] = ($FFB[$i][0] * $FFB[$i][2] + $v) / ($FFB[$i][2] + 1) $FFB[$i][1] += ($v - $FFB[$i][0]) ^ 2 $FFB[$i][2] += 1 $t += 1 If $t >= $iIterMax Then ExitLoop WEnd Next Local $Ret[] If $bQuadraticInterpolation Then Local $ixa = ($ik - 3) / $s5d + $FFB[$iSteps][1], $ixb = ($ik - 2) / $s5d + $FFB[$iSteps][1], $ixc = ($ik - 1) / $s5d + $FFB[$iSteps][1], $ixd = $ik / $s5d + $FFB[$iSteps][1] Local $P3L = __FFB_Func3P($ixa, $FFB[$ik - 1][0], $ixb, $FFB[$ik - 0][0], $ixc, $FFB[$ik + 1][0]) Local $P3H = __FFB_Func3P($ixb, $FFB[$ik - 0][0], $ixc, $FFB[$ik + 1][0], $ixd, $FFB[$ik + 2][0]) $Ret[0] = ($P3L[0] * $x^2 + $P3L[1] * $x + $P3L[2]) * (1 - $alpha) + ($P3H[0] * $x^2 + $P3H[1] * $x + $P3H[2]) * $alpha Else $Ret[0] = $FFB[$ik][0] * (1 - $alpha) + $FFB[$ik + 1][0] * $alpha EndIf $Ret[1] = (Sqrt($FFB[$ik][1]) / ($FFB[$ik][2] - 1)) * (1 - $alpha) + (Sqrt($FFB[$ik + 1][1]) / ($FFB[$ik + 1][2] - 1)) * $alpha Return $Ret ; [0] = Wert, [1] = Unsicherheit EndFunc ;==>_FFB_Call1D Func _FFB_Create1D($xFunc, $fMinInclusive = 0, $fMaxInclusive = 1, $iSteps = 100, $nBorderEpsilon = 1E-6) $fMinInclusive -= $nBorderEpsilon $fMaxInclusive += $nBorderEpsilon Local $_[$iSteps + 1][3] $_[$iSteps][0] = $xFunc $_[$iSteps][1] = $fMinInclusive $_[$iSteps][2] = $fMaxInclusive - $fMinInclusive ; [i][0] = Mittelwert ; [i][1] = VarianzSumme ; [i][2] = NumSamples Return $_ EndFunc ;==>_FFB_Create1D Func __FFB_Range($sLeft = '[', $fMin = 0, $fMax = 1, $sRight = ']', $iSteps = 10) Local $a[$iSteps], $_[2], $l = $sLeft = '[' ? 0 : 1, $s = ($fMax - $fMin) / ($iSteps - 1 + ($sRight = ']' ? 0 : 1) + $l) For $i = 0 To $iSteps - 1 Step 1 $_[0] = $i $_[1] = ($i + $l) * $s + $fMin $a[$i] = $_ Next Return $a EndFunc ;==>__FFB_Range Func __FFB_Func2P($x0, $y0, $x1, $y1) Local $_[] ; f(x) = ax + b $_[0] = ($y1 - $y0) / ($x1 - $x0) $_[1] = $y0 - $_[0] * $x0 Return $_ EndFunc Func __FFB_Func3P($x0, $y0, $x1, $y1, $x2, $y2) Local $_[] ; f(x) = ax² + bx + c $_[0] = ($x2 * ($y1 - $y0) + $x1 * ($y0 - $y2) + $x0 * ($y2 - $y1)) / (($x0 - $x1) * ($x0 - $x2) * ($x1 - $x2)) ; a $_[1] = (($y1 - $y0) + $_[0] * ($x0 ^ 2 - $x1 ^ 2)) / ($x1 - $x0) ; b $_[2] = $y0 - $_[0] * $x0 ^ 2 - $_[1] * $x0 ; c Return $_ EndFunc
lg
M
-
In der deutschen Übersetzung fälschlich "Blitz"
Jedes Mal, wenn ich auf der MS Seite etwas nachschlage und diese furchtbaren deutschen Übersetzungen (teilweise von Naturkonstanten wie "BLACKNESS" beim BitBlt) sehe, klicke ich "diese Seite war nicht hilfreich" an und schreibe in den Kommentar rein, dass sämtliche Wörter die mit Programmcode zu tun haben bitte nicht übersetzt werden sollen. Ich hab schon Tabellen mit Enums gesehen die man von Start bis Ende in die Tonne treten konnte weil fast alle Bezeichnungen falsch waren
Ist denen aber egal. Wenn ich nicht 90% der Namen von Sachen die ich dort suche schonmal gehört hätte wäre ich echt sauer, aus genanntem Grund bin ich nur "genervt" von sowas...
M
-
Moin,
wer kennt es nicht: Ich möchte eine Funktion f(t) -> (x(t),y(t)) zeichnen und wähle einfach 100 gleichverteilte Punkte in t um das zu tun. Das Ergebnis sieht mies aus. Ich wähle 200 Punkte. Immernoch mies. 1000 vielleicht? Okay, jetzt sieht es OK aus, aber weil meine Kurve irgendwo ein paar fiese Kanten & Peaks hat ist das Ergebnis immernoch nicht Pixelgenau... Also 10000 Punkte?
Anbei ist ein Skript mit 3 Methoden um eine Kurve zu zeichnen.
1. Linear (das was oben beschrieben wurde, 1 f(t) call pro Punkt)
2. Adaptiv (Zunächst mit niedriger Auflösung Linear, dann "schätzen" wo gute Orte für weitere Punkte sind, 1 f(t) call pro Punkt)
3. Adaptiv2 (Es wird mehr oder weniger via BruteForce herausgefunden wo gute Orte für weitere Punkte sind, "viele" f(t) calls pro Punkt)
Es sei angemerkt, dass nicht jede Funktion für jeden Anwendungsfall sinnvoll ist. 1 & 2 eignen sich für Echtzeitanwendungen (sie brauchen für ~100 Punkte nur ein paar Millisekunden, je nach PC). 3 ist dafür geeignet wenn man die Funktion mit den wenigst möglichen Punkten "nahezu" bestmöglich abbilden will und die benötigte Zeit keine Rolle spielt (z.B. wenn man die Punkte irgendwo puffert, dann muss man sie nur 1x berechnen und kann sie anschließend relativ performant anzeigen, weil es so wenige sind).
Die Geschwindigkeit ist leider ziemlich mies, da ich an einigen Stellen faul war (z.B. lineare Liniensuche statt Newton, etc.). Außerdem fehlen mir gewisse Datenstrukturen in AutoIt die ich, mangels Pointersupport, auch nicht nachbauen konnte (bzw. ich war einfach zu faul alles via DllStruct zu machen).
PS: Jede Funktion f(x) = ... lässt sich als f(x) = (x, y(x)) umschreiben, wie auch im Beispiel verwendet. Man muss also nicht zwingend f:R->R² Funktionen verwenden
Edit: Um zu demonstrieren, dass es auch mit "echten" R² Funktionen klappt kann man z.B. sowas hier verwenden:
CodeFunc F($t) Local $__[] $__[0] = $t * $iGuiW * 0.9 + $iGuiW * 0.05 $__[1] = 50 * ManyGauss($t * 100 - 60) + 100*(2*$t-1)^2 Local $a = 0.1, $cx = $iGuiW / 2, $cy = 0 Local $_[] $_[0] = $cx + ($__[0] - $cx) * Cos($a) - ($__[1] - $cy) * Sin($a) $_[1] = $cy + ($__[0] - $cx) * Sin($a) + ($__[1] - $cy) * Cos($a) Return $_ EndFunc
Eine gewöhnliche f(x) -> R Funktion könnte soetwas nicht abbilden, da einige x-Werte mehrere y-Werte besitzen. Fälle die in diesem Skript "nicht" abgedeckt sind, sind unstetige Funktionen. Falls es irgendwo einen "echten" Sprung in der Funktion gibt (z.B. Funktionen die aus mehreren Teilen bestehen die in einem Plot zu mehreren Linien führen), kann die hier gezeigte Methode nicht verwendet werden.
lg
M
-
Meine Frage wäre: Was möchtest du konkret aus den Daten herauslesen?
Soweit ich das verstehe sind die Daten wie folgt: Eintrag1 = [#Artikelnummer1 #Ankaufszahl1 #Verkaufszahl1, #DatumBzwZeitraum1, #WeitereInfos1], ... usw. für tausende Produkte und verschiedene Zeitpunkte/Zeiträume.Eine übliche Methode um ein Gefühl für Große Datenmengen zu bekommen ist erstmal die Ansicht verschiedener Scatterplots/Heatmaps (z.B. x-Achse = Datum, y-Achse = Verkaufszahl, Fabcode = Produkttyp. Hier muss man einiges an Kombinationen durchprobieren). Darin ergeben sich dann eindeutige Muster (je nachdem wie man den Plot parametrisiert), die man anschließend weiter auswerten kann.
Bin aber nicht sicher, ob dir hier AutoIt weiterhelfen kann... Also einen Scatterplot kann man schnell und einfach basteln, aber das kann z.B. Gnuplot ebenfalls (ganz ohne Programmieraufwand). Die "Analyse" wird sich bei AutoIt auch auf lineare Regression einzelner Plotabschnitte beschränken (siehe oben), der Informationsgewinn hält sich dabei aber in Grenzen. Den Trend erkennt man ja schon am Plot.Edit: Falls du Trends extrapolieren willst wird es auch eher knifflig und ich vermute da bist du bei Machine-Learning-Leuten besser aufgehoben. Die kennen sich mit Voodoo aus
lg
M -
Sieht fast genauso aus wie etwas das ich immer verwende um Maps in die Konsole zu verfrachten
Falls gemischte Keys (Integer-Keys & String-Keys) verwendet werden ist hier noch eine kleine Ergänzung:$sOut &= StringFormat('%s%-20s%s%s\n', $aC[$n], (IsString($k) And StringIsInt($k)) ? '"' & $k & '"' : $k, $vValue).
Damit sieht man eindeutig womit man es zu tun hat.
lg
M
-
Das ist ein super Beispiel. Hier wird Die Kugel einfach "Scheibchenweise" mit einer linearen Matrix gezeichnet, sodass insgesamt der Eindruck entsteht man hätte es irgendwie nichtlinear gelöst. Dafür muss man aber ein Sleep(100) einbauen und $iStep = 15 setzen, sonst sieht man das nicht weil es zu schnell und zu fein aufgelöst ist
-
Sehr interessant. Hier noch eine Idee: Finde eine Transformation um die Einzelpixelrechnung komplett aus dem Spiel zu nehmen.
Der Texturabdruck dieser Formel ist auch nicht ganz richtig für eine "korrekte" perspektivische Projektion einer Ebene auf eine Kugeloberfläche (Das Abbild ist eine um 45° gedrehte Raute). Da ich hier kein Profi bin ist Folgendes nur eine Vermutung: Die 3x2 Matrizen aus GDI+ werden hierfür wahrscheinlich nicht reichen, weil sie die Verzerrung nicht abbilden können. Dafür müsste man dann doch wieder nichtlineare Elemente einbringen die GDI+ nicht abbilden kann sodass man sie doch von Hand ausrechnen muss... Ist wahrscheinlich im Endeffekt kein Vorteil, aber ganz kurz dachte ich "vielleicht reicht die GDI+ übliche Matrix ja doch". Bin da kein Profi, von daher: Vielleicht bringt die Idee ja irgendwen weiter
Den Texturfootprint kann man mit folgendem Skript einsehen:
AutoIt
Alles anzeigen#include <GDIPlus.au3> #include <GUIConstantsEx.au3> OnAutoItExitRegister(_exit) Opt("GUIOnEventMode", 1) Global Const $PI = ACos(-1), $PI_2 = ASin(1), $PI_4 = ATan(1), $_2PI = $PI + $PI main() Func main() Local $mC = _b3d_createCanvas(1000, 750) ; start moving textured ball Local $mTexture = _b3d_importTexture(@ScriptDir & "\13h_310x156.bmp") _b3d_ballMoving($mC, 50, 1000/2, 750/2, 0, 0, $mTexture) ; GUI endless loop While Sleep(100) WEnd EndFunc ; demo function for drawing a moving ball Func _b3d_ballMoving(ByRef $mCanvas, Const $iRadius, Const $iXStart, Const $iYStart, $fVx, $fVy, $mTexture, Const $fRotX0 = 0, Const $fRotY0 = 0) Local $iXPos = $iXStart, $iYPos = $iYStart Local $fRotX = $fRotX0, $fRotY = $fRotY0 Local $fU = 2 * $PI * $iRadius Local $hBitmap = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\13h_310x156.bmp") Local $aSize = _GDIPlus_ImageGetDimension($hBitmap) Local $hCopy = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, $aSize[0], $aSize[1]) Local $hGFX = _GDIPlus_ImageGetGraphicsContext($hBitmap) Local $i = 0 Local $hPEN = _GDIPlus_PenCreate(0xFF808080, 3) Do $fVx = Sin($i/30) $fVy = Cos($i/30) $i += 1 ; clear old image _GDIPlus_GraphicsClear($mCanvas.Context, 0xFF303030) _GDIPlus_GraphicsDrawImageRect($hGFX, $hCopy, 0, 0, $aSize[0], $aSize[1]) ; draw textured sphere _b3d_drawTexturedSphere($mCanvas, $iXPos, $iYPos, $iRadius, $mTexture, $fRotX, $fRotY, $hBitmap) _GDIPlus_GraphicsDrawImage($mCanvas.Context, $hBitmap, 10, 550) _b3d_canvasShow($mCanvas) $iXPos += $fVx $iYPos += $fVy $fRotX += __b3d_modPos($fVy, $fU) / $fU * $_2PI $fRotY -= __b3d_modPos($fVx, $fU) / $fU * $_2PI Until $iXPos > 90000 _GDIPlus_PenDispose($hPEN) _GDIPlus_BitmapDispose($hBitmap) _GDIPlus_BitmapDispose($hCopy) EndFunc ; draws a sphere and map a texture on it Func _b3d_drawTexturedSphere(ByRef $mCanvas, $iMx, $iMy, $iR, $mTexture, $iRotX = 0, $iRotY = 0, $hTexture = 0) Local $iTexWidth = $mTexture.width Local $iTexHeight = $mTexture.height Local $iX, $iY, $iHalfChord, $iSegmentHeight Local $fXTex, $fYTex Local $iColor Local $aBitmap = $mTexture.Pixels ; faster than _GDIPlus_BitmapGetPixel Local $hBitmap = $mCanvas.Bitmap ; Koordinaten-Transformation als LUT um Doppelberechnung zu vermeiden ; Zum jeweiligen aktuellen Kreissegment (Radius - aktuelle Position im Kreis) wird die dazugehörige Koordinate im Texturraum berechnet Local $aTexCoordsY[$iR + 1][2] Local $aTexCoordsX[$iR + $iR + 1] Local $fRad, $fRadX, $fRadY, $fRadYBottom For $iH = 0 To $iR ; der Kreisbogenabstand vom Zenitpunkt (=Kugelwinkel in rad) $fRad = ASin(($iR-$iH) / $iR) ; upper half $fRadY = $fRad + $iRotX $aTexCoordsY[$iH][0] = Round(__b3d_modPos($PI_2 - $fRadY, $Pi) / $Pi * ($iTexHeight - 1)) ; lower half $fRadYBottom = $fRadY - $fRad - $fRad $aTexCoordsY[$iH][1] = Round(__b3d_modPos($PI_2 - $fRadYBottom, $Pi) / $Pi * ($iTexHeight - 1)) ; left half $fRadX = $PI - $fRad + $iRotY ; "+ $PI": um 0-Punkt auf Texturmitte zu platzieren $aTexCoordsX[$iH] = Round(__b3d_modPos($fRadX , $_2PI) / $_2PI * ($iTexWidth - 1)) ; right half $fRadXRight = $fRad + $PI + $iRotY ; "+ $PI": um 0-Punkt auf Texturmitte zu platzieren $aTexCoordsX[$iR + $iR - $iH] = Round(__b3d_modPos($fRadXRight, $_2PI) / $_2PI * ($iTexWidth - 1)) Next ; middle line (extra to avoid double processing): $iYTexMid = $aTexCoordsY[$iR][0] For $iX = $iMx - $iR To $iMx + $iR $fXTex = $aTexCoordsX[$iX - $iMx + $iR] $iColor = $aBitmap[$fXTex][$iYTexMid] DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hTexture, "int", $fXTex, "int", $iYTexMid , "uint", 0xFF00FFFF) DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $iX, "int", $iMy, "uint", $iColor) ; faster than extra _GDIPlus_BitmapSetPixel() Next ; rest of circle area For $iSegmentHeight = 0 To $iR - 1 ; halbe Sehnenlänge $iHalfChord = Int(Round(Sqrt(2*$iR*$iSegmentHeight - ($iSegmentHeight*$iSegmentHeight)))) ; Koordinaten des Quellpixels aus dem Texturbitmap $fYTex = $aTexCoordsY[$iSegmentHeight][0] $fYTexBottom = $aTexCoordsY[$iSegmentHeight][1] For $iX = $iMx - $iHalfChord To $iMx + $iHalfChord $fXTex = $aTexCoordsX[$iX - $iMx + $iR] ; draw top case $iColor = $aBitmap[$fXTex][$fYTex] $iY = $iMy + $iSegmentHeight - $iR DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hTexture, "int", $fXTex, "int", $fYTex , "uint", 0xFF00FFFF) DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $iX, "int", $iY, "uint", $iColor) ; draw bottom case $iColor = $aBitmap[$fXTex][$fYTexBottom] $iY = $iMy - $iSegmentHeight + $iR DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hTexture, "int", $fXTex, "int", $fYTexBottom , "uint", 0xFF00FFFF) DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $iX, "int", $iY, "uint", $iColor) Next Next EndFunc Func _b3d_importTexture($sPath) Local $mTexture[] Local $hBitmap = _GDIPlus_BitmapCreateFromFile($sPath) $mTexture.Bitmap = $hBitmap If @error Then Return SetError(@error, @extended, Null) $mTexture.width = _GDIPlus_ImageGetWidth($hBitmap) $mTexture.height = _GDIPlus_ImageGetHeight($hBitmap) ; convert to AutoIt-Array for faster pixel access Local $aBitmap[$mTexture.width][$mTexture.height], $x, $y For $x = 0 To $mTexture.width - 1 For $y = 0 To $mTexture.height - 1 $aBitmap[$x][$y] = _GDIPlus_BitmapGetPixel($hBitmap, $x, $y) Next Next $mTexture.Pixels = $aBitmap Return $mTexture EndFunc ; function to draw a filled circle on a bitmap Func _b3d_drawCircleFilled(ByRef $mCanvas, $iMx, $iMy, $iR, $sColor = "0xFFFFFFFF") Local $iX, $iY, $iHalfChord, $iSegmentHeight ; middle line (extra to avoid double processing): For $iX = $iMx - $iR To $iMx + $iR _GDIPlus_BitmapSetPixel($mCanvas.Bitmap, $iX, $iMy, $sColor) Next ; rest of circle area For $iSegmentHeight = 0 To $iR - 1 $iHalfChord = Round(Sqrt(2*$iR*$iSegmentHeight - ($iSegmentHeight*$iSegmentHeight))) For $iX = $iMx - $iHalfChord To $iMx + $iHalfChord $iY = $iMy + $iSegmentHeight - $iR _GDIPlus_BitmapSetPixel($mCanvas.Bitmap, $iX, $iY, $sColor) $iY = $iMy - $iSegmentHeight + $iR _GDIPlus_BitmapSetPixel($mCanvas.Bitmap, $iX, $iY, $sColor) Next Next EndFunc ; zeigt den aktuellen Zustand der Canvas (des Zeichnungsbitmaps an) Func _b3d_canvasShow(ByRef $mCanvas) _GDIPlus_GraphicsDrawImage($mCanvas.Graphic, $mCanvas.Bitmap, 0, 0) EndFunc Func _b3d_createCanvas($iWidth, $iHeight) ; map which holds all the necessary parameters Local $mCanvas[] $mCanvas.width = $iWidth $mCanvas.height = $iHeight ; Initialize GDI+ library _GDIPlus_Startup() ; create GUI $mCanvas.GUI = GUICreate("Ball 3D", $iWidth, $iHeight) GUISetBkColor(0x303030, $mCanvas.GUI) ;set GUI background color GUISetOnEvent($GUI_EVENT_CLOSE, _exit) GUISetState(@SW_SHOW, $mCanvas.GUI) ; create Canvas $mCanvas.Graphic = _GDIPlus_GraphicsCreateFromHWND($mCanvas.GUI) $mCanvas.Bitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $mCanvas.Graphic) $mCanvas.Context = _GDIPlus_ImageGetGraphicsContext($mCanvas.Bitmap) Return $mCanvas EndFunc ; positive modulo Func __b3d_modPos($divident, $divisor) Local $m = Mod($divident, $divisor) Return $m < 0 ? $m + $divisor : $m EndFunc Func _exit() _GDIPlus_Shutdown() Exit EndFunc
lg
M
-
p.s. für einen Hook hat MS ja 4ms als Wert festgelegt. Also müsste schon bei 10ms eigentlich die Progressproc abbrechen...
Hinweis: Das "Sleep()" von AutoIt kann keine kleineren Schritte als 10ms verwenden. Du kannst zum Spaß mal 1000x Sleep(4) laufen lassen und jeweils mit TimerInit & Timerdiff stoppen wie viel Zeit tatsächlich geschlafen wurde. Leider funktionieren auch alternative Methoden wie delayexecution oder nanosleep mit AutoIt nicht zuverlässig (manchmal schon, manchmal aber auch nicht... Zumindest nach meiner Erfahrung).
Das hilft dir jetzt nicht bei deinem Problem, aber die Info wollte ich loswerden, nicht dass du versuchst "Sleep(4)" anzuwenden und dich dann wunderst was hier eigentlich los istlg
M
-
The problem is:
- This is impossible as long as noone knows everything about map/struct itself (what exactly is TdlgDXImages2, Font, TcxImageList, etc.). You cannot assemble a mapping without knowing all members.
- This looks like a "map" from another programming language. If "everything" is known one might construct something with nested maps (in AutoIt) to represent the data but the memory layout will be vastly different. Also AutoIt does not allow to reinterpret_cast<map*>(ptr), so noone will be able to even get a memory dump of a map here (and vice versa). A dedicated function to r/w is needed.
- Wrapping this into a "struct" requires the knowledge of the whole memory layout. This is impossible, especially for maps with variant datatypes or other "unknown inner workings" like: What exactly is "[]" in memory? This looks like an empty list but only god knows how this is represented in RAM (assuming the shown binary data is a memory dump).
- etc.
Most people here are skilled in reading/writing code but I fear your request cannot be fulfilled by anyone without "the whole picture".
To sum it up:
- If "everything" about this map is known, it is possible to write a "ReadBinaryToNestedMap/WriteNestedMapToBinary" function.
- If you find someone who wants to do this (after "everything" is known) is another story.
M -
Mit Ausgangspunkt ist gemeint, dass man das als Vorstufe für einen Kompressionsalgorithmus verwenden kann. Üblicherweise bekommt man eine bessere Kompression, wenn irgendeine Struktur in den Daten vorliegt die man ausnutzen kann. In diesem Fall: Sehr viel mehr Nullen als Einsen, dafür aber etwas unstrukturierter. (Ist also für einen Kodierer der Muster erkennt ungeeignet, die Muster wurden ja quasi in Nullen umgewandelt)
Mögliche Folgeschritte wären:
- Lauflängenkodierung (ist intuitiv das erste was mir einfällt)
- Falls Lauflängenkodierung im Binärformat -> Arithmetische Entropiekodierung als Folgeschritt (huffman geht hier nicht besonders gut, da die Symbole nicht mehr aligned sind).
- Falls Lauflängenkodierung mit Tokens -> Irgendeine Entropiekodierung (hier hat man die Symbole einzeln -> Jede Methode geht) als Folgeschritt -> Fertig.
Probleme der aktuellen Methode:
- Je größer der LUT, desto länger ist die Warmlaufphase, da der LUT erstmal gefüllt werden muss
- Je größer der LUT, desto besser das Ergebnis nach der Warmlaufphase, aber man ist auf 16 Bit beschränkt.
Lösungsansatz den ich irgendwann ausprobiere:
- Baue einen beliebig großen "pseudo" LUT aus mehreren 8Bit Blöcken zusammen.
- So siehts aus: [Block n-2][Block n-1][Block n][Bit x] -> Akuell wird nur [Block n] verwendet um x vorherzusagen. Man könnte allerdings auch alle anderen Blöcke einbeziehen. Da hier (aus Stochastik-Sicht) keine Unabhängigkeit vorliegt (es ist also ein Unterschied ob ich ausgehend von [Block n-1 (8Bit)] und [Block n (8Bit)] das x vorhersage, oder ob ich einen einzigen 16Bit Block nehme) muss man für halbwegs gute Ergebnisse vermutlich eine Art Interleaving verwenden.Trivialbeispiel mit 4 x 8Bit Blöcken -> [aaaaaaaa][bbbbbbbb][cccccccc][dddddddd][x] -> 4 Vorhersagen mit den Blöcken ohne Änderung (habe keine Nummern drangeschrieben, die aaaaaaaa sind eigentlich a1a2a3...usw)
Zusätzlich mit Interleaving [abcdabcd][abcdabcd][abcdabcd][abcdabcd][x] -> 4 Weitere Vorhersagen für x
Eine Linearkombination (mit irgendwelchen Koeffizienten die ich nicht kenne) dieser 8 Vorhersagen dient als Approximation der Vorhersage die ein einziger 32Bit Block liefern könnte. Je mehr Vorhersagen mit verschieden Verwobenenen 8 Bit Blöcken man verwendet, desto besser die Approximation. Gleichzeitig sinkt die Warmlaufphase, da man nicht 2^32 Zustände, sondern (im Beispielfall) nur 8 * 2^8 = 2048 Zustände vollmachen muss. Ich schätze damit sind auch bei "normalem Text" 90%+ Nullen möglich (statt 79%). Wäre zumindest lustig, wenn das gehen würdeDanach kommt die "swap Methode" (aus dem Permutationen Komprimieren Thread) zum Einsatz (wobei hier die Nullen und Einsen geswappt werden um sie zu sortieren). Dann sind die Daten in folgender Form: [Bits zur Steuerung der Swaps][alle Einsen][alle Nullen]. Alle Einsen und Alle Nullen können als 2 Integer gespeichert werden, sodass die komprimierten Daten nur noch aus Swap-Positionen + 2 Int bestehen. Hehehe. Damit werde ich die Welt erobern.
M
-
Moin,
habe neulich nochmal über die LZ77 Methode nachgedacht und überlegt, dass man einen ähnlichen Effekt vermutlich auch deutlich einfacher bekommen kann. Die Idee ist folgendes:
- Die Daten sind Binär '010101...' und wir wollen eine "Mustererkennung" ohne wirklich irgendwas zu rechnen.
- Baue einen Lookuptable auf, der für jede Bitfolge (von z.B. 8 Bit) angibt, wie wahrscheinlich eine "0" oder eine "1" auf diese 8 Bit folgt.
- Laufe alle Daten durch und ersetze sie durch "0" oder "1", je nachdem ob die Vorhersage gestimmt hat. Aktualisiere den LUT entsprechend nach jedem Schritt.
- Das Ganze ist trivial reversibel.
- Für einen Lookuptable mit >8Bit wird eine Map mit Stringkeys verwendet (das ist langsam). Falls man das mal in einer anderen Sprache programmiert müsste die Methode extrem schnell sein (es ist im Prinzip nur triviales Bitgeschiebe und Lookups), sollte auch ASM-freundlich sein.
- Aktuell wird nichts komprimiert, sondern nur "die Anzahl der Nullen in den Binären Daten maximiert". Vielleicht kann man die Methode aber für irgendwas als Ausgangspunkt verwenden (z.B. Lauflängenkodierung, etc). Daher "Preprocessing", es ist ein Vorverarbeitungsschritt der redundante Daten durch Nullen ersetzt.
Vermutlich hatten schon hunderte Leute dieselbe Idee, und was besonderes ist es auch nicht (daher in Off-Topic). Vielleicht kann damit ja trotzdem jemand etwas anfangen
Beispiel mit zwei Datensätzen (oben im Skript via "GetSomeData" und "GetSomeData2") abrufbar. In der Konsole kann beobachtet werden die der Algorithmus "warmläuft", zu Beginn ändert sich fast nichts am Input (da jede Vorhersage daneben liegt), später bestehen die Daten aber zum Großteil aus Nullen (im Redundanten Fall bestehen sie quasi exklusiv aus Nullen). Getestet wurde nur rudimentär.
AutoIt
Alles anzeigen; Test Local $sOriginal = GetSomeData() ; Normaler Text ohne wiederholungen ;~ Local $sOriginal = GetSomeData2() ; Sehr redundanter Text Local $v = StringToStruct($sOriginal) ; Um jegliche Encoding Probleme zu umgehen -> Array of Bytes (kennt nur Bytes und sonst nichts) Local $b = StructToBin($v) Local $LUT_Bits = 16 ; Wert zwischen 1 und 16. Bis 8 Bit gehts "schnell" ab 8 Bit wirds langsam (StringLUT = Langsam). Größerer Table = besser (Falls genug Daten vorhanden sind, ab ca. 4KB ist ein 16Bit Table am besten) Local $c = PredictionEncode($b, $LUT_Bits) Stats($c, $LUT_Bits, 'encoded') Local $d = PredictionDecode($c, $LUT_Bits) Stats($d, $LUT_Bits, 'decoded') ConsoleWrite(($d = $b ? '+ OK' : '! FAIL') & @CRLF) ConsoleWrite('original: ' & $b & @CRLF) ConsoleWrite('reduced naive entropy: ' & $c & @CRLF) ConsoleWrite('restored naive entropy: ' & $d & @CRLF) Func Stats($x, $n, $info = '') StringReplace($x, '0', '', 0, 1) Local $zero = @extended StringReplace($x, '1', '', 0, 1) Local $one = @extended ConsoleWrite($info & ' Bits: ' & StringLen($x) & ' LUT-size: ' & StringRight(' ' & $n, 2) & ' #0: ' & $zero &StringFormat(' (%.1f%%)',(100*$zero/($zero+$one))) & ' #1: ' & $one & StringFormat(' (%.1f%%)',(100*$one/($zero+$one))) & @CRLF) EndFunc Func PredictionDecode($sBin, $n = 8) Local $intN = Int(2^$n) Local $_[$intN][2] ; Linearer Lookup für die letzten N bits: [i][0] = Akkumulierte Einsen, [i][1] = Anzahl Gesamt For $i = 0 To $intN - 1 Step 1 $_[$i][0] = 0.5 ; 50/50 chance zu Beginn. (da > 0.5 gecheckt wird ist das per default eine Null) $_[$i][1] = 1 ; Initialwert hat das Gewicht von 1. Ansich kann man jede Zahl >0 verwenden, aber 1 war intuitiv Next Local $start = $n + 1, $end = StringLen($sBin) Local $rest = '', $roll = StringLeft($sBin, $n) Local $iLast = '', $pred = '', $right = '', $iLUT = 0 If $n <= 8 Then ; Maps für einen schnellen Lookup [11111111] gehen leider nicht bis 16 Bit, also [1111111111111111] Local Static $Int256 = Int256() ; 8Bit Lookup ohne führende Nullen (da Integerkey) For $i = $start To $end Step 1 $iLast = Int($roll) $iLUT = $Int256[$iLast] $pred = ($_[$iLUT][0] / $_[$iLUT][1]) > 0.5 ? 1 : 0 $right = StringMid($sBin, $i, 1) = '1' ? 1 - $pred : $pred $_[$iLUT][0] += Int($right) ; 0 oder 1 $_[$iLUT][1] += 1 $rest &= $right $roll = StringTrimLeft($roll, 1) & $right Next Else ; Stringkeys sind wiederum in Ordnung, aber eben langsamer. Local Static $Int65536 = Int65536() ; 16Bit Lookup mit führenden Nullen (da Stringkey) For $i = $start To $end Step 1 $sLast = StringRight('0000000000000000' & $roll, 16) $iLUT = $Int65536[$sLast] $pred = ($_[$iLUT][0] / $_[$iLUT][1]) > 0.5 ? 1 : 0 $right = StringMid($sBin, $i, 1) = '1' ? 1 - $pred : $pred $_[$iLUT][0] += Int($right) ; 0 oder 1 $_[$iLUT][1] += 1 $rest &= $right $roll = StringTrimLeft($roll, 1) & $right Next EndIf Return StringLeft($sBin, $n) & $rest EndFunc Func PredictionEncode($sBin, $n = 8) Local $intN = Int(2^$n) Local $_[$intN][2] ; Linearer Lookup für die letzten N bits: [i][0] = Akkumulierte Einsen, [i][1] = Anzahl Gesamt For $i = 0 To $intN - 1 Step 1 $_[$i][0] = 0.5 ; 50/50 chance zu Beginn. (da > 0.5 gecheckt wird ist das per default eine Null) $_[$i][1] = 1 ; Initialwert hat das Gewicht von 1. Ansich kann man jede Zahl >0 verwenden, aber 1 war intuitiv Next Local $start = $n + 1, $end = StringLen($sBin) Local $rest = '', $roll = StringLeft($sBin, $n) Local $iLast = '', $pred = '', $right = '', $iLUT = 0 If $n <= 8 Then ; Maps für einen schnellen Lookup [11111111] gehen leider nicht bis 16 Bit, also [1111111111111111] Local Static $Int256 = Int256() ; 8Bit Lookup ohne führende Nullen (da Integerkey) For $i = $start To $end Step 1 $iLast = Int($roll) $iLUT = $Int256[$iLast] $pred = ($_[$iLUT][0] / $_[$iLUT][1]) > 0.5 ? 1 : 0 $right = StringMid($sBin, $i, 1) $_[$iLUT][0] += Int($right) ; 0 oder 1 $_[$iLUT][1] += 1 $rest &= ($pred = $right) ? 0 : 1 $roll = StringTrimLeft($roll, 1) & $right Next Else ; Stringkeys sind wiederum in Ordnung, aber eben langsamer. Local Static $Int65536 = Int65536() ; 16Bit Lookup mit führenden Nullen (da Stringkey) For $i = $start To $end Step 1 $sLast = StringRight('0000000000000000' & $roll, 16) $iLUT = $Int65536[$sLast] $pred = ($_[$iLUT][0] / $_[$iLUT][1]) > 0.5 ? 1 : 0 $right = StringMid($sBin, $i, 1) $_[$iLUT][0] += Int($right) ; 0 oder 1 $_[$iLUT][1] += 1 $rest &= ($pred = $right) ? 0 : 1 $roll = StringTrimLeft($roll, 1) & $right Next EndIf Return StringLeft($sBin, $n) & $rest EndFunc Func StringToStruct($sString) Local $vString = DllStructCreate('char s[' & StringLen($sString) & ']') $vString.s = $sString Return $vString EndFunc Func StructToString($vString) Local $v = DllStructCreate('char s[' & DllStructGetSize($vString) & ']', DllStructGetPtr($vString)) Return $v.s EndFunc Func BinToStruct($sBin) Local Static $Int256 = Int256() Local $vRet = DllStructCreate('byte b[' & Int(StringLen($sBin) / 8) & ']'), $k = 1 For $i = 1 To StringLen($sBin) Step 8 DllStructSetData($vRet, 1, $Int256[Int(StringMid($sBin, $i, 8))], $k) $k += 1 Next Return $vRet EndFunc Func StructToBin($vStruct) Local Static $Bin256 = Bin256() Local $vBytes = DllStructCreate('byte b[' & DllStructGetSize($vStruct) & ']', DllStructGetPtr($vStruct)), $sRet = '' For $i = 1 To DllStructGetSize($vStruct) Step 1 $sRet &= $Bin256[$vBytes.b(($i))] Next Return $sRet EndFunc Func Bin256() Local Static $Bin16 = Bin16() Local $Bin256[] For $i = 0 To 255 Step 1 $Bin256[$i] = $Bin16[Int($i/16)] & $Bin16[Int($i - Int($i/16) * 16)] Next Return $Bin256 EndFunc Func Int256() Local Static $Bin16 = Bin16() Local $Int256[] For $i = 0 To 255 Step 1 $Int256[Int($Bin16[Int($i/16)] & $Bin16[Int($i - Int($i/16) * 16)])] = $i Next Return $Int256 EndFunc Func Int65536() Local Static $Bin256 = Bin256() Local $Int65536[] ; Ja, Maps sind "langsamer" als Arrays bei sehr vielen Elementen. Ich habe die Zeiten hier nicht gestoppt. Vielleicht gehts schneller, ist aber für dieses Beispiel wurst. For $i = 0 To 65535 Step 1 $Int65536[$Bin256[Int($i/256)] & $Bin256[Int($i - Int($i/256) * 256)]] = $i ; StringKeys, da Array Indices hier nicht mehr gehen, da 1111111111111111 ungefähr 2^50 Next Return $Int65536 EndFunc Func Bin16() Local $Bin16[] $Bin16[0] = '0000' $Bin16[1] = '0001' $Bin16[2] = '0010' $Bin16[3] = '0011' $Bin16[4] = '0100' $Bin16[5] = '0101' $Bin16[6] = '0110' $Bin16[7] = '0111' $Bin16[8] = '1000' $Bin16[9] = '1001' $Bin16[10] = '1010' $Bin16[11] = '1011' $Bin16[12] = '1100' $Bin16[13] = '1101' $Bin16[14] = '1110' $Bin16[15] = '1111' Return $Bin16 EndFunc Func GetSomeData() Return 'Ich bin ein Teststring. Hier könnte alles mögliche stehen. Irgendwie muss ich ein paar KB Text voll bekommen... Wie könnte man das anstellen?' & _ 'Func Int65536()' & _ ' Local Static $Bin256 = Bin256()' & _ ' Local $Int65536[] ; Ja, Maps sind "langsamer" als Arrays bei sehr vielen Elementen. Es ist aber dennoch schneller als ein Funktionsaufruf oder irgendwelche zusätzlichen Operatoren.' & _ ' For $i = 0 To 65535 Step 1' & _ ' $Int65536[$Bin256[Int($i/256)] & $Bin256[Int($i - Int($i/256) * 256)]] = $i ; StringKeys, da Array Indices hier nicht mehr gehen, da 1111111111111111 ungefähr 2^50' & _ ' Next' & _ ' Return $Int65536' & _ 'EndFunc' & _ 'Leider lässt die Methode erst bei ziemlich viel Text (ein paar KB) die Muskeln spielen. Für sehr kleine Textmengen sind niedrige LUT Größen besser geeignet, wir wollen hier aber den 16-Bit Table verwenden!' & _ 'To use this method, one proves that the history of the given process can be recorded in an efficient way, such that the state of the process at any past time can be recovered from the current state and this record, and such that the amount of additional information that is recorded at each step of the process is (on average) less than the amount of new information randomly generated at each step. The resulting growing discrepancy in total information content can never exceed the fixed amount of information in the current state, from which it follows that the process must eventually terminate. This principle can be formalized and made rigorous using Kolmogorov complexity.[3]' & _ 'Ein bisschen Wikipediatext kann nicht schaden...' & _ 'An example given by both Fortnow[3] and Tao[4] concerns the Boolean satisfiability problem for Boolean formulas in conjunctive normal form, with uniform clause size. These problems can be parameterized by two numbers (k,t) where k is the number of variables per clause and t is the maximum number of different clauses that any variable can appear in. If the variables are assigned to be true or false randomly, then the event that a clause is unsatisfied happens with probability 2−k and each event is independent of all but r = k(t − 1) other events. It follows from the Lovász local lemma that, if t is small enough to make r < 2k/e (where e is the base of the natural logarithm) then a solution always exists. The following algorithm can be shown using entropy compression to find such a solution when r is smaller by a constant factor than this bound: ' & _ 'Zeilenumbrüche ignorieren wir mal. Selbstverständlich klappt es damit auch!' & @CRLF & _ 'Das hier kann super komprimiert werden: ------------------------------------------------------------------------------------------------------- ziemlich cool. 3.141592654' & @CRLF & _ 'blablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablabla' & _ 'Sooo wir sind jetzt bei 22336 Bits angekommen.' & _ 'Es folgen ein paar Stellen von PI damit "zufällige" Daten vorliegen: 3.1415926535 8979323846 2643383279 5028841971 6939937510 5820974944 5923078164 0628620899 8628034825 3421170679 8214808651 3282306647 0938446095 5058223172 5359408128 4811174502 8410270193 8521105559 6446229489 5493038196 4428810975 6659334461 2847564823 3786783165 2712019091 4564856692 3460348610 4543266482 1339360726 0249141273 7245870066 0631558817 4881520920 9628292540 9171536436 7892590360 0113305305 4882046652 1384146951 9415116094 3305727036 5759591953 0921861173 8193261179 3105118548 0744623799 6274956735 1885752724 8912279381 8301194912' & _ 'Ist nicht wirklich zufällig, aber man weiß was ich meine. Der Witz ist jetzt, wenn man die selben Zahlen wiederholt, werden sie fast komplett durch nullen ersetzt, weil genau diese Abfolge ja bereits bekannt ist:' & _ '3.1415926535 8979323846 2643383279 5028841971 6939937510 5820974944 5923078164 0628620899 8628034825 3421170679 8214808651 3282306647 0938446095 5058223172 5359408128 4811174502 8410270193 8521105559 6446229489 5493038196 4428810975 6659334461 2847564823 3786783165 2712019091 4564856692 3460348610 4543266482 1339360726 0249141273 7245870066 0631558817 4881520920 9628292540 9171536436 7892590360 0113305305 4882046652 1384146951 9415116094 3305727036 5759591953 0921861173 8193261179 3105118548 0744623799 6274956735 1885752724 8912279381 8301194912' & _ 'Das kann man jetzt im "reduced naive entropy" Stream beobachten :)' & @CRLF & _ 'Hier noch ein paar Plot-Daten:' & _ '# 256 Symbols' & @CRLF & _ '128 9.4' & @CRLF & _ '256 10.1' & @CRLF & _ '512 11.4' & @CRLF & _ '1024 11.7' & @CRLF & _ '2048 13.3' & @CRLF & _ '4096 16' & @CRLF & _ '35k Bits sollten zu Demonstrationszwecken ausreichen.' & _ 'In diesem Beispiel wird die Anzahl der Nullen von 55.9% auf 79.0% erhöht. Damit kann man doch bestimmt irgendwas anfangen (z.B. Lauflängencodierung etc...)' EndFunc Func GetSomeData2() Return 'Zu Demonstrationszwecken bei sehr redundanten daten gibts hier noch ein Beispiel:' & _ '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _ '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _ '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _ '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _ '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _ '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _ '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _ '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _ '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _ '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _ '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _ 'Das sind 44144 Bits und davon sind 97.9% Nullen' EndFunc
(Edit: Genau das Gleiche habe ich vor Urzeiten schonmal gebastelt (nur viel umständlicher) und den Code nicht mehr gefunden)
lg
M