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 arrowhead curve

You are encouraged to solve this task according to the task description, using any language you may know.

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

## 11l

Translation of: Nim
`V sqrt3_2 = sqrt(3) / 2 F sierpinski_arrowhead_next(points)   V result = [(0.0, 0.0)] * (3 * (points.len - 1) + 1)   V j = 0   L(i) 0 .< points.len - 1      V (x0, y0) = points[i]      V (x1, y1) = points[i + 1]      V dx = x1 - x0      result[j] = (x0, y0)      I y0 == y1         V d = abs(dx * :sqrt3_2 / 2)         result[j + 1] = (x0 + dx / 4, y0 - d)         result[j + 2] = (x1 - dx / 4, y0 - d)      E I y1 < y0         result[j + 1] = (x1, y0)         result[j + 2] = (x1 + dx / 2, (y0 + y1) / 2)      E         result[j + 1] = (x0 - dx / 2, (y0 + y1) / 2)         result[j + 2] = (x0, y1)      j += 3   result[j] = points.last   R result V size = 600V iterations = 8V outfile = File(‘sierpinski_arrowhead.svg’, ‘w’) outfile.write(‘<svg xmlns='http://www.w3.org/2000/svg' width='’size‘' height='’size"'>\n")outfile.write("<rect width='100%' height='100%' fill='white'/>\n")outfile.write(‘<path stroke-width='1' stroke='black' fill='none' d='’)V margin = 20.0V side = size - 2 * marginV x = marginV y = 0.5 * size + 0.5 * sqrt3_2 * sideV points = [(x, y), (x + side, y)]L 0 .< iterations   points = sierpinski_arrowhead_next(points)L(point) points   outfile.write(I L.index == 0 {‘M’} E ‘L’)   outfile.write(point.x‘,’point.y"\n")outfile.write("'/>\n</svg>\n")`
Output:

Output is similar to Nim and C++.

Library: APDF
Even order curves are drawn pointing downwards.
`with Ada.Command_Line;with Ada.Numerics.Generic_Elementary_Functions;with Ada.Text_IO;with PDF_Out; procedure Arrowhead_Curve is    package Real_Math is     new Ada.Numerics.Generic_Elementary_Functions (PDF_Out.Real);   use Real_Math, PDF_Out, Ada.Command_Line, Ada.Text_IO;    subtype Angle_Deg  is Real;   type    Order_Type is range 0 .. 7;    Purple : constant Color_Type := (0.7, 0.0, 0.5);   Length : constant Real       := 340.0;   Corner : constant Point      := (120.0, 480.0);    Order     : Order_Type;   Current   : Point      := (0.0, 0.0);   Direction : Angle_Deg  := Angle_Deg'(0.0);   Doc       : PDF_Out_File;    procedure Curve (Order : Order_Type; Length : Real; Angle : Angle_Deg) is   begin      if Order = 0 then         Current := Current + Length * Point'(Cos (Direction, 360.0),                                              Sin (Direction, 360.0));         Doc.Line (Corner + Current);      else         Curve (Order - 1, Length / 2.0, -Angle);  Direction := Direction + Angle;         Curve (Order - 1, Length / 2.0,  Angle);  Direction := Direction + Angle;         Curve (Order - 1, Length / 2.0, -Angle);      end if;   end Curve; begin   if Argument_Count /= 1 then      Put_Line ("arrowhead_curve <order>");      Put_Line ("  <order>   0 .. 7");      Put_Line ("open sierpinski-arrowhead-curve.pdf to view ouput");      return;   end if;   Order := Order_Type'Value (Argument (1));    Doc.Create ("sierpinski-arrowhead-curve.pdf");   Doc.Page_Setup (A4_Portrait);   Doc.Margins (Margins_Type'(Left   => Cm_2_5,                              others => One_cm));   Doc.Stroking_Color (Purple);   Doc.Line_Width (2.0);   Doc.Move (Corner);   if Order mod 2 = 0 then      Direction := 0.0;      Curve (Order, Length, 60.0);   else      Direction := 60.0;      Curve (Order, Length, -60.0);   end if;   Doc.Finish_Path (Close_Path => False,                    Rendering  => Stroke,                    Rule       => Nonzero_Winding_Number);   Doc.Close;end Arrowhead_Curve;`

## ALGOL W

Produces an Ascii Art Sierpinski Arrowhead Curve using the algorithm from the Wikipedia page.
Note that the Wikipedia algotrithm draws even order curves with the base at the top.

