String mischen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Jochen1980
User
Beiträge: 40
Registriert: Montag 15. August 2011, 18:44

Servus,

wie gehe ich geschickt vor, wenn meine Funktion einen String erhält, ich dann zweimal zwischen 0 und range(len(meineingangsstring)) würfeln will und dann die beiden Zeichen im String tauschen möchte?

Danke vorab.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Hab nur eine unschöne Lösung zu bieten :?

Code: Alles auswählen

>>> from string import ascii_lowercase
>>> import random
>>> a, b = random.sample(xrange(0, len(ascii_lowercase)), 2)
>>> a
15
>>> b
7
>>> a, b = a if a < b else b, b if b > a else a
>>> a
7
>>> b
15
>>> ascii_lowercase = ascii_lowercase[:a] + ascii_lowercase[b] + ascii_lowercase[a+1:b] + ascii_lowercase[a] + ascii_lowercase[b+1:]
>>> ascii_lowercase
'abcdefgpijklmnohqrstuvwxyz'
Jochen1980
User
Beiträge: 40
Registriert: Montag 15. August 2011, 18:44

Sodala, das ist mal meine Lösung - scheint zu klappen, aber da dies auch fix laufen soll, bitte ich um Verbesserungen.

Code: Alles auswählen

def randomize_string(string_to_randomize, factor_of_shuffling):
    number_of_chars = len( string_to_randomize)
    number_of_shuffles = factor_of_shuffling * number_of_chars
    # strings sind unveraenderbar, daher lieber string in liste wandeln
    list_of_chars = list(string_to_randomize)
    #print( "String:", string_to_randomize, "Liste:", list_of_chars)

    for i in range(number_of_shuffles):
        #print("Run:", i ) 
        first_random = random.randint(0, (number_of_chars - 1))
        second_random = random.randint(0, (number_of_chars - 1))
        #print( "... Zufallszahlen:", first_random, second_random )
        first_pick = list_of_chars[first_random]
        second_pick = list_of_chars[second_random]
        list_of_chars[first_random] = second_pick
        list_of_chars[second_random] = first_pick
    
    randomized_string = ''.join( list_of_chars )
    #print("Randomisierter String:", randomized_string)
    return randomized_string
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Ich würde es so machen (Python 3.x):

Code: Alles auswählen

import random

def chunkwise(t, size=2):
    return zip(*[iter(t)]*size)

def randomswaps(iterable, n=1):
    result = list(iterable)
    for a, b in chunkwise(random.sample(range(len(result)), n * 2)):
        result[a], result[b] = result[b], result[a]
    return result

for i in range(3):
    print(''.join(randomswaps('pillmuncher', 3)))
Ergebnis:

Code: Alles auswählen

plirmuhcnel
piulhlecmnr
pillenuchmr
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Folgendes sollte es eigentlich auch tun:

Code: Alles auswählen

def swap(iterable, n=1):
    result = list(iterable)
    for i in xrange(n):
        i,j = (random.randint(0, len(result)) for _ in range(2))
        result[i], result[j] = result[j], result[i]
    return ''.join(result)
Grüße
Gerrit
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@gkuhl: Bei deiner Lösung kann es aber passieren, dass i == j ist, und somit gar nichts vertauscht wird. Außerdem kann verschiedenes anderes passieren, so zB. wenn i und j dieselben oder umgekehrten Werte haben wie beim Schleifendurchlauf zuvor, dann wird zwar vertauscht, aber eben gleich danach wieder zurüsckgetauscht. Oder es kann passieren, das erst zB. die Buchstaben mit den Indizes 3 und 5, und danach die mit den Indizes 5 und 4 vertauscht werden. Gilt das dann immer noch als zwei Vertauschungen, wenn nicht vier, sondern nur drei Buchstaben die Plätze gewechselt haben? Aus der Nachricht des OPs geht nicht hervor, ob das erlaubt sein soll, oder nicht. Deswegen habe ich in meiner Lösung den strengeren Ansatz gewählt, der auf jeden Fall gültig ist.

Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

@pillmuncher: Dein strengerer Ansatz macht aus Sicht der Performance sicherlich Sinn. Allerdings gehe ich immer davon aus, dass alles, was nicht explizit verboten wird, möglich sein sollte. Ich hatte am Anfang auch überlegt "sample" zu benutzen mich dann aber, gerade weil z.B. i==j möglich sein sollte, dagegen entschieden.

Grüße
Gerrit
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

pillmuncher hat geschrieben:@gkuhl: Bei deiner Lösung kann es aber passieren, dass i == j ist, und somit gar nichts vertauscht wird. Außerdem kann verschiedenes anderes passieren, so zB. wenn i und j dieselben oder umgekehrten Werte haben wie beim Schleifendurchlauf zuvor, dann wird zwar vertauscht, aber eben gleich danach wieder zurüsckgetauscht. Oder es kann passieren, das erst zB. die Buchstaben mit den Indizes 3 und 5, und danach die mit den Indizes 5 und 4 vertauscht werden. Gilt das dann immer noch als zwei Vertauschungen, wenn nicht vier, sondern nur drei Buchstaben die Plätze gewechselt haben? Aus der Nachricht des OPs geht nicht hervor, ob das erlaubt sein soll, oder nicht. Deswegen habe ich in meiner Lösung den strengeren Ansatz gewählt, der auf jeden Fall gültig ist.
Doch, aus der Nachricht des OP, in der überhaupt erst Mehrfachvertauschungen erwähnt werden, geht es schon hervor. Ist alles erlaubt.
Antworten