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



## Sekiro24 (7. April 2019)

Hallo zusammen, 
ich stehe erneut vor einem Problem. Undzwar soll ich ein Spiel Namens Domino erstellen, der die Felder des Arrays mit den gleichen Augenzahlen aneinander legen und als Bruch darstellen soll. 
Zuerst wollte ich mal das einlesen thematisieren. Dies soll über eine zusätzliche Funktion Namens "einlesen" passieren.

Das Problem hierbei ist, dass nach 7 Zeilen Iteration, ich immer noch etwas eingeben kann obwohl ja nach 7 Zeilen die Schleife aufhören soll. 
Vielleicht kann mir jemand dabei helfen auch die Ausgabe als Bruch vorerst darzustellen, ohne die Sortierung. 


```
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int Steine[7][2];
int i_zeile, i_spalte, k;
    
main(){
    printf("Bitte geben Sie nun 7 Dominosteine ein\n");
    einlesen();
    for(k = 0; k < 7; k++)printf("%d. %d\n", (k+1) ,Steine[k][k]); /*Hier soll die Ausgabe als Bruch dargestellt werden*/
}

einlesen(){
    /*Einlesen der Zahlen, Zeilen- und Spaltenweise*/
    for(i_zeile = 0; i_zeile < 7; i_zeile){
        for(i_spalte = 0; i_spalte < 2; i_spalte){
            scanf("%d", &Steine[i_zeile][i_spalte]);
        }
    }
    
}
```


----------



## cwriter (8. April 2019)

Sekiro24 hat gesagt.:


> Das Problem hierbei ist, dass nach 7 Zeilen Iteration, ich immer noch etwas eingeben kann obwohl ja nach 7 Zeilen die Schleife aufhören soll.


Was sollte im letzten Feld eines for-Loops stehen?
for(Start; Condition; Statement). Du hast im Statement eine reine Expression (keine Veränderung des Zustands).




Sekiro24 hat gesagt.:


> Vielleicht kann mir jemand dabei helfen auch die Ausgabe als Bruch vorerst darzustellen, ohne die Sortierung.


Ehrlich gesagt kann ich mir darunter nichts vorstellen.
Meinst du

```
Zahl1 / Zahl2

oder

Zahl1 | Zahl2

oder

Zahl1
---------
Zahl2
```

cwriter


----------



## Sekiro24 (8. April 2019)

cwriter hat gesagt.:


> Was sollte im letzten Feld eines for-Loops stehen?
> for(Start; Condition; Statement). Du hast im Statement eine reine Expression (keine Veränderung des Zustands).
> 
> 
> ...


Genau Zahl1 / Zahl2 soll ausgegeben werden. 
Nur wie mache ich das so, dass es mit einem zweidimensionalen Array funktioniert. 
Zuerst natürlich, sollte die Eingabe erfolgen.


----------



## Technipion (8. April 2019)

Ehrlichgesagt sehe ich noch einige andere Problemchen im Code.
Deine main() und die Funktion einlesen() scheinen keinen Typ zu haben?

Außerdem ein kleiner Tipp direkt am Anfang: Die Variablen `Steine[][]` und `i_zeile`, `i_spalte` und `k` sind sogenannte globale Variablen, weil sie von überall (in deiner Quellcode-Datei) sichtbar sind. Eigentlich versucht man immer so gut es geht globale Variablen zu vermeiden, in seltenen Fällen (oder als Anfänger) kann man sie jedoch benutzen. Allerdings ist es dann immer schön sie als global zu kennzeichnen. Ich z.B. beginne ihre Namen dann immer mit "g_". Also aus `int Steine[7][2];` würde dann `int g_Steine[7][2];`. Nur ein kleiner Tipp, damit erinnert man sich immer daran, dass diese Variablen global sind.

Zur for-Schleife: Hast du verstanden was cwriter gemeint hat? Falls ja poste mal deinen aktualisierten Code. Falls nein: Wo genau liegt das Problem?

Gruß Technipion


----------



## cwriter (8. April 2019)

Sekiro24 hat gesagt.:


> Zuerst natürlich, sollte die Eingabe erfolgen.


Du inkrementierst die for-loop-Iterationsvariable nicht.


Sekiro24 hat gesagt.:


> Nur wie mache ich das so, dass es mit einem zweidimensionalen Array funktioniert.


?

```
printf("%d / %d", Steine[i][0], Steine[i][1]);
```
Es fällt mir ein bisschen schwer, deinen Kenntnisstand zu lesen. Die logische Herangehensweise bei diesen Dingen geht über die Typen.

Du hast einen Array von einem Array von ints namens Steine. Wir schreiben den Typ mal als [[int]]. Wenn du einmal dereferenzierst, bekommst du den Typ [int]. Das passt aber noch nicht für printf. Also musst du nochmals dereferenzieren. Das tatest du ja schon
Nun ist der 1x dereferenzierte Typ aber int[2]. D.h. du kannst auf 0 und 1 als Index zugreifen.
Vielleicht erklärt das die Herangehensweise ja etwas.



Technipion hat gesagt.:


> Deine main() und die Funktion einlesen() scheinen keinen Typ zu haben?


Sekiro nutzt C89, wo alles implizit int ist. Nicht mein Stil, aber naja...
Übrigens ist selbst in C11 noch implizit int - da aber mit einer Warnung. Aber anständige Menschen tun das nicht, da hast du schon recht 



Technipion hat gesagt.:


