I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Sierpinski curve

Sierpinski curve is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Produce a graphical or ASCII-art representation of a Sierpinski curve of at least order 3.

## AutoHotkey

Translation of: Go

Requires Gdip Library

`SierpinskiW	:= 500SierpinskiH	:= 500level 		:= 5cx		:= SierpinskiW/2cy		:= SierpinskiHh		:= cx / (2**(level+1))Arr := []squareCurve(level)xmin := xmax := ymin := ymax := 0for i, point in Arr{	xmin := A_Index = 1 ? point.x : xmin < point.x ? xmin : point.x	xmax := point.x > xmax ? point.x : xmax	ymin := A_Index = 1 ? point.y : ymin < point.y ? ymin : point.y	ymax := point.y > ymax ? point.y : ymax}SierpinskiX := A_ScreenWidth/2 - (xmax-xmin)/2	, SierpinskiY := A_ScreenHeight/2 - (ymax-ymin)/2for i, point in Arr	points .= point.x - xmin + SierpinskiX "," point.y - ymin + SierpinskiY "|"points := Trim(points, "|")gdip1()Gdip_DrawLines(G, pPen, Points)UpdateLayeredWindow(hwnd1, hdc, 0, 0, Width, Height)return ; ---------------------------------------------------------------lineTo(newX, newY) {	global	Arr[Arr.count()+1, "x"] := newX-SierpinskiW/2+h	Arr[Arr.count()  , "y"] := SierpinskiH-newY+2*h	cx := newX	cy := newY}; ---------------------------------------------------------------sierN(level) {	global	if (level = 1) {		lineTo(cx+h, cy-h)	; lineNE()		lineTo(cx, cy-2*h)	; lineN()		lineTo(cx-h, cy-h)	; lineNW()	}	else{		sierN(level - 1)		lineTo(cx+h, cy-h)	; lineNE()		sierE(level - 1)		lineTo(cx, cy-2*h)	; lineN()		sierW(level - 1)		lineTo(cx-h, cy-h)	; lineNW()		sierN(level - 1)	}}; ---------------------------------------------------------------sierE(level) {	global	if (level = 1) {		lineTo(cx+h, cy+h)	; lineSE()		lineTo(cx+2*h, cy)	; lineE()		lineTo(cx+h, cy-h)	; lineNE()	}	else {		sierE(level - 1)		lineTo(cx+h, cy+h)	; lineSE()		sierS(level - 1)		lineTo(cx+2*h, cy)	; lineE()		sierN(level - 1)		lineTo(cx+h, cy-h)	; lineNE()		sierE(level - 1)	}}; ---------------------------------------------------------------sierS(level) {	global	if (level = 1) {		lineTo(cx-h, cy+h)	; lineSW()		lineTo(cx, cy+2*h)	; lineS()		lineTo(cx+h, cy+h)	; lineSE()	}	else {		sierS(level - 1)		lineTo(cx-h, cy+h)	; lineSW()		sierW(level - 1)		lineTo(cx, cy+2*h)	; lineS()		sierE(level - 1)		lineTo(cx+h, cy+h)	; lineSE()		sierS(level - 1)	}}; ---------------------------------------------------------------sierW(level) {	global	if (level = 1) {		lineTo(cx-h, cy-h)	; lineNW()		lineTo(cx-2*h, cy)	; lineW()		lineTo(cx-h, cy+h)	; lineSW()	}	else {		sierW(level - 1)		lineTo(cx-h, cy-h)	; lineNW()		sierN(level - 1)		lineTo(cx-2*h, cy)	; lineW()		sierS(level - 1)		lineTo(cx-h, cy+h)	; lineSW()		sierW(level - 1)	}}; ---------------------------------------------------------------squareCurve(level) {	global	sierN(level)	lineTo(cx+h, cy-h)	; lineNE()	sierE(level)	lineTo(cx+h, cy+h)	; lineSE()	sierS(level)	lineTo(cx-h, cy+h)	; lineSW()	sierW(level)	lineTo(cx-h, cy-h)	; lineNW()	lineTo(cx+h, cy-h)	; lineNE()} ; ---------------------------------------------------------------gdip1(){	global	If !pToken := Gdip_Startup()	{		MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system		ExitApp	}	OnExit, Exit	Width := A_ScreenWidth, Height := A_ScreenHeight	Gui, 1: -Caption +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop	Gui, 1: Show, NA	hwnd1 := WinExist()	hbm := CreateDIBSection(Width, Height)	hdc := CreateCompatibleDC()	obm := SelectObject(hdc, hbm)	G := Gdip_GraphicsFromHDC(hdc)	Gdip_SetSmoothingMode(G, 4)	pPen := Gdip_CreatePen(0xFFFF0000, 2)}; ---------------------------------------------------------------gdip2(){	global	Gdip_DeleteBrush(pBrush)	Gdip_DeletePen(pPen)	SelectObject(hdc, obm)	DeleteObject(hbm)	DeleteDC(hdc)	Gdip_DeleteGraphics(G)}; ---------------------------------------------------------------Exit:gdip2()Gdip_Shutdown(pToken)ExitAppReturn `

