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²: 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: 6740
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.
SuperDAU²
User
Beiträge: 20
Registriert: Sonntag 24. Mai 2009, 12:47

Warum "f = reduce"? Was heißt "lambda"? Was berechnst du in der ersten Klammer? womit ist a, b und c definiert?

Code: Alles auswählen

x=f(lambda(a,b),c:([(b>=c,c)]+a,b-(b>=c)*c)
Was soll print ausgeben? Und wie setzt du das um?

Ich glaube, dass ich gerade gehörig auf dem Schlauch stehe.

PS: Die for-Schleife habe ich nun verstanden

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 schein in scheine:
    if betrag >= scheine:
        auszahlung.append(str(scheine))
        betrag = betrag - scheine
print auszahlung
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)
Allerdings habe ich, wenn ich in der Mitte mir "print auszahlung" anzeigen lasse, kein einziges Listenelement. Demnach funktioniert irgendetwas mit der for-Schleife und somit auch die Hausfrauenmischung nicht.

Code: Alles auswählen

Wieviel soll ausgezahlt werden? 675
[]
Ihre Auszahlung: 1*500, 0*200, 1*100, 1*50, 1*20, 0*10, 1*5
Deswegen habe ich weiter daran gebastelt.

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 schein in scheine:
    if betrag >= scheine:
        print schein
        print scheine
        auszahlung.append(str(scheine))
        betrag = betrag - scheine
    scheine.reverse()
    while betrag > 0:
        while betrag >= scheine:
            auszahlung.append(str(scheine)
            betrag = betrag - scheine

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)
Ich bekomme allerdings folgenden Fehlercode(Kann aber keinen Fehler in Zeile 22 entdecken):

Code: Alles auswählen

python Python/bankautomat3.py
  File "Python/bankautomat3.py", line 22
    betrag = betrag - scheine
         ^
SyntaxError: invalid syntax
Die Auszahlungsliste werde ich auch noch überarbeiten.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@SuperDAU²:

Du bist ja lustig. Der Hinweis, dass die `int()`-Umwandlungen sinnfrei sind, da sie schon in der Liste als Integer eingetragen sind, meinte mitnichten, dass du überall ein `str()` vorsetzen sollst. Warum machst du dir das Leben so kompliziert? Ich habe doch gesagt, dass man die Umwandlungen, die für `join()` nötig sind, am Ende mappen kann:

Code: Alles auswählen

In [21]: lst = [1,2,3]

In [22]: lst
Out[22]: [1, 2, 3]

In [23]: map(str, lst)
Out[23]: ['1', '2', '3']
SuperDAU² hat geschrieben:Ich bekomme allerdings folgenden Fehlercode(Kann aber keinen Fehler in Zeile 22 entdecken):

Code: Alles auswählen

python Python/bankautomat3.py
  File "Python/bankautomat3.py", line 22
    betrag = betrag - scheine
         ^
SyntaxError: invalid syntax
In solchen Fällen hilft es oft, eine Zeile höher zu schauen und dann entdeckt man auch den Fehler: In Zeile 21 fehlt am Ende eine schließende Klammer. :)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Argh. Danke, war wohl gestern schon spät.

Code: Alles auswählen

", ".join(reduce(lambda(a,c),b:(a%b,c+["%d*%d"%(a/b,b)]),[500,200,100,50,20,10,5],(input(),[]))[1])
Wir haben aber beide noch Probleme mit beliebigen Scheinen. Angenommn wir haben die Beträge 7 und 5 und möchten 10 Euro abheben, dann werden wir nur 7 bekommen. Vielleicht sollten wir also die Vorraussetzung beibehalten, dass jeder Schein durch eine Kombination der kleineren Scheine konstruiert werden kann (wirklich ausreichende Bedingung?).

Edit: Nimmt man die oben genannte Voraussetzung an, so lässt sich über die Teilbarkeit der auszahlbaren Beträge durch den kleinsten Geldschein leicht zeigen, dass immer eine vollständige Auszahlung erfolgen kann. Interessant wäre nun noch, ob Systeme existieren welche die oben genannte Bedingung nicht erfüllen und trotzdem immer vollständig auszahlen (natürlich falls möglich).

Edit: das Beispiel mal richtig gemacht.
Zuletzt geändert von EyDu am Mittwoch 27. Mai 2009, 14:41, insgesamt 2-mal geändert.
Das Leben ist wie ein Tennisball.
SuperDAU²
User
Beiträge: 20
Registriert: Sonntag 24. Mai 2009, 12:47

Also so in der Art:

Code: Alles auswählen

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

print 'Ihre Auszahlung:', map(str, auszahlungsliste)
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wenn beim `append()` in Zeile 16 ebenfalls keine Strings angehängt werden, kannst du auch `count()` normale Zahlen übergeben. Wie kamst du eigentlich auf die Idee? Denkst du, Listen dürfen nur Strings enthalten? Listenelemente können alle möglichen Objekte sein, z.B. auch Klasseninstanzen oder weitere Listen. Es gibt da keine Limitierungen.

Und ansonsten:

Code: Alles auswählen

[(auszahlung.count(schein), schein) for schein in scheine]
Geht natürlich nur, wenn man keine Strings anhängt. ;)
Antworten