> Eigentlich versucht man immer so gut es geht globale Variablen zu vermeiden, in seltenen Fällen (oder als Anfänger) kann man sie jedoch benutzen. Allerdings ist es dann immer schön sie als global zu kennzeichnen. Ich z.B. beginne ihre Namen dann immer mit "g_". Also aus `int Steine[7][2];` würde dann `int g_Steine[7][2];`. Nur ein kleiner Tipp, damit erinnert man sich immer daran, dass diese Variablen global sind.


Alles völlig richtig, aber für diese Aufgabenprogramme sollte das schon reichen - korrekterweise müsste man es lokal halten und per Pointer übergeben, aber es ist sowieso C89 - und damit ist die Chance, dass dieser Code irgendwo produktiv eingesetzt wird, nahezu 0 

Gruss
cwriter


----------



## Sekiro24 (8. April 2019)

cwriter hat gesagt.:


> Du inkrementierst die for-loop-Iterationsvariable nicht.


?
Jo total übersehen. Vielen Dank.


```
printf("%d / %d", Steine[i][0], Steine[i][1]);
```
Es fällt mir ein bisschen schwer, deinen Kenntnisstand zu lesen. Die logische Herangehensweise bei diesen Dingen geht über die Typen.

Du hast einen Array von einem Array von ints namens Steine. Wir schreiben den Typ mal als [[int]]. Wenn du einmal dereferenzierst, bekommst du den Typ [int]. Das passt aber noch nicht für printf. Also musst du nochmals dereferenzieren. Das tatest du ja schon
Nun ist der 1x dereferenzierte Typ aber int[2]. D.h. du kannst auf 0 und 1 als Index zugreifen.
Vielleicht erklärt das die Herangehensweise ja etwas.


Sekiro nutzt C89, wo alles implizit int ist. Nicht mein Stil, aber naja...
Übrigens ist selbst in C11 noch implizit int - da aber mit einer Warnung. Aber anständige Menschen tun das nicht, da hast du schon recht 


Alles völlig richtig, aber für diese Aufgabenprogramme sollte das schon reichen - korrekterweise müsste man es lokal halten und per Pointer übergeben, aber es ist sowieso C89 - und damit ist die Chance, dass dieser Code irgendwo produktiv eingesetzt wird, nahezu 0 

Gruss
cwriter[/QUOTE]
Mir ist schon bewusst das man eher zu lokalen Variablen neigt als zu globalen und diese dann an die jeweiligen Funktionen, die man verwenden möchte weitergibt. Die Aufgabe ist es vom Dozenten das Verständnis hinter globalen und lokalen Variablen klar zu machen. Nachher kommt noch eine weitere Funktion, der man dann Laufvariablen i und j übergeben soll. Diese Funktion soll berechnen heißen und die Zahlen der Dominosteine die gleich sind aneinander legen/sortieren.  
Beispielsweise:
1. 5/2
2. 6/3
3. 1/4
4. 6/2
unsortiert

1. 5/2 
2. 2/6
3. 6/3
4. 1/4
sortiert

Also 2 an 2 und 6 an 6
Dabei kann der Stein auch gedreht werden.


----------



## Sekiro24 (11. April 2019)

Sekiro24 hat gesagt.:


> ?
> Jo total übersehen. Vielen Dank.
> 
> 
> ...


Mir ist schon bewusst das man eher zu lokalen Variablen neigt als zu globalen und diese dann an die jeweiligen Funktionen, die man verwenden möchte weitergibt. Die Aufgabe ist es vom Dozenten das Verständnis hinter globalen und lokalen Variablen klar zu machen. Nachher kommt noch eine weitere Funktion, der man dann Laufvariablen i und j übergeben soll. Diese Funktion soll berechnen heißen und die Zahlen der Dominosteine die gleich sind aneinander legen/sortieren.
Beispielsweise:
1. 5/2
2. 6/3
3. 1/4
4. 6/2
unsortiert

1. 5/2
2. 2/6
3. 6/3
4. 1/4
sortiert

Also 2 an 2 und 6 an 6
Dabei kann der Stein auch gedreht werden.[/QUOTE]

Ich benutze momentan den Code Blocks Editor. Wenn ich den Code compilieren möchte, [\QUOTE]
Kann ich keine zweite Eingabe machen. Wieso ? mit Cygwin hatte es irgendwie geklappt.
Der Code sieht bis hierhin wie folgt aus:

```
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int Steine[7][2];
int i_zeile, i_spalte, j, k;

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

einlesen(){
    for(i_zeile = 0; i_zeile < 7; i_zeile++){
        for(i_spalte = 0; i_spalte < 2; i_spalte++){
            scanf("%d. %d", i_zeile, &Steine[i_zeile][i_spalte]);
        }
    }
}
[\CODE]
```


----------



## cwriter (11. April 2019)

Sekiro24 hat gesagt.:


> Ich benutze momentan den Code Blocks Editor. Wenn ich den Code compilieren möchte,
> Kann ich keine zweite Eingabe machen. Wieso ? mit Cygwin hatte es irgendwie geklappt.
> Der Code sieht bis hierhin wie folgt aus:


Naja, was macht denn scanf?
Wenn du "%d. %d" als scanf format string hast, dann wird nach i_zeile gelesen - bzw. auch nicht, das Programm sollte abstürzen.
Nimm das "%d." und die 'i_zeile' auis dem Scanf raus, dann solltest du alle Zahlen eingeben können.

Gruss
cwriter


----------



## Sekiro24 (22. April 2019)