## C++

Output is a file in SVG format. The curve is generated using the Lindenmayer system method.

`// See https://en.wikipedia.org/wiki/Sierpi%C5%84ski_curve#Representation_as_Lindenmayer_system#include <cmath>#include <fstream>#include <iostream>#include <string> class sierpinski_curve {public:    void write(std::ostream& out, int size, int length, int order);private:    static std::string rewrite(const std::string& s);    void line(std::ostream& out);    void execute(std::ostream& out, const std::string& s);    double x_;    double y_;    int angle_;    int length_;}; void sierpinski_curve::write(std::ostream& out, int size, int length, int order) {    length_ = length;    x_ = length/std::sqrt(2.0);    y_ = 2 * x_;    angle_ = 45;    out << "<svg xmlns='http://www.w3.org/2000/svg' width='"        << size << "' height='" << size << "'>\n";    out << "<rect width='100%' height='100%' fill='white'/>\n";    out << "<path stroke-width='1' stroke='black' fill='none' d='";    std::string s = "F--XF--F--XF";    for (int i = 0; i < order; ++i)        s = rewrite(s);    execute(out, s);    out << "'/>\n</svg>\n";} std::string sierpinski_curve::rewrite(const std::string& s) {    std::string t;    for (char c : s) {        if (c == 'X')            t += "XF+G+XF--F--XF+G+X";        else            t += c;    }    return t;} void sierpinski_curve::line(std::ostream& out) {    double theta = (3.14159265359 * angle_)/180.0;    x_ += length_ * std::cos(theta);    y_ -= length_ * std::sin(theta);    out << " L" << x_ << ',' << y_;} void sierpinski_curve::execute(std::ostream& out, const std::string& s) {    out << 'M' << x_ << ',' << y_;    for (char c : s) {        switch (c) {        case 'F':        case 'G':            line(out);            break;        case '+':            angle_ = (angle_ + 45) % 360;            break;        case '-':            angle_ = (angle_ - 45) % 360;            break;        }    }} int main() {    std::ofstream out("sierpinski_curve.svg");    if (!out) {        std::cerr << "Cannot open output file\n";        return 1;    }    sierpinski_curve s;    s.write(out, 545, 7, 5);    return 0;}`
Output:

See: sierpinski_curve.svg (offsite SVG image)

## Factor

Works with: Factor version 0.99 2020-08-14
`USING: accessors kernel L-system sequences ui ; : curve ( L-system -- L-system )    L-parser-dialect    { "G" [ dup length>> draw-forward ] } suffix >>commands    [ 45 >>angle ] >>turtle-values    "F--XF--F--XF" >>axiom    {        { "X" "XF+G+XF--F--XF+G+X" }    } >>rules ; [ <L-system> curve "Sierpinski curve" open-window ] with-ui`

When using the L-system visualizer, the following controls apply:

Camera controls
Button Command
a zoom in
z zoom out
left arrow turn left
right arrow turn right
up arrow pitch down
down arrow pitch up
q roll left
w roll right
Other controls
Button Command
x iterate L-system

## Go

Library: Go Graphics
Translation of: Phix

