Zeilen und Spaltenweise einlesen und als Bruch darstellen(Zweidimensionales Array)

Sekiro24

Mitglied
Also laut den testwerten:
1. 3/5 2. 4/2 2. 3/3 3. 4/1 4. 4/1 5. 2/5 6. 1/3 7. 1/4
Kommt bei mir wieder dieselbe Reihenfolge raus.
Eigentlich sollte rauskommen:
1. 3/2 2. 5/2 3. 2/4 4.4/1 5. 1/3 6.3/3
Hier nochmal der ganze Code.
C:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int Steine[7][2];
int berechnen(int, int);
int einlesen();
int i, j, temp, temp1;
int main(){


    printf("Bitte geben Sie nun 7 Dominosteine ein\n");
    einlesen();
    for(i = 0; i < 7; i++)printf("%d. %d/%d\n", (i+1) ,Steine[i][0], Steine[i][1]);
    for(i = 0; i < 7; i++)
      if(berechnen(i, i+1) == 0)
        {

        }
    return 0;
}

int einlesen(){
    for(i = 0; i < 7; i++){
        printf("%d.\n", (i+1));
        for(j = 0; j < 2; j++)
          scanf("%d", &Steine[i][j]);
    }
    return 0;
}

int berechnen(int i, int j) {
    if(i > 7 || j > 7) return 0;
    if(Steine[i][0] == Steine[j][0])
        return 1;
    else
        if(Steine[i][0] == Steine[j][1])
        {
            /*Drehen*/
            temp = Steine[j][1];
            Steine[j][1] = Steine[j][0];
            Steine[j][0] = temp;
            return 1;
        }
    else{
           if (berechnen(i, j+1) == 1)
                {
                  /*Tauschen*/
                  temp = Steine[i + 1][0];
                  temp1 = Steine[i + 1][1];
                  Steine[i + 1][0] = Steine[j + 1][0];
                  Steine[i + 1][1] = Steine[j + 1][1];
                  Steine[j + 1][0] = temp;
                  Steine[j + 1][1] = temp1;
                }
        }
    return 0;
}
 

Sekiro24

Mitglied
Ich habe mal ein paar testwerte eingesetzt. Jedoch werden diese nicht sortiert oder in die richtige Position gebracht.

Hier nochmal der ganze Code

C:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int Steine[7][2];
int berechnen(int, int);
int einlesen();
int i, j, temp, temp1;
int main(){


    printf("Bitte geben Sie nun 7 Dominosteine ein\n");
    einlesen();
    for(i = 0; i < 7; i++)printf("%d. %d/%d\n", (i+1) ,Steine[i][0], Steine[i][1]);
    for(i = 0; i < 7; i++)
      if(berechnen(i, i+1) == 0)
        {

        }
    return 0;
}

int einlesen(){
    for(i = 0; i < 7; i++){
        printf("%d.\n", (i+1));
        for(j = 0; j < 2; j++)
          scanf("%d", &Steine[i][j]);
    }
    return 0;
}

int berechnen(int i, int j) {
    if(i > 7 || j > 7) return 0;
    if(Steine[i][0] == Steine[j][0])
        return 1;
    else
        if(Steine[i][0] == Steine[j][1])
        {
            /*Drehen*/
            temp = Steine[j][1];
            Steine[j][1] = Steine[j][0];
            Steine[j][0] = temp;
            return 1;
        }
    else{
           if (berechnen(i, j+1) == 1)
                {
                  /*Tauschen*/
                  temp = Steine[i + 1][0];
                  temp1 = Steine[i + 1][1];
                  Steine[i + 1][0] = Steine[j + 1][0];
                  Steine[i + 1][1] = Steine[j + 1][1];
                  Steine[j + 1][0] = temp;
                  Steine[j + 1][1] = temp1;
                }
        }
    return 0;
}
 

cwriter

