Aufgabe mit Liste nicht verständlich

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
CodeRS
User
Beiträge: 2
Registriert: Montag 30. März 2020, 15:59

Hallo alle zusammen,
derzeitig hänge ich an einer Aufgabenstellung, welche ich nicht lösen kann. Die Aufgabe lautet wie folgt:


Schreiben Sie eine Python-Funktion, die eine Liste aller Worte aus Kleinbuchstaben (keine Umlaute) erzeugt, die aus genau 4 Buchstaben bestehen und die keine drei direkt aufeinanderfolgenden Konsonanten enthält.


Nach stundenlangem Herumprobieren entstand dieser Code:

Code: Alles auswählen

 
import string
l_1 = list(string.ascii_lowercase)
l_2 = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z']
l_3 = []
l_4 = []
def wort_liste():
    for i in range(26):
        for y in range(26):
            for n in range(26):
                for r in range(26):
                    l_3.append(l_1[i]+l_1[y]+l_1[n]+l_1[r])

    for i in range(len(l_2)):
        for y in range(len(l_2)):
            for n in range(len(l_2)):
                l_4.append(l_2[i] + l_2[y]+ l_2[n])


    for elem in l_4:
        for elem_2 in l_3:
            if elem in elem_2:
                l_3.remove(elem_2)
                continue
    return l_3

Zwar wird das Programm kompiliert, aber selbst nach einigen Minuten erhalte ich keine Ausgabe. 
Wäre über jede Hilfe dankbar :)




print(wort_liste()) 
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

welche (Fehler-) Meldung bekommst du denn, wenn du dein Programm mit STRG+C abbrichst? Dann siehst du in der Regel, wo es hängt bzw. gerade läuft.