A partial translation anyway which produces a static image of a SC of level 5, yellow on blue, which can be viewed with a utility such as EOG.

`package main import (    "github.com/fogleman/gg"    "math") var (    width  = 770.0    height = 770.0    dc     = gg.NewContext(int(width), int(height))) var cx, cy, h float64 func lineTo(newX, newY float64) {    dc.LineTo(newX-width/2+h, height-newY+2*h)    cx, cy = newX, newY} func lineN() { lineTo(cx, cy-2*h) }func lineS() { lineTo(cx, cy+2*h) }func lineE() { lineTo(cx+2*h, cy) }func lineW() { lineTo(cx-2*h, cy) } func lineNW() { lineTo(cx-h, cy-h) }func lineNE() { lineTo(cx+h, cy-h) }func lineSE() { lineTo(cx+h, cy+h) }func lineSW() { lineTo(cx-h, cy+h) } func sierN(level int) {    if level == 1 {        lineNE()        lineN()        lineNW()    } else {        sierN(level - 1)        lineNE()        sierE(level - 1)        lineN()        sierW(level - 1)        lineNW()        sierN(level - 1)    }} func sierE(level int) {    if level == 1 {        lineSE()        lineE()        lineNE()    } else {        sierE(level - 1)        lineSE()        sierS(level - 1)        lineE()        sierN(level - 1)        lineNE()        sierE(level - 1)    }} func sierS(level int) {    if level == 1 {        lineSW()        lineS()        lineSE()    } else {        sierS(level - 1)        lineSW()        sierW(level - 1)        lineS()        sierE(level - 1)        lineSE()        sierS(level - 1)    }} func sierW(level int) {    if level == 1 {        lineNW()        lineW()        lineSW()    } else {        sierW(level - 1)        lineNW()        sierN(level - 1)        lineW()        sierS(level - 1)        lineSW()        sierW(level - 1)    }} func squareCurve(level int) {    sierN(level)    lineNE()    sierE(level)    lineSE()    sierS(level)    lineSW()    sierW(level)    lineNW()    lineNE() // needed to close the square in the top left hand corner} func main() {    dc.SetRGB(0, 0, 1) // blue background    dc.Clear()    level := 5    cx, cy = width/2, height    h = cx / math.Pow(2, float64(level+1))    squareCurve(level)    dc.SetRGB255(255, 255, 0) // yellow curve    dc.SetLineWidth(2)    dc.Stroke()    dc.SavePNG("sierpinski_curve.png")}`

## Java

Translation of: C++
`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://www.w3.org/2000/svg' width='%d' height='%d'>\n", size, size);        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;}`
Output:

See: sierpinski_curve.svg (offsite SVG image)

## Julia

### Turtle procedural (lineto) version

Modified from Craft of Coding blog, Processing version

`using Luxor function sierpinski_curve(x0, y0, h, level)    x1, y1 = x0, y0    lineto(x, y) = begin line(Point(x1, y1), Point(x, y), :stroke); x1, y1 = x, y end    lineN() = lineto(x1,y1-2*h)    lineS() = lineto(x1,y1+2*h)    lineE() = lineto(x1+2*h,y1)    lineW() = lineto(x1-2*h,y1)    lineNW() = lineto(x1-h,y1-h)    lineNE() = lineto(x1+h,y1-h)    lineSE() = lineto(x1+h,y1+h)    lineSW() = lineto(x1-h,y1+h)    function drawN(i)        if i == 1            lineNE(); lineN(); lineNW()        else            drawN(i-1); lineNE(); drawE(i-1); lineN(); drawW(i-1); lineNW(); drawN(i-1)        end    end    function drawE(i)        if i == 1            lineSE(); lineE(); lineNE()        else            drawE(i-1); lineSE(); drawS(i-1); lineE(); drawN(i-1); lineNE(); drawE(i-1)        end    end    function drawS(i)        if i == 1            lineSW(); lineS(); lineSE()        else            drawS(i-1); lineSW(); drawW(i-1); lineS(); drawE(i-1); lineSE(); drawS(i-1)        end    end    function drawW(i)        if i == 1            lineNW(); lineW(); lineSW()        else            drawW(i-1); lineNW(); drawN(i-1); lineW(); drawS(i-1); lineSW(); drawW(i-1)        end    end    function draw_curve(levl)        drawN(levl); lineNE(); drawE(levl); lineSE()        drawS(levl); lineSW(); drawW(levl); lineNW()    end    draw_curve(level)end Drawing(800, 800)sierpinski_curve(10, 790, 3, 6)finish()preview() `

