Buchstabenverdreher

Code-Stücke können hier veröffentlicht werden.
Milcheiweiß
User
Beiträge: 7
Registriert: Donnerstag 3. Oktober 2019, 12:34

Dienstag 8. Oktober 2019, 14:40

Hi Ihr,
Ich habe die Aufgabe ein Programm zu schreiben das in einem Text bei allen Wörtern die Buchstaben zufällig vertauscht wobei der erste und der letzte Buchstabe gleich bleibt. Basiert auf einer Studie die besagt, das man es lesen kann solange der erste und letzte Buchstabe stimmt und sonst nur die anderen Buchstaben vetauscht. Also zB: "Es kmmot auf die Vrpunekacg an".

Ich dachte mir das ungefähr so:

Code: Alles auswählen

from random import shuffle
s = input("Give me a string: ")
print(s)
x = s.split()
print(x)
print(shuffle(x))
Da kommt am Ende nur None raus.
Ich weiß das so gar nicht rauskommen kann was ich brauche, aber ich habe keine Ahnung wie ich weiter machen soll.
Ich habe auch schon anderes ausprobiert, aber da kam ich auf nichts sinnvolles.

Ich dachte mir ich müsste es so machen:
1. eine Variabale einem Input geben (gemacht)
2.den Input in eine Liste aufteilen damit die Wörter einzeln anwählbar sind(gemacht)
3. die Wörter einzeln Anwählen und mit Variable[1:-1] dafür sorgen das der erste und letzte Buchstabe gleich bleibt.
4. die Buchstaben der angewählten Wörter zufällig vertauschen und als neue Liste speichern.
5.Die neue Liste drucken.

Kann man das irgendwie mit Python machen oder habe ich da schon einen Fehler in meiner Denkweise?

vielen Dank und Grüße,

M.
__deets__
User
Beiträge: 6386
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dienstag 8. Oktober 2019, 14:48

Hast du dir mal die Dokumentation von shuffle angeschaut? Was gibt die denn zurueck, und was hat das in dem Moment fuer Konsequenzen fuer deinen Code?
Milcheiweiß
User
Beiträge: 7
Registriert: Donnerstag 3. Oktober 2019, 12:34

Dienstag 8. Oktober 2019, 15:05

__deets__ hat geschrieben:
Dienstag 8. Oktober 2019, 14:48
Hast du dir mal die Dokumentation von shuffle angeschaut? Was gibt die denn zurueck, und was hat das in dem Moment fuer Konsequenzen fuer deinen Code?
Wenn ich es richtig verstehe bringt der print(shuffle(x)) Befehl nichts.
Ich muss zuerst shuffle(x) anwenden und dann print(x)
die Liste x wird durch das shuffle verändert.

Aber wie schaffe ich es die Wörter einzeln anzuwählen und die Buchstaben zu shufflen?
Benutzeravatar
__blackjack__
User
Beiträge: 4192
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Dienstag 8. Oktober 2019, 15:27

@Milcheiweiß: Teil das Problem in kleinere Teilprobleme auf und die dann wieder, solange bis Du Teilprobleme hast, die Du mit wenigen Zeilen Code in einer Funktion lösen kannst. Das dann testen und nicht mit dem nächsten Teilproblem weitermachen, bevor das nicht funktioniert.

Und verwende gleich von Anfang an korrekte Namen. Richtige, ausgeschriebene Namen, nicht `s` oder `x`. Wenn `x` korrekt benannt wäre, wäre das direkt beim `shuffle()` schon aufgefallen, dass das offensichtlich falsch ist! Gute Namen sind keine Kosmetik die man später macht, sondern wirklich wichtig beim Programmieren.
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
nezzcarth
User
Beiträge: 753
Registriert: Samstag 16. April 2011, 12:47

Dienstag 8. Oktober 2019, 18:54

Für mich stellt sich auch die Frage, ob du mit "Text" lediglich einfache Zeichenketten meinst, oder tatsächlich "echte" Texte. Letzteres ist deutlich schwieriger, da es bestimmte Randfälle gibt (zum Beispiel Satzzeichen, Zahlen, Abkürzungen, etc.), an die man denken muss. Um das mal an einem Satz aus dem englischen Wikipediaartikel über Python zu illustrieren:

Code: Alles auswählen

In [1]: from random import shuffle                                                                                                                            

In [2]: def scrable(word): 
	...                                                                                         

In [3]: text = "The Python 2 language, i.e. Python 2.7.x, is \"sunsetting\" on January 1, 2020, and the Python team of volunteers will not fix security issues
   ...: , or improve it in other ways after that date. With the end-of-life, only Python 3.6.x and later, e.g. Python 3.8 which should be released in October 
   ...: 2019 (currently in beta), will be supported."                                                                                                         

In [4]: scrabled_text = ...                                                                                     

