hilfe hausaufgabe python

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.
BlackJack

@SuperDAU²: Du berechnest immer noch ``betrag - scheine`` zweimal. Wie gesagt, die Bedingung in der inneren ``while``-Schleife kann man so umstellen, dass man da nichts ausrechnen muss.

Und statt der äusseren ``while``-Schleife würde ich eine ``for``-Schleife über `scheine` schreiben. Dann wirst Du das `i` los. Wenn Du nicht alle Scheine durchlaufen möchtest, auch wenn der `betrag` schon bei 0 ist, kannst Du die Schleife auch immer noch durch ein `break` verlassen.

Du gehst auch nicht mit dem Fall um, wenn der Anwender einen Betrag eingibt, der nicht durch die vorhandenen Scheine abgebildet werden kann.
SuperDAU²
User
Beiträge: 20
Registriert: Sonntag 24. Mai 2009, 12:47

Ich habe es mal probiert:

Code: Alles auswählen

#!/usr/bin/env python
# Bankautomat mit Hausfrauenmischung

scheine = [500, 200, 100, 50, 20, 10, 5]
scheine2 = [5, 10, 20, 50, 100, 200, 500]
trennzeichen = ', '
auszahlung = []
betrag = int(raw_input('Wieviel soll ausgezahlt werden? '))

for i in range(0, 7):
    if betrag >= scheine2[i]:
        auszahlung.append(str(scheine2[i]))
        betrag = betrag - scheine2[i]
        continue

while betrag > 0:
    while betrag >= scheine[i]:
        auszahlung.append(str(scheine[i]))
        betrag = betrag - scheine[i]
    i = i + 1

print 'Ihre Auszahlung:', trennzeichen.join(auszahlung)
Allerdings habe ich folgende Ausgabe:

Code: Alles auswählen

Wieviel soll ausgezahlt werden? 675
Ihre Auszahlung: 5, 10, 20, 50, 100, 200, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
Das gibt zwar exakt 675, aber trotzdem wird die while-Schleife nicht richtig ausgeführt.

Edit: Problem selbst gelöst:

Code: Alles auswählen

#!/usr/bin/env python
# Bankautomat

scheine = [500, 200, 100, 50, 20, 10, 5]
scheine2 = [5, 10, 20, 50, 100, 200, 500]
trennzeichen = ', '
u = 0
auszahlung = []
betrag = int(raw_input('Wieviel soll ausgezahlt werden? '))

for i in range(0, 7):
    if betrag >= scheine2[i]:
        auszahlung.append(str(scheine2[i]))
        betrag = betrag - scheine2[i]
        continue

while betrag > 0:
    while betrag >= scheine[u]:
        auszahlung.append(str(scheine[u]))
        betrag = betrag - scheine[u]
    u = u + 1

print 'Ihre Auszahlung:', trennzeichen.join(auszahlung)
Um eine bessere Übersicht zu erhalten, hätte ich gerne etwas wie das

Code: Alles auswählen

Ihre Auszahlung: 2*200, 1*100, 2*50, 3*20, 1*10, 1*5
Zuletzt geändert von SuperDAU² am Sonntag 24. Mai 2009, 17:13, insgesamt 1-mal geändert.
BlackJack

SuperDAU²: Was denkst Du was `i` in Zeile 15 für einen Wert hat? Überprüf mal ob Deine Erwartung mit der Realität übereinstimmt.

Und die erste Schleife sollte definitiv über die `scheine2` gehen, ohne den Index. Und man sollte dafür keine extra Liste angeben, wenn man die auch aus `scheine` erstellen kann -> `reversed()`.

Das ``continue`` ist sinnfrei.
SuperDAU²
User
Beiträge: 20
Registriert: Sonntag 24. Mai 2009, 12:47

Hier nochmals der überarbeitete Code:

Code: Alles auswählen

#!/usr/bin/env python

scheine = [5, 10, 20, 50, 100, 200, 500]
trennzeichen = ', '
u = 0
auszahlung = []
betrag = int(raw_input('Wieviel soll ausgezahlt werden? '))