### LSystem version

`using Lindenmayer # https://github.com/cormullion/Lindenmayer.jl sierpcurve = LSystem(Dict("X" => "XF+G+XF--F--XF+G+X"), "F--XF--F--XF") drawLSystem(sierpcurve,    forward = 10,    turn = 45,    startingpen= (0.2, 0.8, 0.8),    startingx = -380,    startingy = 380,    startingorientation = π/4,    iterations = 5,    filename = "sierpinski_curve.png",    showpreview = true) `

## Perl

`use strict;use warnings;use SVG;use List::Util qw(max min); use constant pi => 2 * atan2(1, 0); my \$rule = 'XF+F+XF--F--XF+F+X';my \$S = 'F--F--XF--F--XF';\$S =~ s/X/\$rule/g for 1..5; my (@X, @Y);my (\$x, \$y) = (0, 0);my \$theta   = pi/4;my \$r       = 6; for (split //, \$S) {    if (/F/) {        push @X, sprintf "%.0f", \$x;        push @Y, sprintf "%.0f", \$y;        \$x += \$r * cos(\$theta);        \$y += \$r * sin(\$theta);    }    elsif (/\+/) { \$theta += pi/4; }    elsif (/\-/) { \$theta -= pi/4; }} my (\$xrng, \$yrng) = ( max(@X) - min(@X),  max(@Y) - min(@Y));my (\$xt,   \$yt)   = (-min(@X) + 10,      -min(@Y) + 10); my \$svg = SVG->new(width=>\$xrng+20, height=>\$yrng+20);my \$points = \$svg->get_path(x=>\@X, y=>\@Y, -type=>'polyline');\$svg->rect(width=>"100%", height=>"100%", style=>{'fill'=>'black'});\$svg->polyline(%\$points, style=>{'stroke'=>'orange', 'stroke-width'=>1}, transform=>"translate(\$xt,\$yt)"); open my \$fh, '>', 'sierpinski-curve.svg';print \$fh  \$svg->xmlify(-namespace=>'svg');close \$fh;`

See: sierpinski-curve.svg (offsite SVG image)

## Phix

