Pascalsche Dreieck ausgeben

JavaIsTheBest

Bekanntes Mitglied
Hallo,
ich bin gerade bei folgender Aufgabe.
Mein bisheriger Code, sieht so aus. Es sind einige Fehler enthalten.

Java:
    public static int[][] pascal(int n){
        int[][] a = new int[n][n];
        for(int i=0;i<a.length;i++){
            for(int j=0;j<a[i].length;j++){
                if(j==0 || j==a[i].length-1 ){
                    a[i][j]=1;
                }
                else{
                    a[i][j]=a[i-1][j-1]+a[i-1][j];
                }
            }
        }
       
    }
 

Anhänge

  • Unbenannt.png
    Unbenannt.png
    53,2 KB · Aufrufe: 185

JavaIsTheBest

Bekanntes Mitglied
Hier, möchte ich eine Methode implementieren, die aus allen Großbuchstaben einen Kleinbuchstaben machen. Warum meckert der Compiler? Ich habe doch aus der Zahl ein char gemacht.

Java:
    public static String toLower(String s){
        String s2;
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)>=65 &&s.charAt(i)<=90)
                s2+=s.charAt(i)+'32';
            else s2+=s.charAt(i);
        }
    }
 
K

kneitzel

Gast
Also wenn Du ein Problem postest, dann schreib bitte auch immer, was Du für ein Problem hast. Wir wollen normalerweise nicht rumrätseln.

Und mische nicht mehrere Probleme in einen Thread. Ist das erste Problem noch akut?

Bezüglich Deines Problems mit dem toLower:
a) s2 sollte initialisiert werden ehe Du es benutzt. Also ein String s2=""; oder so.
b) Hinweis: Strings durch Concatenation zusammen bauen ist nicht gut. Dafür nutzt man einen StringBuilder!
c) charAt liefert einen Char. Du willst an den Char ja nichts anhängen sondern dem Ascii Code etwas hinzu addieren. Dafür musst Du den Char als Zahl sehen. Und dann willst Du doch die Zahl 32 hinzufügen. Dein '32' ist aber keine Zahl! (' ist eigentlich eine Begrenzug für ein Zeichen. '32' ist aber nicht ein Zeichen sondern zwei Zeichen. Also komplett illegal.) Und nach der Addition musst Du das Resultat wieder als Char nehmen.
d) Wenn die Funktion etwas zurück geben soll, dann brauchst Du ein return statement.

Also unter dem Strich wäre meine Empfehlung, noch einmal die Grundlagen von Java an Hand eines Tutorials durchzuarbeiten. Ideal wäre ein Tutorial mit Beispielen, so dass Du an den gegebenen Beispielen auch rumspielen kannst.

Konrad
 
K

kneitzel

Gast
Ach ja - bitte überlege genau, was Du mit Variablen machen willst und benenne die Variablen entsprechend. "s2", "s", "i" sind sehr ungünstige Namen für Variablen.
 
K

kneitzel

Gast
Zur Funktion pascal auch noch ein paar Hinweise:
a) return fehlt
b) wenn i = 0 ist, dann versuchst Du auf ein i-1 Element zuzugreifen was natürlich nicht geht.
c) Wieso willst du am Ende des Arrays eine 1 erzwingen? Da kann doch auch ruhig eine 0 stehen? Könnte egal sein, weil die Aufgabe nicht vorgibt, was da drin zu stehen hat.
 

JavaIsTheBest

Bekanntes Mitglied
Zur Funktion pascal auch noch ein paar Hinweise:
a) return fehlt
b) wenn i = 0 ist, dann versuchst Du auf ein i-1 Element zuzugreifen was natürlich nicht geht.
c) Wieso willst du am Ende des Arrays eine 1 erzwingen? Da kann doch auch ruhig eine 0 stehen? Könnte egal sein, weil die Aufgabe nicht vorgibt, was da drin zu stehen hat.

Mein Problem ist, ich bekomme kein dreieckiges Array hin. Wenn ich das dreieckige Array habe, dann möchte ich in der 1. und letzten Spalte lauter Einsen haben.

Java:
public static int[][] pascal(int n){
        int[][] a = new int[n][n];
        for(int i=0;i<a.length;i++){
            for(int j=0;j<a[i].length;j++){
                if(j==0 || j==a[i].length-1 ){
                    a[i][j]=1;
                }
                else{
                    a[i][j]=a[i-1][j-1]+a[i-1][j];
                }
            }
        }
        return a;
    }
 
K

kneitzel

