Geldautomat programmieren

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
DiegoSquaratti
User
Beiträge: 4
Registriert: Dienstag 15. Oktober 2019, 19:16

Hallo zusammen

Ich nehme gerade das E-Tutorial von der ETH Zürich durch. Bis jetzt läuft alles gut, jedoch gibt es jetzt eine Aufgabe, wo man einen Geldautomaten programmieren soll und laut ihnen soll man nicht länger als 2 Stunden für diese Aufgabe brauchen. Ich bin jedoch jetzt seit 2 Tagen dahinter. Ich komme einfach nicht weiter

Aufgabenstellung:
[i"]In dieser Aufgabe sollen Sie einen Geldautomaten simulieren. Die Kundin oder der Kunde
soll eingeben können, wie viel Geld er oder sie abheben möchte. Der Geldautomat soll
dann berechnen, wie viele und welche Banknoten (100er, 50er, 20er und 10er) er ausgeben
soll. Die Anzahl der verwendeten Variablen soll möglichst klein gehalten werden, indem
sie wiederverwendet werden. Berechne zusätzlich den Restbetrag."[/i]

---Die Ausrechnung, wie viele Noten für einen input raussollen, habe ich berechnet. Jedoch will man ja so nah wie möglich an den eingegebenen Input ran (z.B: input 581 --> 5 Hunderter/1 Fünfziger/3 Zehner und Restbetrag 1), und nicht bei jeder Note die Anzahl neu berechnen (z.B: input 581 --> 5 Hunderter/11 Fünfziger/58 Zehner und Restbetrag 1). Wie kann ich das aufteilen? Und beim Restbetrag bekomme ich immer das Vierfache vom eigentlichen Betrag (Also statt Restbetrag 1 bekomme ich 4, weil ich bei 4 verschiedenen Noten den Restbetrag ausrechne, die werden dann summiert. Wenn ich sie aber durch 4 teile, kommt eine viel grössere Zahl raus.)

Mein Code sieht so aus:

Betrag=float(input("Geben Sie einen Betrag ein"))

x=100
y=(50)
z=(20)
xyz=(10)

#Berechnung 100er Noten
x=(int(Betrag/x))
print("100er Noten:",(x))
Viertel100=x*0.25
Rest1=float(Betrag-Viertel100)



#Berechnung 50er Noten
y=(int(Betrag/y))
print("50er Noten:",(y))
Viertel50=y*0.25
Rest2=float(Betrag-Viertel50)


#Berechnung 20er Noten
z=(int(Betrag/z))
print("20er Noten:",(z))
Viertel20=z*0.25
Rest3=float(Betrag-Viertel20)


#Berechnung 10er Noten
xyz=(int(Betrag/xyz))
print("10er Noten:",(xyz))
Viertel10=xyz*0.25
Rest4=float(Betrag-Viertel10)

#Berechnung Rest der Noten
Rest=(int(Rest1+Rest2+Rest3+Rest4))
print("Rest",(Rest))


PROGRAMM ENDE

Ich weiss, mein Problem ist auf mangelnden rationalen Kenntnissen zurückzuführen (Ich weiss, dass die Aufgabe eigentlich einfach ist).
Trotzdem danke ich euch für die Antwort und (vielleicht) für die Hilfe!

LG
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich weiß nicht ob ihr schon Datenstrukturen hattet. Oder ob Code-Duplikation erlaubt ist. Konzeptionell ist erstmal aber gleich, dass die Anzahl der Noten mit Nennwert X der ganzzahlige Anteil der Division “Betrag / Wert” ist. Und dann musst du natürlich den schon ausgerechneten Teilbetrag abziehen, um den Rest zu berechnen.

In Python also

Code: Alles auswählen

hunderter = betrag // 100 # // ist WICHTIG!
betrag -= hunderter * 100
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Man könnte die Geldscheingrößen in eine Liste packen und die Anzahl-Berechnung in eine Funktion, die dann aufgerufen wird. Das könnte den Code smell reduzieren.
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

__deets__ hat zwar jetzt schon erklärt, wie es auch ohne geht, aber ich frage zur Sicherheit doch noch mal: Sind die Python Operatoren '%' (Modulo/Divisionrest) oder im besten Fall sogar 'divmod' in deinem Kurs schon vorgekommen? Damit würde man es nämlich ansonsten lösen.
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Ich dachte an so etwas hier:

Code: Alles auswählen

def anzahl_banknoten(betrag, banknote):
    return (betrag // banknote, betrag % banknote)

betrag = int(input("Wie viel möchten Sie abheben (Ganzzahl!)? "))

banknoten = [100, 50, 20, 10, 5]

for banknote in banknoten:
    anzahl, betrag = anzahl_banknoten(betrag, banknote)
    print("Sie erhalten {} x {} €".format(anzahl, banknote))

print("Ich kann {} € nicht auszahlen.".format(betrag))
Würde dann Folgendes in der Konsole liefern:

Code: Alles auswählen

Wie viel möchten Sie abheben (Ganzzahl!)? 373
Sie erhalten 3 x 100 €
Sie erhalten 1 x 50 €
Sie erhalten 1 x 20 €
Sie erhalten 0 x 10 €
Sie erhalten 0 x 5 €
Ich kann 3 € nicht auszahlen.
Das könnte man sicherlich schöner machen, man müsste wohl auch prüfen, ob das Konto des Kunden die Auszahlung überhaupt hergibt usw., aber die Auszahlung würde ich so etwa machen, wobei die Variable betrag einmal der Auszahlungsbetrag des Kunden und dann der Restbetrag zur Auszahlung ist (nicht schön, aber lauffähig). BTW: Bankautomaten, die ich kenne, vereinfachen den Prozess, indem Sie feste Beträge zur Auszahlung vorgeben, also z. B. 500, 200, 100, 50 usw. und wahrscheinlich intern schon feste Auszahlungsabläufe gespeichert haben, etwa - wenn 500, dann 4 x 100, 1 x 50, 2 x 20, 1 x 10 oder so.
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

@DiegoSquaratti: Könntest Du mal einen Link auf das E-Tutorial der ETH-Zürich geben? Ich habe zwar eine Seite gefunden, nehme aber mal an, dass das Tutorial hinter einem Login liegt?
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Schön, das du mal wieder eine komplette Lösung vorkaust 😒
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

@__deets__: Sorry, ich konnte nicht widerstehen. Momentan habe ich seit Sommer nichts anderes gemacht als Probleme fremder Leute in Code zu gießen, das hier bot einen Ausweg aus der Tristes des Alltags. Ich gelobe Besserung... Meine Lösung finde ich übrigens nicht so toll (keine 2 Stunden) und daher durchaus verbesserungswürdig, was ich angedeutet habe. Wenn man 2 Tage über einem Problem brütet, hilft vielleicht durchaus mal eine Lösung in Ansätzen, um Wege aufzuzeigen...
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@pixewakb: `anzahl_banknoten()` lässt sich kürzer schreiben:

Code: Alles auswählen

anzahl_banknoten = divmod
🙂
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

pixewakb hat geschrieben: Dienstag 15. Oktober 2019, 20:28 @__deets__: Sorry, ich konnte nicht widerstehen. Momentan habe ich seit Sommer nichts anderes gemacht als Probleme fremder Leute in Code zu gießen, das hier bot einen Ausweg aus der Tristes des Alltags. Ich gelobe Besserung... Meine Lösung finde ich übrigens nicht so toll (keine 2 Stunden) und daher durchaus verbesserungswürdig, was ich angedeutet habe. Wenn man 2 Tage über einem Problem brütet, hilft vielleicht durchaus mal eine Lösung in Ansätzen, um Wege aufzuzeigen...
Das ist doch genauso ein Problem von jemand anderem. Was also hat das damit zu tun? Auch die Rechtfertigung es ginge ja noch besser ist schwach.

Wir haben uns hier (schon vor langem)darauf geeinigt, Hilfe zur Selbsthilfe zu leisten.Gerade bei Leuten, die klar lernen wollen/müssen. Was du auch weißt. Die Diskussion haben wir ja nicht zum ersten Mal. Stattdessen hast du Fischplatte serviert. Um mal ein beliebtest Gleichnis zu paraphrasieren. Entsprechend sieht es mE mit dem Lernerfolg aus.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und noch ein Nachtrag: auch andere haben dieses Bedürfnis, und stillen es. __blackjack__ zB. Doch der wartet 2 Wochen. Wenn die Abgabe schon war.
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Oder ich poste sofort eine Lösung — in einer Sprache wie BASIC. In diesem Fall GW-BASIC (sollte so aber auch einem C64 lauffähig sein):

Code: Alles auswählen

10 INPUT"Betrag";A:IF A<0 THEN PRINT"Betrag muss positiv sein!":GOTO 10
20 IF A=0 THEN END
30 READ V:IF V=-1 THEN 60
40 N=INT(A/V):IF N=0 THEN 30
50 PRINT N;"mal";V;"EUR":A=A-N*V:IF A<>0 THEN 30
60 IF A<>0 THEN PRINT"Restbetrag:";A;"EUR"
70 RESTORE:GOTO 10
80 DATA 100,50,20,10,5,-1
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@DiegoSquaratti: gewöhn Dir gleich an, sprechende Variablennamen zu verwenden, x, y, z oder gar xyz sind das nicht.
Wenn man sinnvolle Namen vergibt, merkt man auch schnell, dass bei der Rechnung etwas nicht stimmen kann.
Für die 100er, sähe das so aus:

Code: Alles auswählen

nennwert_100er = 100
anzahl_100er = (int(Betrag / nennwert_100er))
print("100er Noten:", anzahl_100er)
viertel_der_anzahl_100er = anzahl_100er * 0.25
rest_betrag = Betrag - viertel_der_anzahl_100er
Was hast Du Dir für Gedanken gemacht, dass Du gerade ein Viertel der Anzahl an Banknoten vom Betrag abziehst?

Überleg Dir bei Deinem Code auch mal, wann Klammern nötig sind und wann sie überflüssig sind.
DiegoSquaratti
User
Beiträge: 4
Registriert: Dienstag 15. Oktober 2019, 19:16

pixewakb hat geschrieben: Dienstag 15. Oktober 2019, 20:25 @DiegoSquaratti: Könntest Du mal einen Link auf das E-Tutorial der ETH-Zürich geben? Ich habe zwar eine Seite gefunden, nehme aber mal an, dass das Tutorial hinter einem Login liegt?
Ja kann ich.

Link: et.ethz.ch (Und dann einfach oben rechts auf E-Tutorial klicken)
Antworten