Erfahrenes Mitglied
1. 3/5 2. 4/2 2. 3/3 3. 4/1 4. 4/1 5. 2/5 6. 1/3 7. 1/4
Wenn du ganz ehrlich bist: Das kann doch niemand lesen, oder?
Informatik ist Datenverarbeitung. Das ist schwierig genug, mache es nicht durch Notationen komplizierter. Ein guter Weg ist immer, mehrere Zeilen zu benutzen. Oder hier: Grössere Abstände einzubauen:
"[3|5] => [4|2] => ..."
Liest sich doch schon leichter oder?

Übrigens weiss ich, dass duvon deiner eigenen Notation verwirrt warst: Du hast z.B. 2x eine 2. mit unterschiedlichen Werten...

Kommt bei mir wieder dieselbe Reihenfolge raus.
Sag mir nicht, dass du das von der Ausgabe weisst - du gibst das ja aus, bevor berechnen() durchläuft.

Dennoch hat der Code ein paar Fehler drin:
C:
// Soll "passt()" darstellen
if(Steine[i][0] == Steine[j][0])
Stimmt das denn so?
Passen diese Steine: [x|y] [x|y] ?

Dasselbe Problem beim Drehe-Code:

C:
if(Steine[i][0] == Steine[j][1])
        {
            /*Drehen*/
Drehe j bei [x|y] [y|x] ?

Dann ist dein Bounds-Check kaputt:
C:
if(i > 7 || j > 7) return 0;
Kann i (oder j) hier 7 sein, i.e. geht der Code weiter, wenn i 7 ist? Und was ist der höchste gültige Index im Array?

Der Code:
C:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>

#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
#endif

int Steine[7][2];
int berechnen(int, int);
int einlesen();
int i, j, temp, temp1;

void setzeStein(int n, int v1, int v2)
{
    Steine[n][0] = v1;
    Steine[n][1] = v2;
}

int main() {


    printf("Bitte geben Sie nun 7 Dominosteine ein\n");
    //einlesen();
    setzeStein(0, 3, 5);
    setzeStein(1, 4, 2);
    setzeStein(2, 3, 3);
    setzeStein(3, 4, 1);
    setzeStein(4, 2, 5);
    setzeStein(5, 1, 4);
    setzeStein(6, 1, 3);
  

    for (i = 0; i < 7; i++)printf("%d. %d/%d\n", (i + 1), Steine[i][0], Steine[i][1]);
    for (i = 0; i < 7; i++)
        if (berechnen(i, i + 1) == 0)
        {

        }
    printf("Resultat: \n");
    for (i = 0; i < 7; i++)printf("%d. %d/%d\n", (i + 1), Steine[i][0], Steine[i][1]);
    return 0;
}

//Snip
setzeStein() ist eine Funktion, damit es schöner aussieht, da ich die Werte nicht bei jeder Ausführung eingeben und keine Datei anlegen will.

Gibt bei mir:

Code:
Bitte geben Sie nun 7 Dominosteine ein
1. 3/5
2. 4/2
3. 3/3
4. 4/1
5. 2/5
6. 1/4
7. 1/3
Resultat:
1. 3/5
2. 5/2
3. 2/4
4. 4/1
5. 1/4
6. 3/3
7. 3/1
Das scheint mir schon ziemlich korrekt.
Angenommen, dein angegebenes Test-Set ist korrekt, dann zeigt das 5/2 eine undokumentierte Funktion, die den Startstein wählen kann.

...

Ok, dann müssen wir noch etwas Code schreiben:

Algorithmus:
Code:
for s in Steine:
    Tausche s mit Stein 0 (sodass s nach dem Tausch an Stelle 0 steht)
    for i in #Steine:
        if berechne(i, i + 1) == 0:
            best_run_value = max(i, best_run_value)
            best_run_index = (s == best_run_value) ? s : best_run_index

// Da wir nicht zwischenspeichern:
tausche(0, best_run_index)
berechne(0, 1)

// Ausgabe

Besonders cool daran: Das löst genau 1 Induktionsstufe mehr. Also ist der Algorithmus asymptotisch immer noch gleich schlecht wie zuvor, mit sehr viel mehr Aufwand. Nice!

Ich habe mal ein paar testwerte eingesetzt. Jedoch werden diese nicht sortiert oder in die richtige Position gebracht.

Hier nochmal der ganze Code
Sorry, aber das nützt uns natürlich auch nichts - wir sehen das Problem ja schon am Post davor. Das ist ja im Prinzip wieder ein Einzeiler, den du mit demselben Code wie vorher wieder aufgeblasen hast. Besser als nichts, aber gib uns keine Informationen, die keine sind (weil der vorhergehende Code identisch ist).

Gruss
cwriter
 

cwriter

Erfahrenes Mitglied
Die Schleifenbedingung mit for i in #Steine soll dann wohl i < sizeof(Steine)/sizeof(int) sein oder ?
Da du die 7 ohnehin überall hardcoded hast, kannst du auch einfach 7 nehmen (oder durch eine entsprechende Konstante ersetzen). Wenn ich mich nicht täusche, müsste es aber
C:
i < sizeof(Steine) / (sizeof(int) * 2)
sein (da Steine ja 7 * 2 * 4 Bytes gross ist).

Gruss
cwriter
 

Sekiro24

Mitglied
Ist ja zweidimensional
und was soll max(best_run_value ) sein ?
In welcher Bibliothek ist die Funktion max hinterlegt und ist das auch ansi standard ?
 

cwriter

Erfahrenes Mitglied
Ist ja zweidimensional
?
sizeof() gibt dir schlicht die Grösse in Bytes des Objekts zurück - die Dimensionen sind dem ziemlich egal. Und wenn du die 2. Dimension mitzählst, gehst du nicht über alle Steine, sondern über alle Werte. Aber probier's doch aus.

und was soll max(best_run_value ) sein ?
Das habe ich nirgends geschrieben...
In welcher Bibliothek ist die Funktion max hinterlegt und ist das auch ansi standard ?
Nirgends.
C:
int max(int a, int b)
{
    return (a >= b) ? a : b;
}

Gruss
cwriter
 

cwriter

Erfahrenes Mitglied
Hier meinte ich das, als du den Algorithmus geschrieben hast.
Nahm ich an.
Aber bitte, lies den Pseudocode nicht 1 zu 1. Mit max() war schlicht gemeint, dass du den grösseren Wert nehmen sollst. Wenn du dann
max(best_run_value )
schreibst, dann hast du ja den Sinn dahinter nicht gesehen (max gibt ja den grösseren Wert von zweien zurück; nur ein Parameter geht ja nicht).
Dieser Pseudocode ist Pseudocode, weil ich dir den Ansatz, nicht die Lösung zeigen wollte. Statt max() kannst du auch den ternären Operator (cond ? x : y) oder mehrere ifs verwenden.
Schreibe doch mal den Code mit dem Algorithmus als Leitfaden. Wenn es dann nicht funktioniert, prüfe, ob der Algorithmus eingehalten wurde. Wenn es dann nicht funktioniert, kannst du ja immer noch Code mit Fehlermeldung / (unerwartetem) Verhalten hier posten und wir können uns das anschauen.

Aber nimm dir die Zeit, zu überlegen, warum der Algorithmus so aussieht. Was macht er? Wenn du irgendeine Zeile entfernen würdest, warum würde es nicht mehr funktionieren?

Einfach Abschreiben ist einfach - mache es dir nicht zu einfach (vor allem mit Blick auf zukünftige Aufgaben/Prüfungen lohnt sich Minimalismus fast nie).

Gruss
cwriter
 

Sekiro24

Mitglied
würde es denn mit der Variante davor also ohne den zwei geschachtelten for schleifen auch funktionieren.
Ich habe mir jetzt mehr darüber Gedanken gemacht .