Wechselautomat

Lennatt

Mitglied
Guten Tag,
Ich habe eine Schulaufgabe bekommen und brauche unbedingt Hilfe. Ich weiß nicht wie ich das angehen soll kann mir jmd helfen ?

Aufgabe :
Die Aufgabe beschreibt einen Wechselautomaten, dieser soll einen Betrag x in Münzen ausgeben. Dabei sollen möglichst wenig Münzen zurückgegeben werden.
Der Automat hat Zugriff auf so viele Münzen, wie er benötigt. Geldscheine kann er jedoch nicht ausgeben.

Ein Beispiel:
Es sollen 4,36€ zurückgegeben werden.
Der Automat sollte berechnen, dass er 2x2€, 1x0,20€, 1x0,10€, 1x0,05€ und 1x0,01€ ausgeben muss.

Die Ausgabe der Geldstücke kann in der Konsole stattfinden, es wird keine Oberfläche für das Programm benötigt.
 

Robat

Top Contributor
Geh erstmal komplett von der Programmierung weg. Wie würdest du die Aufgabe denn lösen wenn du jemanden das Wechselgeld ausgeben müsstest und dabei so wenig Münzen wie möglich nutzen sollst?
 

Lennatt

Mitglied
Ich würde z.B wenn einer 10 Euro zurückbekommen sollte ihn 5 mal 2 Euro stücke geben, weil das ja dann die wenigste münzanzahl wäre, anstatt z.B 10 mal 1 Euro Stücke
 

Robat

Top Contributor
So du würdest also mit der Münze, die den höchsten Wert hat, anfangen und schauen ob, du diesen Wert vom Betrag abziehen kannst. Was würdest du danach machen? Wann weißt du, dass du fertig bist mit der Auszahlung?
 
X

Xyz1

Gast
Genau, erst die "Stücke" mit der höheren Wertigkeit. ... Aber was tust Du bei unrunden Beträgen?
 

Lennatt

Mitglied
Ich würde solange auszahlen, bis der der Gesamtbetrag ausgezahlt wurde. Halt jetzt 2 mal 2 Euro und danach wäre es nicht mehr möglich weitere 2 Euro auszahlen, weil die 4 Euro sonst überschritten werden und danach würde ich mich um die Cents kümmern
 

Robat

Top Contributor
Genau. Jetzt brauchst du a) eine Möglichkeit um dir die Münz-Beträge zu merken und b) eine Möglichkeit um dir zu merken, wie oft du eine Münze verwendest hast. Fällt dir da eine Möglichkeit ein?
 

Lennatt

Mitglied
boolean könnte mir ja was bringen, weil das programm ja dann mit true und false sieht ob der gewünschte Geldbetrag jetzt ausgezahlt wurde oder nicht?
 

Robat

Top Contributor
Und was wenn der Betrag mehrmals ausgezahlt wird? Wie willst du da mit einem boolean zählen wie oft er ausgezahlt wurde?
 

Robat

Top Contributor
Dann versuch dir doch mal zu überlegen wie du das mit arrays umsetzen könntest (noch mal der Hinweis auf den Link von oben)
 

Robat

Top Contributor
Lass dir mal nicht alles aus der Nase ziehen ;) Was genau verstehst du denn nicht?
Was wir bereits festgestellt haben:
Code:
Der Algorithmus muss so lange laufen, bis die auszuzahlende Summe ausgezahlt wurde
Der Algorithmus muss über alle verfügbaren Münzen laufen
Falls Mögliche: Zahle den Teil der Summe mit der aktuellen Münze aus
Falls das nicht mehr Möglich ist: gehe zur nächsten Münze
Du hast nun schon den Hinweis auf Arrays und sogar eine fertige Lösung (in dem Link) bekommen. Mittels Arrays kannst du mehrere Werte speichern und mittels Index darauf zugreifen. Hier mal ein kleiner Hinweis:
Was wäre wenn man Wert der verfügbaren Münzen in einem double Array speichert und in einem int Array speichert man wie oft welche Münze ausgezahlt wurde. Dabei gehört der Wert aus dem double Array an Stelle 0 zu dem Wert aus dem int Array an Stelle 0.
Java:
double[] coins = { 2d, .5d };
int[] amount = { 1, 0 };
Wir hätten hier also 1 x 2,00€ und 0 x 0,50€ ausgezahlt.
Mit einer Schleife könnte man nun durch das Münzen-Array gehen und den Betrag solange auszahlen wie es geht. Dabei wird der Wert in dem Anzahl-Array immer um eins erhöht. Das ganze passiert solange wie entweder noch Münzen da sind oder wir noch mehr auszahlen müssen.
 

httpdigest

Top Contributor
Ich empfehle zusätzlich, ausschließlich mit Ganzzahlwerten zu arbeiten (also alle Werte als Centbeträge; nicht 0.50 sondern 50). Dann wird die Arithmetik sehr einfach: Die einzigen Operationen, die man dann noch braucht, sind Ganzzahldivision und Modulo.
 

httpdigest

Top Contributor
Ja, es gibt noch viel mehr solcher Beiträge, die man aber nicht mehr findet, weil Leute Überschriften wie etwa "Brauche Hilfe!" verwenden. Ich vermisse noch mindestens einen Beitrag von 2018. :)
 

White_Fox

Top Contributor
Hat jmd zufällig ein funktionierendes Beispiel parat ?
Wir helfen dir ja gerne, aber: Jeder hier von uns ist diesen steinigen Weg auch gegangen. Und dich lassen wir den auch gehen. Weil:
  • Wir nur deshalb heute das wissen, was wir wissen, weil wir diese Anstrengung auch hinter uns gebracht haben.
  • Und deshalb auch wissen, daß es keinen anderen Weg gibt.

Einen guten Tipp hat hier schon jemand gegeben: Schau dir den Moduloperator (wird das eigentlich mit o oder oo in der Mitte geschrieben?) mal genauer an. Beschreib doch mal mit deinen Worten, was der genau macht.
 

httpdigest

Top Contributor
Wenn man's mal genau nimmt, liegt es ja nicht in unserer Verantwortung, Leute davor zu bewahren, dumm zu bleiben, weil sie Aufgaben nicht selbst lösen, sondern nach fertigen Lösungen fragen.
Das hier kannst du kopieren und abgeben (vermutlich wird dich dein Lehrer da aber nur ungläubig angucken):
Java:
public class Muenzautomat {
  public static void main(String[] args) {
    java.util.stream.IntStream
    .of(200, 100, 50, 20, 10, 5, 2, 1)
    .reduce(436, (rest, muenze) -> {
      System.out.println(String.format(
          "%d x €%.2f", rest / muenze, muenze / 100.0));
      return rest % muenze;
    });
  }
}
 

Lennatt

Mitglied
ich danke dir. Ich habe die anderen beispiele angeguckt, aber wurde nicht schlau drauß. Könntest du, wenn du möchtest, kurz erläutern was du da gemacht hast bzw. wie das funktioniert.
 

Lennatt

Mitglied
Wir helfen dir ja gerne, aber: Jeder hier von uns ist diesen steinigen Weg auch gegangen. Und dich lassen wir den auch gehen. Weil:
  • Wir nur deshalb heute das wissen, was wir wissen, weil wir diese Anstrengung auch hinter uns gebracht haben.
  • Und deshalb auch wissen, daß es keinen anderen Weg gibt.
Einen guten Tipp hat hier schon jemand gegeben: Schau dir den Moduloperator (wird das eigentlich mit o oder oo in der Mitte geschrieben?) mal genauer an. Beschreib doch mal mit deinen Worten, was der genau macht.

ich werde mich damit befassen müssen, weil ich das brauche da hast du recht. Ich muss die Basics verstehen
 

mihe7

Top Contributor
ich danke dir. Ich habe die anderen beispiele angeguckt, aber wurde nicht schlau drauß.
Dann ist ja gut, dass @httpdigest jetzt eine so einfache Anfänger-Lösung gepostet hat :p

Könntest du, wenn du möchtest, kurz erläutern was du da gemacht hast bzw. wie das funktioniert.
Er errechnet in einem Schritt per Division, wie viele Münzen eines bestimmten Wertes maximal in einen gegebenen Betrag passen und gibt das Ergebnis aus. Dieser Schritt wird mit dem daraus ergebenden Restbetrag und dem nächst niedrigerem Münzwert wiederholt, so lange noch ein niedrigerer Münzwert existiert.

Ich muss die Basics verstehen
Ja, wobei diese Art der Basics erstmal nichts mit der Programmiersprache zu tun haben.

@Robat hat Dir den Algorithmus in allgemeiner Form ja schon präsentiert:
Code:
Der Algorithmus muss über alle verfügbaren Münzen laufen
Falls Mögliche: Zahle den Teil der Summe mit der aktuellen Münze aus
Falls das nicht mehr Möglich ist: gehe zur nächsten Münze
Jetzt musst Du halt mal anfangen, die einzelnen Schritte etwas konkreter zu formulieren. Da ist von Dir bislang nichts gekommen und insofern hilft Dir auch fertiger Code nichts. Also, zeig mal, welche Schritte (kein Java Code) Du der Reihe nach ausführen würdest.
 
X

Xyz1

Gast
Ob man es nun prozedural oder OO löst, ist nicht so wichtig, nur funktional wie von @httpdigest vergeschlagen würde ich es für den Anfang nicht lösen.

BTW muenze / 100.0 ist noch nicht so schön, da besser ein DecimalFormat + setMultiplier(int newValue) ;) So würden es Profis machen...

setCurrency(Currency currency) ggf. auch mal ein Blick wert!
 

AndiE

Top Contributor
Wenn ich das versinnbildliche, dann habe ich ein Anzahl Geldsäulen auf dem Tisch. Diese haben einen long-Wert(200,100,50,20,10,5,2,1), und eine int als Anzahl. Nun brauche ich eine Methode "machLeer()", die die Säule leer macht, "int getAnzahl()" für die anzahl der Münzen und "long berechneAnzahl( long betrag);. Obwohl mir jetzt die englische Entsprechung nicht einfällt, wäre der Kunstruktor "public Sauele( long wert)".

Herauskommen würde etwas sowas:
Java:
puplic void main(){
    long betrag;
    long rest;
    Saeule zweiEuro= new Saeule(200);
    Sauele einEuro= new Sauele(100);
    Sauele fuenfzigCent= new Saule(50);
    Sauele zwanzigCent= new Sauele(20);
    Sauele zehnCent= new Sauele(10);
    Sauele fuenfCent= new Saele(5);
    Sauele zweiCent= new Sauele(2);
    Sauele eincent= new Sauele(1);
    betrag= 436;
    rest= zweiEuro.berechneAnzahl(betrag);
    betrag=rest;
    rest=einEuro.berechneAnzahl(betrag);
    betrag=rest;
    rest=fuenfzigCent.berechneAnzahl(betrag);
    betrag=rest;
    rest=zwanzigCent.berechneAnzahl(betrag);
    betrag=rest;
    rest=zehnCent.berechneAnzahl(betrag);
    betrag=rest;
    rest=fuenfCent.berechneAnzahl(betrag);
    betrag=rest;
    rest=zweiCent.berechneAnzahl(betrag);
    betrag=rest;
    rest=einCent.berechne Anzahl(betrag);
    System.out.println(zweiEuro.getAnzahl());
    System.out.println(einEuro.getAnzahl());
    System.out.println(fuenfzigCent.getAnzahl());
    System.out.println(zwanzigCent.getAnzahl());
    System.out.println(zehnCent.getAnzahl());
    System.out.println(fuenfCent.getAnzahl());
    System.out.println(zweiCent.getAnzahl());
    System.out.println(einCent.getAnzahl());

}

Das wäre jetzt die direkte Umsetzung der physischen Situation in Code. Als Fachmann würde man jetzt in einem weiteren Schritt die gleichartigen Programmzeilen zusammenfassen, wahrscheinlich durch ein Array of Saeule(s).

Didaktisch finde ich es aber dennoch gut so, weil man zuerst die Datenobjekte aufgrund vorhandener materiell vorhandener Dinge erstellt, dann feststellt, dass sie ähnliches Machen, man sie also in einer Klasse zusammenfassen kann und dann diese Objekte miteinander kommunizieren. Wobei hier die Methodenaufrufe der realen Tätigkeit angenähert sind, so dass das Programm im Ablauf schon verständlich gehalten ist.
 

mihe7

Top Contributor
Wenn ich das versinnbildliche, dann habe ich ein Anzahl Geldsäulen auf dem Tisch.
Man könnte das noch weiter spinnen, denn es geht ja um einen Wechselautomaten, den man sich als Gerät vorstellen kann.
Das Gerät besitzt ein Ausgabefach, das die Münzen für die Ausgabe sammelt, außerdem befinden sich in diesem Gerät mehrere "Münzspender". Ein solcher Münzspender gibt eine entsprechende Anzahl an Münzen aus (-> Ausgabefach) und kann mit einem weiteren Münzspender verbunden sein, der sich um den Restbetrag kümmert.

Das bringt uns dann zu etwas wie (Skizze, Code ungetestet EDIT: funktioniert):

Java:
interface Muenzsammler {
    void sammle(int wert, int anzahl);
}
Java:
class Muenzspender {
    public static Muenzspender LEER_SPENDER = new Muenzspender() {
        @Override
        void wechsle(int betrag) {}
    };

    final int wert;
    final Muenzsammler ausgabe;
    final Muenzspender naechster;

    private Muenzspender() { this.ausgabe = null; this.naechster = null; this.wert = 0; }

    Muenzspender(int wert, Muenzsammler ausgabe) { this(wert, ausgabe, LEER_SPENDER); }
    Muenzspender(int wert, Muenzsammler ausgabe, Muenzspender naechster) {
        if (ausgabe == null) { throw new IllegalArgumentException("Ohne Ausgabe wird das nix."); }
        if (naechster == null) { throw new IllegalArgumentException("Weiterer Muenzspender erforderlich"); }

        this.wert = wert;
        this.naechster = naechster;
        this.ausgabe = ausgabe;
    }

    void wechsle(int betrag) {
        ausgabe.sammle(wert, betrag / wert);
        naechster.wechsle(betrag % wert);
    }
}
Java:
class Muenzwechsler {
    private Muenzspender spender;
    private Muenzsammler centSammler = new Muenzsammler() {
        @Override
        public void sammle(int wert, int anzahl) {
             System.out.printf("%d x %d-Cent-Muenze(n)\n", anzahl, wert);
        }
    };

    private Muenzsammler euroSammler = new Muenzsammler() {
        @Override
        public void sammle(int wert, int anzahl) {
             System.out.printf("%d x %d-Euro-Muenze(n)\n", anzahl, wert / 100);
        }
    };
  
    public Muenzwechsler() {
        Muenzspender einCent = new Muenzspender(1, centSammler);
        Muenzspender zweiCent = new Muenzspender(2, centSammler, einCent);
        Muenzspender fuenfCent = new Muenzspender(5, centSammler, zweiCent);
        Muenzspender zehnCent = new Muenzspender(10, centSammler, fuenfCent);
        Muenzspender zwanzigCent = new Muenzspender(20, centSammler, zehnCent);
        Muenzspender fuenfzigCent = new Muenzspender(50, centSammler, zwanzigCent);
        Muenzspender einEuro = new Muenzspender(100, euroSammler, fuenfzigCent);
        spender = new Muenzspender(200, euroSammler, einEuro);
    }

    public void wechsle(int betrag) {
        spender.wechsle(betrag);
    }
}

Java:
import java.util.Scanner;

class GeldwechselnFizzBuzzEdition {
    public static void main(String[] args) {
        Muenzwechsler wechsler = new Muenzwechsler();
        Scanner sc = new Scanner(System.in);
        boolean done = false;
        do {
            System.out.print("Betrag: ");
            double betrag = sc.nextDouble();
            done = betrag <= 0.0;
            if (!done) {
                int cent = (int)(Math.round(betrag*100.0));
                wechsler.wechsle(cent);
            }
        } while (!done);
    }
}
 

httpdigest

Top Contributor
Das Management befürchtet, dass im Programm hart verdrahtete Münzvarianten (€2, €1, ..., €0,01) nicht zukunftssicher sind, falls neue Euromünzen in den Umlauf kommen (wie es zum Beispiel bei der €10 Sondermünzprägung der Fall ist, die auch als gültiges Zahlungsmittel gilt). Stattdessen sollte dies über eine externe Programmkonfiguration flexibel festgelegt werden können.
 

Neue Themen


Oben