`begin % draw sierpinski arrowhead curves using ascii art %    integer CANVAS_WIDTH;    CANVAS_WIDTH := 200;    begin        % the ascii art canvas and related items %        string(1) array canvas ( 1 :: CANVAS_WIDTH, 1 :: CANVAS_WIDTH );        integer         heading, asciiX, asciiY, width, maxX, maxY, minX, minY;        % draw a line using ascii art - the length is ignored and the heading determines the %        %                               character to use                                     %        % the position is updated                                                            %        procedure drawLine( real value length ) ;            begin                % stores the min and max coordinates %                procedure updateCoordinateRange ;                    begin                        if asciiX > maxX then maxX := asciiX;                        if asciiY > maxY then maxY := asciiY;                        if asciiX < minX then minX := asciiX;                        if asciiY < minY then minY := asciiY                    end updateCoordinateRange ;                if      heading =   0 then begin                    updateCoordinateRange;                    canvas( asciiX, asciiY ) := "_";                    asciiX := asciiX + 1                    end                else if heading =  60 then begin                    updateCoordinateRange;                    canvas( asciiX, asciiY ) := "/";                    asciiY := asciiY - 1;                    asciiX := asciiX + 1                    end                else if heading = 120 then begin                    asciiX := asciiX - 1;                    updateCoordinateRange;                    canvas( asciiX, asciiY ) := "\";                    asciiY := asciiY - 1                    end                else if heading = 180 then begin                    asciiX := asciiX - 1;                    updateCoordinateRange;                    canvas( asciiX, asciiY ) := "_"                    end                else if heading = 240 then begin                    asciiX := asciiX - 1;                    asciiY := asciiY + 1;                    updateCoordinateRange;                    canvas( asciiX, asciiY ) := "/"                    end                else if heading = 300 then begin                    asciiY := asciiY + 1;                    updateCoordinateRange;                    canvas( asciiX, asciiY ) := "\";                    asciiX := asciiX + 1                end if_various_headings            end drawLine ;        % changes the heading by the specified angle ( in degrees ) - angle must be +/- 60 %        procedure turn( integer value angle ) ;            if angle > 0            then heading := ( heading + angle ) rem 360            else begin                 heading := heading + angle;                 if heading < 0 then heading := heading + 360            end tuen ;        % initialises the ascii art canvas %        procedure initArt ;            begin                heading :=   0;                asciiX  :=  CANVAS_WIDTH div 2;                asciiY  := asciiX;                maxX    := asciiX;                maxY    := asciiY;                minX    := asciiX;                minY    := asciiY;                for x := 1 until CANVAS_WIDTH do for y := 1 until CANVAS_WIDTH do canvas( x, y ) := " "            end initArt ;        % shows the used parts of the canvas %        procedure drawArt ;            begin                for y := minY until maxY do begin                    write();                    for x := minX until maxX do writeon( canvas( x, y ) )                end for_y ;                write()            end drawIArt ;        % draws a sierpinski arrowhead curve of the specified order and line length %        procedure sierpinskiArrowheadCurve( integer value order; real value length ) ;            begin                % recursively draws a segment of the sierpinski arrowhead curve %                procedure curve( integer value order; real value length; integer value angle ) ;                if 0 = order then drawline( length )                else begin                    curve( order - 1, length / 2, - angle );                    turn(  angle );                    curve( order - 1, length / 2,   angle );                    turn(  angle );                    curve( order - 1, length / 2, - angle )                end curve ;                if not odd( order ) then begin % order is even, we can just draw the curve. %                    curve( order, length, +60 );                    end                else begin % order is odd %                    turn( +60 );                    curve( order, length, -60 )                end if_not_odd_order__            end sierpinskiArrowheadCurve ;        % draw curves %        i_w := 1; s_w := 0; % set output formatting %        for order := 5 do begin            write( "Sierpinski arrowhead curve of order ", order );            write( "=====================================" );            write();            initArt;            sierpinskiArrowheadCurve( order, 1 );            drawArt        end for_order    endend.`
Output:
```Sierpinski arrowhead curve of order 5
=====================================

_
/ \
\ /
_/ \_
/     \
\_   _/
_  \ /  _
/ \_/ \_/ \
\         /
_/         \_
/  _       _  \
\_/ \     / \_/
_    /     \    _
/ \   \_   _/   / \
\ /  _  \ /  _  \ /
_/ \_/ \_/ \_/ \_/ \_
/                     \
\_                   _/
_  \                 /  _
/ \_/                 \_/ \
\    _               _    /
_/   / \             / \   \_
/  _  \ /             \ /  _  \
\_/ \_/ \_           _/ \_/ \_/
_          \         /          _
/ \        _/         \_        / \
\ /       /  _       _  \       \ /
_/ \_      \_/ \     / \_/      _/ \_
/     \    _    /     \    _    /     \
\_   _/   / \   \_   _/   / \   \_   _/
_  \ /  _  \ /  _  \ /  _  \ /  _  \ /  _
/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \
```

## AutoHotkey

Translation of: Go

Requires Gdip Library

`order	:= 7theta	:= 0 curve := []curve.curveW	:= 1000curve.curveH	:= 1000curve.iy	:= 1curve.cx	:= curve.curveW/2curve.cy	:= curve.curveHcurve.ch	:= curve.cx/2 arrowhead(order, curve, theta, Arr :=[])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}arrowheadX := A_ScreenWidth/2 - (xmax-xmin)/2	, arrowheadY := A_ScreenHeight/2 - (ymax-ymin)/2for i, point in Arr	points .= point.x - xmin + arrowheadX "," point.y - ymin + arrowheadY "|" points := Trim(points, "|")gdip1()Gdip_DrawLines(G, pPen, Points)UpdateLayeredWindow(hwnd1, hdc, 0, 0, Width, Height)return ; ---------------------------------------------------------------arrowhead(order, curve, theta, Arr) {	length := curve.cx	if (order&1 = 0)		curve(order, length, theta, 60, Arr)	else	{		theta := turn(theta, 60)		theta := curve(order, length, theta, -60, Arr)	}	drawLine(length, theta, Arr)}; ---------------------------------------------------------------drawLine(length, theta, Arr) {	global curve	Arr[Arr.count()+1, "x"] := curve.cx-curve.curveW/2+curve.ch	Arr[Arr.count(), "y"] := (curve.curveH-curve.cy)*curve.iy+2*curve.ch	pi := 3.141592653589793	curve.cx := curve.cx + length * Cos(theta*pi/180)	curve.cy := curve.cy + length * Sin(theta*pi/180)}; ---------------------------------------------------------------turn(theta, angle) {	return theta := Mod(theta+angle, 360)}; ---------------------------------------------------------------curve(order, length, theta, angle, Arr) {	if (order = 0)		drawLine(length, theta, Arr)	else	{		theta := curve(order-1, length/2, theta, -angle, Arr)		theta := turn(theta, angle)		theta := curve(order-1, length/2, theta, angle, Arr)		theta := turn(theta, angle)		theta := curve(order-1, length/2, theta, -angle, Arr)	}	return theta}; ---------------------------------------------------------------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

This code is based on the Phix and Go solutions, but produces a file in SVG format.

`// See https://en.wikipedia.org/wiki/Sierpi%C5%84ski_curve#Arrowhead_curve#include <math.h>#include <stdio.h>#include <stdlib.h> // Structure to keep track of current position and orientationtypedef struct cursor_tag {    double x;    double y;    int angle;} cursor_t; void turn(cursor_t* cursor, int angle) {    cursor->angle = (cursor->angle + angle) % 360;} void draw_line(FILE* out, cursor_t* cursor, double length) {    double theta = (M_PI * cursor->angle)/180.0;    cursor->x += length * cos(theta);    cursor->y += length * sin(theta);    fprintf(out, "L%g,%g\n", cursor->x, cursor->y);} void curve(FILE* out, int order, double length, cursor_t* cursor, int angle) {    if (order == 0) {        draw_line(out, cursor, length);    } else {        curve(out, order - 1, length/2, cursor, -angle);        turn(cursor, angle);        curve(out, order - 1, length/2, cursor, angle);        turn(cursor, angle);        curve(out, order - 1, length/2, cursor, -angle);    }} void write_sierpinski_arrowhead(FILE* out, int size, int order) {    const double margin = 20.0;    const double side = size - 2.0 * margin;    cursor_t cursor;    cursor.angle = 0;    cursor.x = margin;    cursor.y = 0.5 * size + 0.25 * sqrt(3) * side;    if ((order & 1) != 0)        turn(&cursor, -60);    fprintf(out, "<svg xmlns='http://www.w3.org/2000/svg' width='%d' height='%d'>\n",            size, size);    fprintf(out, "<rect width='100%%' height='100%%' fill='white'/>\n");    fprintf(out, "<path stroke-width='1' stroke='black' fill='none' d='");    fprintf(out, "M%g,%g\n", cursor.x, cursor.y);    curve(out, order, side, &cursor, 60);    fprintf(out, "'/>\n</svg>\n");} int main(int argc, char** argv) {    const char* filename = "sierpinski_arrowhead.svg";    if (argc == 2)        filename = argv[1];    FILE* out = fopen(filename, "w");    if (!out) {        perror(filename);        return EXIT_FAILURE;    }    write_sierpinski_arrowhead(out, 600, 8);    fclose(out);    return EXIT_SUCCESS;}`
Output:

See: sierpinski_arrowhead.svg (offsite SVG image)

## C++

The output of this program is an SVG file.

`#include <fstream>#include <iostream>#include <vector> constexpr double sqrt3_2 = 0.86602540378444; // sqrt(3)/2 struct point {    double x;    double y;}; std::vector<point> sierpinski_arrowhead_next(const std::vector<point>& points) {    size_t size = points.size();    std::vector<point> output(3*(size - 1) + 1);    double x0, y0, x1, y1;    size_t j = 0;    for (size_t i = 0; i + 1 < size; ++i, j += 3) {        x0 = points[i].x;        y0 = points[i].y;        x1 = points[i + 1].x;        y1 = points[i + 1].y;        double dx = x1 - x0;        output[j] = {x0, y0};        if (y0 == y1) {            double d = dx * sqrt3_2/2;            if (d < 0) d = -d;            output[j + 1] = {x0 + dx/4, y0 - d};            output[j + 2] = {x1 - dx/4, y0 - d};        } else if (y1 < y0) {            output[j + 1] = {x1, y0};            output[j + 2] = {x1 + dx/2, (y0 + y1)/2};        } else {            output[j + 1] = {x0 - dx/2, (y0 + y1)/2};            output[j + 2] = {x0, y1};        }    }    output[j] = {x1, y1};    return output;} void write_sierpinski_arrowhead(std::ostream& out, int size, int iterations) {    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='";    const double margin = 20.0;    const double side = size - 2.0 * margin;    const double x = margin;    const double y = 0.5 * size + 0.5 * sqrt3_2 * side;    std::vector<point> points{{x, y}, {x + side, y}};    for (int i = 0; i < iterations; ++i)        points = sierpinski_arrowhead_next(points);    for (size_t i = 0, n = points.size(); i < n; ++i)        out << (i == 0 ? "M" : "L") << points[i].x << ',' << points[i].y << '\n';    out << "'/>\n</svg>\n";} int main() {    std::ofstream out("sierpinski_arrowhead.svg");    if (!out) {        std::cerr << "Cannot open output file\n";        return EXIT_FAILURE;    }    write_sierpinski_arrowhead(out, 600, 8);    return EXIT_SUCCESS;}`
Output:

See: sierpinski_arrowhead.svg (offsite SVG image)

## Factor

Works with: Factor version 0.99 2020-08-14
`USING: accessors L-system ui ; : arrowhead ( L-system -- L-system )    L-parser-dialect >>commands    [ 60 >>angle ] >>turtle-values    "XF" >>axiom    {        { "X" "YF+XF+Y" }        { "Y" "XF-YF-X" }    } >>rules ; [ <L-system> arrowhead "Arrowhead" 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

## Forth

Works with: gforth version 0.7.3

### ASCII

`( ASCII output with use of ANSI terminal control ) : draw-line ( direction -- )  case  0 of  .\" _"              endof ( horizontal right:          _          )  1 of  .\" \e[B\\"         endof (       down right:     CUD  \          )  2 of  .\" \e[D\e[B/\e[D"  endof (        down left: CUB CUD  /  CUB     )  3 of  .\" \e[D_\e[D"      endof (  horizontal left:     CUB  _  CUB     )  4 of  .\" \e[D\\\e[A\e[D" endof (          up left:     CUB  \  CUU CUB )  5 of  .\" /\e[A"          endof (         up right:          /  CUU     )  endcase                         ( cursor is up-right of the last point  ); : turn+ 1+ 6 mod ;: turn- 1- 6 mod ; defer curve: A-rule ( order direction -- ) turn+  2dup 'B curve  turn-  2dup 'A curve  turn-  'B curve ;: B-rule ( order direction -- ) turn-  2dup 'A curve  turn+  2dup 'B curve  turn+  'A curve ; :noname ( order direction type -- )  2 pick 0 = if drop draw-line drop exit then \ draw line when order is 0  rot 1- rot rot  'A = if A-rule else B-rule then; is curve  : arrowhead ( order -- )  page  s" Sierpinski arrowhead curve of order " type dup . cr  s" =====================================" type cr  0 'A curve; 5 arrowhead`
Output:
```Sierpinski arrowhead curve of order 5
=====================================
_   _   _   _   _   _   _   _   _   _    ok
\_/ \ / \_/ \ / \_/ \ / \_/ \ / \_/ \ / \_/
_/ \_    / \    _/ \_    / \    _/ \_
/     \   \_/   /     \   \_/   /     \
\_   _/      _  \     /  _      \_   _/
\ /       / \_/     \_/ \       \ /
/ \       \_           _/       / \
\_/         \         /         \_/
_   _   _/         \_   _   _
/ \_/ \ /             \ / \_/ \
\_    / \             / \    _/
\   \_/             \_/   /
/  _                   _  \
\_/ \                 / \_/
_/                 \_
/                     \
\_   _   _   _   _   _/
\ / \_/ \ / \_/ \ /
/ \    _/ \_    / \
\_/   /     \   \_/
_  \     /  _
/ \_/     \_/ \
\_           _/
\         /
/  _   _  \
\_/ \ / \_/
_/ \_
/     \
\_   _/
\ /
/ \
\_/
```

### SVG file

`( SVG ouput ) : draw-line ( direction -- ) \ line-length=10 ; sin(60)=0.87 ; cos(60)=0.5  case  0 of s" h 10"      type cr endof  1 of s" l  5  8.7" type cr endof  2 of s" l -5  8.7" type cr endof  3 of s" h -10"     type cr endof  4 of s" l -5 -8.7" type cr endof   5 of s" l  5 -8.7" type cr endof  endcase; : turn+ 1+ 6 mod ;: turn- 1- 6 mod ; defer curve: A-rule ( order direction -- ) turn+  2dup 'B curve  turn-  2dup 'A curve  turn-  'B curve ;: B-rule ( order direction -- ) turn-  2dup 'A curve  turn+  2dup 'B curve  turn+  'A curve ; :noname ( order direction type -- )  2 pick 0 = if drop draw-line drop exit then \ draw line when order is 0  rot 1- rot rot  'A = if A-rule else B-rule then; is curve : raw. ( u -- ) 0 <# #s #> type ; : svg-start  dup 1 swap lshift 10 * ( -- order image-width ) \ image-width is 2 power order  s" sierpinski_arrowhead.svg" w/o create-file throw to outfile-id  s" <svg xmlns='http://www.w3.org/2000/svg' width='" type dup raw.  87 * 100 / ( -- order image-height ) \ image-height; sin(60)=0.87  s" ' height='" type raw. s" '>" type cr  s" <rect width='100%' height='100%' fill='white'/>" type cr  s" <path stroke-width='1' stroke='black' fill='none' d='" type cr  s" M 0 0" type cr;: svg-end  s" '/> </svg>" type cr  outfile-id close-file throw; : arrowhead ( order -- )  outfile-id >r svg-start  0 'A curve  svg-end r> to outfile-id; 5 arrowhead`

