Task: Sierpinski curve





Java: import java.io.*;

public class SierpinskiCurve {
    public static void main(final String[] args) {
        try (Writer writer = new BufferedWriter(new FileWriter("sierpinski_curve.svg"))) {
            SierpinskiCurve s = new SierpinskiCurve(writer);
            s.currentAngle = 45;
            s.currentX = 5;
            s.currentY = 10;
            s.lineLength = 7;
            s.begin(545);
            s.execute(rewrite(5));
            s.end();
        } catch (final Exception ex) {
            ex.printStackTrace();
        }
    }

    private SierpinskiCurve(final Writer writer) {
        this.writer = writer;
    }

    private void begin(final int size) throws IOException {
        write("<svg xmlns='http:
        write("<rect width='100%%' height='100%%' fill='white'/>\n");
        write("<path stroke-width='1' stroke='black' fill='none' d='");
    }

    private void end() throws IOException {
        write("'/>\n</svg>\n");
    }

    private void execute(final String s) throws IOException {
        write("M%g,%g\n", currentX, currentY);
        for (int i = 0, n = s.length(); i < n; ++i) {
            switch (s.charAt(i)) {
                case 'F':
                case 'G':
                    line(lineLength);
                    break;
                case '+':
                    turn(ANGLE);
                    break;
                case '-':
                    turn(-ANGLE);
                    break;
            }
        }
    }

    private void line(final double length) throws IOException {
        final double theta = (Math.PI * currentAngle) / 180.0;
        currentX += length * Math.cos(theta);
        currentY -= length * Math.sin(theta);
        write("L%g,%g\n", currentX, currentY);
    }

    private void turn(final int angle) {
        currentAngle = (currentAngle + angle) % 360;
    }

    private void write(final String format, final Object... args) throws IOException {
        writer.write(String.format(format, args));
    }

    private static String rewrite(final int order) {
        String s = AXIOM;
        for (int i = 0; i < order; ++i) {
            final StringBuilder sb = new StringBuilder();
            for (int j = 0, n = s.length(); j < n; ++j) {
                final char ch = s.charAt(j);
                if (ch == 'X')
                    sb.append(PRODUCTION);
                else
                    sb.append(ch);
            }
            s = sb.toString();
        }
        return s;
    }

    private final Writer writer;
    private double lineLength;
    private double currentX;
    private double currentY;
    private int currentAngle;

    private static final String AXIOM = "F--XF--F--XF";
    private static final String PRODUCTION = "XF+G+XF--F--XF+G+X";
    private static final int ANGLE = 45;
}



Python: import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import hsv_to_rgb as hsv

def curve(axiom, rules, angle, depth):
    for _ in range(depth):
        axiom = ''.join(rules[c] if c in rules else c for c in axiom)

    a, x, y = 0, [0], [0]
    for c in axiom:
        match c:
            case '+':
                a += 1
            case '-':
                a -= 1
            case 'F' | 'G':
                x.append(x[-1] + np.cos(a*angle*np.pi/180))
                y.append(y[-1] + np.sin(a*angle*np.pi/180))

    l = len(x)
    
    for i in range(l - 1):
        plt.plot(x[i:i+2], y[i:i+2], color=hsv([i/l, 1, .7]))
    plt.gca().set_aspect(1)
    plt.show()

curve('F--XF--F--XF', {'X': 'XF+G+XF--F--XF+G+X'}, 45, 5)