Buchstaben mischen

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

ichdotcom
Posts: 9
Joined: 14 Nov 2017, 04:42

Buchstaben mischen

13 Dec 2018, 15:59

Hallo zusammen,

gerade als ich Google durchforstet hab und ich dort leider nicht fundig geworden bin, dachte ich,
ich wende mich gewissenhaft einfach an die Menschen, die mir vllt. wirklich helfen können.

Leider bin ich noch immer etwas unerfahren was den Umgang und die Benutzung von AutoHotkey betrifft.
Die Logik des Problems, sagen wirs so... ich steig da auch noch nicht so ganz durch, das wird aber XD

Folgendes Problem/Frage habe ich.

Anfang:
Ich hab einen Text. z.B. ABCDE

Ende:
Es soll eine Random Reihenfolge davon erstellt werden. z.B. EBDAC


Wird also ne Mischung aus String und Random, nur wie vergleich ich die Buchstaben, so dass sie nicht erneut ausgegeben werden? z.b. EEACD

Es wäre sehr lieb wenn Ihr mir helfen könnt :)
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Buchstaben mischen

13 Dec 2018, 17:17

Versuch mal:

Code: Select all

Start := "ABCDE"
Ende := ""

while StrLen(Start) {
    Random, num, 1, StrLen(Start)
    Letter := SubStr(Start, num, 1)
    Start := StrReplace(Start, Letter)
    Ende .= Letter
}

MsgBox, % Ende
Ich hoffe das hilft.

Die idee dahinter geht so: Nimm einen (zufälligen) Buchstaben vom start-string, schneid ihn raus, häng ihn ans Ende dran.
Dann braucht's keine Vergleiche. Am ende stehen alle buchstaben in zufälliger Reihenfolge im anderen String.

Ach so, Sort kann das auch in einem Rutsch, wenn man delimiter hat im start-string, hier ein Beispiel mit "|"

Code: Select all

Start := "A|B|C|D|E"
Sort, Start, Random D|
MsgBox, % Start
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 03:27

Ich würde hier empfehlen eher mit einem Array zu arbeiten.
StrReplace kann hier unangenehme Folgen haben.
Sort habe ich mir mal angeschaut und es sofort wieder bereut.

Code: Select all

string := "Hello World!" ;eingabe text
stringArray := strSplit(string) ;eingabe text in array verwandeln
mixedStringArray := []            ;ausgabe array erstellen
for each, letter in stringArray { ;für alle Buchstaben in dem Eingabe array
	Random, newPosition, 1, %A_Index% ;würfle eine neue position
	mixedStringArray.insertAt(newPosition, letter) ;füge den Buchstaben an diese Position ein (und verschiebe die anderen wenn notwendig) 
}
outputString := "" ;den ausgabe string erzeugen
for each, letter in mixedStringArray {  ;für jeden Buchstaben im ausgabe array
	outputString .= letter ;diesen an den Ausgabe String anhängen
}
Msgbox % outputString
Edit: Hab grade gesehen, dass doppelte Buchstaben entfernt werden sollen.
Dann macht dieser Code keinen Sinn.
Daher der folgende code:

Code: Select all

string := "Hello World!" ;eingabe text
stringArray := {} ;eingabe assoziativ array verwenden
for each, letter in strSplit(string)
{
	stringArray[letter] := "" ;Einen Eintrag im Array unter Buchstabe machen
	;(jeder Buchstabe kann nur einen Eintrag haben d.h. werden alle doppelten Aussortiert)
}

mixedStringArray := []            ;ausgabe array erstellen
for letter, _ in stringArray { ;für alle Einträge in dem Eingabe array
	Random, newPosition, 1, %A_Index% ;würfle eine neue position
	mixedStringArray.insertAt(newPosition, letter) ;füge den Buchstaben an diese Position ein (und verschiebe die anderen wenn notwendig) 
}

