Wolfram's Rule 30 is proper interesting, isn't it?
Here is a Java implementation:
Wolfram.java
package org.adrianwalker.cellularautomation; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.File; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import javax.imageio.ImageIO; public final class Wolfram { private static final int MAX_TIME = 500; private static final int MAX_SPACE = MAX_TIME * 2; private static final int WHITE = Color.WHITE.getRGB(); private static final int BLACK = Color.BLACK.getRGB(); private static final String FORMAT = "png"; private static final String OUTPUT = "/var/tmp/output.png"; // cell to RGB lookup private static final Map<Integer, Integer> CELL_RGB = new HashMap<>(); static { CELL_RGB.put(0, WHITE); CELL_RGB.put(1, BLACK); } // RGB to cell lookup private static final Map<Integer, Integer> RGB_CELL = new HashMap<>(); static { RGB_CELL.put(WHITE, 0); RGB_CELL.put(BLACK, 1); } // http://en.wikipedia.org/wiki/Rule_30 // // current pattern 111 110 101 100 011 010 001 000 // new state for center cell 0 0 0 1 1 1 1 0 private static final Map<Integer, Integer> RULE_30 = new HashMap<>(); static { RULE_30.put(Arrays.hashCode(new int[]{1, 1, 1}), 0); RULE_30.put(Arrays.hashCode(new int[]{1, 1, 0}), 0); RULE_30.put(Arrays.hashCode(new int[]{1, 0, 1}), 0); RULE_30.put(Arrays.hashCode(new int[]{1, 0, 0}), 1); RULE_30.put(Arrays.hashCode(new int[]{0, 1, 1}), 1); RULE_30.put(Arrays.hashCode(new int[]{0, 1, 0}), 1); RULE_30.put(Arrays.hashCode(new int[]{0, 0, 1}), 1); RULE_30.put(Arrays.hashCode(new int[]{0, 0, 0}), 0); } public static void main(final String[] args) throws Throwable { BufferedImage image = new BufferedImage(MAX_SPACE, MAX_TIME, BufferedImage.TYPE_INT_RGB); init(image); execute(image, RULE_30); ImageIO.write(image, FORMAT, new File(OUTPUT)); } private static void init(final BufferedImage image) { int time; int space; for (time = 0; time < MAX_TIME; time++) { for (space = 0; space < MAX_SPACE; space++) { image.setRGB(space, time, WHITE); } } time = 0; space = MAX_SPACE / 2; image.setRGB(space, time, BLACK); } private static void execute(final BufferedImage image, final Map<Integer, Integer> rule) { for (int time = 1; time < MAX_TIME; time++) { for (int space = 1; space < MAX_SPACE - 1; space++) { int[] pattern = { RGB_CELL.get(image.getRGB(space - 1, time - 1)), RGB_CELL.get(image.getRGB(space, time - 1)), RGB_CELL.get(image.getRGB(space + 1, time - 1)) }; int cell = rule.get(Arrays.hashCode(pattern)); image.setRGB(space, time, CELL_RGB.get(cell)); } } } }