In der 3. for-Schleife änderst du die Liste, über die du iterierst. Das ist schlecht, weil der Iterator da durcheinander kommen kann.
Über Listen (bzw. alles was iterierbar ist, kann man direkt iterieren, ohne `range` und Index-Zugriff, also z.B

Code: Alles auswählen

letters = string.ascii_lowercase
for letter in letters:
    print(letter)
Deine Variablenname sind ziemlich nichtssagend, nimm' für die bessere Verständlichkeit aussagekräftige Namen. Ist im gegeben Fall ja relativ einfach, z.B. letters, consonants, all_words und result.

Um den Test auf drei Konsonanten zu machen, ist Slicing der bessere Weg (und ich vermutet mal, dass das hier auch eingesetzt werden soll. Eine String aus vier Buchstaben hat ja nur zwei 3er-Gruppen, also word[0:3] und word[1:4]. Darüber iterierst du dann und vergleichst mit dem in-Operator gegen die Liste der Konsonanten.

Alle 4er-Kombination kann man übrigens auch sehr einfach mit einer Methode aus dem `itertools` Modul generieren - ist hier aber wahrscheinlich nicht der Lösungsweg, der eingeschlagen werden soll ;-)

Gruß, noisefloor
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Die Aufgabe gab es hier schon mal: viewtopic.php?f=1&t=46861&p=355183

Bei der Liste mit den Buchstaben fehlt übrigens das ß, denn das ist ein Kleinbuchstabe und kein Umlaut. 😎
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
DeaD_EyE
User
Beiträge: 1020
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Schreiben Sie eine Python-Funktion, die eine Liste aller Worte aus Kleinbuchstaben (keine Umlaute) erzeugt, die aus genau 4 Buchstaben bestehen und die keine drei direkt aufeinanderfolgenden Konsonanten enthält.
Ich würde anfangen die Aufgabe in kleinere Teile zu unterteilen (Funktionen).

Code: Alles auswählen

def no_umlauts(word):
    """
    Diese Funktion liefert True zurück, wenn keine Umlaute vorhanden sind.
    Ansonsten wird False ausgegeben.
    """


def no_double_consonants(word):
    """
    Diese Funktion ist von Schwierigkeitsgrad schon etwas höher.
    Letztendlich soll die Funktion True zurück liefern, wenn das Wort keine aufeinander folgenden Konsonanten hat.
    Mögliche Ansätze:
        - 2 Iteratoren
        - oder index-zugriff mit ein bisschen rechnen +1
    """


def erstelle_liste(woerterbuch):
    """
    Das 'woerterbuch' ist ein zusammenhängender Text (str).
    Kriterien:
        - alles Kleinbuchstaben (umwandeln oder nach den Rechtschreibregeln?)
        - Länge des Wortes == 4 Zeichen
        - Keine Umlaute
        - Keine Doppelkonsonanten
    """
    words = woerterbuch.lower() # Aufgabe 1, alles in Kleinbuchstaben
    # da der ganze Text jetzt in Kleinbuchstaben ist, muss später nichts mehr geändert werden.
    # falls die Rechtschreibung damit gemeint ist, wäre dieser Ansatz falsch
    # dann lässt man words = woerterbuch.lower() einfach weg,
    # weil es wird ja eh später gerprüft ob die Zeichen des Wortes in string.ascii_lowercase enthalten sind.
    results = []
    for wort in words.split():
        if len(wort) != 4:
            # zum nächsten Wort, wenn das Wort nicht aus 4 Zeichen besteht.
            continue
        if no_umlauts(wort) and no_double_consonants(wort): # Der Test
            results.append(wort)
    return results
Für die Funktion no_umlauts kann man sich bei string.ascii_lowercase bedienen. Der str enthält die Zeichen a-z.
Entweder kann man das ganz klassisch in einer for-schleife testen, ob jedes Zeichen aus dem Wort in string.ascii_lowercase enthalten ist.
Natürlich könntest du die Zeichenkette auch selbst angeben. Ich würde jedenfalls die Funktion all mit einer Generator Expression nutzen.

So prüft man, ob ein Zeichen oder mehrere Zeichen in einem String vorkommen:

Code: Alles auswählen

gesucht = "Nadel"
heuhaufen = "heuhaufenheuhaufenNadelheuhaufenheuhaufen"

gefunden = gesucht in heuhaufen
if gefunden:
    print("Nadel gefunden")
else:
    print("Keine Nadel :-/")
Es muss nun Zeichen für Zeichen geprüft werden, ob dieses in string.ascii_lowercase vorkommt, dass auch vorher nicht in eine Liste umgewandelt werden muss, da str bereits eine Sequenz ist.

Die Funktion no_double_consonants ist schwieriger umzusetzen, wenn man mit iteratoren arbeiten möchte und noch nicht so ganz weiß, was die machen.
Anfänger tendieren eher zu gucken wie lang das Wort ist, um dann mit einer Zählschleife auf die Indices zuzugreifen und das letzte Element mit dem aktuellen vergleichen wird usw.

Code: Alles auswählen

word = "tesst"
wlen = len(word)
is_ok = True
for idx in range(wlen - 1): # 0, ... len - 2
    if word[idx] == word[idx + 1]:
        is_ok = False
        break # wir wissen jetzt, dass zwei Zeichen aufeinander folgen
                   # wenn jetzt zwei Vokale aufeinander folgen, wird auch erkannt
                   # Deswegen brauchst du auch eine Liste mit Konsonanten, um das mit jeden Buchstaben zu prüfen

Da ich faul bin, mache ich keine Liste, sondern ein set.

Code: Alles auswählen

vokale = set("aeiou")
konsonanten= set(string.ascii_lowercase) - vokale
print(konsonanten)
print(sorted(konsonanten))
Sortieren braucht man die Konsonanten nicht. Man prüft einfach nur, ob der Buchstabe in dem set vorkommt.

Code: Alles auswählen

print("a" in konsonanten)
Ich hoffe, dass ich nicht zuviel gemacht habe. Falls doch, einfach löschen...
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DeaD_EyE: Du hast den Begriff „Worter” falsch verstanden. Es geht nicht um tatsächliche Worte aus irgendeiner Sprache sondern einfach nur um alle Möglichen Arten vier Buchstaben zusammen zu pappen, mit den genannten Einschränkungen. `no_umlauts()` braucht es also nicht, denn die braucht man nicht ausfiltern wenn man sie gar nicht erst ins Spiel bringt.

Bei Konsonanten wäre noch interessant ob „y“ als Konsonant zählt oder nicht. Ich hätte bei der Aufgabe ja rein aus Querdenkerei „ß“ mit zu den Kleinbuchstaben und „y“ zu den Konsonanten gezählt. Natürlich mit entsprechender Erklärung. Einfach um zu zeigen wo die Aufgabenstellung unpräzise ist.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
DeaD_EyE
User
Beiträge: 1020
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Achso...
Also Kombinatorik mit Wiederholung + Permutation?
Da man dann ja nur die erlaubten Buchstaben zur Konstruktion der Möglichkeiten verwendet, braucht man die nicht vorhandenen Umlaute nicht zu filtern. Stimmt :lol:

Jedenfalls wäre dann itertools die richtige Richtung.
Habe das selbst mal ausprobiert, aber man muss vorher genau lesen was diese Funktionen machen und entsprechend miteinander Kombinieren.
Falls man sie miteinander kombinieren muss und es keine bessere Lösung gibt.

Mögliche Lösung:

Code: Alles auswählen

result = {
    "".join(word) for word_combo in itertools.combinations_with_replacement(string.ascii_lowercase, 4)
    for word in itertools.permutations(word_combo)
    if not any(
        word[idx] in "aeiou"
        and word[idx] == word[idx + 1]
        for idx in range(len(word) - 1)
    )
}
Wobei ich hier 1. nicht weiß ob diese richtig ist und ob man es nicht noch besser machen kann.
Und 3. hilft es wahrscheinlich dem OP nicht wirklich.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DeaD_EyE: Das sieht mir recht kompliziert aus. Was hast Du gegen `product()`?

Meine Lösung aus dem bereits bestehenden Thema zu dieser Aufgabe war das hier:

Code: Alles auswählen

#!/usr/bin/env python3
import re
from itertools import filterfalse, product
from string import ascii_lowercase

ALPHABET = ascii_lowercase + "ß"
VOWELS = "aeiouy"
CONSONANTS = "".join(letter for letter in ALPHABET if letter not in VOWELS)

WORD_LENGTH = 4
MAX_CONSONANT_RUN_LENGTH = 3

contains_consonant_run = re.compile(
    f"[{re.escape(CONSONANTS)}]{{{MAX_CONSONANT_RUN_LENGTH}}}"
).search

assert len(VOWELS) + len(CONSONANTS) == len(ALPHABET)
assert WORD_LENGTH > 0 and MAX_CONSONANT_RUN_LENGTH < WORD_LENGTH


def main():
    all_words = map("".join, product(ALPHABET, repeat=WORD_LENGTH))
    for word in filterfalse(contains_consonant_run, all_words):
        print(word)


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
DeaD_EyE
User
Beiträge: 1020
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

__blackjack__ hat geschrieben: Mittwoch 1. April 2020, 13:54 @DeaD_EyE: Das sieht mir recht kompliziert aus. Was hast Du gegen `product()`?
Dagegen? Gegen itertools kann man nicht sein. Nutze sogar noch more_itertools, aber nicht komplett.
Bei product muss ich immer an Kartenspiele denken bzw. nutze ich das um z.B. verschachtelte Schleifen zu vermeiden.
`Flat is better than nested`


Jedenfalls wusste ich bis jetzt noch nicht, dass product auch repeat als Parameter nimmt.
Also müsste product alle möglichen Kombinationen entsprechend der Länge inklusive der Wiederholungen produzieren.
Ist ja viel einfacher als mit combinations + permutations im set.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten