Das Zahlenspiel

Skiruna

Mitglied
Hallo,

Um es mal direkt zu sagen: Ich bin neu in diesem Forum. Ich habe mir eigentlich die Regeln durchgelesen, allerdings kann es sein, dass ich hier in ner falschen Rubrik poste.
Naja wie auch immer.
Mein Bruder hat in der Schule das Zahlenspiel bekommen. Dieses geht so. Man hat 2 unbekannte Zahlen, die, wenn man die Summe, die Differenz, das Produkt und den Quotienten addiert, eine bestimmte Summe ergeben müssen, die vorgegeben ist. Ich mach das nochmal mit buchstaben damits leichter ist. Die beiden unbekannten Zahlen heißen a und b. (a+b)+(a-b)+(a*b)+(a/b)=1000. Nun dachte ich mir entwickel ich ein Java-Programm welches a und b errechnen kann. Allerdings stoße ich auf das Problem, dass bei mir nie die Zahlen gefunden wird...
[JAVA=1]
public class Rechner
{
public static void main(String[] args)
{
double zahlsum = 4;
//double zahlsum = InOut.readDouble( "Geben Sie bitte die erwünschte Summe ein und bestätigen Sie mit Enter: " );
double zahla = 0,
zahlb = 0;
boolean arbeit = true;
kontrollieren( zahla, zahlb, zahlsum );
while( kontrollieren( zahla, zahlb, zahlsum ) != true && arbeit == true )
{
while( zahla < zahlsum && kontrollieren( zahla, zahlb, zahlsum ) != true )
{
zahla = zahla + 0.1;
while( zahlb < zahlsum && kontrollieren( zahla, zahlb, zahlsum ) != true )
{
zahlb = zahlb + 0.1;
kontrollieren( zahla, zahlb, zahlsum );
}
zahlb = 0;
}
arbeit = false;
}
if( kontrollieren( zahla, zahlb, zahlsum ) == true )
{
System.out.println( "Die Zahlen lauten: " + zahla + " und " + zahlb + "." );
}
else
{
System.out.println( "Leider konnte keine der Zahlen ermittelt werden." );
}
}

public static boolean kontrollieren( double zahla, double zahlb, double zahlsum )
{
double plus = zahla + zahlb;
double minus = zahla - zahlb;
double mal = zahla * zahlb;
double geteilt = zahla / zahlb;
double ges = plus + minus + mal + geteilt;
if( ges == zahlsum )
{
return true;
}
else
{
return false;
}
}
}
[/code]
Die Summe soll frei wählbar sein. Ich probier es hier immer mit der Summe 4, da müssten a und b jeweils 1 sein. Ich habe mir gedacht ich probier alle Kombinationen von a und b aus solange sie kleiner als die Summe sind. Die Schritte könnte ich auch noch verkleinern, sobald es erstmal funktioniert ...

Ich denke das schildert mein Problem ganz gut und hoffe mir kann jemand helfen. :)
Außerdem bin ich Anfänger, also bitte nicht schimpfen, wenn ich was offensichtliches übersehen habe oder meine Programme nicht sonderlich perfekt aufschreibe. :)
Ansonsten noch eine gute Nacht und danke fürs lesen!

lg
Runa
 
H

hüteüberhüte

Gast
Z.B.:
Java:
    public static int calc(int a, int b) {
        return (a + b) + (a - b) + (a * b) + (a / b); // or 2*a + a*b + a/b
    }

    public static void main(String[] args) {

        final int result = 1000;

        for (int a = 0; a < 1000; a++) {
            for (int b = 1; b < 1000; b++) {
                if (calc(a, b) == result) {
                    System.out.println("a=" + a + ", b=" + b);
                    break;
                }
            }
        }
    }

Ergibt:
Code:
a=1, b=998
a=2, b=498
a=4, b=248
a=5, b=198
a=8, b=123
a=10, b=98
a=20, b=48
a=25, b=38
a=37, b=25
a=90, b=9
a=139, b=5
a=160, b=4
a=250, b=1

Aber er müsste doch eigentlich trotzdem abbrechen, sobald er ein Ergebnis hat...

Dann musst du die Schleife verlassen/abbrechen.
 
Zuletzt bearbeitet von einem Moderator:

Logaff

Bekanntes Mitglied
was du brauchst ist eine Iterativ-vertiefende-Tiefensuche oder Breitensuche^^

Also das Problem ist wenn du zwei Zahlen a und b hast und die Berechnung (B) wie oben ergibt nicht das richtige Ergebniss (E) denn hast du folgende möglichkeiten: a größer machen, b größermachen, a und b größer, a größer b kleiner, a kleiner b größer.

Wenn du jetzt dir vorstellst du hast einen Zeitpunkt 0 wo A=B=0 hast du von diesen Punkt aus 5 Möglichkeiten -> 5 neue Knoten. Von jedem dieser Knoten hast du wieder 5 Möglichkeiten usw...

1) 5Mgl
2) 5*5 = 25 Mgl
3) 5*5*5 = 125 Mgl
.
.
.
n) 5^n Mgl

und das sollte schnell recht ekelig werden.

Wenn man aber ab einen Zeitpunkt p: B<E und p1: B>E gilt kann man diesen Baum "beschneiden" usw. Aus Graphentheoretischersicht ist es Sinn eine Belegung a,b in diesen Graph so das B=E -> such ein Knoten mit irg ner Eigenschaft -> Breitsuchen (Nachteil kein Abbruch aber findet kürzeten Lösungsweg) oder iterativ-vertiefende-Tiefensuche(praktisch Tiefensuche und durch iterative Vertiefung mit Begrenzung ist es auch nicht möglich sich in unendlichen Pfaden zu verirren)^^

Ich hoffe das war nicht zuviel des Guten^^ Man kann ein Problem auchsolange analysieren bis es tot ist^^ THEORETISCHE INFORMATIK FTW!
 

Fant

Bekanntes Mitglied
@hüteüberhüte
Dein Programm liefert aufgrund der int-Division falsche Ergebnisse. Multipliziert man beide Seiten der zu lösenden Gleichung mit b, so kann man das umgehen:

Java:
public static int calc(int a, int b) {
    return a*(b*(2+b) + 1);
}

public static void main(String[] args) {

    final int result = 1000;

    for (int a = 0; a < 1000; a++) {
        for (int b = 1; b < 1000; b++) {
            if (calc(a, b) == result*b) {
                System.out.println("a=" + a + ", b=" + b);
                break;
            }
        }
    }
}
(siehe Zeile 2 und 11)

Ausgabe:
Code:
a=90, b=9
a=160, b=4
a=250, b=1
 

Fant

Bekanntes Mitglied
Die Summe soll frei wählbar sein. Ich probier es hier immer mit der Summe 4, da müssten a und b jeweils 1 sein. Ich habe mir gedacht ich probier alle Kombinationen von a und b aus solange sie kleiner als die Summe sind.

Gib doch einfach Werte für a vor und berechne dann die (0 bis 2) dazugehörigen möglichen Werte für b.

In deinem Programm fängst du mit
Code:
sum=4
und
Code:
a=0.1
an.
Die dazugehörigen Werte für b sind
Code:
19-6 sqrt(10)
und
Code:
19+6 sqrt(10)

Da siehst du auch direkt, wieso du da mit deinen 0.1er-Schritten nix findest. Für die anderen gewählten a-Werte sieht das vermutlich vergleichbar aus.
 
Zuletzt bearbeitet:
H

hüteüberhüte

Gast
@Logaff: Meinst du das mit der Breitensuche ungefähr so:

Java:
        final int result = 1000;

        Deque<int[]> queue = new ArrayDeque<int[]>(Arrays.asList(new int[]{0, 1}));

        while (!queue.isEmpty()) {
            int a = queue.peek()[0];
            int b = queue.peek()[1];
            queue.poll();
            if (calc(a, b) == result) {
                System.out.println("a=" + a + ", b=" + b);
            } else if (a + b <= 2000) {
                queue.add(new int[]{a + 1, b});
                queue.add(new int[]{a, b + 1});
            }
        }

Das Problem dabei ist, dass oft schon einmal vorhandene Werte-Paare hinzugefügt werden
 

Skiruna

Mitglied
Also ersteinmal vielein Dank für die schnelle Hilfe. Ich als Laie blick in den letzten Antworten allerdigns nicht mehr durch :D. Ich glaube ich werde einfach fragen, ob man nach int oder double werten suchen möchte. Allerdings wird sich mein Programm bei doublewerten recht schnell aufhängen, also bau ich einfach ne Grenze ein :). Trotzdem Danke für die vielen Antworten :) Ich wil allerdings nichts schreiben, was ich nicht zur gänze verstehe, bin eben Laie :D

lg
Runa
 
H

hüteüberhüte

Gast
Quasi ja. vorhandene Wertepaare umgehen -> [JAPI]Set[/JAPI]

Daran hatte ich auch gedacht, dann ungefähr so:

Java:
    public static int calc(int a, int b) {
        if (a % b == 0) {
            return (a + b) + (a - b) + (a * b) + (a / b);
        }
        return -1;
    }

    public static void main(String[] args) {

        final int result = 1000;

        Deque<int[]> queue = new ArrayDeque<int[]>(Arrays.asList(new int[]{0, 1}));
        Set<Integer> set = new HashSet<Integer>(Arrays.asList(0 << 16 | 1));

        while (!queue.isEmpty()) {
            int a = queue.peek()[0];
            int b = queue.peek()[1];
            queue.poll();
            // System.out.println(" " + a + " " + b);
            if (calc(a, b) == result) {
                System.out.println("a=" + a + ", b=" + b);
            }
            if (Math.abs(a - b) < 500 && a + b < 2000) {
                if (!set.contains(a + 1 << 16 | b)) {
                    queue.add(new int[]{a + 1, b});
                    set.add(a + 1 << 16 | b);
                }
                if (!set.contains(a << 16 | b + 1)) {
                    queue.add(new int[]{a, b + 1});
                    set.add(a << 16 | b + 1);
                }
            }
        }
    }

Jetzt stimmt die Ausgabe auch mit (a+b)+(a-b)+(a*b)+(a/b)=1000 - Wolfram|Alpha (Integer solutions) überein:

Code:
a=90, b=9
a=160, b=4
a=250, b=1

Ich habe noch
Code:
if (a % b == 0)
hinzugefügt -> Wenn a nicht durch b teilbar ist, dann gibt es auch kein ganzzahliges Ergebnis

Mit Zeile 23 lässt sich bestimmen, bis in welche "Breite" gesucht werden soll

@Skiruna: Mit double-Werten hast du ein Problem, denn dabei treten immer formatbedingte Abweichungen auf. Ich würde mich nur auf "integer solutions" beschränken. Um deine Fragen beantworten zu können, musst du sie am besten mit der Angabe der Zeile und der Fehlermeldung stellen, dann können wir weiterhelfen
 
Zuletzt bearbeitet von einem Moderator:

Skiruna

Mitglied
Ok, super, vielen Dank für die promte und hilfereiche Unterstützung. Ich werd mich nochmal dahinterhängen. Es ist ja auch keine Hausaufgabe oder so, es ist ja "nur für mich", was eine HA ja auch sein sollte :D Ich wollte eben nur mal gucken, ob ich das so hinkriege und ich denke das mit den Integer solutions ist der richtige, da ein doublewert ja höchstwahrscheinlich auch nur eine Rundung ist, da er ja zb keine Wurzelwerte enthält.

lg
Runa
 
H

hüteüberhüte

Gast
Java:
        for (int a = 0; a < 1000; a++) {
            for (int b = 1; b < 1000; b++) {

Sollte immer noch am effizientesten sein...

Also, wenn du was nicht verstehst, Fragen :D

double-Werte werden auf eine bestimmte Weise gespeichert, für den direkten Vergleich taugen sie nix...
 

Skiruna

Mitglied
ich war verreist und, deshalb hats etwas gedauert:

Ja eben die Double-Werte taugen nichts, das hab ich feststellen müssen :D
Deshalb gibt er vermutlich auch die "Integer-Ergebnisse" als double nicht an. ich glaub das hab ich been nicht verstanden, warum er bei Beispiel 4 nicht 1 und 1 finden konnte. Naja wie auch immer. Ich danke euch für die Hilfe und werde den Thread nun schließen ;)

Wenn noch was superdupadringendes ist dann bitte per PM. Falls jemand die bahnbrechende Entwicklung für dieses Programm entwickelt hat oder so xD

lg
Runa
 
Ähnliche Java Themen

Ähnliche Java Themen

Neue Themen


Oben