Ansonsten ja, keine Includes und keine DllCalls.
Dann sieht es ganz danach aus, dass Dein Username nichts mit Deinen AutoIt-Kenntnissen zu tun hat. ![]()
![]()
Ansonsten ja, keine Includes und keine DllCalls.
Dann sieht es ganz danach aus, dass Dein Username nichts mit Deinen AutoIt-Kenntnissen zu tun hat. ![]()
![]()
aber ansonsten gefallen mir die Werte schon ganz gut:
Beeindruckend! Super Werte! Sowol die Ratio, als auch die Geschwindigkeit.
Nur AutoIt-Code?
könntest du bei der Prüfroutine eine Abfrage einbauen, ob die Daten binär sind? StringLen wandelt die Binärdaten in Hex und gibt dadurch die doppelte Länge zurück.
Wir können die Auswertung komplett auf BinaryLen umstellen, da BinaryLen auch bei Strings "richtige" Werte zurückgibt.
Legeiich mit GUICtrlSetBkColor für Buttons eine Hintergrundfarbe fest, so erhält der erste Button den Tastatur-Focus.
Das hat nichts mit GUICtrlSetBkColor zu tun, sondern damit, dass Windows standardmäßig immer dem ersten Button den Eingabe-Fokus zuweist.
Benutze einen Dummy-Button oder ein anderes Input-Controlelement, um den Fokus dorthin zu legen:
#include <GuiButton.au3>
#include <GUIConstantsEx.au3>
GUICreate("My GUI Button", 300, 200, 0, @DesktopHeight / 2)
Global $Dummy = GUICtrlCreateButton("", -2, -2, 0, 0)
Opt("GUICoordMode", 2)
Global $Button_1 = GUICtrlCreateButton("ja", 10, 30, 100)
$yy = _GUICtrlButton_GetFocus($Button_1)
GUICtrlSetBkColor(-1, 0xFEFE00)
$yyy = _GUICtrlButton_GetFocus($Button_1)
Global $Button_2 = GUICtrlCreateButton("nein", 0, -1)
$zz = _GUICtrlButton_GetFocus($Button_2)
GUICtrlSetBkColor(-1, 0xFEFE00)
GUISetState()
;~ _GUICtrlButton_SetFocus($Dummy)
$yyyy = _GUICtrlButton_GetFocus($Button_1)
$zzzz = _GUICtrlButton_GetFocus($Button_2)
MsgBox(0, "", "$yy::" & $yy & " $yyy:: " & $yyy & " $yyyy:: " & $yyyy & " $zzzz:: " & $zzzz)
While 1
$msg = GUIGetMsg()
If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd
Alles anzeigen
Eigentlich wollte ich selbst ja gar nicht teilnehmen, aber ich musste feststellen, dass man einiges dabei lernt.
Mein neuester Versuch ergibt dieses Resultat:
============================================================
Result for "Oscar"
============================================================
Decompressed = Original: True
Length Original: 6033
Length compressed: 5097
Length decompressed: 6033
Compress-Ratio: 15.515 %
Time compressed: 43 ms
Time decompressed: 3 ms
============================================================
Erstaunlich schnell! Hätte ich von AutoIt so jetzt nicht erwartet.
Ok, das sind momentan "nur" Wörterbuch-Ersetzungen, aber trotzdem recht schnell.
Bei mir ist es das genaue Gegenteil: Kompression ist "okay"
Uih, das ist schon eine Hausnummer!
Ich muss aber auch gestehen, dass ich mich damit bisher nie beschäftigt habe. Es gibt ja externe Libs. ![]()
Ich habe mich jetzt mal selbst an der Aufgabe versucht. Dabei ist mir aufgefallen, dass man mit zu kurzen Texten Probleme bei der Effektivität bekommt.
Deswegen habe ich jetzt mal einen längeren Text erstellt, der dann auch als Datei vorliegt (neue Version in Post #1).
Mein bisheriges Ergebnis (außer Konkurrenz):
============================================================
Result for "Oscar"
============================================================
Decompressed = Original: True
Length Original: 6033
Length compressed: 5500
Length decompressed: 6033
Compress-Ratio: 8.835 %
Time compressed: 68 ms
Time decompressed: 9 ms
============================================================
Alles anzeigen
Das ist zwar recht schnell, aber die Compress-Ratio noch verbesserungswürdig. ![]()
Ich würde bei sowas volle Bytes zählen
Ja, so sehe ich das auch. Der Speicherverbrauch (in Bytes) des komprimierten Strings.
Wenn sich der Speicherverbrauch Deines Datentyps nicht mit StringLen erfassen lässt, müsste man das Auswerteprogramm entsprechend anpassen.
Ist das fehlende Leerzeichen bei "\nAt" Absicht oder ein Fehler im Text?
In Verbindung mit StringFormat ist das "\n" ein Linefeed @LF. Also Absicht! ![]()
Und: Global $iTimer = TimerInit() wurde 2mal eingesetz
Ok, das zweite Global ist zuviel, aber das TimerInit() ist notwendig, weil ich jede Funktion einzeln ausmessen muss.
sprich zählen dazu auch Windows Libs, wie z.B. GDI+, User32, etc.?
Alle Libs, die eine Komprimierung vornehmen.
Es sollte schon reiner AutoIt-Code sein. Um schnellere Textsuchen zu ermöglichen würde ich das ScriptingDictionary-Objekt zulassen.
Ggf prüfen, ob der String nachher wirklich identisch mit dem Input ist.
Das geschieht bereits bei der Auswertung.
Man kann davon ausgehen, dass "nicht nur der Text aus der Aufgabenstellung" bei der Bewertung ausprobiert wird oder?
Zur Bewertung wird der Text aus der Aufgabenstellung benutzt. Die Funktionen sollten aber mit jeder Textdatei funktionieren. Also ASCII, keine Binaries.
Kann man davon ausgehen, dass "zu langsame" Algorithmen nicht teilnehmen können?
Sagen wir mal, dass _StringCompress für die 1274 Bytes unter eine Minute brauchen sollte.
Die Aufgabe besteht darin einen uebergebenen String so effektiv wie möglich (aber verlustfrei) zu komprimieren (keine externen Librarys, nur AutoIt-Code erlaubt).
Dazu müsst ihr zwei Funktionen programmieren _StringCompress und _StringDecompress.
Nachtrag 23.02.2022: Der Variablentyp fuer den komprimierten Text muss natürlich kein String sein. Dort könnt ihr euch ein eigenes Format ausdenken. Hauptsache am Ende von _StringDecompress kommt wieder der ursprüngliche String raus. Ich hab's im Beispiel mal angepasst.
Nachtrag 24.02.2022: Um ein besseres Ergebnis beim komprimieren zu bekommen, habe ich den zu komprimierenden Text etwas erweitert. Die Länge beträgt nun 6033 Bytes und befindet sich in der Datei "original.txt" im ZIP-Archiv.
Die Scripte als PN an mich.
Einsendeschluss: 31. März 2022, 23:59:59 Uhr
Gewonnen hat derjenige, der die beste Compress-Ratio erreicht.
Ergebnis:
Es hat drei Einsendungen gegeben und, soviel schonmal vorweg, alle drei haben mich sehr beeindruckt.
Die Aufgabe bestand darin, die beste Kompressionsrate zu erreichen, ohne Rücksicht auf die Zeit (solange sie im "Rahmen" bleibt).
Von daher erkläre ich Mars zum Sieger, weil er mit 50.174% tatsächlich die 50er Hürde übertroffen hat. Gratulation! ![]()
AspirinJunkie mit 49.255% liegt nur knapp dahinter, hat aber ein Script abgeliefert, was ihm klar die Perfomance-Krone verleiht.
Ahnungslos folgt dann mit 47.404% auf den dritten Platz.
Die Ergebnisse im einzelnen:
============================================================
Result for "Mars"
============================================================
Decompressed = Original:True
Length Original: 6033
Length compressed: 3006
Length decompressed: 6033
Compress-Ratio: 50.174 %
Time compressed: 57940 ms
Time decompressed: 54119 ms
============================================================
============================================================
Result for "AspirinJunkie"
============================================================
Decompressed = Original:True
Length Original: 6105
Length compressed: 3098
Length decompressed: 6033
Compress-Ratio: 49.255 %
Time compressed: 1314 ms
Time decompressed: 189 ms
============================================================
============================================================
Result for "Ahnungslos"
============================================================
Decompressed = Original:True
Length Original: 6105
Length compressed: 3211
Length decompressed: 6033
Compress-Ratio: 47.404 %
Time compressed: 5647 ms
Time decompressed: 294 ms
============================================================
Das alle drei im Ergebnis nicht mal 3% auseinanderliegen, hätte ich so nicht erwartet. Zeigt aber, dass die Algorithmen wohl ziemlich ausgereizt sind.
Ich habe mich vor dem Wettbewerb nie damit beschäftigt, wusste also nicht viel darüber. Unsere drei Kandidaten dagegen haben ein gutes Fachwissen
bewiesen und es macht Spass, sich die Scripte mal genauer anzusehen (ich habe sie gepackt als "Scripte.zip" in den Anhang gelegt).
Das AutoIt-Gerüst habe ich mal vorbereitet (auch als Anhang):
Global Const $sUsername = 'Oscar' ; <- hier den eigenen AutoIt.de Usernamen eintragen
; Funktion zum komprimieren (verlustfrei)
; Uebergeben wird ein beliebiger String, Rueckgabe muss der komprimierte Datentyp sein
Func _StringCompress($sString)
Local $vCompress
$vCompress = $sString ; den String bearbeiten
Return $vCompress
EndFunc
; Funktion zum dekomprimieren
; Uebergeben wird der komprimierte Datentyp, Rueckgabe muss der dekomprimierte String sein
Func _StringDecompress($vCompress)
Local $sString
$sString = $vCompress ; den urspruenglichen String wiederherstellen
Return $sString
EndFunc
#Region Achtung! Diese Region darf nicht veraendert werden!
Global $hFile = FileOpen(@ScriptDir & '\original.txt', 128)
If $hFile = -1 Then Exit
Global $sOriginal = FileRead($hFile)
FileClose($hFile)
Global $iOriginalLen = StringLen($sOriginal)
Global $iTimer = TimerInit()
Global $vCompressed = _StringCompress($sOriginal)
Global $iTimeDiffComp = TimerDiff($iTimer)
Global $iCompressedLen = StringLen($vCompressed)
Global $iTimer = TimerInit()
Global $sDecompressed = _StringDecompress($vCompressed)
Global $iTimeDiffDecomp = TimerDiff($iTimer)
Global $iDecompressedLen = StringLen($sDecompressed)
ConsoleWrite('============================================================' & @CRLF)
ConsoleWrite(StringFormat('Result for "%s"\r\n', $sUsername))
ConsoleWrite('============================================================' & @CRLF)
ConsoleWrite(StringFormat('Decompressed = Original: %s\r\n', $sOriginal == $sDecompressed))
ConsoleWrite(StringFormat('Length Original: %i\r\n', $iOriginalLen))
ConsoleWrite(StringFormat('Length compressed: %i\r\n', $iCompressedLen))
ConsoleWrite(StringFormat('Length decompressed: %i\r\n', $iDecompressedLen))
ConsoleWrite(StringFormat('Compress-Ratio: %s %%\r\n', Round(100 - (100 / $iOriginalLen * $iCompressedLen), 3)))
ConsoleWrite(StringFormat('Time compressed: %i ms\r\n', $iTimeDiffComp))
ConsoleWrite(StringFormat('Time decompressed: %i ms\r\n', $iTimeDiffDecomp))
ConsoleWrite('============================================================' & @CRLF)
#EndRegion Achtung! Diese Region darf nicht veraendert werden!
Alles anzeigen
Kennt jemand diesen Effekt?
Wenn Du ein x64 System hast, musst Du das Script im x64-Modus starten/compilieren:
Ich habe jetzt eine eigene Properties Datei für Nim erstellt
Hast Du ein vernünftiges Syntax-Highlighting für Nim gefunden?
wo stell ich dass denn ein dass ich die Konsolenausgabe bekomme?
Im Menü "View" bei "Output" den Haken setzen:
Beim WMI Script kommt zwar kein Fehler, aber leider sonst nicht viel:(
Du solltest unbedingt mal den Rat befolgen und SciTE4AutoIt installieren, damit Du die Ausgabe in der Console auch sehen kannst.
In der Möglichkeit, ein Fenster zu schließen, hätte ich für mich einen Weg gesehen, um auszuschließen, dass es zu Konfrontationen mit anderen Fenstern kommt.
Hier mal ein kleines Beispiel mit 2 Fenstern (im Label wird die ganze Zeit die Uhrzeit angezeigt):
#include <GUIConstantsEx.au3>
Global $hGui_1 = GUICreate('Fenster 1', 640, 480)
Global $idButton_Gui_1 = GUICtrlCreateButton('Öffne Fenster 2', 10, 10, 120, 30)
Global $idLabel_Gui_1 = GUICtrlCreateLabel('', 520, 10, 110, 30)
GUICtrlSetFont(-1, 18, 400)
Global $hGui_2 = GUICreate('Fenster 2', 480, 240, -1, -1, -1, -1, $hGui_1)
Global $idButton_Gui_2 = GUICtrlCreateButton('Starte den Taschenrechner', 10, 10, 180, 30)
GUISetState(@SW_SHOW, $hGui_1) ; erstmal nur Fenster 1 anzeigen
Global $aMsg, $iOldSec
While True
$aMsg = GUIGetMsg($GUI_EVENT_ARRAY) ; GuiGetMsg im erweiterten Modus aufrufen (Array-Ausgabe)
Switch $aMsg[1] ; in [1] steht das Fenster-Handle vom Event
Case $hGui_1 ; Event vom Fenster 1
Switch $aMsg[0] ; in [0] steht das eigentliche Event
Case $GUI_EVENT_CLOSE
Exit
Case $idButton_Gui_1
GUISetState(@SW_SHOW, $hGui_2)
EndSwitch
Case $hGui_2 ; Event vom Fenster 2
Switch $aMsg[0] ; in [0] steht das eigentliche Event
Case $GUI_EVENT_CLOSE
GUISetState(@SW_HIDE, $hGui_2)
Case $idButton_Gui_2
ShellExecute('calc.exe')
EndSwitch
EndSwitch
If @SEC <> $iOldSec Then ; Uhrzeit nur bei neuer Sekunde aendern
GUICtrlSetData($idLabel_Gui_1, StringFormat('%02i:%02i:%02i', @HOUR, @MIN, @SEC))
$iOldSec = @SEC
EndIf
WEnd
Alles anzeigen
Edit:
Und hier das gleiche Beispiel, nur dieses Mal im OnEvent-Modus (IMHO ist dieser Modus übersichtlicher, als der MessageLoop-Modus):
#include <GUIConstantsEx.au3>
Opt('GUIOnEventMode', 1) ; umschalten auf den OnEvent-Modus (kein GUIGetMsg)
Global $hGui_1 = GUICreate('Fenster 1', 640, 480)
GUISetOnEvent($GUI_EVENT_CLOSE, '_CloseGui_1', $hGui_1) ; beim Fenster GUISetOnEvent
Global $idButton_Gui_1 = GUICtrlCreateButton('Öffne Fenster 2', 10, 10, 120, 30)
GUICtrlSetOnEvent(-1, '_OpenGui_2') ; bei den Ctrl-Elementen GUICtrlSetOnEvent
Global $idLabel_Gui_1 = GUICtrlCreateLabel('', 520, 10, 110, 30)
GUICtrlSetFont(-1, 18, 400)
Global $hGui_2 = GUICreate('Fenster 2', 480, 240, -1, -1, -1, -1, $hGui_1)
GUISetOnEvent($GUI_EVENT_CLOSE, '_CloseGui_2', $hGui_2) ; beim Fenster GUISetOnEvent
Global $idButton_Gui_2 = GUICtrlCreateButton('Starte den Taschenrechner', 10, 10, 180, 30)
GUICtrlSetOnEvent(-1, '_OpenCalc') ; bei den Ctrl-Elementen GUICtrlSetOnEvent
GUISetState(@SW_SHOW, $hGui_1) ; erstmal nur Fenster 1 anzeigen
Global $iOldSec
; Im OnEvent-Modus ist das Sleep in der Endlosschleife wichtig, um die Prozessorlast zu minimieren
While Sleep(250)
If @SEC <> $iOldSec Then ; Uhrzeit nur bei neuer Sekunde aendern
GUICtrlSetData($idLabel_Gui_1, StringFormat('%02i:%02i:%02i', @HOUR, @MIN, @SEC))
$iOldSec = @SEC
EndIf
WEnd
Func _CloseGui_1()
Exit
EndFunc
Func _CloseGui_2()
GUISetState(@SW_HIDE, $hGui_2)
EndFunc
Func _OpenGui_2()
GUISetState(@SW_SHOW, $hGui_2)
EndFunc
Func _OpenCalc()
ShellExecute('calc.exe')
EndFunc
Alles anzeigen
Ich hätte hier noch eine Version mit WMI:
ConsoleWrite('Windows is activated: ' & _IfWinActivated() & @CRLF)
Func _IfWinActivated()
Local $sCommand, $iPID, $sData
$sCommand = @ComSpec & ' /c WMIC /NAMESPACE:\\root\CIMV2 PATH SoftwareLicensingProduct WHERE LicenseStatus=1 GET LicenseStatus | findstr "1"'
$iPID = Run($sCommand, @ScriptDir, @SW_HIDE, 0x2)
ProcessWait($iPID)
Do
$sData &= StdoutRead($iPID)
Until @error <> 0
Return StringLeft($sData, 1) == '1'
EndFunc
Alles anzeigen
Und mir ist aufgefallen das die CMD im Hintergrund noch weiter downloadet aber das Autoit Programm beendet sich
Du musst Deine Funktion "ReadStream" auch aufrufen.
GuiDelete($hGui) hab ich jetzt ausprobiert - mache aber wahrscheinlich was falsch, denn das Script geht dann immer in eine Art Standby-Modus
Bitte das Script posten!
Ansonsten können wir nur raten.
Aber kann ich auch ein Fenster(1) schließen
Kommt darauf an. Wenn "schließen" verstecken heißt, dann GuiSetState(@SW_HIDE, $hGui).
Wenn "schließen" löschen heißt, dann GuiDelete($hGui).