In [5]: print(text)                                                                                                                                           
The Python 2 language, i.e. Python 2.7.x, is "sunsetting" on January 1, 2020, and the Python team of volunteers will not fix security issues, or improve it in other ways after that date. With the end-of-life, only Python 3.6.x and later, e.g. Python 3.8 which should be released in October 2019 (currently in beta), will be supported.

In [6]: print(scrabled_text)                                                                                                                                  
                                                                                                                           
The Pthyon 2 lgaaugne, ie.. Pyothn 2..7x, is "tgnisentus" on Juaarny 1, 2200, and the Pothyn taem of voetluenrs wlil not fix stuicery isssue, or imvopre it in oehtr ways atfer taht daet. With the en-filedf-o, olny Phtoyn 36..x and lerat, eg.. Pytohn 3.8 whcih sluohd be reeealsd in Ocbtoer 2019 (ctnrleruy in be)at, will be sdporeupt.



Im günstigsten Fall würde man den Text daher zuvor tokenisieren. Für eine einfache Programmieraufgabe ist das aber vermutlich overkill.
Benutzeravatar
__blackjack__
User
Beiträge: 4192
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mittwoch 9. Oktober 2019, 13:23

Im Fall von solchem Text lohnt es sich `re.sub()` anzuschauen und daran zu denken das man für das Ersetzungsargument auch eine Funktion angeben kann.
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
nezzcarth
User
Beiträge: 753
Registriert: Samstag 16. April 2011, 12:47

Mittwoch 9. Oktober 2019, 19:10

__blackjack__ hat geschrieben:
Mittwoch 9. Oktober 2019, 13:23
Im Fall von solchem Text lohnt es sich `re.sub()` anzuschauen und daran zu denken das man für das Ersetzungsargument auch eine Funktion angeben kann.
Das würde mich ja jetzt schon interessieren, was dir das genau vorschwebt, aber wir wollen ja nicht zu viel verraten... ;)

Das Ergebnis mit Tokenizer aber ohne regex sähe jedenfalls schon eher so aus, wie man sich das bei "normalem" Text so vorstellt:

Code: Alles auswählen

In [9]: print(scrambled_text)                                                                                                                                 
The Ptohyn 2 laagnuge, i.e. Pthoyn 2.7.x, is "sstnitnueg" on Jaanruy 1, 2020, and the Pytohn team of vuetoerlns will not fix sruticey iusses, or ivomrpe it in oehtr wyas atfer that date. Wtih the end-of-lfie, olny Pyohtn 3.6.x and laetr, e.g. Ptoyhn 3.8 wihch suhold be reeaesld in Obcoter 2019 (crlrtuney in btea), will be stpopreud. 
Zuletzt geändert von nezzcarth am Mittwoch 9. Oktober 2019, 19:16, insgesamt 1-mal geändert.
Benutzeravatar
__blackjack__
User
Beiträge: 4192
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mittwoch 9. Oktober 2019, 19:16

@nezzcarth: Mir schwebte so etwas vor wie ``scrambled_text = re.sub('pattern für worte', scramble_matched_word, text)`` mit einer Funktion `scramble_matched_word()` die ein ”Match”-Objekt entgegennimmt und ein ”buchstabenverdrehtes Wort” zurück gibt.
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
Sirius3
User
Beiträge: 10549
Registriert: Sonntag 21. Oktober 2012, 17:20

Mittwoch 9. Oktober 2019, 19:21

So ähnlich wie der Zahlendreher:

Code: Alles auswählen

re.sub("[0-9]+", lambda m: m.group(0)[::-1], "Das Jahr hat 365 Tage und der Tag 24 Stunden.")
nezzcarth
User
Beiträge: 753
Registriert: Samstag 16. April 2011, 12:47

Mittwoch 9. Oktober 2019, 20:44

Jetzt habe ich verstanden, was du/ihr mein(s)t. Ist jedenfalls etwas "leicht-gewichtiger" als mein Ansatz :)
Milcheiweiß
User
Beiträge: 7
Registriert: Donnerstag 3. Oktober 2019, 12:34

Donnerstag 10. Oktober 2019, 13:46

Also ich habe es jetzt für das erste Wort geschafft:

Code: Alles auswählen

from random import shuffle
text = input("Give me a string: ")
print(text)

text_list = text.split()
print(text_list)
print("".join(text_list))
text_list_0 = text_list[0]
print(text_list_0)

text_list_0_split = list(text_list_0)
print(text_list_0_split)
text_list_0_split_innen = text_list_0_split[1:-1]
print(text_list_0_split_innen)
shuffle(text_list_0_split_innen)
print(text_list_0_split_innen)

text_list_0_split_innen = "".join(text_list_0_split_innen)

