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 < no_of_row; i++) {
for (int j = 0; j <= i; j++) {
if (j == 0 || j == i) {
tri[i][j] = 1;
}
if (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 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 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 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 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 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 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
2 Answers 2
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<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);
}
}
}
Making main
more high level
main
should be very high level. It should look like a description of the task, like:
int[][] pascalTriangle = buildPascalTriangle(50);
printSierspinkyFromPascalTriangle(pascalTriangle);
You may then separate your code currently in main
into the two methods, and you'll have code that reads as English!
Constants
50
should be a constant named TRIANGLE_SIZE
, using names for important settings also improves readibility.