Habs denke ich mal verstanden. 
Jetzt soll ich noch das mit dem berechnen machen. Ich hab da mal was geschrieben, jedoch blicke ich da noch nicht richtig durch, wie ich das realisieren soll, dass der überübernächste kontrolliert werden soll. Das ganze soll rekursiv erfolgen. Also das sich die Funktion berechnen selbst aufruft. 
Ich dachte da an  eine geschachtelte for in for Schleife aber dann ist es doch nicht mehr rekursiv oder ?

```
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int Steine[7][2];
int berechnen(int, int);
int i, j;
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]);
    i = 0; j = 0;
    berechnen(i,j);
    return 0;
}

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

/*Überprüfung, ob der aktuelle Stein durch Anlegen mit dem nächsten Stein identisch ist bsp: 1.)3/4,4/2,2/1*/
/*Auch durch drehen*/
int berechnen(int i, int j) {
    int temp1, temp2;
    if(Steine[i][0] == Steine[j][0])
    {
        i++;
        j++;
        brechnen(i,j);
    }
    else
        if(Steine[i][0] == Steine[j][1])
        {
            temp1 = Steine[j][0];
            temp2 = Steine[j][1];
            Steine[j][0] = temp2;
            Steine[j][1] = temp1;
        }
    else{
        /*Wenn der aktuelle Stein nicht passt soll der übernächste Stein überprüft werden. Wenn dieser nicht passt
        soll der überübernächste Stein überprüft werden*/
    }

}
```


----------



## cwriter (23. April 2019)

Sekiro24 hat gesagt.:


> Jetzt soll ich noch das mit dem berechnen machen. Ich hab da mal was geschrieben, jedoch blicke ich da noch nicht richtig durch, wie ich das realisieren soll, dass der überübernächste kontrolliert werden soll.


Da sind wir ja schon zwei.




Sekiro24 hat gesagt.:


> Ich dachte da an eine geschachtelte for in for Schleife aber dann ist es doch nicht mehr rekursiv oder ?


Naja - auch mit 2 Schleifen kann sich eine Funktion noch selbst aufrufen...


Da ich dir nicht die Arbeit abnehmen will, aber dennoch einen guten Rat geben kann, habe ich mal ein Beispiel in C++ implementiert. Das ist ähnlich genug, um den Algorithmus zu zeigen, aber weit genug entfernt, dass man nicht mit "1 zu 1" umschreiben davonkommt. Am besten lässt du das Beispiel durch einen C++ Compiler, um die Resultate zu sehen:

```
#include <iostream>
#include <time.h>
#include <vector>
#include <string>

constexpr size_t blockcount = 10;

struct Stein {
    Stein(int a, int b)
        : v1(a), v2(b) {

    }

    std::string format(bool normal = true) const {
        auto a = normal ? v1 : v2;
        auto b = normal ? v2 : v1;
        return "(" + std::to_string(a) + "|" + std::to_string(b) + ")";
    }

    std::string format(int expect) const {
        return format(expect == v1);
    }
    int v1;
    int v2;
};

std::vector<int> berechne(std::vector<int> used, const std::vector<Stein>& all, int i, int orientation)
{
    // Copy the existing path as a reference return value
    decltype(used) maxpath = used;

    // Check all bricks
    for (size_t j = 0; j < all.size(); ++j)
    {
        // Check if the current brick being checked is not already used
        bool not_this = false;
        for (size_t f = 0; f < used.size(); ++f) {
            if (used[f] == j) {
                not_this = true;
                continue;
            }
        }

        if (not_this) continue; // Skip if already used

        // Copy the orientation
        decltype(orientation) new_orientation = orientation;
        // If not the first block
        if (i != -1)
        {
            // Set the orientations of the next blocks
            if (orientation == 1 || orientation == 0) {
                // "Normal"
                if (all[i].v2 == all[j].v1) {
                    // orientation stays the same
                    new_orientation = 1;
                }
                else if (all[i].v2 == all[j].v2) {
                    // swap
                    new_orientation = -1;
                }
                else continue;
            }
            else if (orientation == -1 || orientation == 0) {
                // Inverted
                if (all[i].v1 == all[j].v1) {
                    // swap
                    new_orientation = 1;
                }
                else if (all[i].v1 == all[j].v2) {
                    // still -1
                    new_orientation = -1;
                }
                else continue;
            }
            else {
                // No match in any orientation, continue
                continue;
            }
        }
        // Copy the current state
        auto cpy = used;
        // Add the selected value to the copied state
        cpy.push_back(j); // Add to list
        // Recurse
        auto r = berechne(cpy, all, j, new_orientation);
        // Assign the maxpath if the path was deeper (As this is DFS)
        if (maxpath.size() < r.size())
            maxpath = r;
    }

    // Return the found path
    return maxpath;

}

int main(int argc, char* argv[])
{
    // Randomize and fill
    srand(time(NULL));

    auto rf = []() { return (rand() % 10) + 1; };

    std::vector<Stein> steine;

    for (size_t i = 0; i < blockcount; ++i) {
        steine.push_back(Stein(rf(), rf()));
    }

    // Start by setting any start block (-1) and a fixed orientation
    std::vector<int> used;
    auto ret = berechne(used, steine, -1, 1);

    // Dump info for all bricks
    std::cout << "All bricks: " << std::endl;
    for (const auto& x : steine) {
        std::cout << x.format() << " => ";
    }

    // Dump info about the sorting
    std::cout << std::endl << "Sorted bricks: " << std::endl;
    int lastval = -1;
    for (const auto& x : ret) {
        if (lastval == -1) {
            // We know that we started with orientation = 1
            lastval = steine[x].v2;

            std::cout << steine[x].format(true) << " => ";
        }
        else {
            std::cout << steine[x].format(lastval) << " => ";
            lastval = steine[x].v1 == lastval ? steine[x].v2 : steine[x].v1;
        }
    }
    std::cout << "\n (missing " << steine.size() - ret.size() << " brick(s))" << std::endl;

    return 0;
}
```