for i in range(0, 7):
    if betrag >= scheine[i]:
        auszahlung.append(str(scheine[i]))
        betrag = betrag - scheine[i]
scheine.reverse()
while betrag > 0:
    while betrag >= scheine[u]:
        auszahlung.append(str(scheine[u]))
        betrag = betrag - scheine[u]
    u = u + 1

print 'Ihre Auszahlung:', trennzeichen.join(auszahlung)
Mir kam die Idee es so umzuschreiben, aber dann bleibt das Programm stehen.

Code: Alles auswählen

#!/usr/bin/env python

scheine = [5, 10, 20, 50, 100, 200, 500]
trennzeichen = ', '
u = 0
auszahlung = []
betrag = int(raw_input('Wieviel soll ausgezahlt werden? '))

for i in range(0, 7):
    if betrag >= scheine[i]:
        auszahlung.append(str(scheine[i]))
        betrag = betrag - scheine[i]
scheine.reverse()
for u in range(0, 7):
    while betrag > 0:
        while betrag >= scheine[u]:
            auszahlung.append(str(scheine[u]))
            betrag = betrag - scheine[u]

print 'Ihre Auszahlung:', trennzeichen.join(auszahlung)
Wo ist der Fehler? Der Interpreter bleibt in Zeile 16 stecken.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Da du die Scheine umkehrst, ist scheine zu Beginn 500. Ist der Betrag < 500, dann ist die Bedingung der inneren while-Schleife nie erfüllt, folglich wird der Betrag nicht verringert und die äußere while-Schleife wird zur Endlosschleife.
BlackJack

SuperDAU²: Vergiss mal die erste auf Modulebene Schleife und gehe die zweite in Gedanken mit dem Betrag 15 mal Schritt für Schritt in Gedanken durch. Dann solltest Du drauf kommen warum das eine Endlosschleife werden kann.
SuperDAU²
User
Beiträge: 20
Registriert: Sonntag 24. Mai 2009, 12:47

Ich habe das Problem jetzt verstanden. Aber ich finde keine andere Lösung dazu als die vorherige Variante.

Was ist mit meiner Frage zwecks der Übersichtlichkeit? Wie bekomme ich eine Ausgabe in der Art von "6*500, 1*200, 1*100, 1*50, 3*20, 1*10, 2*5"?
Benutzeravatar
snafu
User
Beiträge: 6831
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Was ist denn das genaue Problem? Falls es um die Anzahl der Vorkommnisse einer Sorte geht: Listen haben die Methode `count()`, die als Argument die Bezeichnung des zu zählenden Elements nimmt.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

@BlackJack: Danke für den Hinweis. Ich hatte die Umformung wegen der besseren Lesbarkeit nicht vorgenommen. Für mein Produktivsystem werde ich dies nun natürlich aus Performance-Gründen entsprechend ändern.
Zuletzt geändert von EyDu am Sonntag 24. Mai 2009, 22:52, insgesamt 2-mal geändert.
Das Leben ist wie ein Tennisball.
SuperDAU²
User
Beiträge: 20
Registriert: Sonntag 24. Mai 2009, 12:47

Vielen Dank an snafu für den Tipp mit "count()". Irgendwie werde ich das Gefühl nicht los, dass man "auszahlungsliste" leichter hätte erstellen können. Geht das etwa wieder mit einer for-Schleife?

Code: Alles auswählen

#!/usr/bin/env python
# Bankautomat

scheine = [5, 10, 20, 50, 100, 200, 500]
u = 0
multi = '*'
trenn = ', '
trenn2 = ''
auszahlung = []
betrag = int(raw_input('Wieviel soll ausgezahlt werden? '))

for i in range(0, 7):
    if betrag >= scheine[i]:
        auszahlung.append(str(scheine[i]))
        betrag = betrag - scheine[i]

scheine.reverse()

