HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Sierpinski triangle from Pascal triangle

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
pascaltrianglefromsierpinski

Problem

I tried to draw a Sierpinski triangle by shading the even number entries of the Pascal triangle. Could you please suggest improvements?

public class Sierpinski {
    public static void main(String[] args) {
        int no_of_row = 50;
        int[][] tri = new int[no_of_row][no_of_row];

        for (int i = 0; i  0 && j > 0 ) {
                    tri[i][j] = tri[i - 1][j - 1] + tri[i - 1][j];
                }
            }
        }

        for (int i = 0; i < no_of_row; i++) {
            printSpace(no_of_row, i);
            for (int j = 0; j <= i; j++) {
                System.out.print(isEven(tri[i][j]));
                System.out.print(" ");
            }
            System.out.println();
        }
    }

    private static void printSpace(int no_of_row, int current_row) {
        for (int i = 0; i < no_of_row - current_row; i++) {
            System.out.print(" ");
        }
    }

    private static String isEven(int n) {
        return n % 2 == 0 ? "x" : " ";
    }
}


Sample output:

```
x

x x x
x x
x x x

x x x x x x x
x x x x x x
x x x x x x x
x x x x
x x x x x x x x x
x x x x x x
x x x x x x x

x x x x x x x x x x x x x x x
x x x x x x x x x x x x x x
x x x x x x x x x x x x x x x
x x x x x x x x x x x x
x x x x x x x x x x x x x x x x x
x x x x x x x x x

Solution

Small rewrite

The code can be divided into two phases. It would be helpful to write a comment on each code block.

The Pascal's triangle loop can be tightened by getting rid of unnecessary conditional logic.

// Generate Pascal's triangle
int[][] tri = new int[SIZE][SIZE];
for (int i = 0; i < SIZE; i++) {
    tri[i][0] = tri[i][i] = 1;
    for (int j = 1; j < i; j++) {
        tri[i][j] = tri[i - 1][j - 1] + tri[i - 1][j];
    }
}


isEven() is poorly named: it looks like it should return true or false, because it follow Java's naming convention for predicates.

As for the printing, calling System.out.print() to output one character at a time is slow and, in my opinion, makes the code more cumbersome. I suggest this loop instead, which marks the places which have even entries, then prints a row at a time.

// Print 'x' where Pascal's Triangle has even entries
char[] buf = new char[2 * SIZE];
for (int i = 0; i < SIZE; i++) {
    Arrays.fill(buf, ' ');
    int leftPad = SIZE - i;
    for (int j = 0; j < i; j++) {
        if ((tri[i][j] & 1) == 0) {
            buf[leftPad + 2 * j] = 'x';
        }
    }
    System.out.println(new String(buf, 0, leftPad + 2 * i));
}


Window dressing

Note that you don't actually need to store the entire Pascal's triangle at once; you can build it a row at a time as you print each line. I suggest making an iterator to take care of that bookkeeping and reduce main() to being just a simple, pretty loop. The Sierpinski object also makes the size and fill character are parameterizable.

import java.util.Arrays;
import java.util.Iterator;

public class Sierpinski implements Iterable {
    private class RowIterator implements Iterator {
        private int row;
        private int[] thisPascalRow = new int[Sierpinski.this.size],
                      nextPascalRow = new int[Sierpinski.this.size];
        private char[] buf = new char[2 * Sierpinski.this.size];

        @Override
        public boolean hasNext() {
            return this.row  iterator() {
        return new RowIterator();
    }

    public static void main(String[] args) {
        for (String line : new Sierpinski(50, 'x')) {
            System.out.println(line);
        }
    }
}

Code Snippets

// Generate Pascal's triangle
int[][] tri = new int[SIZE][SIZE];
for (int i = 0; i < SIZE; i++) {
    tri[i][0] = tri[i][i] = 1;
    for (int j = 1; j < i; j++) {
        tri[i][j] = tri[i - 1][j - 1] + tri[i - 1][j];
    }
}
// Print 'x' where Pascal's Triangle has even entries
char[] buf = new char[2 * SIZE];
for (int i = 0; i < SIZE; i++) {
    Arrays.fill(buf, ' ');
    int leftPad = SIZE - i;
    for (int j = 0; j < i; j++) {
        if ((tri[i][j] & 1) == 0) {
            buf[leftPad + 2 * j] = 'x';
        }
    }
    System.out.println(new String(buf, 0, leftPad + 2 * i));
}
import java.util.Arrays;
import java.util.Iterator;

public class Sierpinski implements Iterable<String> {
    private class RowIterator implements Iterator<String> {
        private int row;
        private int[] thisPascalRow = new int[Sierpinski.this.size],
                      nextPascalRow = new int[Sierpinski.this.size];
        private char[] buf = new char[2 * Sierpinski.this.size];

        @Override
        public boolean hasNext() {
            return this.row < Sierpinski.this.size;
        }

        // For compatibility with Java < 8
        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }

        @Override
        public String next() {
            try {
                // Generate the next row of Pascal's Triangle
                nextPascalRow[0] = nextPascalRow[row] = 1;
                for (int i = 1; i < row; i++) {
                    nextPascalRow[i] = thisPascalRow[i - 1] + thisPascalRow[i];
                }

                // Format it as a line of text in Sierpinski's Triangle
                int leftPad = Sierpinski.this.size - this.row;
                int length = leftPad + 2 * this.row;
                Arrays.fill(this.buf, 0, length, ' ');
                for (int i = 0; i < this.row; i++) {
                    if ((nextPascalRow[i] & 1) == 0) {
                        this.buf[leftPad + 2 * i] = Sierpinski.this.fill;
                    }
                }

                return new String(this.buf, 0, length);
            } finally {
                // Prepare for next call.  Swap to avoid reallocating arrays.
                this.row++;
                int[] swap = this.thisPascalRow;
                this.thisPascalRow = nextPascalRow;
                this.nextPascalRow = swap;
            }
        }
    }

    private final int size;
    private final char fill;

    public Sierpinski(int size, char fill) {
        this.size = size;
        this.fill = fill;
    }

    @Override
    public Iterator<String> iterator() {
        return new RowIterator();
    }

    public static void main(String[] args) {
        for (String line : new Sierpinski(50, 'x')) {
            System.out.println(line);
        }
    }
}

Context

StackExchange Code Review Q#110386, answer score: 3

Revisions (0)

No revisions yet.