Kurze Theorie dazu: Das ist ein DFS (depth first search) basierter Ansatz, der sehr teuer ist, was Stack / Speicher angeht, aber einfach zu verstehen.
Im Prinzip wird in jeder Tiefe geschaut, welche Steine passen. Für jeden der passenden Steine wird das Problem verkleinert (minus den Stein, der gerade genommen wurde) und wieder gelöst.

Ich habe keine Ahnung, wie es mit nur den 2 Parametern i und j gehen soll, und es macht auch keinen Sinn, Rekursion und Iteration (mit Speicher ausserhalb) zu mischen.

Dieser Code findet immer einen Optimalen Pfad. Als Übung kannst du den Beweis dazu schreiben 
Vielleicht hilft das ja als Ansatz.

Tipps für C++ => C:
1) push_back fügt ein Element ans Ende des Arrays an. In C macht man das normalerweise, indem man einen genügend grossen Array reserviert und eine Iterationsvariable hat, an deren Position eingefügt wird, und dann wird diese Variable um 1 erhöht. Es gibt hier aber auch elegantere Methoden (da ohnehin kopiert wird) mit memcpy.
2) decltype übernimmt den Typ einer Variable.
3) auto übernimmt den Typ der zugewiesenen Variable
4) In diesem Beispiel werden die Vektoren by value übergeben. C-Arrays müssen zuerst kopiert werden!
5) std::cout kann man mit printf() ersetzen, std::string mit const char*. Aber: Scopes im Auge behalten! (Compilerwarnungen lesen, -Wall -Wextra)
6) Stein ist ein Struct mit einem Konstruktor. Die Memberfunktionen kannst du ebenfalls schnell umschreiben.

Gruss
cwriter


----------



## Sekiro24 (23. April 2019)

Mit dem C++ Code konnte ich leider nichts anfangen. Ich schicke ma trotzdem die Aufgabenstellung.

Die Funktion berechnen(int i, int j) soll folgendes machen.

mit dem aktuellen Stein i soll immer der Nachfolger j im Array Steine betrachtet werden.
Passt der aktuelle Nachfolger wird die Funktion verlassen und der nächste Stein betrachtet.
Passt der aktuelle Nachfolger indem man ihn dreht, dann wird er gedreht, die Funktion wird verlassen und der nächste Stein betrachtet.
Passt der aktuelle Nachfolger nicht(auch nicht durch drehen), dann wird die Funktion berechnen(int i, int j) erneut aufgerufen(Rekursion) und der übernächste Nachfolger überprüft. Passt der übernächste nicht, wird der überübernächste überprüft usw..
D.h. wenn Sie im Hauptprogramm Stein i = 1 an berechnen(int i, int j) übergeben haben, dann überprüft berechnen(int i, int j) rekursiv der Reihe nach die Steine j = 2 ... 7, ob sie (ggf. auch durch drehen) passen. Wenn Sie im Hauptprogramm Stein j = 4 an berechnen(int i, int j) übergeben haben, dann überprüft berechnen(int i, int j) rekursiv der Reihe nach die Steine 5 - 7, ob sie (ggf. auch durch drehen) passen
Falls der übernächste, drittnächste etc. Stein passt, wird er mit dem unmittelbar nächsten Stein im Array Steine vertauscht.
Wenn es bei den restlichen Steinen keinen passenden Anlegekandidaten mehr gibt soll das Spiel mit einer entsprechenden Bildschirmausgabe beendet werden.
D.h bei jedem Drehen oder Steinetausch, wird die Reihenfolge bzw. Anordnung der Steine Array Steine aktualisiert.

Idee:
Zuerst dachte ich daran, dass ich in der main eine For-Schleife schreibe und die Laufvariable i übergebe aber da bin ich mir nicht sicher ob ich da richtig liege, da ich ja auch irgendwie die Variable j übergeben muss. Also meine Frage hier muss ich in der main eine for in for schreiben mit den jeweiligen Variablen i für die äussere Schleife und j für die innere Schleife ?
Wenn ja, wie mache ich das mit der Rekursion in der Funktion berechnen(int i, int j) ?


----------



## Technipion (23. April 2019)

Sekiro24 hat gesagt.:


> Also meine Frage hier muss ich in der main eine for in for schreiben mit den jeweiligen Variablen i für die äussere Schleife und j für die innere Schleife ?


Jein. So wie ich das sehe brauchst du in der main() zwar eine for-Schleife, die über i = 0 .. n läuft, aber das j soll eigentlich von der Funktion berechnen(i, j) selbst bestimmt werden (über Rekursion). Also quasi

```
main {
    for i in 0 .. n {
        ...
        berechnen(i, i+1);
        ...
    }
}


func berechnen(i, j) {
    // teste ob Stein Nr. j passt:
    ...
    // ggf. nächsten Stein überprüfen:
    berechnen(i, j+1); // <--- Rekursion
}
```

Gruß Technipion


----------



## cwriter (23. April 2019)

Sekiro24 hat gesagt.:


> Zuerst dachte ich daran, dass ich in der main eine For-Schleife schreibe und die Laufvariable i übergebe aber da bin ich mir nicht sicher ob ich da richtig liege, da ich ja auch irgendwie die Variable j übergeben muss.


