Anfänger - Übung - Brauche Hilfe

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
Rage_mode
User
Beiträge: 4
Registriert: Samstag 27. Juli 2019, 16:37

Hi Leute,

glaubt mir bitte, dass ich euch mit so etwas nicht belästigen würde, wenn ich nicht seit 3 Stunden davorhängen würde, ohne es zu begreifen.
Versuche Python 3 zu lernen und komme bei dieser Aufgabe einfach nicht weiter. Bitte gebt mir einfach die Lösung, damit es Klick macht. Danke.

Tipp lautet erst xy, dann yz, dann xy. Es ergibt einfach keinen Sinn für mich. Immer fehlt mir was.

Scramble Exercise: Sorting Scramble
Code scramble: make the program sort the three numbers x, y and z into increasing order, so that x has the smallest value, y has the next smallest value, and z has the largest value.
Drag and drop with your mouse to rearrange the lines. Click for a hint.

y = tmp
tmp = max(x, y)
y = tmp
x = min(x, y)
x = min(x, y)
y = min(y, z)
tmp = max(x, y)
tmp = max(y, z)
z = tmp
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum nicht einfach:

Code: Alles auswählen

x, y, z = sorted([x, y, z])
Wenn man kein `sort` benutzen darf, warum dann `max` und `min`?

Mal doch mal auf Papier, wie man drei Zahlen durch größer/kleiner-Vergleiche sortieren kann.
Rage_mode
User
Beiträge: 4
Registriert: Samstag 27. Juli 2019, 16:37

Ja, es geht halt darum, es nur mit "min/max" zu machen, um sich eine Denkweise anzugewöhnen und Probleme unterschiedlich lösen zu können. Normal wäre "sort". Ich werde es vermutlich echt auf Papier machen müssen -.-
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@Rage_mode: das Problem ist hier nur, dass man sich solch eine Denkweise erst gar nicht angewöhnen sollte.
Statt `tmp` gibt es in Python Tuple-Zuweisungen. Das hier schreibt niemand:

Code: Alles auswählen

tmp = max(y, z)
y = min(y, z)
z = tmp
Statt dessen würde man das schreiben:

Code: Alles auswählen

y, z = min(y, z), max(y, z)
Was aber genauso unlesbar ist, weil man es durch ein viel klareres `if` ersetzen könnte:

Code: Alles auswählen

if y > z: y, z = z, y
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wenn man nicht drüber nachdenken möchte, aber trotzdem alle 8 Lösungen finden möchte, lässt man den Rechner einfach alle Varianten durchprobieren. :-) Sind am Ende ja nur etwas mehr als zwei Millionen.

Code: Alles auswählen

#!/usr/bin/env python3
from itertools import permutations

LINES = '''\
y = tmp
tmp = max(x, y)
y = tmp
x = min(x, y)
x = min(x, y)
y = min(y, z)
tmp = max(x, y)
tmp = max(y, z)
z = tmp
'''.splitlines()

NAMES = list('xyz')


def check_source(source):
    for values in permutations(range(3)):
        namespace = dict(zip(NAMES, values))
        try:
            exec(source, namespace)
        except NameError:
            return False
        else:
            if any(
                namespace[name] != expected
                for name, expected in zip(NAMES, range(3))
            ):
                return False
    return True
                

def main():
    solutions = list()
    sources = ('\n'.join(lines) for lines in permutations(LINES))
    solutions = list(filter(check_source, sources))
    print(solutions)
    print(len(solutions))


if __name__ == '__main__':
    main()
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@__blackjack__: die 8 Lösungen sind in Wirklichkeit ja doch nur eine Lösung, weil drei mal zwei Zeilen identisch sind.

Noch ein paar Zahlen: von den 362880 Varianten sind nur 45360 unterschiedlich, von denen 22680 überhaupt ohne NameError laufen, und 1 die richtige Lösung liefert.
Rage_mode
User
Beiträge: 4
Registriert: Samstag 27. Juli 2019, 16:37

Vielen Dank für eure Antworten Leute. Ihr habt mir bezüglich meines Grundverständnisses schon sehr geholfen.
@_blackjack_ Danke für den interessanten Lösungsansatz es einfach zu automatisieren. Bin leider noch nicht soweit, dass ich vollständig verstehe was du da genau gemacht hast, aber werde das kontinuierlich überprüfen, bis ich es begriffen habe :)
@ Sirius3 Ja, genau deswegen hab ich auch so ein Problem mit der Aufgabe, hätte es wenn nicht mit 'sort', dann zumindest mit 'if' gelöst xD
Rage_mode
User
Beiträge: 4
Registriert: Samstag 27. Juli 2019, 16:37

@_blackjack_ Hab deinen Code ausprobieren wollen und bekomme: Line1. synthax error. unexpected character after line continuation character. Habe den Code komplett kopiert und unter xyz.py gespeichert und ausgeführt.
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Rage_mode: Nach dem \ darf nichts stehen. Auch kein Leerzeichen.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Das Programm so erweitert, dass die Zahlen die Sirius3 bereits genannt hat, ermittelt werden:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import namedtuple
from enum import Enum
from itertools import permutations
from math import factorial
from operator import attrgetter

from more_itertools import map_reduce

LINES = '''\
y = tmp
tmp = max(x, y)
y = tmp
x = min(x, y)
x = min(x, y)
y = min(y, z)
tmp = max(x, y)
tmp = max(y, z)
z = tmp
'''.splitlines()

NAMES = list('xyz')

Category = Enum('Category', 'CORRECT INCORRECT NAME_ERROR')
Result = namedtuple('Result', 'category source')


def check_source(source):
    expected_values = range(len(NAMES))
    for values in permutations(expected_values):
        namespace = dict(zip(NAMES, values))
        namespace['__builtins__'] = {'min': min, 'max': max}
        try:
            exec(source, namespace)
        except NameError:
            return Result(Category.NAME_ERROR, source)
        else:
            if any(
                namespace[name] != expected
                for name, expected in zip(NAMES, expected_values)
            ):
                return Result(Category.INCORRECT, source)
    
    return Result(Category.CORRECT, source)
                

def main():
    sources = set('\n'.join(lines) for lines in permutations(LINES))
    print(
        f'Checking {len(sources)} unique sources from max. possible'
        f' {factorial(len(LINES))}.\n'
    )
    category2sources = map_reduce(
        map(check_source, sources), attrgetter('category'), attrgetter('source')
    )

    for category in Category:
        print(
            f'{category.name:>12}:{len(category2sources.get(category, [])):6}'
        )

    for solution in category2sources.get(Category.CORRECT, []):
        print()
        print(solution)


if __name__ == '__main__':
    main()
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Antworten