## Go

Library: Go Graphics
Translation of: Phix

A partial translation anyway which produces a static image of a SAC of order 6, magenta on black, 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))    iy     = 1.0    theta  = 0) var cx, cy, h float64 func arrowhead(order int, length float64) {    // if order is even, we can just draw the curve    if order&1 == 0 {        curve(order, length, 60)    } else {        turn(60)        curve(order, length, -60)    }    drawLine(length) // needed to make base symmetric} func drawLine(length float64) {    dc.LineTo(cx-width/2+h, (height-cy)*iy+2*h)    rads := gg.Radians(float64(theta))    cx += length * math.Cos(rads)    cy += length * math.Sin(rads)} func turn(angle int) {    theta = (theta + angle) % 360} func curve(order int, length float64, angle int) {    if order == 0 {        drawLine(length)    } else {        curve(order-1, length/2, -angle)        turn(angle)        curve(order-1, length/2, angle)        turn(angle)        curve(order-1, length/2, -angle)    }} func main() {    dc.SetRGB(0, 0, 0) // black background    dc.Clear()    order := 6    if order&1 == 0 {        iy = -1 // apex will point upwards    }    cx, cy = width/2, height    h = cx / 2    arrowhead(order, cx)    dc.SetRGB255(255, 0, 255) // magenta curve    dc.SetLineWidth(2)    dc.Stroke()    dc.SavePNG("sierpinski_arrowhead_curve.png")}`

## jq

Works with: jq

Works with gojq, the Go implementation of jq

This entry uses an L-system and turtle graphics to generate an SVG file, which can be viewed using a web browser, at least if the file type is `.svg`.

See Category_talk:Jq-turtle for the turtle.jq module used here. Please note that the `include` directive may need to be modified depending on the location of the included file, and the command-line options used.

`include "turtle" {search: "."}; # Compute the curve using a Lindenmayer system of rulesdef rules:  {X: "Yf+Xf+Y", Y: "Xf-Yf-X", "": "X"}; def sierpinski(\$count):  rules as \$rules  | def repeat(\$count):      if \$count == 0 then .      else ascii_downcase | gsub("x"; \$rules["X"]) | gsub("y"; \$rules["Y"])      | repeat(\$count-1)      end;  \$rules[""] | repeat(\$count) ; def interpret(\$x):  if   \$x == "+" then turtleRotate(60)  elif \$x == "-" then turtleRotate(-60)  elif \$x == "f" then turtleForward(3)  else .  end; def sierpinski_curve(\$n):  sierpinski(\$n)  | split("")   | reduce .[] as \$action (      turtle([0,-350]) | turtleDown | turtleRotate(60);      interpret(\$action) ) ; # viewBox = <min-x> <min-y> <width> <height># Input: {svg, minx, miny, maxx, maxy}def svg:  "<svg viewBox='\(.minx|floor) \(.miny - 4 |floor) \(.maxx - .minx|ceil) \(6 + .maxy - .miny|ceil)'",  "     preserveAspectRatio='xMinYmin meet'",  "     xmlns='http://www.w3.org/2000/svg' >",  path("none"; "red"; 1),  "</svg>"; sierpinski_curve(8)| svg `

## Julia

`using Lindenmayer # https://github.com/cormullion/Lindenmayer.jl scurve = LSystem(Dict("F" => "G+F+Gt", "G"=>"F-G-F"), "G") drawLSystem(scurve,    forward = 3,    turn = 60,    startingy = -350,    iterations = 8,    startingorientation = π/3,    filename = "sierpinski_arrowhead_curve.png",    showpreview = true) `

## Lambdatalk

` {def sierp {def sierp.r  {lambda {:order :length :angle}   {if {= :order 0}    then M:length    else {sierp.r {- :order 1} {/ :length 2} {- :angle}}         T:angle         {sierp.r {- :order 1} {/ :length 2} :angle}         T:angle         {sierp.r {- :order 1} {/ :length 2} {- :angle}} }}} {lambda {:order :length}  {if {= {% :order 2} 0}   then {sierp.r :order :length 60}   else T60        {sierp.r :order :length -60}}}} the output can be seen in http://lambdaway.free.fr/lambdawalks/?view=sierpinsky `

## Mathematica / Wolfram Language

`ClearAll[DoStep]DoStep[Line[{x_, y_}]] := Module[{diff, perp, pts},  diff = y - x;  perp = Cross[diff] Sqrt[3]/2;  pts = {x, x + diff/4 + perp/2, x + 3 diff/4 + perp/2, y};  {Line[pts[[{2, 1}]]], Line[pts[[{2, 3}]]], Line[pts[[{4, 3}]]]}  ]lns = {Line[{{0.0, 0.0}, {1.0, 0.0}}]};lns = Nest[Catenate[DoStep /@ #] &, lns, 5];Graphics[lns]`

## Nim

Translation of: C++

Output is an SVG file.

`import math const Sqrt3_2 = sqrt(3.0) / 2.0 type Point = tuple[x, y: float]  func sierpinskiArrowheadNext(points: seq[Point]): seq[Point] =  result.setLen(3 * (points.len - 1) + 1)  var j = 0  for i in 0..<points.high:    let (x0, y0) = points[i]    let (x1, y1) = points[i + 1]    let dx = x1 - x0    result[j] = (x0, y0)    if y0 == y1:      let d = abs(dx * Sqrt3_2 / 2)      result[j + 1] = (x0 + dx / 4, y0 - d)      result[j + 2] = (x1 - dx / 4, y0 - d)    elif y1 < y0:      result[j + 1] = (x1, y0)      result[j + 2] = (x1 + dx / 2, (y0 + y1) / 2)    else:      result[j + 1] = (x0 - dx / 2, (y0 + y1) / 2)      result[j + 2] = (x0, y1)    inc j, 3  result[j] = points[^1]  proc writeSierpinskiArrowhead(outfile: File; size, iterations: int) =  outfile.write "<svg xmlns='http://www.w3.org/2000/svg' width='", size, "' height='", size, "'>\n"  outfile.write "<rect width='100%' height='100%' fill='white'/>\n"  outfile.write "<path stroke-width='1' stroke='black' fill='none' d='"  const Margin = 20.0  let side = size.toFloat - 2 * Margin  let x = Margin  let y = 0.5 * size.toFloat + 0.5 * Sqrt3_2 * side  var points = @[(x: x, y: y), (x: x + side, y: y)]  for _ in 1..iterations:    points = sierpinskiArrowheadNext(points)  for i, point in points:    outfile.write if i == 0: 'M' else: 'L', point.x, ',', point.y, '\n'  outfile.write "'/>\n</svg>\n"  let outfile = open("sierpinski_arrowhead.svg", fmWrite)outfile.writeSierpinskiArrowhead(600, 8)outfile.close()`
Output:

See output of C++ program.

## Perl

`use strict;use warnings;use SVG;use List::Util qw(max min);use constant pi => 2 * atan2(1, 0); my %rules = (    X => 'YF+XF+Y',    Y => 'XF-YF-X');my \$S = 'Y';\$S =~ s/([XY])/\$rules{\$1}/eg for 1..7; my (@X, @Y);my (\$x, \$y) = (0, 0);my \$theta   = 0;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/3; }    elsif (/\-/) { \$theta -= pi/3; }} 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-arrowhead-curve.svg';print \$fh  \$svg->xmlify(-namespace=>'svg');close \$fh;`

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

## Phix

Library: Phix/pGUI

You can run this online here, and experiment with [shift] +/- as noted below.

```--
-- ===========================================
--
--  Draws curves lo to hi (simultaneously), initially {6,6}, max {10,10}, min {1,1}
--  Press +/- to change hi, shift +/- to change lo.
--  ("=_" are also mapped to "+-", for the non-numpad +/-)
--
with javascript_semantics
include pGUI.e

Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

integer width, height,
lo = 6, hi = 6
atom cx, cy, h, theta

integer iy = +1

procedure draw_line(atom l)
cdCanvasVertex(cddbuffer, cx-width/2+h, (height-cy)*iy+2*h)
end procedure

procedure turn(integer angle)
theta = mod(theta+angle,360)
end procedure

procedure curve(integer order, atom l, integer angle)
if order=0 then
draw_line(l)
else
curve(order-1, l/2, -angle)
turn(angle)
curve(order-1, l/2,  angle)
turn(angle)
curve(order-1, l/2, -angle)
end if
end procedure

procedure sierpinski_arrowhead_curve(integer order, atom l)
-- If order is even we can just draw the curve.
if and_bits(order,1)=0 then
curve(order, l, +60)
else -- order is odd
turn( +60)
curve(order, l, -60)
end if
draw_line(l)
end procedure

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/)
{width, height} = IupGetIntInt(canvas, "DRAWSIZE")
cdCanvasActivate(cddbuffer)
for order=lo to hi do
cx = width/2
cy = height
h = cx/2
theta = 0
iy = iff(and_bits(order,1)?-1:+1)
cdCanvasBegin(cddbuffer, CD_OPEN_LINES)
cdCanvasEnd(cddbuffer)
end for
cdCanvasFlush(cddbuffer)
return IUP_DEFAULT
end 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_DEFAULT
end 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(10,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 arrowhead curve (%d..%d)",{lo,hi})
cdCanvasClear(cddbuffer)
IupUpdate(canvas)
end if
return IUP_DEFAULT
end 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 arrowhead curve (6..6)")
IupSetCallback(dlg, "K_ANY", Icallback("key_cb"))

IupMap(dlg)
IupShowXY(dlg,IUP_CENTER,IUP_CENTER)
if platform()!=JS then
IupMainLoop()
IupClose()
end if
end procedure

main()
```

## Processing

`final PVector t = new PVector(20, 30, 60); void setup() {  size(450, 400);  noLoop();  background(0, 0, 200);  stroke(-1);  sc(7, 400, -60, t);} PVector sc(int o, float l, final int a, final PVector s) {  if (o > 0) {    sc(--o, l *= .5, -a, s).z += a;    sc(o, l, a, s).z += a;    sc(o, l, -a, s);  } else line(s.x, s.y,     s.x += cos(radians(s.z)) * l,     s.y += sin(radians(s.z)) * l);  return s;}`
The sketch can be run online :
here.

### Processing Python mode

`  t = { 'x': 20, 'y': 30, 'a': 60 } def setup():    size(450, 400)    background(0, 0, 200)    stroke(-1)    sc(7, 400, -60) def sc(o, l, a, s = t, X = 'x', Y = 'y', A = 'a', HALF = .5):    if o:        o -= 1        l *= HALF        sc(o, l, -a)[A] += a        sc(o, l, a)[A] += a        sc(o, l, -a)    else:        x, y = s[X], s[Y]        s[X] += cos(radians(s[A])) * l        s[Y] += sin(radians(s[A])) * l        line(x, y, s[X], s[Y])     return s `

The sketch can be run online :
here.

## Python

` import matplotlib.pyplot as pltimport math  def nextPoint(x, y, angle):    a = math.pi * angle / 180    x2 = (int)(round(x + (1 * math.cos(a))))    y2 = (int)(round(y + (1 * math.sin(a))))    return x2, y2  def expand(axiom, rules, level):    for l in range(0, level):        a2 = ""        for c in axiom:            if c in rules:                a2 += rules[c]            else:                a2 += c        axiom = a2    return axiom  def draw_lsystem(axiom, rules, angle, iterations):    xp = [1]    yp = [1]    direction = 0    for c in expand(axiom, rules, iterations):        if c == "F":            xn, yn = nextPoint(xp[-1], yp[-1], direction)            xp.append(xn)            yp.append(yn)        elif c == "-":            direction = direction - angle            if direction < 0:                direction = 360 + direction        elif c == "+":            direction = (direction + angle) % 360     plt.plot(xp, yp)    plt.show()  if __name__ == '__main__':    # Sierpinski Arrowhead Curve L-System Definition    s_axiom = "XF"    s_rules = {"X": "YF+XF+Y",               "Y": "XF-YF-X"}    s_angle = 60     draw_lsystem(s_axiom, s_rules, s_angle, 7) `

## Prolog

Works with: SWI Prolog
Translation of: C
`main:-    write_sierpinski_arrowhead('sierpinski_arrowhead.svg', 600, 8). write_sierpinski_arrowhead(File, Size, Order):-    open(File, write, Stream),    format(Stream,           "<svg xmlns='http://www.w3.org/2000/svg' width='~d' height='~d'>\n",           [Size, Size]),    write(Stream, "<rect width='100%' height='100%' fill='white'/>\n"),    write(Stream, "<path stroke-width='1' stroke='black' fill='none' d='"),    Margin = 20.0,    Side is Size - 2.0 * Margin,    X = Margin,    Y is 0.5 * Size + 0.25 * sqrt(3) * Side,    Cursor = cursor(X, Y, 0),    (Order mod 2 == 1 -> turn(Cursor, -60, Cursor1) ; Cursor1 = Cursor),    format(Stream, "M~g,~g", [X, Y]),    curve(Stream, Order, Side, Cursor1, _, 60),    write(Stream, "'/>\n</svg>\n"),    close(Stream). turn(cursor(X, Y, A), Angle, cursor(X, Y, A1)):-    A1 is (A + Angle) mod 360. draw_line(Stream, cursor(X, Y, A), Length, cursor(X1, Y1, A)):-    Theta is (pi * A)/180.0,    X1 is X + Length * cos(Theta),    Y1 is Y + Length * sin(Theta),    format(Stream, "L~g,~g", [X1, Y1]). curve(Stream, 0, Length, Cursor, Cursor1, _):-    !,    draw_line(Stream, Cursor, Length, Cursor1).curve(Stream, Order, Length, Cursor, Cursor1, Angle):-    Order1 is Order - 1,    Angle1 is -Angle,    Length2 is Length/2.0,    curve(Stream, Order1, Length2, Cursor, Cursor2, Angle1),    turn(Cursor2, Angle, Cursor3),    curve(Stream, Order1, Length2, Cursor3, Cursor4, Angle),    turn(Cursor4, Angle, Cursor5),    curve(Stream, Order1, Length2, Cursor5, Cursor1, Angle1).`
Output:

See: sierpinski_arrowhead.svg (offsite SVG image)

## Quackery

Using an L-system.

`  [ \$ "turtleduck.qky" loadfile ] now!   [ stack ]                      is switch.arg (   --> [ )   [ switch.arg put ]             is switch     ( x -->   )   [ switch.arg release ]         is otherwise  (   -->   )   [ switch.arg share     != iff ]else[ done      otherwise ]'[ do ]done[ ]    is case       ( x -->   )   [ \$ "" swap witheach       [ nested quackery join ] ] is expand     ( \$ --> \$ )   [ \$ "L" ]                      is L          ( \$ --> \$ )   [ \$ "R" ]                      is R          ( \$ --> \$ )   [ \$ "BLALB" ]                  is A          ( \$ --> \$ )   [ \$ "ARBRA" ]                  is B          ( \$ --> \$ )   \$ "A"   6 times expand   turtle  witheach    [ switch        [ char L case [ -1 6 turn ]          char R case [  1 6 turn ]          otherwise   [  4 1 walk ] ] ]`
Output:

## 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 \$arrow = 'X' but Lindenmayer( { X => 'YF+XF+Y', Y => 'XF-YF-X' } ); \$arrow++ xx 7; my \$w = 800;my \$h = (\$w * 3**.5 / 2).round(1); my \$scale = 6;my @points = (400, 15);my \$dir = pi/3; for \$arrow.comb {    state (\$x, \$y) = @points[0,1];    state \$d = \$dir;    when 'F' { @points.append: (\$x += \$scale * \$d.cos).round(1), (\$y += \$scale * \$d.sin).round(1) }    when '+' { \$d += \$dir }    when '-' { \$d -= \$dir }    default { }} my \$out = './sierpinski-arrowhead-curve-perl6.svg'.IO; \$out.spurt:  SVG.serialize(    svg => [        :width(\$w), :height(\$h),        :rect[:width<100%>, :height<100%>, :fill<black>],        :polyline[ :points(@points.join: ','), :fill<black>, :style<stroke:#FF4EA9> ],    ],);`

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

## REXX

Translation of: Algol W
`/*REXX pgm computes and displays a Sierpinski Arrowhead Curve using the characters: \_/ */parse arg order .                                /*obtain optional argument from the CL.*/if order=='' | order==","  then order=   5       /*Not specified?  Then use the default.*/say '  Sierpinski arrowhead curve of order'   order             /*display the   title.  */say '═════════════════════════════════════════'                 /*   "     "  separator.*/\$= init()                                        /*initialize a bunch of variables.     */if order//2  then do;  call turn +60;  call curve order, len, -60;  end    /*CURVE odd? */             else                      call curve order, len, +60          /*CURVE even.*/        do    row=Ly  to Hy;   a=                 /*show arrowhead graph 1 row at a time.*/          do col=Lx  to Hx;   a= a || @.col.row  /*build a row of   "   " col  " "   "  */          end   /*col*/;  say strip(a, 'T')      /*show  "  "   "   "     row  " "   "  */       end      /*row*/exit 0                                           /*stick a fork in it,  we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/init:  @.=" "; #=0; len=512; x=len; y=x;Hx=x;Hy=y;Lx=x;Ly=y; return '@. # Hx Hy Lx Ly x y'turn:  parse arg angle; #= (#+angle)//360;  if #<0  then #= #+360;  return  /*normalize.*//*──────────────────────────────────────────────────────────────────────────────────────*/curve: procedure expose (\$);  parse arg order,len,angle  /*\$:  list of exposed variables*/       if order==0  then call draw len                   /*Is ORDER zero?  Then draw it.*/                    else do;  call curve order-1, len/2, -angle;      call turn angle                              call curve order-1, len/2, +angle;      call turn angle                              call curve order-1, len/2, -angle                         end       return                                    /*The  CURVE  function is recursive.   *//*──────────────────────────────────────────────────────────────────────────────────────*/draw:  select                                    /*draw part of the curve using a char. */           when #==  0  then do;    @.x.y= '_';      x= x + 1;                        end           when #== 60  then do;    @.x.y= '/';      x= x + 1;        y= y - 1;       end           when #==120  then do;    x= x - 1;        @.x.y= '\';      y= y - 1;       end           when #==180  then do;    x= x - 1;        @.x.y= '_';                      end           when #==240  then do;    x= x - 1;        y= y + 1;        @.x.y= '/';     end           when #==300  then do;    y= y + 1;        @.x.y= '\';      x= x + 1;       end           end   /*select*/                      /*curve character is based on direction*/       Lx= min(Lx,x);  Hx= max(Hx,x);  Ly= min(Ly,y);  Hy= max(Hy,y)  /*min&max  of  x,y*/       return                                    /*#:  heading in degrees of the curve. */`
output   when using the default input value of:     5
```  Sierpinski arrowhead curve of order 5
═════════════════════════════════════════
_
/ \
\ /
_/ \_
/     \
\_   _/
_  \ /  _
/ \_/ \_/ \
\         /
_/         \_
/  _       _  \
\_/ \     / \_/
_    /     \    _
/ \   \_   _/   / \
\ /  _  \ /  _  \ /
_/ \_/ \_/ \_/ \_/ \_
/                     \
\_                   _/
_  \                 /  _
/ \_/                 \_/ \
\    _               _    /
_/   / \             / \   \_
/  _  \ /             \ /  _  \
\_/ \_/ \_           _/ \_/ \_/
_          \         /          _
/ \        _/         \_        / \
\ /       /  _       _  \       \ /
_/ \_      \_/ \     / \_/      _/ \_
/     \    _    /     \    _    /     \
\_   _/   / \   \_   _/   / \   \_   _/
_  \ /  _  \ /  _  \ /  _  \ /  _  \ /  _
/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \
```

## Ruby

Library: RubyGems
Library: JRubyArt

For grammar see Hilbert Curve

` load_libraries :grammarattr_reader :points def setup  sketch_title 'Sierpinski Arrowhead'  sierpinski = SierpinskiArrowhead.new(Vec2D.new(width * 0.15, height * 0.7))  production = sierpinski.generate 6 # 6 generations looks OK  @points = sierpinski.translate_rules(production)  no_loopend def draw  background(0)  render pointsend def render(points)  no_fill  stroke 200.0  stroke_weight 3  begin_shape  points.each_slice(2) do |v0, v1|    v0.to_vertex(renderer)    v1.to_vertex(renderer)  end  end_shapeend def renderer  @renderer ||= GfxRender.new(g)end  def settings    size(800, 800)end # SierpinskiArrowhead classclass SierpinskiArrowhead  include Processing::Proxy  attr_reader :draw_length, :pos, :theta, :axiom, :grammar  DELTA = PI / 3 # 60 degrees  def initialize(pos)    @axiom = 'XF' # Axiom    rules = {      'X' => 'YF+XF+Y',      'Y' => 'XF-YF-X'    }    @grammar = Grammar.new(axiom, rules)    @theta = 0    @draw_length = 200    @pos = pos  end   def generate(gen)    @draw_length = draw_length * 0.6**gen    grammar.generate gen  end   def forward(pos)    pos + Vec2D.from_angle(theta) * draw_length  end   def translate_rules(prod)    [].tap do |pts| # An array to store line vertices as Vec2D      prod.scan(/./) do |ch|        case ch        when 'F'          new_pos = forward(pos)          pts << pos << new_pos          @pos = new_pos        when '+'          @theta += DELTA        when '-'          @theta -= DELTA        when 'X', 'Y'        else          puts("character #{ch} not in grammar")        end      end    end  endend  `

## Rust

Output is a file in SVG format. Another variation on the same theme as the C, Go and Phix solutions.

`// [dependencies]// svg = "0.8.0" const SQRT3_2: f64 = 0.86602540378444; use svg::node::element::path::Data; struct Cursor {    x: f64,    y: f64,    angle: i32,} impl Cursor {    fn new(x: f64, y: f64) -> Cursor {        Cursor {            x: x,            y: y,            angle: 0,        }    }    fn turn(&mut self, angle: i32) {        self.angle = (self.angle + angle) % 360;    }    fn draw_line(&mut self, data: Data, length: f64) -> Data {        let theta = (self.angle as f64).to_radians();        self.x += length * theta.cos();        self.y += length * theta.sin();        data.line_to((self.x, self.y))    }} fn curve(mut data: Data, order: usize, length: f64, cursor: &mut Cursor, angle: i32) -> Data {    if order == 0 {        return cursor.draw_line(data, length);    }    data = curve(data, order - 1, length / 2.0, cursor, -angle);    cursor.turn(angle);    data = curve(data, order - 1, length / 2.0, cursor, angle);    cursor.turn(angle);    curve(data, order - 1, length / 2.0, cursor, -angle)} fn write_sierpinski_arrowhead(file: &str, size: usize, order: usize) -> std::io::Result<()> {    use svg::node::element::Path;    use svg::node::element::Rectangle;     let margin = 20.0;    let side = (size as f64) - 2.0 * margin;    let y = 0.5 * (size as f64) + 0.5 * SQRT3_2 * side;    let x = margin;    let mut cursor = Cursor::new(x, y);    if (order & 1) != 0 {        cursor.turn(-60);    }    let mut data = Data::new().move_to((x, y));    data = curve(data, order, side, &mut cursor, 60);    let rect = Rectangle::new()        .set("width", "100%")        .set("height", "100%")        .set("fill", "white");    let mut document = svg::Document::new()        .set("width", size)        .set("height", size)        .add(rect);    let path = Path::new()        .set("fill", "none")        .set("stroke", "black")        .set("stroke-width", "1")        .set("d", data);    document = document.add(path);    svg::save(file, &document)} fn main() {    write_sierpinski_arrowhead("sierpinski_arrowhead.svg", 600, 8).unwrap();}`
Output:

See: sierpinski_arrowhead.svg (offsite SVG image)

## Sidef

Uses the LSystem() class from Hilbert curve.

`var rules = Hash(    x => 'yF+xF+y',    y => 'xF-yF-x',) var lsys = LSystem(    width:  550,    height: 500,     xoff: -20,    yoff: -30,     len:   4,    turn: -90,    angle: 60,    color: 'dark green',) lsys.execute('xF', 7, "sierpiński_arrowhead.png", rules)`

Output image: Sierpiński arrowhead

## Wren

Translation of: Go
Library: DOME
`import "graphics" for Canvas, Color, Pointimport "dome" for Window class Game {    static init() {        Window.title = "Sierpinski Arrowhead Curve"        __width = 770        __height = 770        Window.resize(__width, __height)        Canvas.resize(__width, __height)        var order = 6        __iy = (order&1 == 0) ? -1: 1  // apex will point upwards        __theta = 0        __cx = __width / 2        __cy = __height        __h  = __cx / 2        __prev = Point.new(__cx-__width/2 +__h, (__height-__cy)*__iy + 2*__h)        __col = Color.white        arrowhead(order, __cx)    }     static update() {}     static draw(alpha) {}     static arrowhead(order, length) {        // if order is even, we can just draw the curve        if (order&1 == 0) {            curve(order, length, 60)        } else {            turn(60)            curve(order, length, -60)        }        drawLine(length) // needed to make base symmetric    }     static drawLine(length) {        var curr = Point.new(__cx-__width/2 +__h, (__height-__cy)*__iy + 2*__h)        Canvas.line(__prev.x, __prev.y, curr.x, curr.y, __col)        var rads = __theta * Num.pi / 180        __cx = __cx + length*(rads.cos)        __cy = __cy + length*(rads.sin)        __prev = curr    }     static turn(angle) { __theta = (__theta + angle) % 360 }     static curve(order, length, angle) {        if (order == 0) {            drawLine(length)        } else {            curve(order-1, length/2, -angle)            turn(angle)            curve(order-1, length/2, angle)            turn(angle)            curve(order-1, length/2, -angle)        }    }}`

## XPL0

`int  PosX, PosY;real Dir; proc Curve(Order, Length, Angle);int  Order; real Length, Angle;[if Order = 0 then        [PosX:= PosX + fix(Length*Cos(Dir));         PosY:= PosY - fix(Length*Sin(Dir));         Line(PosX, PosY, \$E \yellow\);        ]else    [Curve(Order-1, Length/2.0, -Angle);         Dir:= Dir + Angle;         Curve(Order-1, Length/2.0, +Angle);         Dir:= Dir + Angle;         Curve(Order-1, Length/2.0, -Angle);        ];]; def Order=5, Length=300.0, Pi=3.141592654, Sixty=Pi/3.0;[SetVid(\$12);   \VGA graphics: 640x480x8PosX:= 640/4;  PosY:= 3*480/4;Move(PosX, PosY);Dir:= 0.0;if (Order&1) = 0 then        Curve(Order, Length, +Sixty)else    [Dir:= Dir + Sixty;        Curve(Order, Length, -Sixty);        ];]`
Output:
```http://www.xpl0.org/rcarrow.gif
```

## zkl

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

`order:=7;sierpinskiArrowheadCurve(order) : turtle(_,order); fcn sierpinskiArrowheadCurve(n){   // Lindenmayer system --> Data of As & Bs   var [const] A="BF+AF+B", B="AF-BF-A";  // Production rules   var [const] Axiom="AF";   buf1,buf2 := Data(Void,Axiom).howza(3), Data().howza(3);  // characters   do(n){      buf1.pump(buf2.clear(),fcn(c){ if(c=="A") A else if(c=="B") B else c });      t:=buf1; buf1=buf2; buf2=t;	// swap buffers   }   buf1		// n=7 --> 6,560 characters} fcn turtle(curve,order){	// Turtle with that can turn +-60*   const D=10.0, a60=60;   dir:=order.isOdd and a60 or 0;	   // start direction depends on order   img,color := PPM(1300,1200), 0x00ff00;  // green on black   x,y := 10, 10;   foreach c in (curve){  // A & B are no-op during drawing      switch(c){	 case("F"){   // draw forward	    a,b := D.toRectangular(dir.toFloat().toRad());	    img.line(x,y, (x+=a.round()),(y+=b.round()), color) 	 }	 case("+"){ dir=(dir - a60)%360; } // turn left  60*	 case("-"){ dir=(dir + a60)%360; } // turn right 60*      }   }   img.writeJPGFile("sierpinskiArrowheadCurve.zkl.jpg");}`
Output:

Offsite image at Sierpinski arrowhead curve order 7