Gast
Ahh, jetzt verstehe ich das Problem. Ich hatte gedacht, die Nutzung eines quadratischen 2D Arrays wäre ok (und es würden dann halt viele Felder nicht genutzt).

Ein 2D Array ist eigentlich ein Array von Arrays.
Daher kannst Du dann so Dinge machen wie:
Code:
int[][] array = new int[2][];
array[0] = new int[1];
array[1] = new int[2];
Und da man dann für das letzte Feld kein Feld drüber hat, wird dieser Check tatsächlich gebraucht.

Konrad
 

JavaIsTheBest

Bekanntes Mitglied
Was ist, wenn n=3 ist. Dann habe ich 3 Zeilen und 3 Spalten. Das wäre dann wieder ein quadratisches Array, was nicht sein soll.
Deswegen, weiß ich immer noch nicht, wie ich ein dreieckiges Array hinbekomme.
 
K

kneitzel

Gast
Ich habe doch schon etwas gezeigt, wie es geht. Du musst es nur noch "generalisieren", d.h. was ich für Größe 2 gemacht habe, müsstest Du für Größe n schreiben.

Wenn Du die Lösung noch nicht siehst, dann schreib doch einmal für n=3 und n=4, was da ausgeführt werden müsste. Vielleicht siehst Du dann, wie da ein Algorithmus sein kann.
 

JavaIsTheBest

Bekanntes Mitglied
So sieht der aktuelle Quellcode meiner Pascalmethode aus.
Beim Aufruf der Methode wird eine OutOfBoundsException geworfen.

Java:
    public static int[][] pascal(int n){
        int[][] a = new int[n][];
        for(int i=0;i<n;i++){
            a[i]=new int[i+1];
            for(int j=0;j<i+1;j++){
                a[i][j]=(j==0 || j==a.length-1)?1:a[i-1][j-1]+a[i-1][j];
            }
        }
        return a;
    }
 
K

kneitzel

Gast
Dann geh doch einfach einmal im Debugger Deine Applikation durch um zu sehen, was da genau passiert!
Und bitte nimm doch einmal aussagekräftige Namen! a, i und j sind keine aussagekräftigen Namen für Variablen.
Und ich finde den ? : Operator unleserlich sobald da etwas komplexere Dinge geprüft werden. Ich bin da dann jemand, der lieber beim altmodischen if else bleibt.
 
K

kneitzel

Gast
Also das ist etwas, das ich nicht nachvollziehen kann. Sinnvolle Namen für Variablen sind das a und o bei der Entwicklung. So schafft Ihr es dann doch tatsächlich, dass selbst kleines Programme nicht mehr nachvollzogen werden können.

a für Array. Und wenn Du mehrere hast, dann hast Du a1, a2, a3, a4?
Und bei noch mehr Schleifen gibt es dann was? k,l,m,n oder gibt es dann i2, j2 und so?

Und das a, i und j verrät Dir auch genau, was in dem Array steht oder was da gezählt wird?

Im Array wird das Ergebnis festgehalten. Daher könnte man das von mir aus result nennen. i und j dienen dazu, durch die zeilen und spalten zu gehen, daher wäre spalte und zeile sinnvoll.

Dadurch wird es dann doch schon gleich viel lesbarer finde ich. Hilft aber nicht direkt bei der Problemlösung. Das Problem mit dem Index bekommst Du aber mit dem Debugger bestimmt schnell raus - evtl. aber den ? : Operator durch ein if ersetzen. Das macht das debuggen evtl. einfacher.
 

JavaIsTheBest

Bekanntes Mitglied
Ich bekomme es mit dem debugger nicht hin. Die erste Zeile funktioniert. Das Programm macht ab der zweiten Zeile und zweiten Spalte nicht das, was es tun sollte.
a.length gibt doch die Anzahl der Zeilen an?
 
K

kneitzel

Gast
Ja, aber willst Du denn prüfen, ob es die Anzahl der Zeilen ist? Oder was willst Du genau prüfen? Ein Zitat von Dir war: "Wenn ich das dreieckige Array habe, dann möchte ich in der 1. und letzten Spalte lauter Einsen haben."
 
K

kneitzel

Gast
Und Deine Analyse ist doch sehr gut. Du hast die genaue Position des Fehlers festgestellt: Zweite Spalte in der zweiten Zeile. Welche Werte haben denn da i und j? Und was für einen Befehl versucht er da dann auszuführen? Und Du hast auch gut erkannt, dass es irgendwie mit der Prüfung mit a.length zu tun haben muss.
==> Das war für den Anfang doch sehr gut! Wenn Du zu diesen Erkenntnissen mit dem Debugger gekommen bist, dann hast Du den Debugger schon sehr gut eingesetzt! Gerade am Anfang kann das alles sehr schwer sein - aber ich habe den Eindruck, dass Du das schon sehr gut gemacht hast. Alles weitere kommt dann mit der Zeit und mit der Übung!
 