text_shuffled_0 = [text_list_0_split[0], text_list_0_split_innen, text_list_0_split[-1]]
print(text_shuffled_0)
text_shuffled_0_joined = "".join(text_shuffled_0)
print(text_shuffled_0_joined)
Jetzt habe ich die Idee das mit einer for Schleife für alle zu machen und dann am Ende alles auszudrucken so das ich einen Satz habe.
Jatzt stecke ich aber fest weil ich das nicht so einfach in eien for Schleife übertragen kann.
Hat jemand eine Idee wie ich da weitermachen sollte?
Sirius3
User
Beiträge: 10549
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 10. Oktober 2019, 16:06

Erster Schritt wäre, eine Funktion zu schreiben, die genau ein Wort verdreht.

Dazu solltest Du bessere Variablennamen wählen: was ist `text_list_0`? Ich würde sagen, das ist ein Wort. Was ist `text_list_0_split_innen`? Das Wortinnere. Usw. Durch diese kleinen Änderungen ist der Code schon viel lesbarer.
`text_shuffled_0_joined` ist dann einfach das verwürfelte Wort.
Milcheiweiß
User
Beiträge: 7
Registriert: Donnerstag 3. Oktober 2019, 12:34

Donnerstag 10. Oktober 2019, 16:37

Ich habe es jetzt mit einer for Schleife bis zu einem, denke ich, guten Punkt gebracht:

Code: Alles auswählen

from random import shuffle
import random
text = input("Give me a string: ")
print(text)

text_list = text.split()
print(text_list)
print("".join(text_list))

for i in text_list:
    if i[-1] == "!":
        innen = ''.join(random.sample(i[1:-2], len(i)-3))
        all = i[0], innen, i[-2:-1]
    else:
        innen = ''.join(random.sample(i[1:-1], len(i)-2))
        all = i[0], innen, i[-1]

    all_word = "".join(all)
    print(all_word)
meine Strategie wäre jetzt alle Wörter in eine Liste zu bekommen und sie danach wieder mit dem join Befehl zu einem Text zu machen.
Hat jemand eine Idee wie ich die Wörter alle in eine Liste bekomme?
Benutzeravatar
__blackjack__
User
Beiträge: 4192
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 10. Oktober 2019, 16:53

@Milcheiweiß: Bei den Namen geht noch was. Grundatentypen sollten nicht in Namen vorkommen. `text_list` wäre ja auch eher treffender `words`. Und `i` für eine Laufvariable die keine ganze Zahl ist, geht gar nicht. Das ist ein `word`.

Das ``if``/``else`` hat in beiden Zweigen fast das gleiche stehen und nur auf "!" zu testen ist ein bisschen wenig. Was ist mit ".", "?", ","? Mindestens.

Listen haben eine `append()`-Methode. Damit kann man Elemente an eine Liste anhängen, also zum Beispiel Wörter in eine Liste bekommen.

Du solltest das wirklich auf kleinere Teilprobleme aufteilen und die dann jeweils mit Funktionen lösen statt das alles als einem, nicht wirklich leicht testbaren, Codeklumpen runterzuhacken.

Edit: Das mit dem `random.sample()` ist Unsinn. Das ist total unübersichtlich das zu verwenden und dann da auch noch das zweite Argument richtig zu berechnen zu müssen.

Was Du auf jeden Fall auch testen/berücksichtigen solltest ist das es auch Sprachen gibt, mit Worten die nur *ein* Zeichen lang sind. Macht Dein Code da das richtige?
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
Milcheiweiß
User
Beiträge: 7
Registriert: Donnerstag 3. Oktober 2019, 12:34

Donnerstag 10. Oktober 2019, 20:01

Hi Ihr,
vielen Dank für eure Hilfe bisher.
Ich habe jetzt etwas womit ich so gut wie fertig bin.
Ich weiß es ist zu umständlich und die Benennung der Variablen könnte besser sein.
Es läuft auf jeden Fall.
Nur habe ich das gefühl das er niemals zu dem Else kommt und sich immer nur in dem if und dem elif bewegt.
Wörter mit 4 Buchstaben werden nie geändert und bei längeren bleiben immer die letzten zwei Buchstaben gleich...
Kann mir jemand sagen warum das so ist?

Code: Alles auswählen

from random import shuffle
import random
text = input("Give me a string: ")
print(text)

text_list = text.split()
print(text_list)
print("".join(text_list))
word_list = []
for i in text_list:
    if len(i) < 3:
        word_list.append(i)
    elif i[-1] == "!" or "." or "?" or ",":
        innen = ''.join(random.sample(i[1:-2], len(i)-3))
        all = i[0], innen, i[-2:]
        all_word = "".join(all)
        print(all_word)
        word_list.append(all_word)
    else:
        innen = "".join(random.sample(i[1:-1], len(i)-2))
        all = i[0], innen, i[-1]
        all_word = "".join(all)
        print(all_word)
        word_list.append(all_word)

print(word_list)
sentence = " ".join(word_list)
print(sentence)
Antworten