Das ist nicht allzu falsch.



Sekiro24 hat gesagt.:


> Wenn ja, wie mache ich das mit der Rekursion in der Funktion berechnen(int i, int j) ?


Gehen wir doch mal die Aufgabenstellung durch:


Sekiro24 hat gesagt.:


> mit dem aktuellen Stein i soll immer der Nachfolger j im Array Steine betrachtet werden.


Interessiert nicht, ist nur Overview.


Sekiro24 hat gesagt.:


> Passt der aktuelle Nachfolger wird die Funktion verlassen und der nächste Stein betrachtet.


Da haben wir:

```
int berechnen(int i, int j)
{
    if(passt(i, j)) return:
}
```



Sekiro24 hat gesagt.:


> Passt der aktuelle Nachfolger indem man ihn dreht, dann wird er gedreht, die Funktion wird verlassen und der nächste Stein betrachtet.


Daraus folgt:

```
int berechnen(int i, int j)
{
    if(passt(i, j)) return 0:
    if(passt(i, gedreht(j)))
    {
        drehe(j);
        return 0;
    }
}
```



Sekiro24 hat gesagt.:


> Passt der aktuelle Nachfolger nicht(auch nicht durch drehen), dann wird die Funktion berechnen(int i, int j) erneut aufgerufen(Rekursion) und der übernächste Nachfolger überprüft. Passt der übernächste nicht, wird der überübernächste überprüft usw..


Also:

```
int berechnen(int i, int j)
{
    if(passt(i, j)) return 1:
    else if(passt(i, gedreht(j)))
    {
        drehe(j);
        return 1;
    }
    else
    {
        berechnen(i, j+1);
    }
}
```



Sekiro24 hat gesagt.:


> Falls der übernächste, drittnächste etc. Stein passt, wird er mit dem unmittelbar nächsten Stein im Array Steine vertauscht.


Also:

```
int berechnen(int i, int j)
{
    if(passt(i, j)) return 1:
    else if(passt(i, gedreht(j)))
    {
        drehe(j);
        return 1;
    }
    else
    {
        if(berechnen(i, j+1) == 1)
        {
            tausche(i+1, j+1);
        }
    }
}
```

Als nächstes ist die Aufgabenstellung mehr als schlecht (mehr dazu später), aber man kann sich ja selbst was überlegen:

```
int berechnen(int i, int j)
{
    if(i > max_stein || j > max_stein) return 0; // Bounds check
    if(passt(i, j)) return 1:
    else if(passt(i, gedreht(j)))
    {
        drehe(j);
        return 1;
    }
    else
    {
        if(berechnen(i, j+1) == 1)
        {
            tausche(i+1, j+1);
        }
    }
    return 0; // Muss was zurückgeben
}
```

Ok, dann zur main: Aus der Aufgabenstellung ist das nicht ganz klar, aber da i nicht verändert wird, muss das wohl mit einer Schleife in der main geschehen:

```
for(i...)
{
    if(berechnen(i, i+1) == 0) // Warum i, i+1? => Weil j per Definitionem ein Nachfolger sein muss
    {
        // Ende der Fahnenstange
    }
}
```

So, viel zu viel geholfen. Nun zum Rant:

Die Aufgabenstellung ist falsch bzw. löst das implizierte Problem nicht. Genauer gesagt ist das ein Greedy-Algorithmus (nimmt die erstbeste Möglichkeit). Das führt zu suboptimalen Resultaten. Ein Beispiel gefällig?

```
(1 | 2) => (2 | 3) => (2 | 2) => (3 | 4) => (4 | 5) => ... usw (in die Unendlichkeit)
```
Es ist offensichtlich, dass hier eine unendlich lange Kette möglich wäre, die alle Steine benutzt (Stein 1, Stein 3, Stein 2, Stein 4, Stein 5, ....). Aber der Beschriebene Algorithmus wird immer den Stein (2 | 2) übrig haben. Warum? Weil er den Stein (2 | 3) nimmt und der Stein (2 | 2) niemals mehr passen wird.
Ok, also haben wir herausgefunden, dass der Algorithmus nicht maximiert. (Dieses Beispiel ist ein einfacher Fall, um zu beweisen, dass der Algorithmus inkorrekt ist - es gibt _viele_ andere Probleme durch die Erzwungene Startorientierung ohne Option, einen anderen Startpunkt zu wählen und die inkomplette Aufzählung der Möglichkeiten).
Dann ist die Rekursion hier völliger Blödsinn und hat überhaupt keine Existenzberechtigung. Man nutzt den Stack ja nicht einmal für Zwischenwerte. (= Unnötiger Stackoverflow für nichts und wieder nichts).
Rekursion ist dann einfacher als Iteration, wenn man einen Zustandsautomaten mit Variablen bauen will. Hier wird das weggeworfen.

Ok, dann schauen wir uns mal die Laufzeit an. Die Laufzeit hier ist O(n^2) durch die beiden Iteratoren. Ist das besser als mein Code oben?
Mein Code hat eine Laufzeit von O(n^n), also ja: Hier ist der Algorithmus der Aufgabe besser.
Parallelisierbarkeit: Nicht vorhanden im Aufgabenalgorithmus, vorhanden im Vorschlag. 


Ach, der Professor wollte wohl nett sein und ein abwechslungsreiches Beispiel bringen, aber ich sehe nichts gutes an der Aufgabe.
Naja, mit den Tipps ist die Aufgabe ja immerhin lösbar.

Gruss
cwriter


----------



## Sekiro24 (4. Mai 2019)