JavaIsTheBest

Bekanntes Mitglied
Also muss ich überprüfen, ob ich mich in der letzten Spalte befinde und dann eine 1 reinschreiben.
Das müsste doch mit
Code:
j==a[i].length-1
funktionieren.
Bsp:
a[0]:
i=0;j=0;a[0].length-1=0

a[1]:
i=1;j=0;a[1].length-1=1
i=1;j=1;a[1].length-1=1

Wenn ich die Methode System.out.print(pascal(4)); aufrufe, dann erscheint diese Ausgabe.
[[I@2a139a55

Java:
public static int[][] pascal(int n){
        int[][] a = new int[n][];
        for(int i=0;i<n;i++){
            a[i]=new int[i+1];
            for(int j=0;j<i+1;j++){
                if(j==0 || j==a[i].length-1)
                a[i][j]=1;
                else a[i][j]= a[i-1][j-1]+a[i-1][j];
            }
        }
        return a;
    }

Java:
public static void print(int[][] a){
        for(int i=0;i<a.length;i++){
            for(int j=0;j<a[i].length;j++){
                System.out.print(a[i][j]+" ");
            }
            System.out.println();
        }
    }
 
K

kneitzel

Gast
In der Funktion hast Du es nun richtig gemacht - im Text hier im Forum hast Du es wieder falsch geschrieben. Es geht nicht um a.length sondern um a.length.
Oder wenn Du das optimieren willst: a.length ist ja i +1, also hast Du da in der Überprüfung j == i + 1 - 1 und das ist dann ein j == i;

Und ja, wenn Du das pascal(4) Ergebnis direkt mit System.out.println ausgibst, dann bekommst Du nur die Referenz ausgegeben. Daher hast Du ja auch eine print Funktion geschrieben. Ruf doch einfach Deine print Funktion auf:
Code:
print(pascal(4));

Gratuliere - damit hast Du jetzt eine recht gute Lösung geschrieben. Aber ich möchte auf den Namen noch etwas herum reiten :)

Also der Funktionsname pascal ist Müll. Klar, ist vorgegeben worden, aber normalerweise heißen Funktionen ja wie Aktionen. toString, toLower, print, ...
Also was macht diese Funktion? Sie erstellt etwas - daher ist ein create schon ein guter Anfang. Dann ist das ja ein Pascal Dreieck - also createPascalTriangle oder so wäre ein guter Name und jeder, der liest:
print(createPascalTriangle(6)); weiss, was da passiert. Aber bei einem Aufruf pascal(4)? Ein Array mit 4 Pascal-Programmen? Ja was machen die denn? :p
Aber klar - das ist vorgegeben und habe ich dann auch einmal gelassen.

Ansonsten habe ich aber einmal die beiden angesprochenen Funktionen in etwas anderer Form für Dich:
Java:
public static int[][] pascal(int n) {
    int[][] result = new int[n][];

    for (int zeile = 0; zeile < result.length; zeile++) {
        result[zeile] = new int[zeile+1];
        for (int spalte = 0; spalte <= zeile; spalte++) {
            if (spalte == 0 || spalte==zeile) {
                result[zeile][spalte] = 1;
            } else {
                result[zeile][spalte] = result[zeile - 1][spalte - 1] + result[zeile - 1][spalte];
            }
        }
    }
    return result;
}

public static final int ASCII_UPPERCASE_A = 65;
public static final int ASCII_UPPERCASE_Z = 90;
public static final int ASCII_LOWERCASE_A = 97;

public static String toLower(String text){
    String result="";
    for(int index=0; index<text.length(); index++){
        if(text.charAt(index) >= ASCII_UPPERCASE_A && text.charAt(index) <= ASCII_UPPERCASE_Z)
            result += (char)((int)text.charAt(index) + ASCII_LOWERCASE_A - ASCII_UPPERCASE_A);
        else result += text.charAt(index);
    }
    return result;
}

Also andere Namen, so dass besser nachvollzogen werden kann, was da passiert und dann die magischen Nummern rausgeschmissen und dafür Konstanten eingeführt.

Und kleine Optimierungen. Also sowas wie i < something + 1 ist das Gleiche wie i <= something.
(Und nimmt eine Addition weg.)
 

Neue Themen


Oben