while betrag > 0:
    while betrag >= scheine[u]:
        auszahlung.append(str(scheine[u]))
        betrag = betrag - scheine[u]
    u = u + 1

auszahlungsliste = [str(auszahlung.count('500')), multi, str(scheine[0]), trenn,
str(auszahlung.count('200')), multi, str(scheine[1]), trenn,
str(auszahlung.count('100')), multi, str(scheine[2]), trenn,
str(auszahlung.count('50')), multi, str(scheine[3]), trenn,
str(auszahlung.count('20')), multi, str(scheine[4]), trenn,
str(auszahlung.count('10')), multi, str(scheine[5]), trenn,
str(auszahlung.count('5')), multi, str(scheine[6])]

print 'Ihre Auszahlung:', trenn2.join(auszahlungsliste)
Außerdem habe ich eine weitere Frage: Wenn ein Schein in "auszahlung" nicht vorkommt, wie kann ich ihn dann in der "auszahlungsliste" entfernen?

Oder habt ihr eine andere bzw bessere Lösung für das Problem?
Zuletzt geändert von SuperDAU² am Sonntag 24. Mai 2009, 22:53, insgesamt 1-mal geändert.
BlackJack

@SuperDAU²: Schau Dir mal die `zip()`-Funktion an, Zeichenkettenformatierung mittels ``%``-Operator, und dann werd endlich mal `i` und `u` los, indem Du direkt über die Elemente der Liste iterierst.

Zumindest solltest Du aber die Initialisierung von `u` direkt vor der Schleife machen und nicht irgendwo oben, als weit weg von der Stelle wo's letztendlich gebraucht wird.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

War doch klar, dass Werte von Geldscheinen auf den ersten binären Nachkommastellen von PI beruhen:

Code: Alles auswählen

>>> reduce(lambda a,b: a+[(a[-1]*(4+b))/2], tuple((int(math.pi*2**8)>>i)&1 for i in range(7, 1, -1)), [5])
[5, 10, 20, 50, 100, 200, 500]
Sollten also neue Noten eingeführt werden, so ergeben sich die Beträge:

Code: Alles auswählen

>>> reduce(lambda a,b: a+[(a[-1]*(4+b))/2], tuple((int(math.pi*2**18)>>i)&1 for i in range(16, 1, -1)), [5])
[5, 10, 25, 50, 100, 250, 500, 1000, 2000, 4000, 10000, 25000, 62500, 156250, 390625, 976562]
Das Leben ist wie ein Tennisball.
SuperDAU²
User
Beiträge: 20
Registriert: Sonntag 24. Mai 2009, 12:47

@BlackJack:
Den Tipp mit zip() habe ich verstanden, aber was du mit
Zeichenkettenformatierung mittels ``%``-Operator, und dann werd endlich mal `i` und `u` los, indem Du direkt über die Elemente der Liste iterierst.
meinst, weiß ich leider nicht. Könntest du mir bitte ein Beispiel geben?

PS: Hast du die Fragen im meinem letzten Post gesehen?

MfG
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

String-Formatierung:

Code: Alles auswählen

>>> "formatiere mich; int: %d, str: %s, float: %f" % (42, "spam", 3.1415)
'formatiere mich; int: 42, str: spam, float: 3.141500'
Indizes:

Code: Alles auswählen

for schein in scheine:
    if betrag >= scheine:
        auszahlung.append(str(scheine))
        betrag = betrag - scheine
Das Leben ist wie ein Tennisball.
BlackJack

Ich hätte da jetzt noch diesen schicken 3-Zeiler im Angebot:

Code: Alles auswählen