outputString := "" ;den ausgabe string erzeugen
for each, letter in mixedStringArray {  ;für jeden Buchstaben im ausgabe array
	outputString .= letter ;diesen an den Ausgabe String anhängen
}
Msgbox % outputString
Recommends AHK Studio
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 03:54

ichdotcom wrote: Wird also ne Mischung aus String und Random, nur wie vergleich ich die Buchstaben, so dass sie nicht erneut ausgegeben werden? z.b. EEACD

Ich vermute mal, dass das so gemeint sein könnte:

Code: Select all

#NoEnv
Eingabe := "ABCDEEDCBA"
Ausgabe := BuchstabenMischen(Eingabe)
MsgBox, 0, Buchstaben mischen, Eingabe:`n%Eingabe%`n`nAusgabe:`n%Ausgabe%
ExitApp

BuchstabenMischen(Eingabe) {
   Local                                     ; lokale Funktionsvariablen erzwingen
   Ausgabe := ""                             ; Grundstellung Ausgabe (kann man auch weglassen)
   For Jedes, Zeichen In StrSplit(Eingabe)   ; Eingabe in Einzelzeichen splitten ...
      Ausgabe .= Zeichen . "`n"              ; ... und mit Trennzeichen `n nach Ausgabe übertragen
   Ausgabe := RTrim(Ausgabe, "`n")           ; letztes `n entfernen
   Sort, Ausgabe, C U                        ; mehrfach vorkommende Zeichen aussortieren (ggf. ohne Option C)
   Sort, Ausgabe, Random                     ; verbliebene Zeichen zufällig sortieren
   Return StrReplace(Ausgabe, "`n")          ; `n aus Ausgabe entfernen und den Rest zurückgeben
}
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Buchstaben mischen

14 Dec 2018, 05:14

nnnik wrote:StrReplace kann hier unangenehme Folgen haben.
Können Sie bitte dazu ein Beispiel anfüren ?
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 05:22

Hmm ja ich hab überlesen, dass die doppelten Buchstaben entfernt werden sollten.
In diesem Fall gibt es kein Problem. Ich muss meinen Post nochmal eiditieren.
Recommends AHK Studio
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 05:33

Allgemein kann ich nur empfehlen zu vergessen, dass Sort existiert.
Recommends AHK Studio
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 06:29

Meine Meinung: Wenn man sich an einige wenige Grundregeln hält, ist die Sort Anweisung schnell und zuverlässig.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 07:14

Die Sort Anweisung ist schlecht implementiert, verwendet einen Haufen Legacy Synatax und wird wahrscheinlich in AHK v2 ersetzt.
Es gibt keine einzige Situation in der Sort konsistenter, lesbarer, modularer und performanter wäre als mögliche Alternativen.
Es gibt keinerlei Grund Sort jemals zu verwenden.
Recommends AHK Studio
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Buchstaben mischen

14 Dec 2018, 07:57

Es gibt keinerlei Grund Sort jemals zu verwenden.

Gegeben sei eine Aufgabe die verlangt einen Algorithmus zu implementieren, der
  1. eine zufällige Permutation des Eingabe-strings erzeugt
  2. keine Variablen erzeugt, also auch ohne Random, num
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 08:06

nnnik wrote: Es gibt keine einzige Situation in der Sort konsistenter, lesbarer, modularer und performanter wäre als mögliche Alternativen.
Da habe ich zumindest in Bezug auf Performance erhebliche Zweifel. Außerdem ist es wohl selbstverständlich, dass ein AHK 1.1 'Kommando' auch die 'Kommandosyntax' nutzt.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 09:34

wolf_II wrote:
14 Dec 2018, 07:57
[*]keine Variablen erzeugt, also auch ohne Random, num
Wenn du keine Variablen erzeugen kannst/wilst kannst du auch gleich aufhören zu programmieren.
Wenn du den Global scope nicht verschmutzen willst gibt es Funktionen.
Da habe ich zumindest in Bezug auf Performance erhebliche Zweifel
Sort verwendet in der implementation Bubble Sort.
Der Grund hierfür ist es, dass der Befehl sich nicht merkt wo die Grenzen der einzelnen Strings sind d.h. immer jedes mal neu nach den Delimitern suchen muss.
Dieses Problem zieht sich durch den ganzen Befehl d.h. haben alle Algorythmen eine Komplexität O(n²). Das arbeiten mit Arrays ist in AHK v1 O(n*log(n)) d.h. um Magnituden Performanter.
Zum Sortieren wird Bubble Sort verwendet. Bubble Sort ist praktisch gesehen ein Witz - hier bloß leider nicht witzig.
Außerdem ist es wohl selbstverständlich, dass ein AHK 1.1 'Kommando' auch die 'Kommandosyntax' nutzt.
Es ist nicht weiter Schlimm die Kommandosyntax zu verwenden. Allerdings gibt es gute und schlechte Kommandos.
Viele der guten Kommandos die häufig verwendet werden haben ein Funktionsequivalent erhalten und sind auf die neue Syntax ausgeweitet worden.
Bei Sort ist dies nicht der Fall da sowohl die Verwendung sowie die Funktionsweise irrelevant geworden sind und es keinen Sinn macht das eine noch das andere zu erhalten.
Recommends AHK Studio
Rohwedder
Posts: 7551
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 10:09

Hallo,
Sort ist schneller!

Code: Select all

string := "ABCDEDEFGHIJKLMNOPQRSTUVWXYZ"
T := A_TickCount
Loop, 100000
{
	stringArray := strSplit(string)
	mixedStringArray := []
	for each, letter in stringArray
	{
		Random, newPosition, 1, %A_Index%
		mixedStringArray.insertAt(newPosition, letter)
	}
	outputString =
	for each, letter in mixedStringArray
		outputString .= letter
}
Text := "Array`n" outputString "`n" (A_TickCount - T)//100 "µs`n"
T := A_TickCount
Loop, 100000
{
	outputString =
	Loop, Parse, string
		outputString .= A_LoopField "|"
	Sort, outputString, Random D|
	outputString := StrReplace(outputString,"|")
}
MsgBox,% Text "Sort`n" outputString "`n" (A_TickCount - T)//100 "µs"
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 11:38

Hast du SetBatchLines, - 1verwendet?
Zudem sind 26 Zeichen relativ wenig. Um relevante Ergebnisse zu erhalten empfiehlt es sich mehr Zeichen zu verwenden. 20000 aufwärts wäre schon interessanter.
Recommends AHK Studio
Rohwedder
Posts: 7551
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 12:04

Nun, jetzt mit 28672 Zeichen erreicht Sort knapp Mach 3.
Das Ergebnis erscheint mir etwas unglaubwürdig, kann aber keinen Fehler finden.

Code: Select all

string := "ABCDEDEFGHIJKLMNOPQRSTUVWXYZ"
Loop, 10
	string.=string
T := A_TickCount
stringArray := strSplit(string)
mixedStringArray := []
for each, letter in stringArray
{
	Random, newPosition, 1, %A_Index%
	mixedStringArray.insertAt(newPosition, letter)
}
outputString =
for each, letter in mixedStringArray
	outputString .= letter
Text := Strlen(String) " Zeichen`nArray`n" (A_TickCount - T) "ms`n"
T := A_TickCount
outputString =
Loop, Parse, string
	outputString .= A_LoopField "|"
Sort, outputString, Random D|
outputString := StrReplace(outputString,"|")
MsgBox,% Text "Sort`n" (A_TickCount - T) "ms"
SetBatchLines, -1 macht nur beide Verfahren um den Faktor 2 schneller.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Buchstaben mischen

14 Dec 2018, 13:47

Ich erhalte bei mir keine Nennenswerte Verzögerung bei der Verwendung von Sort,..Random.
Und 500ms bei der Array Variante bekomme.
Ich habe probleme das Nachzuvollziehen werde aber nicht weiter nachforschen.

Es scheint wohl so zu sein, dass Sort, Random in der Tat schneller ist als das manuelle Random und umsortieren.
Kommt jedoch das Aussortieren mit ins Spiel verliert Sort gegen die Array variante:

Code: Select all

SetBatchLines,  -1
String := ""
Loop % (2**10)
	String .= chr(A_Index)
string := BuchstabenMischen2(string) ;Zufällige Sortierung
Loop, 10
	string .= string
t:= A_TickCount
ausgabe := BuchstabenMischen(string)
Msgbox % A_TickCount - t . " für " . StrLen(ausgabe) . " Zeichen ausgabe und " . StrLen(string) . " eingabe"
t:= A_TickCount
ausgabe := BuchstabenMischen2(string)
Msgbox % A_TickCount - t . " für " . StrLen(ausgabe) . " Zeichen ausgabe und " . StrLen(string) . " eingabe"


BuchstabenMischen(Eingabe) {
	Local                                     ; lokale Funktionsvariablen erzwingen
	Ausgabe := ""                             ; Grundstellung Ausgabe (kann man auch weglassen)
	For Jedes, Zeichen In StrSplit(Eingabe)   ; Eingabe in Einzelzeichen splitten ...
		Ausgabe .= Zeichen . "`n"              ; ... und mit Trennzeichen `n nach Ausgabe übertragen
	Ausgabe := RTrim(Ausgabe, "`n")           ; letztes `n entfernen
	Sort, Ausgabe, C U                        ; mehrfach vorkommende Zeichen aussortieren (ggf. ohne Option C)
	Sort, Ausgabe, Random                     ; verbliebene Zeichen zufällig sortieren
	Return StrReplace(Ausgabe, "`n")          ; `n aus Ausgabe entfernen und den Rest zurückgeben
}


BuchstabenMischen2(string) {
	stringArray := {} ;eingabe assoziativ array verwenden
	for each, letter in strSplit(string)
	{
		stringArray[letter] := "" ;Einen Eintrag im Array unter Buchstabe machen
		;(jeder Buchstabe kann nur einen Eintrag haben d.h. werden alle doppelten Aussortiert)
	}

	mixedStringArray := []            ;ausgabe array erstellen
	for letter, _ in stringArray { ;für alle Einträge in dem Eingabe array
		Random, newPosition, 1, %A_Index% ;würfle eine neue position
		mixedStringArray.insertAt(newPosition, letter) ;füge den Buchstaben an diese Position ein (und verschiebe die anderen wenn notwendig) 
	}

	outputString := "" ;den ausgabe string erzeugen
	for each, letter in mixedStringArray {  ;für jeden Buchstaben im ausgabe array
		outputString .= letter ;diesen an den Ausgabe String anhängen
	}
	return outputString
}
Zudem verschluckt es auch noch das Trennzeichen.
Recommends AHK Studio
ichdotcom
Posts: 9
Joined: 14 Nov 2017, 04:42

Re: Buchstaben mischen

14 Dec 2018, 15:58

Wow Leute,

ca 24h später bekommt man jede menge Hilfe,
ich bedanke mich sehr für die vielen Post und kann sagen das der erste von wolf_II mir schon sehr geholfen hat, er ist kompakt und passt überall rein,
mit deinem Einverständnis würde ich den gern weiterverwenden/ändern/rumprobieren.
Da steht sogar noch mehr. Unter anderem hab ich mich gefragt wie man hintereinander folgende Ergebnisse in eine Variable speichern kann.

mit Var := ""

echt klasse... DAAAANKEE!!!
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Buchstaben mischen

14 Dec 2018, 16:48

@ichdotcom: Selbstverständlich kannst du das verwenden/zerplücken und verändern. Viel Spass. :thumbup:

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: gero, Rohwedder and 37 guests