Library: Phix/pGUI
`-- demo\rosetta\Sierpinski_curve.exw----  Draws curves lo to hi (simultaneously), initially {1,1}, max {8,8}--  Press +/- to change hi, shift +/- to change lo.--  ("=_" are also mapped to "+-", for the non-numpad +/-)--include pGUI.e Ihandle dlg, canvascdCanvas cddbuffer, cdcanvas integer width, height,        lo = 1, hi = 1atom cx, cy, h procedure lineTo(atom newX, newY)    cdCanvasVertex(cddbuffer, newX-width/2+h, height-newY+2*h)    cx = newX    cy = newYend procedure procedure lineN() lineTo(cx,cy-2*h) end procedureprocedure lineS() lineTo(cx,cy+2*h) end procedureprocedure lineE() lineTo(cx+2*h,cy) end procedureprocedure lineW() lineTo(cx-2*h,cy) end procedure procedure lineNW() lineTo(cx-h,cy-h) end procedureprocedure lineNE() lineTo(cx+h,cy-h) end procedureprocedure lineSE() lineTo(cx+h,cy+h) end procedureprocedure lineSW() lineTo(cx-h,cy+h) end procedure procedure sierN(integer level)   if level=1 then      lineNE()  lineN()      lineNW()   else      sierN(level-1)  lineNE()      sierE(level-1)  lineN()      sierW(level-1)  lineNW()      sierN(level-1)    end ifend procedure procedure sierE(integer level)   if level=1 then      lineSE()  lineE()      lineNE()    else      sierE(level-1)  lineSE()      sierS(level-1)  lineE()      sierN(level-1)  lineNE()      sierE(level-1)    end ifend procedure procedure sierS(integer level)   if level=1 then      lineSW()  lineS()      lineSE()    else      sierS(level-1)  lineSW()      sierW(level-1)  lineS()      sierE(level-1)  lineSE()      sierS(level-1)    end ifend procedure procedure sierW(integer level)   if level=1 then      lineNW()  lineW()      lineSW()    else      sierW(level-1)  lineNW()      sierN(level-1)  lineW()      sierS(level-1)  lineSW()      sierW(level-1)    end ifend procedure procedure sierpinskiCurve(integer level)   sierN(level)     lineNE()   sierE(level)     lineSE()   sierS(level)     lineSW()   sierW(level)     lineNW()end procedure function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)    {width, height} = IupGetIntInt(canvas, "DRAWSIZE")    cdCanvasActivate(cddbuffer)    for level=lo to hi do        cx = width/2        cy = height        h = cx/power(2,level+1)        cdCanvasBegin(cddbuffer, CD_CLOSED_LINES)        sierpinskiCurve(level)        cdCanvasEnd(cddbuffer)    end for    cdCanvasFlush(cddbuffer)    return IUP_DEFAULTend function function map_cb(Ihandle ih)    cdcanvas = cdCreateCanvas(CD_IUP, ih)    cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)    cdCanvasSetBackground(cddbuffer, CD_WHITE)    cdCanvasSetForeground(cddbuffer, CD_BLUE)    return IUP_DEFAULTend function function key_cb(Ihandle /*ih*/, atom c)    if c=K_ESC then return IUP_CLOSE end if    if find(c,"+=-_") then        bool bShift = IupGetInt(NULL,"SHIFTKEY")        if c='+' or c='=' then            if bShift then                lo = min(lo+1,hi)            else                hi = min(8,hi+1)            end if        elsif c='-' or c='_' then            if bShift then                lo = max(1,lo-1)            else                hi = max(lo,hi-1)            end if        end if        IupSetStrAttribute(dlg, "TITLE", "Sierpinski curve (%d..%d)",{lo,hi})        cdCanvasClear(cddbuffer)        IupUpdate(canvas)    end if    return IUP_CONTINUEend function procedure main()    IupOpen()     canvas = IupCanvas(NULL)    IupSetAttribute(canvas, "RASTERSIZE", "770x770")    IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))    IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))     dlg = IupDialog(canvas)    IupSetAttribute(dlg, "TITLE", "Sierpinski curve (1..1)")    IupSetCallback(dlg, "K_ANY", Icallback("key_cb"))     IupMap(dlg)    IupShowXY(dlg,IUP_CENTER,IUP_CENTER)    IupMainLoop()    IupClose()end procedure main()`

## Raku

(formerly Perl 6)

Works with: Rakudo version 2020.02
`use SVG; role Lindenmayer {    has %.rules;    method succ {        self.comb.map( { %!rules{\$^c} // \$c } ).join but Lindenmayer(%!rules)    }} my \$sierpinski = 'F--XF--F--XF' but Lindenmayer( { X => 'XF+G+XF--F--XF+G+X' } ); \$sierpinski++ xx 5; my \$dim = 640;my \$scale = 8;my \$dir = pi/4;my @points = (316, -108); for \$sierpinski.comb {    state (\$x, \$y) = @points[0,1];    state \$d = 0;    when 'F'|'G' { @points.append: (\$x += \$scale * \$d.cos).round(1), (\$y += \$scale * \$d.sin).round(1) }    when '+' { \$d -= \$dir }    when '-' { \$d += \$dir }    default { }} my \$out = './sierpinski-curve-perl6.svg'.IO; \$out.spurt: SVG.serialize(    svg => [        :width(\$dim), :height(\$dim),        :rect[:width<100%>, :height<100%>, :fill<black>],        :polyline[          :points(@points.join: ','), :fill<black>,          :transform("rotate(45, 320, 320)"), :style<stroke:#F7DF1E>,        ],    ],);`

See: Sierpinski-curve-perl6.svg (offsite SVG image)

## Rust

Program output is a file in SVG format.