S=500,200,100,50,20,10,5;f=reduce;print', '.join('%d*%d'%(a,b) for a,b in zip((
lambda r,x:[a+b for a,b in zip(f(lambda (a,b),c:(a+[b//c],b%c),S,([],x))[0],
r[::-1])])(*f(lambda(a,b),c:(a+[b>=c],b-(b>=c)*c),S[::-1],([],input()))),S))
Berechnet die Haushaltsmischung. Falls beim Betrag ein Rest bleiben sollte, also der Betrag nicht durch 5 teilbar ist, fällt dieser Rest einfach weg. Testlauf:

Code: Alles auswählen

bj@s8n:~$ python forum2.py
355
0*500, 0*200, 2*100, 2*50, 2*20, 1*10, 1*5
Ein Beispiel für Zeichenkettenformatierung ist auch drin. :-)
SuperDAU²
User
Beiträge: 20
Registriert: Sonntag 24. Mai 2009, 12:47

@EyDu:
Das mit der Stringformatierung hab ich jetzt auch verstanden. Wo mir das weiterhilft muss ich noch herausfinden :P

und zu dem 2. Codeblock:
Wenn ich den in mein Programm einfüge, wird dieser Block einfach übersprungen. Außerdem verstehe ich nicht, womit "schein" definiert ist.

@BlackJack:
Toll, wenn du mir den 3-Zeiler noch erklären kannst. :roll:
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Immerhin passt der Code schon auf eine Bildschirmzeile:

Code: Alles auswählen

print reduce(lambda(a,c),b:(a%b,c+(a/b and[(a/b,b)]or[])),[500,200,100,50,20,10,5],(input(),[]))
print reduce(lambda(a,c),b:(a%b,c+[(a/b,b)]),[500,200,100,50,20,10,5],(input(),[]))

Code: Alles auswählen

sebastian@sepp:~$ python test.py
227
(2, [(1, 200), (1, 20), (1, 5)])
227
(2, [(0, 500), (1, 200), (0, 100), (0, 50), (1, 20), (0, 10), (1, 5)])
Und der Restbetrag erledigt sich ganz von alleine.

@SuperDAU²: du sollst den Code nicht einfach bei dir einfügen, er ersetzt deine erste for-Schleife des Codes. Wenn du das mit "schein" nicht verstehst, dann wirf noch einmal einen Blick ins Tutorial.

Edit: Indizes gespart.
Edit2: Modulo existiert... :roll:
Das Leben ist wie ein Tennisball.
BlackJack

Da waren doch glatt noch 21 Zeichen "zuviel" drin:

Code: Alles auswählen

S=500,200,100,50,20,10,5;f=reduce;r,x=f(lambda(a,b),c:([b>=c]+a,b-(b>=c)*c),
S[::-1],([],input()));print', '.join('%d*%d'%(a,b)for a,b in zip([a+b for a,b
in zip(f(lambda(a,b),c:(a+[b/c],b%c),S,([],x))[0],r)],S))
@SuperDAU²: Was ist denn daran nicht verständlich!? ;-)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

@BlackJack: ich hab mir deine Version mal genauer angeschaut, da haben wir wohl nahezu identischen Code produziert.

Und mal mit Formatierung:

Code: Alles auswählen

print ", ".join("%d*%d"%x for x in reduce(lambda(a,c),b:(a%b,c+[(a/b,b)]),[500,200,100,50,20,10,5],(input(),[]))[1])

Code: Alles auswählen

sebastian@sepp:~$ python test.py
227
0*500, 1*200, 0*100, 0*50, 1*20, 0*10, 1*5
Das Leben ist wie ein Tennisball.
BlackJack

@EyDu: Jup, das sieht von der Struktur her aus wie meins. Nur das ich die Haushaltsmischung noch mit aufgenommen habe. Jetzt mit 41 Zeichen weniger, bin jetzt bei 173:

Code: Alles auswählen

f=reduce;r,x=f(lambda(a,b),c:([(b>=c,c)]+a,b-(b>=c)*c),[5,10,20,50,100,200,500],
([],input()));print', '.join(f(lambda(a,b),(c,d):(a+['%d*%d'%(b/d+c,d)],b%d),r,
([],x))[0])
Die Zeichenkettenformatierung könntest Du auch noch weiter reinziehen und damit den Generatorausdruck einsparen.
Antworten