Task: Abelian sandpile model
C: #include<stdlib.h>
#include<string.h>
#include<stdio.h>

int main(int argc, char** argv)
{
	int i,j,sandPileEdge, centerPileHeight, processAgain = 1,top,down,left,right;	
	int** sandPile;
	char* fileName;
	static unsigned char colour[3];

	if(argc!=3){
		printf("Usage: %s <Sand pile side> <Center pile height>",argv[0]);
		return 0;
	}

	sandPileEdge = atoi(argv[1]);
	centerPileHeight = atoi(argv[2]);

	if(sandPileEdge<=0 || centerPileHeight<=0){
		printf("Sand pile and center pile dimensions must be positive integers.");
		return 0;
	}

	sandPile = (int**)malloc(sandPileEdge * sizeof(int*));

	for(i=0;i<sandPileEdge;i++){
		sandPile[i] = (int*)calloc(sandPileEdge,sizeof(int));
	}

	sandPile[sandPileEdge/2][sandPileEdge/2] = centerPileHeight;

	printf("Initial sand pile :\n\n");

	for(i=0;i<sandPileEdge;i++){
		for(j=0;j<sandPileEdge;j++){
			printf("%3d",sandPile[i][j]);
		}
		printf("\n");
	}

	while(processAgain == 1){

		processAgain = 0;
		top = 0;
		down = 0;
		left = 0;
		right = 0;

		for(i=0;i<sandPileEdge;i++){
			for(j=0;j<sandPileEdge;j++){
				if(sandPile[i][j]>=4){				
					if(i-1>=0){
						top = 1;
						sandPile[i-1][j]+=1;
						if(sandPile[i-1][j]>=4)
							processAgain = 1;
					}
					if(i+1<sandPileEdge){
						down = 1;
						sandPile[i+1][j]+=1;
						if(sandPile[i+1][j]>=4)
							processAgain = 1;
					}
					if(j-1>=0){
						left = 1;
						sandPile[i][j-1]+=1;
						if(sandPile[i][j-1]>=4)
							processAgain = 1;
					}
					if(j+1<sandPileEdge){
						right = 1;
						sandPile[i][j+1]+=1;
						if(sandPile[i][j+1]>=4)
							processAgain = 1;
					}
				sandPile[i][j] -= (top + down + left + right);
				if(sandPile[i][j]>=4)
					processAgain = 1;
				}
			}
		}
	}

	printf("Final sand pile : \n\n");

	for(i=0;i<sandPileEdge;i++){
		for(j=0;j<sandPileEdge;j++){
			printf("%3d",sandPile[i][j]);
		}
		printf("\n");
	}

	fileName = (char*)malloc((strlen(argv[1]) + strlen(argv[2]) + 23)*sizeof(char));

	strcpy(fileName,"Final_Sand_Pile_");
	strcat(fileName,argv[1]);
	strcat(fileName,"_");
	strcat(fileName,argv[2]);
	strcat(fileName,".ppm");
	
	FILE *fp = fopen(fileName,"wb");

	fprintf(fp,"P6\n%d %d\n255\n",sandPileEdge,sandPileEdge);

	for(i=0;i<sandPileEdge;i++){
		for(j=0;j<sandPileEdge;j++){
			colour[0] = (sandPile[i][j] + i)%256;
			colour[1] = (sandPile[i][j] + j)%256;
			colour[2] = (sandPile[i][j] + i*j)%256;
			fwrite(colour,1,3,fp);
		}
	}
	
	fclose(fp);

	printf("\nImage file written to %s\n",fileName);

	return 0;
}

Java: import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class AbelianSandpile {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Frame frame = new Frame();
                frame.setVisible(true);
            }
        });
    }

    private static class Frame extends JFrame {
        private Frame() {
            super("Abelian Sandpile Model");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            Container contentPane = getContentPane();
            JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
            JButton start = new JButton("Restart Simulation");
            start.addActionListener(e -> restartSimulation());
            JButton stop = new JButton("Stop Simulation");
            stop.addActionListener(e -> stopSimulation());
            controlPanel.add(start);
            controlPanel.add(stop);
            contentPane.add(controlPanel, BorderLayout.NORTH);
            contentPane.add(canvas = new Canvas(), BorderLayout.CENTER);
            timer = new Timer(100, e -> canvas.runAndDraw());
            timer.start();
            pack();
        }

        private void restartSimulation() {
            timer.stop();
            canvas.initGrid();
            timer.start();
        }

        private void stopSimulation() {
            timer.stop();
        }

        private Timer timer;
        private Canvas canvas;
    }

    private static class Canvas extends JComponent {
        private Canvas() {
            setBorder(BorderFactory.createEtchedBorder());
            setPreferredSize(new Dimension(600, 600));
        }

        public void paintComponent(Graphics g) {
            int width = getWidth();
            int height = getHeight();
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, width, height);
            int cellWidth = width/GRID_LENGTH;
            int cellHeight = height/GRID_LENGTH;
            for (int i = 0; i < GRID_LENGTH; ++i) {
                for (int j = 0; j < GRID_LENGTH; ++j) {
                    if (grid[i][j] > 0) {
                        g.setColor(COLORS[grid[i][j]]);
                        g.fillRect(i * cellWidth, j * cellHeight, cellWidth, cellHeight);
                    }
                }
            }
        }

        private void initGrid() {
            for (int i = 0; i < GRID_LENGTH; ++i) {
                for (int j = 0; j < GRID_LENGTH; ++j) {
                    grid[i][j] = 0;
                }
            }
        }

        private void runAndDraw() {
            for (int i = 0; i < 100; ++i)
                addSand(GRID_LENGTH/2, GRID_LENGTH/2);
            repaint();
        }

        private void addSand(int i, int j) {
            int grains = grid[i][j];
            if (grains < 3) {
                grid[i][j]++;
            }
            else {
                grid[i][j] = grains - 3;
                if (i > 0)
                    addSand(i - 1, j);
                if (i < GRID_LENGTH - 1)
                    addSand(i + 1, j);
                if (j > 0)
                    addSand(i, j - 1);
                if (j < GRID_LENGTH - 1)
                    addSand(i, j + 1);
            }
        }

        private int[][] grid = new int[GRID_LENGTH][GRID_LENGTH];
    }

    private static final Color[] COLORS = {
        Color.WHITE,
        new Color(0x00, 0xbf, 0xff),
        new Color(0xff, 0xd7, 0x00),
        new Color(0xb0, 0x30, 0x60)
    };
    private static final int GRID_LENGTH = 300;
}