`// [dependencies]// svg = "0.8.0" use svg::node::element::path::Data;use svg::node::element::Path; struct SierpinskiCurve {    current_x: f64,    current_y: f64,    current_angle: i32,    line_length: f64,} impl SierpinskiCurve {    fn new(x: f64, y: f64, length: f64, angle: i32) -> SierpinskiCurve {        SierpinskiCurve {            current_x: x,            current_y: y,            current_angle: angle,            line_length: length,        }    }    fn rewrite(order: usize) -> String {        let mut str = String::from("F--XF--F--XF");        for _ in 0..order {            let mut tmp = String::new();            for ch in str.chars() {                match ch {                    'X' => tmp.push_str("XF+G+XF--F--XF+G+X"),                    _ => tmp.push(ch),                }            }            str = tmp;        }        str    }    fn execute(&mut self, order: usize) -> Path {        let mut data = Data::new().move_to((self.current_x, self.current_y));        for ch in SierpinskiCurve::rewrite(order).chars() {            match ch {                'F' => data = self.draw_line(data),                'G' => data = self.draw_line(data),                '+' => self.turn(45),                '-' => self.turn(-45),                _ => {}            }        }        Path::new()            .set("fill", "none")            .set("stroke", "black")            .set("stroke-width", "1")            .set("d", data)    }    fn draw_line(&mut self, data: Data) -> Data {        let theta = (self.current_angle as f64).to_radians();        self.current_x += self.line_length * theta.cos();        self.current_y -= self.line_length * theta.sin();        data.line_to((self.current_x, self.current_y))    }    fn turn(&mut self, angle: i32) {        self.current_angle = (self.current_angle + angle) % 360;    }    fn save(file: &str, size: usize, order: usize) -> std::io::Result<()> {        use svg::node::element::Rectangle;        let x = 5.0;        let y = 10.0;        let rect = Rectangle::new()            .set("width", "100%")            .set("height", "100%")            .set("fill", "white");        let mut s = SierpinskiCurve::new(x, y, 7.0, 45);        let document = svg::Document::new()            .set("width", size)            .set("height", size)            .add(rect)            .add(s.execute(order));        svg::save(file, &document)    }} fn main() {    SierpinskiCurve::save("sierpinski_curve.svg", 545, 5).unwrap();}`
Output:

See: sierpinski_curve.svg (offsite SVG image)

## Sidef

Uses the LSystem() class from Hilbert curve.

`var rules = Hash(    x => 'xF+G+xF--F--xF+G+x',) var lsys = LSystem(    width:  550,    height: 550,     xoff: -9,    yoff: -271,     len:   5,    angle: 45,    color: 'dark green',) lsys.execute('F--xF--F--xF', 5, "sierpiński_curve.png", rules)`

Output image: Sierpiński curve

## zkl

Uses Image Magick and the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

`sierpinskiCurve(5) : turtle(_,45,45);	// n=5 --> 11,606 characters fcn sierpinskiCurve(order){   LSystem("F--XF--F--XF",Dictionary("X","XF+G+XF--F--XF+G+X"), order)}fcn LSystem(axiom,rules,order){   // Lindenmayer system    buf1,buf2 := Data(Void,axiom).howza(3), Data().howza(3);  // characters   do(order){      buf1.pump(buf2.clear(),'wrap(c){ rules.find(c,c) });   // change if rule      t:=buf1; buf1=buf2; buf2=t;	// swap buffers   }   buf1} fcn turtle(curve,angle,startAngle){  // angles in degrees   const D=10.0;   dir:=startAngle;   img,color := PPM(800,800), 0x00ff00;  // green on black   x,y := 15, img.h - x;   foreach c in (curve){      switch(c){	 case("F","G"){   // draw forward	    a,b := D.toRectangular(dir.toFloat().toRad());	    img.line(x,y, (x+=a.round()),(y+=b.round()), color) 	 }	 case("+"){ dir=(dir + angle)%360; } // turn left  angle	 case("-"){ dir=(dir - angle)%360; } // turn right angle      }   }   img.writeJPGFile("sierpinskiCurve.zkl.jpg");}`
Output:

Offsite image at Sierpinski curve order 5