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
Beiträge von Mars
-
-
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
-
Es gibt mehrere Möglichkeiten zur UI Gestaltung. Vermutlich ist es am einfachsten das ISN-AutoItStudio zu verwenden, wenn man eine Grafische Benutzeroberfläche haben will (ISN AutoIt Studio). Da ist ein GUI-Editor dabei.
Wenn man es via Code machen will (und sich schon etwas auskennt) habe ich dafür auch eine UDF: ([UIBB.au3] User Interface mit automatischer Anordnung der Ctrls - Vorschläge / Wünsche / Ideen). Die Beispiele dazu verwenden aber auch sehr viele Variablen wie "$hRightBot" etc. Das wurde dort so gemacht, damit man besser versteht wie die UDF arbeitet.
Edit: "UDF" = "User Defined Functions". Im AutoIt-Kontext steht der Begriff stellvertretend für "Bibliothek mit ein paar praktischen Funktionen die man via #include verwenden kann".
lg
M
-
Aufwandseinschätzung (von jemandem der sich mit AutoIt ein wenig auskennt):
- <15 Minuten (für das was bei dir im Screenshot angezeigt wird)
- ~1-5h (wenn man ein ordentliches UI haben will, ggf. mit Interaktionsmöglichkeiten wie "Spalte hinzufügen", "Items editieren", "Laden & Speichern", etc.. Aufwand abhängig davon wie viel man haben will)Startpunkt sollte sein: Verwende Arrays (oder Maps)
- Deine Items (also die Tupel aus "Name" und "Preis") -> In ein Array damit.
- Deine UI-Elemente ("ein" möglicher Lösungsweg) -> Jede Zeile in eine Map mit ['Name'] = LabelFürName, ['Anzahl'] = InputboxFürAnzahl, ['Einzelpreis'] = LabelFürPreis, etc. Dann ein Array (oder Map) für alle Zeilen anlegen, sodass man Zeilen dynamisch hinzufügen und entfernen kann.Ich weiß nicht wie versiert du im Programmieren im Allgemeinen bist, aber sehr viele AutoIt-Anfänger geben jedem UI-Element und allen anderen Sachen eigene Variablen (z.B. $LabelItem1Links, $LabelItem2Links, usw) und haben dann 500+ Zeilen an Copy&Paste um eine Tabelle anzuzeigen. Deshalb der Hinweis auf Arrays und Maps
Edit: Ich glaube du bist hier im falschen Forenabschnitt. Vermutlich wolltest du "Hilfe und Unterstützung" ?
lg
M
-
Ich weiß nicht ob dir das hilft, aber vor urzeiten (10 Jahre her) habe ich mal eine UDF geschrieben um Arrays auf die Platte zu schreiben (als einzelner String). Damals war der Map-Datentyp noch sehr experimentell, weshalb er nicht supported wird.
Ich kann leider keine Garantie dafür geben, dass alles so funktioniert wie es soll, da sich in der langen Zeit wohl irgendwas in der AutoIt-Internen Handhabung von "Binary" geändert hat (musste da eben ein paar Sachen fixen, vermutlich sind aber immernoch irgendwelche Fehler drin).
Was die UDF macht (bzw. machen soll):
- Nimm ein beliebiges 1D oder 2D Array (auch verschachtelt) und mache "einen einzigen String" daraus. (Es gibt Optionen dafür um GDI+Bitmaps, oder "Dateien" nicht als Pointer/String, sondern als "Bitmap" oder "Datei" zu interpretieren. In dem Fall werden die Bitmapdaten (mit .png Kompression, also nicht als Rohdaten) bzw. die komplette Datei eingefügt. Damit lässt sich die UDF auch als Container für Bitmaps und Dateien verwenden)
- Rekonstruiere dieses Array (incl aller Datentypen) wieder aus diesem String. Importierte Dateien werden NICHT automatisch irgendwo niedergeschrieben, sie sind als String im resultierenden Array. Importierte Bitmaps werden automatisch geladen und ein Pointer im Array hinterlegt.
- Dieser String lässt sich auch auf der Platte speichern (als Datei) und zu jedem späteren Zeitpunkt wieder auslesen.
Zur Sicherheit empfehle ich folgendes: Wandle dein Array in einen String um, speichere es als temporäre Datei. Lies diese Datei und mache wieder ein Array daraus. Vergleiche die Arrays vollständig. Nur wenn dieser Vergleich erfolgreich war ist das was auf der Platte liegt wirklich "das was du haben willst". Fall nicht -> Irgendwo ist ein bug den du mir gerne mitteilen kannst, dann schaue ich in der UDF und fixe das.
lg
M
-
Das liegt daran, weil es für diese Art von Problemen so viele Lösungen gibt
Jetzt haben wir:
- Verschachtelte Arrays (Indexbasiert)
- Verschachtelte Maps (Indexbasiert)
- Verschachtelte Maps (Stringkey basiert)
- SQLite (DB basiert, ist teil des Standards in AutoIt)
- JSON (Stringkey basiert, falls man es damit machen möchte, dann geht das auch, da gibts ne gute UDF)
- Dict (Stringkey basiert, mit BuiltIn Funktionen, oDict)
- Irgendwo habe ich neulich auch eine Table-UDF (für Tabellen) gesehen. Habe aber vergessen wo.
lgM
-
Ich bin bei Enums ganz altbacken und verwende Großbuchstaben und Unterstriche (auch wenn ich das im Fließtext nicht gemacht habe) ohne Datentyp (typisch für #Define in C).
Hier wäre das also sowas wie:
...
$OLIST_WIDTH, _ ; Spaltenindex in der Objektliste (die 2D Map) für das Feld "Breite"
...Das sieht dann zwar aus wie Code aus den 80ern (obwohl ich da noch nichtmal gelebt habe), ist für mich aber am besten Lesbar. Dann sieht man direkt was Globale Konstanten sind.
lg
M
-
Damit habe ich sowas gemeint wie _ObjectList_AddItem($mmList, $mItem), _ObjectList_GetItemByKey($mmList, $iFuesse), etc. Die üblichen Verdächtigen. Oder DB-Ähnliche Queries wie _ObjectList_GetAllItemsWith($mmList, $iKey, $xValue). (Den prefix 'mm' kann man auch weglassen. Der ist zur Übersicht, dass man nicht vergisst dass "List" eine "Map of Maps" ist. "x" steht für "Unbekannter Typ" und "i" für Integer)
Noch ein Hinweis zu Maps (der eigentlich offensichtlich ist, aber der hat mich schon einige Nerven beim debuggen gekostet): MapRemove erzeugt Löcher.AutoIt
Alles anzeigenLocal $_[] $_[0] = 'Null' $_[1] = 'Eins' $_[2] = 'Zwei' MapRemove($_, 1) For $i = 0 To UBound($_) - 1 Step 1 ; Falsch. Wirft aber keinen Error. ConsoleWrite($i & ' ' & $_[$i] & @CRLF) Next For $i In $_ ; Man hat keinen Index, bekommt aber alle Elemente (Alternative zu MapKeys) ConsoleWrite($i & @CRLF) Next
lg
M
-
Richtige Klassen und richtige Structs gibt es in AutoIt nach wie vor nicht. (DllStructs zählen nicht, die muss man von Hand verschachteln, und wenn man Strings als Datentyp hat muss man immer char[] verwenden was oft etwas nervig ist)
Maps verwende ich inzwischen quasi exklusiv, wenn es um "kleine Arrays", oder "Fake Klassen" geht. Mein Vorgehen ist dabei eigentlich immer wie folgt:
AutoItGlobal Enum $TYPE_VECTOR2 Func Vector2($vx = 0, $vy = 0) Local $_[] $_[0] = $vx $_[1] = $vy $_[99] = $TYPE_VECTOR2 Return $_ EndFunc
Der Trick ist nun, dass du via Switch $_[99] aussortieren kannst welche "Typen" wie behandelt werden.
Soweit ich das sehen kann sind Maps inzwischen stabil, haben keine Memory Leaks (zumindest keine die ich noch finden konnte, ich habe selbstverständlich danach gesucht), und zu allem Überfluss sind sie für Integer-Keys in den meisten Fällen schneller als Arrays (bis zu einer gewissen Größe).
Von daher:
- Mach dir eine 2D Map (Map of Maps). Die kann man via $Map[][] in 2D auch direkt lesen und schreiben und sie verhält sich bei Integer-Keys exakt wie ein 2D Array. Hat aber den Vorteil dass man Zeilen hinzufügen kann, während man ein Array nicht einfach erweitern kann. Ich persönlich verwende immer Integer-Keys und ein "Global Enum mit $Name, $ID, $Fuesse, $Teileliste" direkt zu Beginn. Maps "kann" man auch mit String-Keys verwenden, aber damit verwirre ich mich meistens eher selbst als dass es was bringt.
- In die erste Zeile kommen wie üblich die Eigenschaften (Name, ID, Füße, Teileliste, etc)
- Teilelisten kannst du auch als Map direkt dort ablegen und dann via "$Map[15][$TeileListe][0] = Erstes Teil" lesen und schreiben.
- Noch ein Vorteil von Integer-Keys (wenn du dich daran hältst sie von 0 an aufsteigend zu verwenden, ohne Lücken): UBound kann verwendet werden statt MapKeys -> Eine Map mit aufsteigenden Integer-Keys kann exakt wie ein Array verwendet werden. (Edit: Das gilt natürlich nicht für "Fake-Klassen" bei denen in der [99] der Typ steht)
Du müsstest natürlich sämtliche Funktionen dieser "Informationsliste" selbst schreiben. Fast alle davon sollten aber trivial sein.
Falls deine Objekteliste 10.000+ Einträge hat ist diese Methode vermutlich zu langsam / zu aufwendig. Dann brauchst du vermutlich eine DB und damit kenne ich mich nicht aus
Edit: Genau für diesen Fall hat AspirinJunkie vermutlich eine geeignete UDF.
lgM
-
Hatte vor Urzeiten auch mal was angefangen: Eine Makrosammlung für C++ (die hinten und vorne nicht funktioniert hat und inzwischen unauffindbar verschwunden ist, vermutlich irgendwann gelöscht beim PC neu aufsetzen...).
Die Idee dahinter war, dass man AutoIt-Code "fast" 1:1 als C++ laufen lassen kann, sofern man die richtigen Makros/Klassen definiert hat (ein bisschen Preprocessing ist trotzdem notwendig). Als jemand der ausschließlich Windows nutzt war der Plan dahinter aber nicht, dass Linux unterstützt wird (das könnte ich gar nicht machen, da kenne ich mich kein Stück aus). Das war einfach eine Spielerei.
M
-
Wahnsinn, wer hätte gedacht dass es es mal AutoIt-Videos auf Deutsch gibt
So ein paar verstreute Beispiele habe ich irgendwo schonmal gesehen, aber mehr ist mehr
lg
M
-
Das ist doch alles nur Spaß
-
(Ich habe meinen Beitrag noch 5x editiert, aber da war die Antwort schon da )
Je komplizierter desto besser. Hmm... stimmt. Die Entropie muss auch noch an anderer Stelle ergänzt werden, weil die "Ziehungen" nicht unabhängig voneinander sind (es ist ja eine Ziehung ohne Zurücklegen) was in der Entropie nicht berücksichtigt wird... (also Wahrscheinlichkeitsverteilung nach jedem Schritt renormieren). Und dann noch das mit den Fehlversuchen die man erst weiß nachdem man danebenlag... Und die Wahrscheinlichkeitsverteilung von Nutzereingaben die sich von der üblichen Buchstabenhäufigkeit unterscheidet...
Ich glaube das wird mir zu kompliziert.
-
- Die Anzahl der Versuche richtet sich nach dem zufällig ausgewähltem Wort:
Mein Vorschlag (mit nicht ganz trivialer Stochastik) zur Berechnung der Anzahl der Fehlversuche wäre daher hierzu folgender:
Da habe ich direkt an folgende Methode gedacht:
Die Entropie eines Worts ist (ungefähr) proportional zur Anzahl Bits, die eine Huffman-Kodierung (mit einem Tree der mit Wahrscheinlichkeiten für deutsche Buchstaben erstellt wurde) von diesem Wort ergibt. Mit unseren bereits implementierten Huffman-Kodierern sollte das trivial machbar sein (bzw. einfach mit der Entropieformel und der Wahrscheinlichkeitsverteilung der Buchstaben, den Kodierer braucht man ja nicht).Ein Problem ist natürlich, dass beim Galgenraten automatisch "alle" Vorkommen des Buchstabens und nicht nur das erste aufgedeckt werden, sodass die reine Entropie hier einen "zu großen" Wert liefert. Vermutlich reicht es das Wort auf die ersten Vorkommnisse zusammenzustauchen: "vorkommnisse" -> "vorkmnise", und dann die Entropie zu berechnen. Der Wert dafür müsste eigentlich ein guter Indikator dafür sein wie kompliziert es ist das Wort "zufällig, aber mit dem Wissen über die Buchstabenverteilung" zu erraten.
In deiner stochastischen Analyse gehst du von einer Gleichverteilung der Buchstaben aus. Das sollte ein wenig zu kleine Ergebnisse liefern. Vielleicht kann man das irgendwie kombinieren und den "Ultimativen Galgenraten Versuchsanzahl Abschätzer" entwickelnlg
M
- Die Anzahl der Versuche richtet sich nach dem zufällig ausgewähltem Wort:
-
Mir wäre das zu viel Text. Wenn ich eine 100 Zeichen Nachricht verschlüsseln will hätte ich keine Lust, dass 300 Zeichen herauskommen. Erst recht wenn man das im Kopf machen muss, so viel RAM hab ich gar nicht
Aber es kann nicht passieren, das hier ein Fehler auftritt.
Das schreibe ich in Zukunft in meine Codekommentare direkt neben "this should never happen".
-
Auf ein Beispiel was du wirklich meinst, wäre ich ECHT gespannt!...und ich bin ziemlich sicher...DU AUCH!
Tatsache. Ich habe nur die Hälfte von dem geschrieben was ich mir dabei gedacht habe, so ergibt das natürlich keinen Sinn (bzw. es ist einfach falsch)
Eigentlich wollte ich da auf die Unterschiede zwischen Clamp und BitAnd eingehen (also aus einer Zahl das 0x00??0000 via BitAnd und Div 256^n rausholen vs: Die gesuchte Zahl berechnen und clampen). Dann dachte ich mir, dass das wahrscheinlich nichts bringt und habe den halben Text irgendwie trotzdem geschrieben. Mysteriös.
lg
M
-
Schau dir BitOr, oder die Addition im Hexadezimalsystem an.
Beispiel:
Du hast: 0xRRGGBB (hex). Jeder dieser Teile hat 8 Bit. Es sind also 0xRR0000 + 0x00GG00 + 0x0000BB
Du möchtest: 0xAARRGGBB, es fehlt also der 0xAA000000 Teil. Je nachdem wie du das angehen möchtest kannst du also "einfach" 0xFF000000 addieren, oder (was sicherer ist, da es das Überlaufen in benachbarte Bytes verhindert, falls einzelne Werte größer als 255 sind. Das sollte bei hardgecodeten Werten nicht passieren, wenn die Werte aber berechnet werden und ein Clamp fehlt macht das beim einfachen Addieren die Farben kaputt) ein BitOr verwenden. Noch eine Alternative wäre das Zerlegen in Strings, sodass man via Int("0xFF" & "1A49BC") ebenfalls zum Ergebnis kommt (das wäre die "nicht mathematische Lösung").
lg
M
-
Mit "das größte Problem sind Datenstrukturen" habe ich natürlich ne steile These hingelegt. Sobald man mit "auto", "impl", Templates oder überladenen Operatoren anfängt (da weiß schon intellisense manchmal nicht mehr was der Code eigentlich macht) ist das Spiel sowieso vorbei
Mit der Geschwindigkeit (also dass man Code ziemlich doll umschreiben muss damit er in AutoIt ebenfalls "schnell" läuft) habe ich "relative geschwindigkeit" gemeint. Natürlich ist AutoIt 1000x langsamer, wenn man mies übersetzt ist es aber 5000x.
Mein Trip endet, sobald meine aktuelle Aufgabe endet.
Dann kommt die nächste Aufgabe und damit der nächste Trip
lg
M
-
Gerade bei der Geometrieverarbeitung erwartet dich in AutoIt nur Trauer und Schmerz. Ich habe selbst einiges aus C++ nach AutoIt übersetzt um einfache Tools zu basteln, und man merkt immer und immer wieder wie Pointer und Datenstrukturen fehlen.
Das ist auch das allergrößte Hindernis an einem Übersetzungsprogramm: Datenstrukturen. (das 2t größte Hindernis sind die 10.000 Stunden Aufwand die ein Übersetzer kostet)
Ja, wir haben DllStruct in AutoIt, die können aber nur primitive Datentypen halten. Möchte man verschachtelte Datenstrukturen verwenden muss man das mit Pointern erledigen. Um Pointer effektiv nutzen zu können muss man via DllstructCreate und kernel32-alloc manuell dafür sorgen, dass die Datenstruktur nicht gelöscht wird sobald keine AutoIt-Variable mehr vorhanden ist die sie hält (man will ja nur den Pointer haben), zusätzlich muss man aber irgendwie trotzdem dafür sorgen, dass der Speicher später freigegeben wird (ist möglich, aber unschön). Möchte man Datenstrukturen "in place" verwenden (z.B. Ball = (float x, float x, float diameter), BallPark = (Ball[10])) um z.B. direkt über alle "Ball" zu loopen muss man im Prinzip rekursives unrolling und alignment betreiben (sodass in der endgültigen Struct nur noch primitive vorhanden sind, die man dann auf umständliche Art und Weise via in Place erzeugter Struct anspricht). usw usw. Da kann man sich auch gleich nen eigenen Speichermanager schreiben. Was wahrscheinlich sowieso mal bitter nötig wäre, wenn man jemals über die "Struct die Primitive enthält" hinauskommen möchte.
Außerdem sind DllStructs in AutoIt deutlich langsamer als z.B. Arrays (oder seit einiger Zeit Maps mit IntegerKeys... die aus "Gründen" schneller sind als Arrays, solange die Größe < 256 Elemente ist). Was in C++ ein immenser Geschwindigkeitsvorteil ist (z.B. loop über alle "Ball", wenn sie aligned im Speicher liegen) ist in AutoIt unfassbar langsam (loop in verschachtelten Arrays/Maps). Apropos verschachtelte Arrays/Maps: Es gibt in AutoIt KEIN same scope ByRef. Du kannst den Inhalt eines Verschachtelten Arrays nicht direkt ansprechen. In der Klammersyntax ($A[0])[0] kann ein Array das in $A[0] liegt nur gelesen, aber nicht geschrieben werden, außerdem wird jedes Mal dereferenziert, wenn man das macht -> Langsam. Einziger Umweg ist über Funktionen mit ByRef Parameter, dann hat man aber den Overhead eines Funktionsaufrufs, was sich nur lohnt, wenn das Array das man beschreiben will eine gewisse Größe hat, für kleine Arrays ist 2x Kopieren schneller als 1x Funktionsaufruf mit ByRef.
Was ich damit eigentlich sagen will: Code der in C++ richtig schnell läuft muss komplett umstrukturiert werden um in AutoIt ebenfalls schnell zu laufen.Es ist schon echt nervtötend "einfache" Sachen aus C++ von Hand zu übersetzen (ich meine nicht platten C-Code (flat API), der geht natürlich easy), und ich bin nicht in der Lage mir ein automatisches Programm dafür auch nur vorstellen zu können...
Edit: Hier mal ein Beispiel das wirklich nur für diesen einen Spezialfall funktioniert:
- Zeigt wie man "in place" eine Liste aus Structs in einer Struct bastelt, die auch (nur in diesem Fall hier) korrekt im Speicher liegt und daher von C++ 1:1 übernommen werden könnte (falls man 32bit aligned ist. bei 128 wird die Ball Struct noch 32Bit padding am Ende bekommen. Wenn man Vektorisierung angeschaltet hat wird das wahrscheinlich so sein, dann kann der Compiler auch automatisch sse verwenden, dann mag er 4x32er Blöcke lieber).
- mit "Spezialfall" meine ich z.B.: Der Typ "BALL" und der Feldname "ball" muss im UpperCase-Fall identisch sein. Man kann nicht mehrere Felder mit "BALL" Typ haben. "BALL" darf keine Feldnamen wie x, y, d haben. Und unendlich + 2 weitere Einschränkungen. Das ist kein Code den ich für irgendwas sinnvolles verwenden würde, er dient nur als Minimalbeispiel.
- Wenn man das "allgemein" Lösen will ist man Monate dran (und nicht die 15 Minuten die mich dieses Beispiel gekostet hat) und hat danach immernoch unendlich viele Bugs.
AutoIt
Alles anzeigen#include <Array.au3> #include <Memory.au3> Global $_DN[] ; Structnamen hinterlegen Global $_DS[] ; Sizes DllStructRegister('BALL;float;float;float') ; numBalls ist nur hier damit man zeigen kann wie man "in diesem Fall hier" das Offset berechnen kann. numBalls wird nicht verwendet. $balls = DllStructCreate2('int numBalls;BALL ball[10]') $oneBall = DllStructCreate2('Ball') DllStructSetData($oneBall, 1, 1) DllStructSetData($oneBall, 2, 2) DllStructSetData($oneBall, 3, 3) For $i = 0 To 9 Step 1 DllStructSetData($oneBall, 1, Random(0, 10, 1)) DllStructSetData($oneBall, 2, Random(0, 10, 1)) DllStructSetData($oneBall, 3, 7) DllStructSetData2($balls, 'ball', $i, $oneBall) ; memcpy Next For $i = 0 To 9 Step 1 $v = DllStructGetData2($balls, 'ball', $i) ; $v ist jetzt die "Ball" Struct (Kopie) ConsoleWrite('Type: ' & VarGetType($v) & ' size: ' & DllStructGetSize($v) & ' -> ') ConsoleWrite('Ball[' & $i & ']: ' & DllStructGetData($v, 1) & ', ' & DllStructGetData($v, 2) & ', ' & DllStructGetData($v, 3) & @CRLF) Next Func DllStructSetData2($v, $sName, $i, $xValue) If MapExists($_DS, StringUpper($sName)) Then Local $size = $_DS[StringUpper($sName)] Local $sStruct = $_DN[StringUpper($sName)] Local $iOffset = DllStructGetPtr($v, $sName) - DllStructGetPtr($v) Return _MemMoveMemory(DllStructGetPtr($xValue), DllStructGetPtr($v) + $iOffset + $size * $i, DllStructGetSize($xValue)) EndIf DllStructSetData($v, $sName, $xValue, $i) EndFunc Func DllStructGetData2($v, $sName, $i) If MapExists($_DS, StringUpper($sName)) Then Local $size = $_DS[StringUpper($sName)] Local $sStruct = $_DN[StringUpper($sName)] Local $iOffset = DllStructGetPtr($v, $sName) - DllStructGetPtr($v) Return DllStructCreate($sStruct, DllStructGetPtr($v) + $iOffset + $size * $i) EndIf Return DllStructGetData($v, $sName, $i) EndFunc Func DllStructCreate2($sStruct) Local $a = StringSplit($sStruct, ';', 2), $b, $s = '', $c, $d For $i = 0 To UBound($a) - 1 Step 1 If StringInStr($a[$i], '[', 0, 1) Then $b = StringSplit($a[$i], '[', 2) ; TYPE name $c = StringSplit($b[0], ' ', 2) If MapExists($_DN, StringUpper($c[0])) Then $d = StringSplit($_DN[StringUpper($c[0])], ';', 2) $s &= $d[0] & ' ' & $c[1] & ';' For $j = 1 To UBound($d) - 1 Step 1 $s &= $d[$j] & ';' Next For $j = 0 To Number(StringTrimRight($b[1], 1)) - 2 Step 1 $s &= $_DN[StringUpper($c[0])] & ';' Next Else $s &= $a[$i] & ';' EndIf Else If MapExists($_DN, StringUpper($a[$i])) Then $s &= $_DN[StringUpper($a[$i])] & ';' Else $s &= $a[$i] & ';' EndIf EndIf Next ConsoleWrite($s & @CRLF) $s = StringTrimRight($s, 1) ; remove ';' Return DllStructCreate($s) EndFunc Func DllStructRegister($sStruct) Local $sName = StringSplit($sStruct, ';', 2)[0] $sStruct = StringTrimLeft($sStruct, StringLen($sName) + 1) $_DN[StringUpper($sName)] = $sStruct ; String Key Local $_ = DllStructCreate($sStruct) $_DS[StringUpper($sName)] = DllStructGetSize($_) EndFunc
lg
M