Seite 1 von 1

String mischen

Verfasst: Montag 29. August 2011, 10:23
von Jochen1980
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.

Re: String mischen

Verfasst: Montag 29. August 2011, 11:00
von derdon
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'

Re: String mischen

Verfasst: Montag 29. August 2011, 11:01
von Jochen1980
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

Re: String mischen

Verfasst: Montag 29. August 2011, 12:02
von pillmuncher
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

Re: String mischen

Verfasst: Montag 29. August 2011, 16:31
von gkuhl
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

Re: String mischen

Verfasst: Montag 29. August 2011, 17:45
von pillmuncher
@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.

Re: String mischen

Verfasst: Montag 29. August 2011, 18:18
von gkuhl
@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

Re: String mischen

Verfasst: Dienstag 30. August 2011, 21:06
von bords0
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.