Ich habe das jetzt mal wie folgt geschrieben, jedoch wird mir vom compiler gesagt, dass es 2 Fehler gibt. 


```
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int Steine[7][2];
int berechnen(int, int);
int i, j, temp;
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;
}

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

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{
            brechnen(i, (j+1));
        }
    return 0;
}
```


----------



## Technipion (4. Mai 2019)

Sekiro24 hat gesagt.:


> jedoch wird mir vom compiler gesagt, dass es 2 Fehler gibt.


Ich weiß das klingt jetzt weit hergeholt, aber wie wäre es - für die Zukunft - wenn du diese Fehler dann auch mitposten würdest?

Mir fällt direkt auf, dass in der `main()` die Funktion `einlesen()` benutzt wird, die der Compiler aber zu dem Zeitpunkt noch gar nicht kennt. Das müsste also einen Error erzeugen. Lösung? Lege ganz oben einen Prototypen an, genau wie bei `berechnen(...)`.

Ich halte mich aber zunächst noch zurück, ich kann nämlich schon cwriters Tastatur klackern hören


----------



## Sekiro24 (4. Mai 2019)

Der Fehler lag eher unten bei berechnen. Ich habe ausversehen brechnen statt berechnen geschrieben.


----------



## Sekiro24 (4. Mai 2019)

Es wird auch nicht wirklich getauscht.


----------



## cwriter (4. Mai 2019)

Sekiro24 hat gesagt.:


> Es wird auch nicht wirklich getauscht.


Nummer 42 der Sekiro'schen Weisheiten. 

Du hast in deinem Code auch keine Zeile, die das tun sollte...

Nicht böse gemeint, aber du solltest wirklich deine Arbeitsweise überdenken. Du eröffnest ein Thema (vor einem Monat), dann liegt es ein paar Wochen brach ohne Lebenszeichen und dann bekommen wir vorwurfsvolle Einzeiler vorgelegt.
Wir sind geduldig und haben schon viel gesehen (und wollen dich sicher nicht entmutigen), aber erweise uns doch den Respekt, etwas mehr Gedanken in deine Posts einfliessen zu lassen. Wenn du etwas nicht verstehst, dann frage nach einer Erklärung (idealerweise mit einer Beschreibung, warum du etwas nicht verstehst). Wenn etwas nicht kompiliert, dann gib uns die Fehlermeldungen (idealerweise 1 zu 1 kopiert). Wenn der Code etwas nicht tut, was er deiner Meinung nach tun sollte, dann sage uns, warum du meinst, dass die Funktionalität da sein soll und wo du die betreffenden Codezeilen vermutest.

Wir geben uns Mühe, unsere Posts so hilfreich wie möglich zu schreiben und lassen viele Gedanken einfliessen - entsprechend kann es sein, dass man mal 20-30 Minuten über einem Post sitzt. Entgegne diese Höflichkeit, indem du es uns gleichtust.

Ok, Schwamm drüber, Blick nach vorne: Zu deinem Problem.

Jetzt, da du weisst, dass du den Code nicht hast: Wo ist der Knoten, der dich daran hindert, den Code zu schreiben?

Gruss
cwriter


----------



## Sekiro24 (4. Mai 2019)

Sorry nochmal trotzdem, musste in letzter Zeit mehr für andere Fächer machen. 
Also ich habe eben bemerkt das ich das mit dem tauschen offensichtlich nicht habe - eingesehen. 
Du hast dazu folgendes geschrieben:



cwriter hat gesagt.:


> if(berechnen(i, j+1) == 1) { tausche(i+1, j+1); }


Für die Stelle wo getauscht werden soll, also "tausche(i+1 , j+1)", habe ich folgendes geschrieben: 


```
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;
                }
```


----------



## cwriter (4. Mai 2019)

Sekiro24 hat gesagt.:


> Sorry nochmal trotzdem, musste in letzter Zeit mehr für andere Fächer machen.


Das kann ich durchaus verstehen . Allerdings ist meine Erfahrung, dass man solche Programme jeweils in höchstens einer Woche bearbeiten sollte, da man sonst mehr Zeit mit dem Wieder-Einlesen verbringt als mit dem Problem selbst. Aber vielleicht ist das bei dir ja anders. Und es kann ja immer etwas wichtigeres dazwischenkommen, da hast du schon recht.



Sekiro24 hat gesagt.:


> Für die Stelle wo getauscht werden soll, also "tausche(i+1 , j+1)", habe ich folgendes geschrieben:


Ok, damit sieht das Programm eigentlich schon recht komplett aus. Ich habe das Programm selbst nicht geschrieben/nicht ausgeführt; geht es denn jetzt wie erwartet?

Gruss
cwriter


----------



## Sekiro24 (5. Mai 2019)

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. 

```
#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 (5. Mai 2019)

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

Hier nochmal der ganze Code


```
#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 (5. Mai 2019)

Sekiro24 hat gesagt.:


> 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...



Sekiro24 hat gesagt.:


> 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:

```
// 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:


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

Dann ist dein Bounds-Check kaputt:

```
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:

```
#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:


```
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:

```
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!



Sekiro24 hat gesagt.:


> 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


----------



## Sekiro24 (5. Mai 2019)

Die Schleifenbedingung mit for i in #Steine soll dann wohl i < sizeof(Steine)/sizeof(int) sein oder ?


----------



## cwriter (5. Mai 2019)

Sekiro24 hat gesagt.:


> 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

```
i < sizeof(Steine) / (sizeof(int) * 2)
```
sein (da Steine ja 7 * 2 * 4 Bytes gross ist).

Gruss
cwriter


----------



## Sekiro24 (5. Mai 2019)

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 (5. Mai 2019)

Sekiro24 hat gesagt.:


> 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.



Sekiro24 hat gesagt.:


> und was soll max(best_run_value ) sein ?


Das habe ich nirgends geschrieben...


Sekiro24 hat gesagt.:


> In welcher Bibliothek ist die Funktion max hinterlegt und ist das auch ansi standard ?


Nirgends.

```
int max(int a, int b)
{
    return (a >= b) ? a : b;
}
```

Gruss
cwriter


----------



## Sekiro24 (5. Mai 2019)

Hier meinte ich das, als du den Algorithmus geschrieben hast. 


cwriter hat gesagt.:


> best_run_value = max(i, best_run_value) best_run_index = (s == best_run_value) ? s : best_run_index


----------



## cwriter (5. Mai 2019)

Sekiro24 hat gesagt.:


> 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 


Sekiro24 hat gesagt.:


> 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 (5. Mai 2019)

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 .


----------



## Sekiro24 (5. Mai 2019)

Also eigentlich ist es doch fasst wie beim Insertion -Sort oder ? 
Da wird ja auch immer von der ausgehenden Zahl alle Zahlen verglichen und diese dann getauscht. Hier wird nur nicht das steigender Zahl geguckt sondern ob beide dann gleich sind oder ?


----------



## cwriter (5. Mai 2019)

Sekiro24 hat gesagt.:


> würde es denn mit der Variante davor also ohne den zwei geschachtelten for schleifen auch funktionieren.





Sekiro24 hat gesagt.:


> 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 wechselt der 1. Stein (von [3|5] auf [3|2]. Ok, ich sehe gerade, dass [3|2] gar nicht im Test-Set ist.
Also sag du es mir: Kann der Startstein wechseln?
Probiere deine Testdaten durch (die du ja offenbar hast). Stimmen die?

Der Extension-Algorithmus ist nur, falls der Startstein wechseln dürfen sollte. Wenn nicht, war der Code davor (mit den entsprechenden Fixes) schon weit genug.



Sekiro24 hat gesagt.:


> Also eigentlich ist es doch fasst wie beim Insertion -Sort oder ?
> Da wird ja auch immer von der ausgehenden Zahl alle Zahlen verglichen und diese dann getauscht. Hier wird nur nicht das steigender Zahl geguckt sondern ob beide dann gleich sind oder ?


Äh...
Das hier hat mit Sortieren nichts zu tun (falls der Algorithmus überhaupt gebraucht wird, ich habe ja keine (nicht-beschädigten) Testdaten...).
Es ist eine Suche, keine Sortierung. Wenn du es dir genauer überlegst, ist der innere Loop mit berechnen() kein Loop auf den Daten selbst - naja, doch: Fehler im Algorithmus, der annimmt, dass die ursprüngliche Reihenfolge der Steine gleich bleibt (was sie ja nicht tut).
Korrigierter Algorithmus:

```
SteineKopie = copy(Steine)
for s in SteineKopie:
    Steine = copy(SteineKopie)
    Tausche s mit Stein 0 in Steine (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:
Steine = copy(SteineKopie)
tausche(0, best_run_index)
berechne(0, 1)

// Ausgabe
```
Dennoch ist die Idee, einen Wert zu suchen - nicht eine Sortierung.
(Was ist die Asymptotische Laufzeit, wenn man die Berechnung rausnimmt? Was ist die asymptotische Laufzeit von InsertionSort? Kann das passen?)

Aber wie gesagt: Vielleicht ist das alles gar nicht nötig...



Sekiro24 hat gesagt.:


> Ich habe mir jetzt mehr darüber Gedanken gemacht .


Show, don't tell.

Gruss
cwriter


----------



## Sekiro24 (9. Mai 2019)

Da mir die doppelt geschachtelte Schleife mit der Schleifenbedingung mit dem Steine Array schwer fällt, habe ich jetzt noch mal das von davor nochmal geschrieben. 
Das mittels Insertion Sort zu lösen, fällt mir in der Umsetzung schwierig. 
Deswegen habe ich nochmal das vom Anfang mit weiteren Funktionen geschrieben. 
Vielleicht könnten wir ja da weiter machen. 
Also der Code sieht bei mir folgendermassen aus: 


```
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <stdbool.h>

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

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)
        {

        }

    }
    for(i = 0; i < 7; i++)
    {
        printf("%d. %d/%d\n", (i+1), Steine[i][0], Steine[i][1]);
    }
    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 drehe(int j)
{
        temp = Steine[j][0];
        temp1 = Steine[j][1];

        Steine[j][0] = Steine[j][1];
        Steine[j][1] = Steine[j][0];

        Steine[j][1] = temp;
        Steine[j][0] = temp1;

}
bool passt(int i,int j)
{
        if(Steine[i][0] == Steine[j][0] && Steine[i][1] == Steine[j][1])
            return true;
        else
            return false;
}
int berechnen(int i, int j) {
    if(i > 7 || j > 7) return 1;
    if(passt(i, j)) return 1;
    else
    {
        drehe(j);
        if(passt(i,j))
        {
            /*Drehen*/
            drehe(j);
            return 1;
        }
    }
    else
    {
       if(berechnen(i,j+1) == 1)
        {
            tausche(i+1,j+1);
        }
    }
    return 0;
}
int tausche(int i, int j){
    temp = Steine[i][0];
    temp1 = Steine[i][1];

    Steine[i][0] = Steine[j][0];
    Steine[i][1] = Steine[j][1];

    Steine[j][0] = temp;
    Steine[j][1] = temp1;
}
```

Die Ausgabe ist damit wie folgt: 

Bitte geben Sie nun 7 Dominosteine ein
1.
3
5
2.
4
2
3.
3
3
4.
4
1
5.
2
5
6.
1
3
7.
1
4
Ausgabe
1. 3/5
2. 4/2
3. 3/3
4. 4/1
5. 4/1
6. 3/1
7. 5/2


----------



## cwriter (9. Mai 2019)

Sekiro24 hat gesagt.:


> Da mir die doppelt geschachtelte Schleife mit der Schleifenbedingung mit dem Steine Array schwer fällt, habe ich jetzt noch mal das von davor nochmal geschrieben.


Ok



Sekiro24 hat gesagt.:


> #include <stdbool.h>


ANSI-C, was? 
stdbool = C99, ANSI-C = C90 = C89.



Sekiro24 hat gesagt.:


> Das mittels Insertion Sort zu lösen, fällt mir in der Umsetzung schwierig.


Insertion Sort hast du ins Gespräch gebracht. Warum willst du Insertion Sort haben?


```
if(Steine[i][0] == Steine[j][0] && Steine[i][1] == Steine[j][1])
```
Wie spielst du denn Domino? Nimm ein Blatt Papier und zeichne dir auf, welche Steine so passen würden.


```
int drehe(int j)
{
        temp = Steine[j][0];
        temp1 = Steine[j][1];

        Steine[j][0] = Steine[j][1];
        Steine[j][1] = Steine[j][0];

        Steine[j][1] = temp;
        Steine[j][0] = temp1;

}
```
Du willst 2 Werte vertauschen und brauchst dafür 2 Ausweichvariablen? (Hint: Dein Code ist äquivalent zu:

```
int drehe(int j)
{
        temp = Steine[j][0];
        temp1 = Steine[j][1];

        Steine[j][1] = temp;
        Steine[j][0] = temp1;

}
```
)
Da kann man noch eine Zeile sparen.

Aber ich wundere mich schon ein bisschen, warum du einen gut funktionierenden Code hattest und jetzt wieder dieselben Fehler neubaust.



Sekiro24 hat gesagt.:


> Die Ausgabe ist damit wie folgt:


Und? Was sollen wir jetzt damit? Stimmt die Ausgabe (da der Code an verschiedenen Stellen falsch ist: Nein), was ist falsch/muss anders sein?

Ich habe das Gefühl, dass wir uns ein bisschen im Kreis drehen...

Gruss
cwriter


----------



## Sekiro24 (9. Mai 2019)

Bei mir wird noch angezeigt, dass das else ohne vorheriges if geschrieben wurde.
Die Funktion drehe sollte eigentlich die Funktion tausche sein.
Die bool Funktion habe ich jetzt wieder vom typ integer deklariert.
Die If-Bedingung der Funktion passt habe ich jetzt auch geändert.
Jetzt weiss ich nicht mehr weiter.


```
#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 passt(int, int);
void drehe(int);
void tausche(int, int);

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)
        {

        }

    }
    for(i = 0; i < 7; i++)
    {
        printf("%d. %d/%d\n", (i+1), Steine[i][0], Steine[i][1]);
    }
    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;
}
void drehe(int j)
{
        temp = Steine[j][0];
        Steine[j][0] = Steine[j][1];
        Steine[j][1] = temp;

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

    }
    return 0;
}
void tausche(int i, int j){
    temp = Steine[i][0];
    temp1 = Steine[i][1];

    Steine[i][0] = Steine[j][0];
    Steine[i][1] = Steine[j][1];

    Steine[j][0] = temp;
    Steine[j][1] = temp1;
}
```


----------



## Sekiro24 (9. Mai 2019)

Ich habe jetzt nochmal was geändert und komme auf folgendes.

```
#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 passt(int, int);
void drehe(int);
void tausche(int, int);

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)
        {

        }

    }
    for(i = 0; i < 7; i++)
    {
        printf("%d. %d/%d\n", (i+1), Steine[i][0], Steine[i][1]);
    }
    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;
}
void drehe(int j)
{
        temp = Steine[j][0];
        Steine[j][0] = Steine[j][1];
        Steine[j][1] = temp;

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

    Steine[i][0] = Steine[j][0];
    Steine[i][1] = Steine[j][1];

    Steine[j][0] = temp;
    Steine[j][1] = temp1;
}
```
Ausgabe
1. 3/5
2. 2/5
3. 0/0
4. 3/3
5. 1/3
6. 1/4
7. 4/1

EDIT: Jo jetzt habe ichs Vielen Dank für deine Hilfe 

Der Code sieht nun wie folgt aus: 

```
#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 passt(int, int);
void drehe(int);
void tausche(int, int);

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)
        {

        }

    }
    for(i = 0; i < 7; i++)
    {
        printf("%d. %d/%d\n", (i+1), Steine[i][0], Steine[i][1]);
    }
    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;
}
void drehe(int j)
{
        temp = Steine[j][0];
        Steine[j][0] = Steine[j][1];
        Steine[j][1] = temp;

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

    Steine[i][0] = Steine[j][0];
    Steine[i][1] = Steine[j][1];

    Steine[j][0] = temp;
    Steine[j][1] = temp1;
}
```
Und die Ausgabe wie folgt:
1. 3/5
2. 5/2
3. 2/4
4. 4/1
5. 1/3
6. 3/3
7. 1/4


----------

