Sierpinski carpet

From Rosetta Code
Task
Sierpinski carpet
You are encouraged to solve this task according to the task description, using any language you may know.
Task

Produce a graphical or ASCII-art representation of a Sierpinski carpet of order   N.


For example, the Sierpinski carpet of order   3   should look like this:

###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################
#########         #########
# ## ## #         # ## ## #
#########         #########
###   ###         ###   ###
# #   # #         # #   # #
###   ###         ###   ###
#########         #########
# ## ## #         # ## ## #
#########         #########
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################

The use of the   #   character is not rigidly required for ASCII art.

The important requirement is the placement of whitespace and non-whitespace characters.


Related task



Ada

with Ada.Text_Io; use Ada.Text_Io;
 
procedure Sierpinski_Carpet is
subtype Index_Type is Integer range 1..81;
type Pattern_Array is array(Index_Type range <>, Index_Type range <>) of Boolean;
Pattern : Pattern_Array(1..81,1..81) := (Others =>(others => true));
procedure Clear_Center(P : in out Pattern_Array; X1 : Index_Type; X2 : Index_Type;
Y1 : Index_Type; Y2 : Index_Type) is
Xfirst : Index_Type;
Xlast  : Index_Type;
Yfirst : Index_Type;
Ylast  : Index_Type;
Diff  : Integer;
begin
Xfirst :=(X2 - X1 + 1) / 3 + X1;
Diff := Xfirst - X1;
Xlast  := Xfirst + Diff;
Yfirst := (Y2 - Y1) / 3 + Y1;
YLast  := YFirst + Diff;
 
for I in XFirst..XLast loop
for J in YFirst..YLast loop
P(I, J) := False;
end loop;
end loop;
end Clear_Center;
 
procedure Print(P : Pattern_Array) is
begin
for I in P'range(1) loop
for J in P'range(2) loop
if P(I,J) then
Put('*');
else
Put(' ');
end if;
end loop;
New_Line;
end loop;
end Print;
 
procedure Divide_Square(P : in out Pattern_Array; Order : Positive) is
Factor : Natural := 0;
X1, X2 : Index_Type;
Y1, Y2  : Index_Type;
Division : Index_Type;
Num_Sections : Index_Type;
begin
while Factor < Order loop
Num_Sections := 3**Factor;
Factor := Factor + 1;
X1  := P'First;
Division  := P'Last / Num_Sections;
X2 := Division;
Y1 := X1;
Y2 := X2;
loop
loop
Clear_Center(P, X1, X2, Y1, Y2);
exit when X2 = P'Last;
X1 := X2;
X2 := X2 + Division;
end loop;
exit when Y2 = P'Last;
Y1 := Y2;
Y2 := Y2 + Division;
X1 := P'First;
X2 := Division;
end loop;
end loop;
end Divide_Square;
 
begin
Divide_Square(Pattern, 3);
Print(Pattern);
end Sierpinski_Carpet;

ALGOL 68

Translation of: python
Works with: ALGOL 68 version Standard - no extensions to language used
Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386
PROC in carpet = (INT in x, in y)BOOL: (
INT x := in x, y := in y;
BOOL out;
DO
IF x = 0 OR y = 0 THEN
out := TRUE; GO TO stop iteration
ELIF x MOD 3 = 1 AND y MOD 3 = 1 THEN
out := FALSE; GO TO stop iteration
FI;
 
x %:= 3;
y %:= 3
OD;
stop iteration: out
);
 
PROC carpet = (INT n)VOID:
FOR i TO 3 ** n DO
FOR j TO 3 ** n DO
IF in carpet(i-1, j-1) THEN
print("* ")
ELSE
print(" ")
FI
OD;
print(new line)
OD;
 
carpet(3)


AppleScript

Translation of: JavaScript

(ES5 Functional version)

-- CARPET MODEL
 
-- sierpinskiCarpet :: Int -> [[Bool]]
on sierpinskiCarpet(n)
 
-- rowStates :: Int -> [Bool]
script rowStates
on lambda(x, _, xs)
 
-- cellState :: Int -> Bool
script cellState
-- inCarpet :: Int -> Int -> Bool
on inCarpet(x, y)
if (x = 0 or y = 0) then
true
else
not ((x mod 3 = 1) and ¬
(y mod 3 = 1)) and ¬
inCarpet(x div 3, y div 3)
end if
end inCarpet
 
on lambda(y)
inCarpet(x, y)
end lambda
end script
 
map(cellState, xs)
end lambda
end script
 
map(rowStates, range(0, (3 ^ n) - 1))
end sierpinskiCarpet
 
 
-- TEST
 
on run
-- Carpets of orders 1, 2, 3
 
set strCarpets to ¬
intercalate(linefeed & linefeed, ¬
map(showCarpet, range(1, 3)))
 
set the clipboard to strCarpets
 
return strCarpets
end run
 
 
-- CARPET DISPLAY
 
-- showCarpet :: Int -> String
on showCarpet(n)
-- showRow :: [Bool] -> String
script showRow
-- showBool :: Bool -> String
script showBool
on lambda(bool)
if bool then
character id 9608
else
" "
end if
end lambda
end script
 
on lambda(xs)
intercalate("", map(my showBool, xs))
end lambda
end script
 
intercalate(linefeed, map(showRow, sierpinskiCarpet(n)))
end showCarpet
 
 
---------------------------------------------------------------------------
 
-- GENERIC LIBRARY FUNCTIONS
 
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to lambda(item i of xs, i, xs)
end repeat
return lst
end tell
end map
 
-- intercalate :: Text -> [Text] -> Text
on intercalate(strText, lstText)
set {dlm, my text item delimiters} to {my text item delimiters, strText}
set strJoined to lstText as text
set my text item delimiters to dlm
return strJoined
end intercalate
 
-- range :: Int -> Int -> [Int]
on range(m, n)
if n < m then
set d to -1
else
set d to 1
end if
set lst to {}
repeat with i from m to n by d
set end of lst to i
end repeat
return lst
end range
 
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property lambda : f
end script
end if
end mReturn
Output:
███
█ █
███

█████████
█ ██ ██ █
█████████
███   ███
█ █   █ █
███   ███
█████████
█ ██ ██ █
█████████

███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████
███   ██████   ██████   ███
█ █   █ ██ █   █ ██ █   █ █
███   ██████   ██████   ███
███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████
█████████         █████████
█ ██ ██ █         █ ██ ██ █
█████████         █████████
███   ███         ███   ███
█ █   █ █         █ █   █ █
███   ███         ███   ███
█████████         █████████
█ ██ ██ █         █ ██ ██ █
█████████         █████████
███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████
███   ██████   ██████   ███
█ █   █ ██ █   █ ██ █   █ █
███   ██████   ██████   ███
███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████

Applesoft BASIC

 100 HGR
110 POKE 49234,0
120 DEF FN M(X) = X - INT (D * 3) * INT (X / INT (D * 3))
130 DE = 4
140 DI = 3 ^ DE * 3
150 FOR I = 0 TO DI - 1
160 FOR J = 0 TO DI - 1
170 FOR D = DI / 3 TO 0 STEP 0
180 IF INT ( FN M(I) / D) = 1 AND INT ( FN M(J) / D) = 1 THEN 200BREAK
190 D = INT (D / 3): NEXT D
200 HCOLOR= 3 * (D = 0)
210 HPLOT J,I
220 NEXT J
230 NEXT I

Asymptote

path across(path p, real node) {
return
point(p, node + 1/3) + point(p, node - 1/3) - point(p, node);
}
 
path corner_subquad(path p, real node) {
return
point(p, node) --
point(p, node + 1/3) --
across(p, node) --
point(p, node - 1/3) --
cycle;
}
 
path noncorner_subquad(path p, real node1, real node2) {
return
point(p, node1 + 1/3) --
across(p, node1) --
across(p, node2) --
point(p, node2 - 1/3) --
cycle;
}
 
void carpet(path p, int order) {
if (order == 0)
fill(p);
else {
for (real node : sequence(0, 3)) {
carpet(corner_subquad(p, node), order - 1);
carpet(noncorner_subquad(p, node, node + 1), order - 1);
}
}
}
 
path q =
// A square
unitsquare
// An oblong rhombus
// (0, 0) -- (5, 3) -- (0, 6) -- (-5, 3) -- cycle
// A trapezoid
// (0, 0) -- (4, 2) -- (6, 2) -- (10, 0) -- cycle
// A less regular quadrilateral
// (0, 0) -- (4, 1) -- (9, -4) -- (1, -1) -- cycle
// A concave shape
// (0, 0) -- (5, 3) -- (10, 0) -- (5, 1) -- cycle
;
 
size(9 inches, 6 inches);
 
carpet(q, 5);

AutoHotkey

Translation of: Python

ahk discussion

Loop 4
MsgBox % Carpet(A_Index)
 
Carpet(n) {
Loop % 3**n {
x := A_Index-1
Loop % 3**n
t .= Dot(x,A_Index-1)
t .= "`n"
}
Return t
}
 
Dot(x,y) {
While x>0 && y>0
If (mod(x,3)=1 && mod(y,3)=1)
Return " "
Else x //= 3, y //= 3
Return "."
}

AWK

# WSC.AWK - Waclaw Sierpinski's carpet contributed by Dan Nielsen
#
# syntax: GAWK -f WSC.AWK [-v o={a|A}{b|B}] [-v X=anychar] iterations
#
# -v o=ab default
# a|A loose weave | tight weave
# b|B don't show | show how the carpet is built
# -v X=? Carpet is built with X's. The character assigned to X replaces all X's.
#
# iterations
# The number of iterations. The default is 0 which produces one carpet.
#
# what is the difference between a loose weave and a tight weave:
# loose tight
# X X X X X X X X X XXXXXXXXX
# X X X X X X X XX XX X
# X X X X X X X X X XXXXXXXXX
# X X X X X X XXX XXX
# X X X X X X X X
# X X X X X X XXX XXX
# X X X X X X X X X XXXXXXXXX
# X X X X X X X XX XX X
# X X X X X X X X X XXXXXXXXX
#
# examples:
# GAWK -f WSC.AWK 2
# GAWK -f WSC.AWK -v o=Ab -v X=# 2
# GAWK -f WSC.AWK -v o=Ab -v X=\xDB 2
#
BEGIN {
optns = (o == "") ? "ab" : o
n = ARGV[1] + 0 # iterations
if (n !~ /^[0-9]+$/) { exit(1) }
seed = (optns ~ /A/) ? "XXX,X X,XXX" : "X X X ,X X ,X X X " # tight/loose weave
leng = row = split(seed,A,",") # seed the array
for (i=1; i<=n; i++) { # build carpet
for (a=1; a<=3; a++) {
row = 0
for (b=1; b<=3; b++) {
for (c=1; c<=leng; c++) {
row++
tmp = (a == 2 && b == 2) ? sprintf("%*s",length(A[c]),"") : A[c]
B[row] = B[row] tmp
}
if (optns ~ /B/) { # show how the carpet is built
if (max_row < row+0) { max_row = row }
for (r=1; r<=max_row; r++) {
printf("i=%d row=%02d a=%d b=%d '%s'\n",i,r,a,b,B[r])
}
print("")
}
}
}
leng = row
for (j=1; j<=row; j++) { A[j] = B[j] } # re-seed the array
for (j in B) { delete B[j] } # delete work array
}
for (j=1; j<=row; j++) { # print carpet
if (X != "") { gsub(/X/,substr(X,1,1),A[j]) }
sub(/ +$/,"",A[j])
printf("%s\n",A[j])
}
exit(0)
}
Sample:
GAWK -f WSC.AWK 1

X X X X X X X X X
X   X X   X X   X
X X X X X X X X X
X X X       X X X
X   X       X   X
X X X       X X X
X X X X X X X X X
X   X X   X X   X
X X X X X X X X X

GAWK -f WSC.AWK -v o=A 1

XXXXXXXXX
X XX XX X
XXXXXXXXX
XXX   XXX
X X   X X
XXX   XXX
XXXXXXXXX
X XX XX X
XXXXXXXXX

BBC BASIC

      Order% = 3
side% = 3^Order%
VDU 23,22,8*side%;8*side%;64,64,16,128
FOR Y% = 0 TO side%-1
FOR X% = 0 TO side%-1
IF FNincarpet(X%,Y%) PLOT X%*16,Y%*16+15
NEXT
NEXT Y%
REPEAT WAIT 1 : UNTIL FALSE
END
 
DEF FNincarpet(X%,Y%)
REPEAT
IF X% MOD 3 = 1 IF Y% MOD 3 = 1 THEN = FALSE
X% DIV= 3
Y% DIV= 3
UNTIL X%=0 AND Y%=0
= TRUE

Sierpinski carpet bbc.gif

Befunge

Translation of: Python

The order, N, is specified by the first number on the stack. The upper limit is implementation dependent and is determined by the interpreter's cell size.

311>*#3\>#-:#1_$:00p00g-#@_010p0>:20p10g30v
>p>40p"#"30g40g*!#v_$48*30g3%1-v^ >$55+,1v>
0 ^p03/3g03/3g04$_v#!*!-1%3g04!<^_^#- g00 <
^3g01p02:0p01_@#-g>#0,#02#:0#+g#11#g+#0:#<^

C

If you write coordinates of any point on the carpet in base 3, the pixel if blank if and only if any matching pair of digits are (1, 1).

#include <stdio.h>
 
int main()
{
int i, j, dim, d;
int depth = 3;
 
for (i = 0, dim = 1; i < depth; i++, dim *= 3);
 
for (i = 0; i < dim; i++) {
for (j = 0; j < dim; j++) {
for (d = dim / 3; d; d /= 3)
if ((i % (d * 3)) / d == 1 && (j % (d * 3)) / d == 1)
break;
printf(d ? " " : "##");
}
printf("\n");
}
 
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef struct sCarpet {
int dim; // dimension
char *data; // character data
char **rows; // pointers to data rows
} *Carpet;
 
/* Clones a tile into larger carpet, or blank if center */
void TileCarpet( Carpet d, int r, int c, Carpet tile )
{
int y0 = tile->dim*r;
int x0 = tile->dim*c;
int k,m;
 
if ((r==1) && (c==1)) {
for(k=0; k < tile->dim; k++) {
for (m=0; m < tile->dim; m++) {
d->rows[y0+k][x0+m] = ' ';
}
}
}
else {
for(k=0; k < tile->dim; k++) {
for (m=0; m < tile->dim; m++) {
d->rows[y0+k][x0+m] = tile->rows[k][m];
}
}
}
}
 
/* define a 1x1 starting carpet */
static char s1[]= "#";
static char *r1[] = {s1};
static struct sCarpet single = { 1, s1, r1};
 
Carpet Sierpinski( int n )
{
Carpet carpet;
Carpet subCarpet;
int row,col, rb;
int spc_rqrd;
 
subCarpet = (n > 1) ? Sierpinski(n-1) : &single;
 
carpet = malloc(sizeof(struct sCarpet));
carpet->dim = 3*subCarpet->dim;
spc_rqrd = (2*subCarpet->dim) * (carpet->dim);
carpet->data = malloc(spc_rqrd*sizeof(char));
carpet->rows = malloc( carpet->dim*sizeof(char *));
for (row=0; row<subCarpet->dim; row++) {
carpet->rows[row] = carpet->data + row*carpet->dim;
rb = row+subCarpet->dim;
carpet->rows[rb] = carpet->data + rb*carpet->dim;
rb = row+2*subCarpet->dim;
carpet->rows[rb] = carpet->data + row*carpet->dim;
}
 
for (col=0; col < 3; col++) {
/* 2 rows of tiles to copy - third group points to same data a first */
for (row=0; row < 2; row++)
TileCarpet( carpet, row, col, subCarpet );
}
if (subCarpet != &single ) {
free(subCarpet->rows);
free(subCarpet->data);
free(subCarpet);
}
 
return carpet;
}
 
void CarpetPrint( FILE *fout, Carpet carp)
{
char obuf[730];
int row;
for (row=0; row < carp->dim; row++) {
strncpy(obuf, carp->rows[row], carp->dim);
fprintf(fout, "%s\n", obuf);
}
fprintf(fout,"\n");
}
 
int main(int argc, char *argv[])
{
// FILE *f = fopen("sierp.txt","w");
CarpetPrint(stdout, Sierpinski(3));
// fclose(f);
return 0;
}

Recursive version:

#include <stdio.h>
#include <stdlib.h>
 
typedef struct _PartialGrid{
char** base;
int xbegin, xend, ybegin, yend; // yend strictly not used
} PartialGrid;
 
void sierpinski_hollow(PartialGrid G){
int len = G.xend - G.xbegin+1;
int unit = len/3;
for(int i = G.xbegin+unit; i <G.xbegin+2*unit;i++){
for(int j = G.ybegin+unit; j <G.ybegin+2*unit;j++){
G.base[j][i] = ' ';
}}
}
 
void sierpinski(PartialGrid G, int iterations){
if(iterations==0)
return;
if((iterations)==1){
sierpinski_hollow(G);
sierpinski(G,0);
}
sierpinski_hollow(G);
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
int length = G.xend-G.xbegin+1;
int unit = length/3;
PartialGrid q = {G.base, G.xbegin + i*unit, G.xbegin+(i+1)*unit-1,
G.ybegin+j*unit, G.ybegin+(j+1)*unit-1};
sierpinski(q, iterations-1);
}
}
}
 
int intpow(int base, int expo){
if(expo==0){
return 1;
}
return base*intpow(base,expo-1);
}
 
int allocate_grid(char*** g, int n, const char sep){
int size = intpow(3,n+1);
*g = (char**)calloc(size, sizeof(char*));
if(*g==NULL)
return -1;
 
for(int i = 0; i < size; ++i){
(*g)[i] = (char*)calloc(size, sizeof(char));
if((*g)[i] == NULL)
return -1;
for(int j = 0; j < size; j++){
(*g)[i][j] = sep;
}
}
 
return size;
}
 
void print_grid(char** b, int size){
for(int i = 0; i < size; i++){
printf("%s\n",b[i]);
}
}
 
int main(){
int n = 3;
 
char** basegrid;
int size = allocate_grid(&basegrid, n, '#');
if(size == -1)
return 1; //bad alloc
PartialGrid b = {basegrid, 0, size-1, 0, size-1};
sierpinski(b, n);
print_grid(basegrid, size);
free(basegrid);
 
return 0;
}

C++

Sierpinski cpp.png

 
#include <windows.h>
#include <math.h>
 
//--------------------------------------------------------------------------------------------------
const int BMP_SIZE = 738;
 
//--------------------------------------------------------------------------------------------------
class Sierpinski
{
public:
void draw( HDC wdc, int wid, int hei, int ord )
{
_wdc = wdc;
_ord = wid / static_cast<int>( pow( 3.0, ord ) );
drawIt( 0, 0, wid, hei );
}
 
void setHWND( HWND hwnd ) { _hwnd = hwnd; }
 
private:
void drawIt( int x, int y, int wid, int hei )
{
if( wid < _ord || hei < _ord ) return;
int w = wid / 3, h = hei / 3;
RECT rc;
SetRect( &rc, x + w, y + h, x + w + w, y + h + h );
FillRect( _wdc, &rc, static_cast<HBRUSH>( GetStockObject( BLACK_BRUSH ) ) );
 
for( int a = 0; a < 3; a++ )
for( int b = 0; b < 3; b++ )
{
if( a == 1 && b == 1 ) continue;
drawIt( x + b * w, y + a * h, w, h );
}
}
 
HWND _hwnd;
HDC _wdc;
int _ord;
};
//--------------------------------------------------------------------------------------------------
class wnd
{
public:
wnd() { _inst = this; }
int wnd::Run( HINSTANCE hInst )
{
_hInst = hInst;
_hwnd = InitAll();
 
_carpet.setHWND( _hwnd );
 
ShowWindow( _hwnd, SW_SHOW );
UpdateWindow( _hwnd );
 
MSG msg;
ZeroMemory( &msg, sizeof( msg ) );
while( msg.message != WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) != 0 )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
return UnregisterClass( "_SIERPINSKI_", _hInst );
}
private:
void wnd::doPaint( HDC dc ) { _carpet.draw( dc, BMP_SIZE, BMP_SIZE, 5 ); }
 
static int WINAPI wnd::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY: PostQuitMessage( 0 ); break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC dc = BeginPaint( hWnd, &ps );
_inst->doPaint( dc );
EndPaint( hWnd, &ps );
}
default:
return DefWindowProc( hWnd, msg, wParam, lParam );
}
return 0;
}
 
HWND InitAll()
{
WNDCLASSEX wcex;
ZeroMemory( &wcex, sizeof( wcex ) );
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = ( WNDPROC )WndProc;
wcex.hInstance = _hInst;
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
wcex.lpszClassName = "_SIERPINSKI_";
 
RegisterClassEx( &wcex );
 
RECT rc = { 0, 0, BMP_SIZE, BMP_SIZE };
AdjustWindowRect( &rc, WS_SYSMENU | WS_CAPTION, FALSE );
int w = rc.right - rc.left,
h = rc.bottom - rc.top;
return CreateWindow( "_SIERPINSKI_", ".: Sierpinski carpet -- PJorente :.", WS_SYSMENU, CW_USEDEFAULT, 0, w, h, NULL, NULL, _hInst, NULL );
}
 
static wnd* _inst;
HINSTANCE _hInst;
HWND _hwnd;
Sierpinski _carpet;
};
wnd* wnd::_inst = 0;
//--------------------------------------------------------------------------------------------------
int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow )
{
wnd myWnd;
return myWnd.Run( hInstance );
}
//--------------------------------------------------------------------------------------------------
 

C#

Translation of: Ruby
Works with: C# version 3.0+
using System;
using System.Collections.Generic;
using System.Linq;
 
class Program
{
static List<string> NextCarpet(List<string> carpet)
{
return carpet.Select(x => x + x + x)
.Concat(carpet.Select(x => x + x.Replace('#', ' ') + x))
.Concat(carpet.Select(x => x + x + x)).ToList();
}
 
static List<string> SierpinskiCarpet(int n)
{
return Enumerable.Range(1, n).Aggregate(new List<string> { "#" }, (carpet, _) => NextCarpet(carpet));
}
 
static void Main(string[] args)
{
foreach (string s in SierpinskiCarpet(3))
Console.WriteLine(s);
}
}

Clojure

Translation of: Scheme
(ns example
(:require [clojure.contrib.math :as math]))
 
(defn in-carpet? [x y]
(loop [x x, y y]
(cond
(or (zero? x) (zero? y)) true
(and (= 1 (mod x 3)) (= 1 (mod y 3))) false
 :else (recur (quot x 3) (quot y 3)))))
 
(defn carpet [n]
(apply str
(interpose
\newline
(for [x (range (math/expt 3 n))]
(apply str
(for [y (range (math/expt 3 n))]
(if (in-carpet? x y) "*" " ")))))))
 
(println (carpet 3))

Common Lisp

This solution works by printing a square of # except where both of the coordinates of a cell contain a 1 in the same digit position in base 3. For example, the central empty square has a 1 in the highest base-3 digit of all its cells, and the smallest empty squares have 1s in the lowest base-3 digit.

(defun print-carpet (order)
(let ((size (expt 3 order)))
(flet ((trinary (x) (format nil "~3,vR" order x))
(ones (a b) (and (eql a #\1) (eql b #\1))))
(loop for i below size do
(fresh-line)
(loop for j below size do
(princ (if (some #'ones (trinary i) (trinary j))
" "
"#")))))))

D

Translation of: Python
import std.stdio, std.string, std.algorithm, std.array;
 
auto sierpinskiCarpet(in int n) pure nothrow @safe {
auto r = ["#"];
foreach (immutable _; 0 .. n) {
const p = r.map!q{a ~ a ~ a}.array;
r = p ~ r.map!q{a ~ a.replace("#", " ") ~ a}.array ~ p;
}
return r.join('\n');
}
 
void main() {
3.sierpinskiCarpet.writeln;
}

More functional style:

import std.stdio, std.algorithm, std.range, std.functional;
 
auto nextCarpet(in string[] c) pure nothrow {
/*immutable*/ const b = c.map!q{a ~ a ~ a}.array;
return b ~ c.map!q{a ~ a.replace("#", " ") ~ a}.array ~ b;
}
 
void main() {
["#"]
.recurrence!((a, n) => a[n - 1].nextCarpet)
.dropExactly(3)
.front
.binaryReverseArgs!writefln("%-(%s\n%)");
}

A more direct and efficient version:

import std.stdio, std.array;
 
char[][] sierpinskiCarpet(in size_t n) pure nothrow @safe {
auto mat = uninitializedArray!(typeof(return))(3 ^^ n, 3 ^^ n);
 
foreach (immutable r, row; mat) {
row[] = '#';
foreach (immutable c, ref cell; row) {
size_t r2 = r, c2 = c;
while (r2 && c2) {
if (r2 % 3 == 1 && c2 % 3 == 1) {
cell = ' ';
break;
}
r2 /= 3;
c2 /= 3;
}
}
}
 
return mat;
}
 
void main() {
writefln("%-(%s\n%)", 3.sierpinskiCarpet);
7.sierpinskiCarpet.length.writeln;
}

DWScript

Translation of: Java
function InCarpet(x, y : Integer) : Boolean;
begin
while (x<>0) and (y<>0) do begin
if ((x mod 3)=1) and ((y mod 3)=1) then
Exit(False);
x := x div 3;
y := y div 3;
end;
Result := True;
end;
 
procedure Carpet(n : Integer);
var
i, j, p : Integer;
begin
p := Round(IntPower(3, n));
 
for i:=0 to p-1 do begin
for j:=0 to p-1 do begin
if InCarpet(i, j) then
Print('#')
else Print(' ');
end;
PrintLn('');
end;
end;
 
Carpet(3);

E

Translation of: Python
def inCarpet(var x, var y) {
while (x > 0 && y > 0) {
if (x %% 3 <=> 1 && y %% 3 <=> 1) {
return false
}
x //= 3
y //= 3
}
return true
}
 
def carpet(order) {
for y in 0..!(3**order) {
for x in 0..!(3**order) {
print(inCarpet(x, y).pick("#", " "))
}
println()
}
}

Elixir

Translation of: Ruby
defmodule RC do
def sierpinski_carpet(n), do: sierpinski_carpet(n, ["#"])
 
def sierpinski_carpet(0, carpet), do: carpet
def sierpinski_carpet(n, carpet) do
new_carpet = Enum.map(carpet, fn x -> x <> x <> x end) ++
Enum.map(carpet, fn x -> x <> String.replace(x, "#", " ") <> x end) ++
Enum.map(carpet, fn x -> x <> x <> x end)
sierpinski_carpet(n-1, new_carpet)
end
end
 
Enum.each(0..3, fn n ->
IO.puts "\nN=#{n}"
Enum.each(RC.sierpinski_carpet(n), fn line -> IO.puts line end)
end)
Output:
N=0
#

N=1
###
# #
###

N=2
#########
# ## ## #
#########
###   ###
# #   # #
###   ###
#########
# ## ## #
#########

N=3
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################
#########         #########
# ## ## #         # ## ## #
#########         #########
###   ###         ###   ###
# #   # #         # #   # #
###   ###         ###   ###
#########         #########
# ## ## #         # ## ## #
#########         #########
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################

Erlang

% Implemented by Arjun Sunel
-module(carpet).
-export([main/0]).
 
main() ->
sierpinski_carpet(3).
 
sierpinski_carpet(N) ->
lists: foreach(fun(X) -> lists: foreach(fun(Y) -> carpet(X,Y) end,lists:seq(0,trunc(math:pow(3,N))-1)), io:format("\n") end, lists:seq(0,trunc(math:pow(3,N))-1)).
 
carpet(X,Y) ->
if
X=:=0 ; Y=:=0 ->
io:format("*");
(X rem 3)=:=1, (Y rem 3) =:=1 ->
io:format(" ");
true ->
carpet(X div 3, Y div 3)
end.
 
Output:
***************************
* ** ** ** ** ** ** ** ** *
***************************
***   ******   ******   ***
* *   * ** *   * ** *   * *
***   ******   ******   ***
***************************
* ** ** ** ** ** ** ** ** *
***************************
*********         *********
* ** ** *         * ** ** *
*********         *********
***   ***         ***   ***
* *   * *         * *   * *
***   ***         ***   ***
*********         *********
* ** ** *         * ** ** *
*********         *********
***************************
* ** ** ** ** ** ** ** ** *
***************************
***   ******   ******   ***
* *   * ** *   * ** *   * *
***   ******   ******   ***
***************************
* ** ** ** ** ** ** ** ** *
***************************
ok

ERRE

 
 
PROGRAM SIERP_CARPET
 
! for rosettacode.org
 
!$INTEGER
 
BEGIN
OPEN("O",1,"OUT.PRN")
PRINT(CHR$(12);) !CLS
DEPTH=3
DIMM=1
 
FOR I=0 TO DEPTH-1 DO
DIMM=DIMM*3
END FOR
 
FOR I=0 TO DIMM-1 DO
FOR J=0 TO DIMM-1 DO
D=DIMM DIV 3
REPEAT
EXIT IF ((I MOD (D*3)) DIV D=1 AND (J MOD (D*3)) DIV D=1)
D=D DIV 3
UNTIL NOT(D>0)
IF D>0 THEN PRINT(#1," ";) ELSE PRINT(#1,"##";) END IF
END FOR
PRINT(#1,)
END FOR
 ! PRINT(#1,CHR$(12);) for printer only!
CLOSE(1)
END PROGRAM
 

Output is redirected to file OUT.PRN: you can change this to SCRN: to screen or "LPTx:" for a parallel printer. Output taken from OUT.PRN file:

Output:
######################################################
##  ####  ####  ####  ####  ####  ####  ####  ####  ##
######################################################
######      ############      ############      ######
##  ##      ##  ####  ##      ##  ####  ##      ##  ##
######      ############      ############      ######
######################################################
##  ####  ####  ####  ####  ####  ####  ####  ####  ##
######################################################
##################                  ##################
##  ####  ####  ##                  ##  ####  ####  ##
##################                  ##################
######      ######                  ######      ######
##  ##      ##  ##                  ##  ##      ##  ##
######      ######                  ######      ######
##################                  ##################
##  ####  ####  ##                  ##  ####  ####  ##
##################                  ##################
######################################################
##  ####  ####  ####  ####  ####  ####  ####  ####  ##
######################################################
######      ############      ############      ######
##  ##      ##  ####  ##      ##  ####  ##      ##  ##
######      ############      ############      ######
######################################################
##  ####  ####  ####  ####  ####  ####  ####  ####  ##
######################################################

Euphoria

 
include std/math.e
 
integer order = 4
 
function InCarpet(atom x, atom y)
while 1 do
if x = 0 or y = 0 then
return 1
elsif floor(mod(x,3)) = 1 and floor(mod(y,3)) = 1 then
return 0
end if
x /= 3
y /= 3
end while
end function
 
for i = 0 to power(3,order)-1 do
for j = 0 to power(3,order)-1 do
if InCarpet(i,j) = 1 then
puts(1,"#")
else
puts(1," ")
end if
end for
puts(1,'\n')
end for
 

F#

Translation of: OCaml
Translation of: Ruby
open System
 
let blank x = new String(' ', String.length x)
 
let nextCarpet carpet =
List.map (fun x -> x + x + x) carpet @
List.map (fun x -> x + (blank x) + x) carpet @
List.map (fun x -> x + x + x) carpet
 
let rec sierpinskiCarpet n =
let rec aux n carpet =
if n = 0 then carpet
else aux (n-1) (nextCarpet carpet)
aux n ["#"]
 
List.iter (printfn "%s") (sierpinskiCarpet 3)

Fan

**
** Generates a square Sierpinski gasket
**
class SierpinskiCarpet
{
public static Bool inCarpet(Int x, Int y){
while(x!=0 && y!=0){
if (x % 3 == 1 && y % 3 == 1)
return false;
x /= 3;
y /= 3;
}
return true;
}
 
static Int pow(Int n, Int exp)
{
rslt := 1
exp.times { rslt *= n }
return rslt
}
 
public static Void carpet(Int n){
for(i := 0; i < pow(3, n); i++){
buf := StrBuf()
for(j := 0; j < pow(3, n); j++){
if( inCarpet(i, j))
buf.add("*");
else
buf.add(" ");
}
echo(buf);
}
}
 
Void main()
{
carpet(4)
}
}

Forth

Translation of: Fan
\ Generates a square Sierpinski gasket
: 1? over 3 mod 1 = ; ( n1 n2 -- n1 n2 f)
: 3/ 3 / swap ; ( n1 n2 -- n2/3 n1)
\ is this cell in the carpet?
: incarpet ( n1 n2 -- f)
begin over over or while 1? 1? and if 2drop false exit then 3/ 3/ repeat
2drop true \ return true if in the carpet
;
\ draw a carpet of n size
: carpet ( n --)
1 swap 0 ?do 3 * loop dup \ calculate power of 3
0 ?do dup 0 ?do i j incarpet if [char] # else bl then emit loop cr loop
drop \ evaluate every cell in the carpet
;
 
cr 4 carpet

Fortran

Works with: Fortran version 90 and later
Translation of: Python
program Sierpinski_carpet
implicit none
 
call carpet(4)
 
contains
 
function In_carpet(a, b)
logical :: in_carpet
integer, intent(in) :: a, b
integer :: x, y
 
x = a ; y = b
do
if(x == 0 .or. y == 0) then
In_carpet = .true.
return
else if(mod(x, 3) == 1 .and. mod(y, 3) == 1) then
In_carpet = .false.
return
end if
x = x / 3
y = y / 3
end do
end function
 
subroutine Carpet(n)
integer, intent(in) :: n
integer :: i, j
 
do i = 0, 3**n - 1
do j = 0, 3**n - 1
if(In_carpet(i, j)) then
write(*, "(a)", advance="no") "#"
else
write(*, "(a)", advance="no") " "
end if
end do
write(*,*)
end do
end subroutine Carpet
end program Sierpinski_carpet

Gnuplot

Works with: gnuplot version 5.0 (patchlevel 3) and above

Version #1.

Note
  • Find plotff.gp file-function for load command here on RC Brownian tree page.
  • dat-files are PARI/GP generated output files. See this page below.
File:SC5gp1.png
Output SC5gp1.png
 
## SCff.gp 1/14/17 aev
## Plotting Sierpinski carpet fractal.
## dat-files are PARI/GP generated output files:
## http://rosettacode.org/wiki/Sierpinski_carpet#PARI.2FGP
#cd 'C:\gnupData'
 
##SC5
clr = '"green"'
filename = "SC5gp1"
ttl = "Sierpinski carpet fractal, v.#1"
load "plotff.gp"
 
Output:
1. All SCff.gp commands.
2. All plotted png-files:
   SC5gp1.png (for now)

Plotting a Sierpinski carpet fractal: versions #2 and #3

plotscf.gp and plotscf1.gp file-functions for the load command are the only possible imitation of the fine functions in the gnuplot.

File:SCF21gp.png
Output SCF21gp.png
File:SCF22gp.png
Output SCF22gp.png
File:SCF31gp.png
Output SCF31gp.png
plotscf.gp
 
## plotscf.gp 12/7/16 aev
## Plotting a Sierpinski carpet fractal to the png-file.
## Note: assign variables: ord (order), clr (color), filename and ttl (before using load command).
## ord (order) # a.k.a. level - defines size of fractal (also number of dots).
reset
set terminal png font arial 12 size 640,640
ofn=filename.".png"
set output ofn
unset border; unset xtics; unset ytics; unset key;
set title ttl font "Arial:Bold,12"
set xrange [0:1]; set yrange [0:1];
sc(n, x, y, d) = n >= ord ? \
sprintf('set object rect from %f,%f to %f,%f fc rgb @clr fs solid;', x, y, x+d, y+d) : \
sc(n+1, x, y, d/3) . sc(n+1, x+d/3, y, d/3) . \
sc(n+1, x+2*d/3, y, d/3) . sc(n+1, x, y+d/3, d/3) . \
sc(n+1, x+2*d/3, y+d/3, d/3) . sc(n+1, x, y+2*d/3, d/3) . \
sc(n+1, x+d/3, y+2*d/3, d/3) . sc(n+1, x+2*d/3, y+2*d /3, d/3);
eval(sc(0, 0.0, 0.0, 1.0))
plot -100
set output
 
plotscf1.gp
 
## plotscf1.gp 12/7/16 aev
## Plotting a Sierpinski carpet fractal to the png-file.
## Note: assign variables: ord (order, just for title), clr (color), filename and ttl (before using load command).
## In this version order is always 5.
reset
set terminal png font arial 12 size 640,640
ofn=filename.".png"
set output ofn
unset border; unset xtics; unset ytics; unset key;
set title ttl font "Arial:Bold,12"
o=3
sqr(x,y) = abs(x + y) + abs(x - y) - o
f(x) = o*abs(x) - o
c0(x,y) = abs(x + y) + abs(x - y) - 1
c1(x,y) = c0(o*x,f(y)) * c0(f(x),o*y) * c0(f(x),f(y))
c2(x,y) = c1(o*x,f(y)) * c1(f(x),o*y) * c1(f(x),f(y))
c3(x,y) = c2(o*x,f(y)) * c2(f(x),o*y) * c2(f(x),f(y))
c4(x,y) = c3(o*x,f(y)) * c3(f(x),o*y) * c3(f(x),f(y))
sc(x,y) = sqr(x,y)>0 || c0(x,y)*c1(x,y)*c2(x,y)*c3(x,y)*c4(x,y)<0 ? 0:1
set xrange [-1.5:1.5]; set yrange [-1.5:1.5];
set pm3d map;
set palette model RGB defined (0 "white", 1 @clr);
set size ratio -1
smp=640; set samples smp; set isosamples smp;
unset colorbox
splot sc(x,y)
set output
 
Plotting v.#2 and v.#3
 
## pSCF.gp 12/7/16 aev
## Plotting Sierpinski carpet fractals.
## Note: assign variables: ord (order), clr (color), filename and ttl (before using load command).
## ord (order) # a.k.a. level - defines size of fractal (also number of dots).
#cd 'C:\gnupData'
 
##SCF21
ord=3; clr = '"red"';
filename = "SCF21gp"; ttl = "Sierpinski carpet fractal #21, ord ".ord;
load "plotscf.gp"
 
##SCF22
ord=5; clr = '"brown"';
filename = "SCF22gp"; ttl = "Sierpinski carpet fractal #22, ord ".ord;
load "plotscf.gp"
 
##SCF31
ord=5; clr = '"navy"';
filename = "SCF31gp"; ttl = "Sierpinski carpet fractal #31, ord ".ord;
load "plotscf1.gp"
 
Output:
1. All pSCF.gp file commands.
2. 3 plotted png-files: SCF21gp, SCF22gp and SCF31gp

Go

Variable "grain" shown set to "#" here, but it's fun to experiment with other values. "|", ". ", "[]", "___", "██", "░░"...

package main
 
import (
"fmt"
"strings"
"unicode/utf8"
)
 
var order = 3
var grain = "#"
 
func main() {
carpet := []string{grain}
for ; order > 0; order-- {
// repeat expression allows for multiple character
// grain and for multi-byte UTF-8 characters.
hole := strings.Repeat(" ", utf8.RuneCountInString(carpet[0]))
middle := make([]string, len(carpet))
for i, s := range carpet {
middle[i] = s + hole + s
carpet[i] = strings.Repeat(s, 3)
}
carpet = append(append(carpet, middle...), carpet...)
}
for _, r := range carpet {
fmt.Println(r)
}
}

Groovy

Solution, uses list-indexing of base 3 string representation:

def base3 = { BigInteger i -> i.toString(3) }
 
def sierpinskiCarpet = { int order ->
StringBuffer sb = new StringBuffer()
def positions = 0..<(3**order)
def digits = 0..<([order,1].max())
 
positions.each { i ->
String i3 = base3(i).padLeft(order, '0')
 
positions.each { j ->
String j3 = base3(j).padLeft(order, '0')
 
sb << (digits.any{ i3[it] == '1' && j3[it] == '1' } ? ' ' : order.toString().padRight(2) )
}
sb << '\n'
}
sb.toString()
}

Test Program:

(0..4).each { println sierpinskiCarpet(it) }
Output:
0 

1 1 1 
1   1 
1 1 1 

2 2 2 2 2 2 2 2 2 
2   2 2   2 2   2 
2 2 2 2 2 2 2 2 2 
2 2 2       2 2 2 
2   2       2   2 
2 2 2       2 2 2 
2 2 2 2 2 2 2 2 2 
2   2 2   2 2   2 
2 2 2 2 2 2 2 2 2 

3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 
3   3 3   3 3   3 3   3 3   3 3   3 3   3 3   3 3   3 
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 
3 3 3       3 3 3 3 3 3       3 3 3 3 3 3       3 3 3 
3   3       3   3 3   3       3   3 3   3       3   3 
3 3 3       3 3 3 3 3 3       3 3 3 3 3 3       3 3 3 
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 
3   3 3   3 3   3 3   3 3   3 3   3 3   3 3   3 3   3 
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 
3 3 3 3 3 3 3 3 3                   3 3 3 3 3 3 3 3 3 
3   3 3   3 3   3                   3   3 3   3 3   3 
3 3 3 3 3 3 3 3 3                   3 3 3 3 3 3 3 3 3 
3 3 3       3 3 3                   3 3 3       3 3 3 
3   3       3   3                   3   3       3   3 
3 3 3       3 3 3                   3 3 3       3 3 3 
3 3 3 3 3 3 3 3 3                   3 3 3 3 3 3 3 3 3 
3   3 3   3 3   3                   3   3 3   3 3   3 
3 3 3 3 3 3 3 3 3                   3 3 3 3 3 3 3 3 3 
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 
3   3 3   3 3   3 3   3 3   3 3   3 3   3 3   3 3   3 
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 
3 3 3       3 3 3 3 3 3       3 3 3 3 3 3       3 3 3 
3   3       3   3 3   3       3   3 3   3       3   3 
3 3 3       3 3 3 3 3 3       3 3 3 3 3 3       3 3 3 
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 
3   3 3   3 3   3 3   3 3   3 3   3 3   3 3   3 3   3 
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 

4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4                   4   4 4   4 4   4 4   4 4   4 4   4                   4   4 4   4 4   4 4   4 4   4 4   4                   4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4 4 4       4 4 4                   4 4 4       4 4 4 4 4 4       4 4 4                   4 4 4       4 4 4 4 4 4       4 4 4                   4 4 4       4 4 4 
4   4       4   4                   4   4       4   4 4   4       4   4                   4   4       4   4 4   4       4   4                   4   4       4   4 
4 4 4       4 4 4                   4 4 4       4 4 4 4 4 4       4 4 4                   4 4 4       4 4 4 4 4 4       4 4 4                   4 4 4       4 4 4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4                   4   4 4   4 4   4 4   4 4   4 4   4                   4   4 4   4 4   4 4   4 4   4 4   4                   4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4                                                       4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4                                                       4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4   4       4   4 4   4       4   4 4   4       4   4                                                       4   4       4   4 4   4       4   4 4   4       4   4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4                                                       4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4                                                       4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4                   4   4 4   4 4   4                                                       4   4 4   4 4   4                   4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4 4 4       4 4 4                   4 4 4       4 4 4                                                       4 4 4       4 4 4                   4 4 4       4 4 4 
4   4       4   4                   4   4       4   4                                                       4   4       4   4                   4   4       4   4 
4 4 4       4 4 4                   4 4 4       4 4 4                                                       4 4 4       4 4 4                   4 4 4       4 4 4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4                   4   4 4   4 4   4                                                       4   4 4   4 4   4                   4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4                                                       4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4                                                       4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4   4       4   4 4   4       4   4 4   4       4   4                                                       4   4       4   4 4   4       4   4 4   4       4   4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4                                                       4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4                                                       4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                                                       4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4                   4   4 4   4 4   4 4   4 4   4 4   4                   4   4 4   4 4   4 4   4 4   4 4   4                   4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4 4 4       4 4 4                   4 4 4       4 4 4 4 4 4       4 4 4                   4 4 4       4 4 4 4 4 4       4 4 4                   4 4 4       4 4 4 
4   4       4   4                   4   4       4   4 4   4       4   4                   4   4       4   4 4   4       4   4                   4   4       4   4 
4 4 4       4 4 4                   4 4 4       4 4 4 4 4 4       4 4 4                   4 4 4       4 4 4 4 4 4       4 4 4                   4 4 4       4 4 4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4                   4   4 4   4 4   4 4   4 4   4 4   4                   4   4 4   4 4   4 4   4 4   4 4   4                   4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4                   4 4 4 4 4 4 4 4 4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 4   4       4   4 
4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 4 4 4       4 4 4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 4   4 
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 

Haskell

inCarpet :: Int -> Int -> Bool
inCarpet 0 _ = True
inCarpet _ 0 = True
inCarpet x y = not ((xr == 1) && (yr == 1)) && inCarpet xq yq
where ((xq, xr), (yq, yr)) = (x `divMod` 3, y `divMod` 3)
 
carpet :: Int -> [String]
carpet n = map
(zipWith
(\x y -> if inCarpet x y then '#' else ' ')
[0..3^n-1]
. repeat)
[0..3^n-1]
 
printCarpet :: Int -> IO ()
printCarpet = mapM_ putStrLn . carpet
Translation of: Ruby
nextCarpet :: [String] -> [String]
nextCarpet carpet = border ++ map f carpet ++ border
where border = map (concat . replicate 3) carpet
f x = x ++ map (const ' ') x ++ x
 
sierpinskiCarpet :: Int -> [String]
sierpinskiCarpet n = iterate nextCarpet ["#"] !! n
 
main :: IO ()
main = mapM_ putStrLn $ sierpinskiCarpet 3

Seems not very different from version above.

main :: IO ()
main = putStr . unlines . (!!3) $ iterate next ["#"]
 
next :: [String] -> [String]
next block =
block ! block ! block
++
block ! center ! block
++
block ! block ! block
where
(!) = zipWith (++)
center = map (map $ const ' ') block

GUI variant

Via high-level vector graphics (diagrams -> cairo -> gtk), very slow.

Works with: GHC
Library: diagrams
{-# LANGUAGE DoRec #-}
import Control.Monad.Trans (lift)
import Data.Colour (Colour)
 
import Diagrams.Prelude hiding (after)
import Diagrams.Backend.Cairo (Cairo)
import Diagrams.Backend.Cairo.Gtk (defaultRender)
 
import Graphics.Rendering.Diagrams.Points ()
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Gdk.GC (gcNew)
 
 
main :: IO ()
main = do
_ <- initGUI
window <- windowNew
_ <- window `onDestroy` mainQuit
window `windowSetResizable` False
 
area <- drawingAreaNew
_ <- area `on` sizeRequest $ return (Requisition 500 500)
_ <- window `containerAdd` area
widgetShowAll window
 
rec con <- area `on` exposeEvent $ do
lift $ signalDisconnect con
lift $ area `defaultRender` carpet 5
switchToPixBuf area
mainGUI
 
 
-- just workaround for slow redrawing
switchToPixBuf :: DrawingArea -> EventM EExpose Bool
switchToPixBuf area =
eventArea >>= \ea -> lift $ do
dw <- widgetGetDrawWindow area
(w,h) <- drawableGetSize dw
Just pb <- pixbufGetFromDrawable dw ea
gc <- gcNew dw
_ <- area `on` exposeEvent $ lift $
False <$ drawPixbuf dw gc pb 0 0 0 0 w h RgbDitherNone 0 0
return False
 
 
carpet :: Int -> Diagram Cairo R2
carpet = (iterate next (cell white) !!)
 
-- of course, one can use hcat / vcat - combinators
next :: Diagram Cairo R2 -> Diagram Cairo R2
next block =
scale (1/3) . centerXY $
 
(block ||| block ||| block)
===
(block ||| centr ||| block)
===
(block ||| block ||| block)
where
centr = cell black
 
cell :: Colour Float -> Diagram Cairo R2
cell color = square 1 # lineWidth 0 # fillColor color
 

Icon and Unicon

The IsFilled procedure is a translation of Java and Python.

$define FILLER "*"  # the filler character
 
procedure main(A)
 
width := 3 ^ ( order := (0 < \A[1]) | 3 )
write("Carpet order= ",order)
 
every !(canvas := list(width)) := list(width," ") # prime the canvas
 
every y := 1 to width & x := 1 to width do # traverse it
if IsFilled(x-1,y-1) then canvas[x,y] := FILLER # fill
 
every x := 1 to width & y := 1 to width do
writes((y=1,"\n")|"",canvas[x,y]," ") # print
end
 
procedure IsFilled(x,y) # succeed if x,y should be filled
while x ~= 0 & y ~= 0 do {
if x % 3 = y %3 = 1 then fail
x /:= 3
y /:=3
}
return
end
Output:
Carpet order= 2

* * * * * * * * *
*   * *   * *   *
* * * * * * * * *
* * *       * * *
*   *       *   *
* * *       * * *
* * * * * * * * *
*   * *   * *   *
* * * * * * * * *

Io

Based on Python translation of Ruby.

sierpinskiCarpet := method(n,
carpet := list("@")
n repeat(
next := list()
carpet foreach(s, next append(s .. s .. s))
carpet foreach(s, next append(s .. (s asMutable replaceSeq("@"," ")) .. s))
carpet foreach(s, next append(s .. s .. s))
carpet = next
)
carpet join("\n")
)
 
sierpinskiCarpet(3) println
Output:
@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ @@ @@ @@ @@ @@ @@ @@ @@ @
@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@   @@@@@@   @@@@@@   @@@
@ @   @ @@ @   @ @@ @   @ @
@@@   @@@@@@   @@@@@@   @@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ @@ @@ @@ @@ @@ @@ @@ @@ @
@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@         @@@@@@@@@
@ @@ @@ @         @ @@ @@ @
@@@@@@@@@         @@@@@@@@@
@@@   @@@         @@@   @@@
@ @   @ @         @ @   @ @
@@@   @@@         @@@   @@@
@@@@@@@@@         @@@@@@@@@
@ @@ @@ @         @ @@ @@ @
@@@@@@@@@         @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ @@ @@ @@ @@ @@ @@ @@ @@ @
@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@   @@@@@@   @@@@@@   @@@
@ @   @ @@ @   @ @@ @   @ @
@@@   @@@@@@   @@@@@@   @@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ @@ @@ @@ @@ @@ @@ @@ @@ @
@@@@@@@@@@@@@@@@@@@@@@@@@@@

J

Like the sierpinski triangle, the carpet is straightforward to produce in J. One approach is based on repeatedly putting a function's argument in a box, forming 9 copies of it into a 3 by 3 array, and then replacing the contents of the middle box with blanks:

N=:3
(a:(<1;1)}3 3$<)^:N' '

But N=:3 is big, so let's use N=:2

   N=:2
(a:(<1;1)}3 3$<)^:N' '
┌─────────────┬─────────────┬─────────────┐
│┌───┬───┬───┐│┌───┬───┬───┐│┌───┬───┬───┐│
││ │ │ │││ │ │ │││ │ │ ││
│├───┼───┼───┤│├───┼───┼───┤│├───┼───┼───┤│
││ │ │ │││ │ │ │││ │ │ ││
│├───┼───┼───┤│├───┼───┼───┤│├───┼───┼───┤│
││ │ │ │││ │ │ │││ │ │ ││
│└───┴───┴───┘│└───┴───┴───┘│└───┴───┴───┘│
├─────────────┼─────────────┼─────────────┤
│┌───┬───┬───┐│ │┌───┬───┬───┐│
││ │ │ ││ ││ │ │ ││
│├───┼───┼───┤│ │├───┼───┼───┤│
││ │ │ ││ ││ │ │ ││
│├───┼───┼───┤│ │├───┼───┼───┤│
││ │ │ ││ ││ │ │ ││
│└───┴───┴───┘│ │└───┴───┴───┘│
├─────────────┼─────────────┼─────────────┤
│┌───┬───┬───┐│┌───┬───┬───┐│┌───┬───┬───┐│
││ │ │ │││ │ │ │││ │ │ ││
│├───┼───┼───┤│├───┼───┼───┤│├───┼───┼───┤│
││ │ │ │││ │ │ │││ │ │ ││
│├───┼───┼───┤│├───┼───┼───┤│├───┼───┼───┤│
││ │ │ │││ │ │ │││ │ │ ││
│└───┴───┴───┘│└───┴───┴───┘│└───┴───┴───┘│
└─────────────┴─────────────┴─────────────┘

or another way of getting the same image starts with the boolean array

   #:7 5 7
1 1 1
1 0 1
1 1 1
and uses that to select either a blank box or a boxed copy if the function's argument:
   N=:2
((#:7 5 7){_2{.<)^:N' '
┌─────────────┬─────────────┬─────────────┐
│┌───┬───┬───┐│┌───┬───┬───┐│┌───┬───┬───┐│
││ │ │ │││ │ │ │││ │ │ ││
│├───┼───┼───┤│├───┼───┼───┤│├───┼───┼───┤│
││ │ │ │││ │ │ │││ │ │ ││
│├───┼───┼───┤│├───┼───┼───┤│├───┼───┼───┤│
││ │ │ │││ │ │ │││ │ │ ││
│└───┴───┴───┘│└───┴───┴───┘│└───┴───┴───┘│
├─────────────┼─────────────┼─────────────┤
│┌───┬───┬───┐│ │┌───┬───┬───┐│
││ │ │ ││ ││ │ │ ││
│├───┼───┼───┤│ │├───┼───┼───┤│
││ │ │ ││ ││ │ │ ││
│├───┼───┼───┤│ │├───┼───┼───┤│
││ │ │ ││ ││ │ │ ││
│└───┴───┴───┘│ │└───┴───┴───┘│
├─────────────┼─────────────┼─────────────┤
│┌───┬───┬───┐│┌───┬───┬───┐│┌───┬───┬───┐│
││ │ │ │││ │ │ │││ │ │ ││
│├───┼───┼───┤│├───┼───┼───┤│├───┼───┼───┤│
││ │ │ │││ │ │ │││ │ │ ││
│├───┼───┼───┤│├───┼───┼───┤│├───┼───┼───┤│
││ │ │ │││ │ │ │││ │ │ ││
│└───┴───┴───┘│└───┴───┴───┘│└───┴───┴───┘│
└─────────────┴─────────────┴─────────────┘

That said, using spaces and '#' characters takes a bit more work. One approach would be:

   N=:2
' #'{~(#:7 5 7) ,/@(1 3 ,/"2@|: */)^:N ,.1
#########
# ## ## #
#########
### ###
# # # #
### ###
#########
# ## ## #
#########
N=:3
' #'{~(#:7 5 7) ,/@(1 3 ,/"2@|: */)^:N ,.1
###########################
# ## ## ## ## ## ## ## ## #
###########################
### ###### ###### ###
# # # ## # # ## # # #
### ###### ###### ###
###########################
# ## ## ## ## ## ## ## ## #
###########################
######### #########
# ## ## # # ## ## #
######### #########
### ### ### ###
# # # # # # # #
### ### ### ###
######### #########
# ## ## # # ## ## #
######### #########
###########################
# ## ## ## ## ## ## ## ## #
###########################
### ###### ###### ###
# # # ## # # ## # # #
### ###### ###### ###
###########################
# ## ## ## ## ## ## ## ## #
###########################

Here, what we are doing is forming a tensor product of our #:7 5 7 boolean array with our argument and then collapsing two of the dimensions so they line up right. Our starting argument is the 1 by 1 array with the value 1. Once we have repeated this process enough times, we select spaces for our zeros and pound signs for our 1s.

Java

Translation of: Python
public static boolean inCarpet(long x, long y) {
while (x!=0 && y!=0) {
if (x % 3 == 1 && y % 3 == 1)
return false;
x /= 3;
y /= 3;
}
return true;
}
 
public static void carpet(final int n) {
final double power = Math.pow(3,n);
for(long i = 0; i < power; i++) {
for(long j = 0; j < power; j++) {
System.out.print(inCarpet(i, j) ? "*" : " ");
}
System.out.println();
}
}

Animated version

Sierpinski carpet java.png
Works with: java version 8
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
 
public class SierpinskiCarpet extends JPanel {
private final int dim = 513;
private final int margin = 20;
 
private int limit = dim;
 
public SierpinskiCarpet() {
setPreferredSize(new Dimension(dim + 2 * margin, dim + 2 * margin));
setBackground(Color.white);
setForeground(Color.orange);
 
new Timer(2000, (ActionEvent e) -> {
limit /= 3;
if (limit <= 3)
limit = dim;
repaint();
}).start();
}
 
void drawCarpet(Graphics2D g, int x, int y, int size) {
if (size < limit)
return;
size /= 3;
for (int i = 0; i < 9; i++) {
if (i == 4) {
g.fillRect(x + size, y + size, size, size);
} else {
drawCarpet(g, x + (i % 3) * size, y + (i / 3) * size, size);
}
}
}
 
@Override
public void paintComponent(Graphics gg) {
super.paintComponent(gg);
Graphics2D g = (Graphics2D) gg;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.translate(margin, margin);
drawCarpet(g, 0, 0, dim);
}
 
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Sierpinski Carpet");
f.setResizable(false);
f.add(new SierpinskiCarpet(), BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}

JavaScript

ES5

In-browser JavaScript (HTML output)

Translation of: Ruby
Works with: JavaScript version 1.6
Works with: Firefox version 1.5+

This version also produces a "graphic" via HTML and CSS.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Sierpinski Carpet</title>
<script type='text/javascript'>
 
var black_char = "#";
var white_char = " ";
 
var SierpinskiCarpet = function(size) {
this.carpet = [black_char];
for (var i = 1; i <= size; i++) {
this.carpet = [].concat(
this.carpet.map(this.sier_top),
this.carpet.map(this.sier_middle),
this.carpet.map(this.sier_top)
);
}
}
 
SierpinskiCarpet.prototype.sier_top = function(x) {
var str = new String(x);
return new String(str+str+str);
}
 
SierpinskiCarpet.prototype.sier_middle = function (x) {
var str = new String(x);
var spacer = str.replace(new RegExp(black_char, 'g'), white_char);
return new String(str+spacer+str);
}
 
SierpinskiCarpet.prototype.to_string = function() {
return this.carpet.join("\n")
}
 
SierpinskiCarpet.prototype.to_html = function(target) {
var table = document.createElement('table');
for (var i = 0; i < this.carpet.length; i++) {
var row = document.createElement('tr');
for (var j = 0; j < this.carpet[i].length; j++) {
var cell = document.createElement('td');
cell.setAttribute('class', this.carpet[i][j] == black_char ? 'black' : 'white');
cell.appendChild(document.createTextNode('\u00a0'));
row.appendChild(cell);
}
table.appendChild(row);
}
target.appendChild(table);
}
 
</script>
<style type='text/css'>
table {border-collapse: collapse;}
td {width: 1em;}
.black {background-color: black;}
.white {background-color: white;}
</style>
</head>
<body>
 
<pre id='to_string' style='float:left; margin-right:0.25in'></pre>
<div id='to_html'></div>
 
<script type='text/javascript'>
var sc = new SierpinskiCarpet(3);
document.getElementById('to_string').appendChild(document.createTextNode(sc.to_string()));
sc.to_html(document.getElementById('to_html'));
</script>
 
</body>
</html>
Output:

Sierpinski carpet js.png


Or, in a functional idiom, generating plain text, and suitable for use in any ES5 JavaScript, whether in a browser or some other environment.

Creates an N by N array of boolean values, which are mapped to lines of characters for output.

// Orders 1, 2 and 3 of the Sierpinski Carpet
// as lines of text.
 
// Generic text output for use in any JavaScript environment
// Browser JavaScripts may use console.log() to return textual output
// others use print() or analogous functions.
 
[1, 2, 3].map(function sierpinskiCarpetOrder(n) {
 
// An (n * n) grid of (filled or empty) sub-rectangles
// n --> [[s]]
var carpet = function (n) {
var lstN = range(0, Math.pow(3, n) - 1);
 
// State of each cell in an N * N grid
return lstN.map(function (x) {
return lstN.map(function (y) {
return inCarpet(x, y);
});
});
},
 
// State of a given coordinate in the grid:
// Filled or not ?
// (See https://en.wikipedia.org/wiki/Sierpinski_carpet#Construction)
// n --> n --> bool
inCarpet = function (x, y) {
return (!x || !y) ? true :
!(
(x % 3 === 1) &&
(y % 3 === 1)
) && inCarpet(
x / 3 | 0,
y / 3 | 0
);
},
 
// Sequence of integers from m to n
// n --> n --> [n]
range = function (m, n) {
return Array.apply(null, Array(n - m + 1)).map(
function (x, i) {
return m + i;
}
);
};
 
// Grid of booleans mapped to lines of characters
// [[bool]] --> s
return carpet(n).map(function (line) {
return line.map(function (bool) {
return bool ? '\u2588' : ' ';
}).join('');
}).join('\n');
 
}).join('\n\n');

Output (orders 1, 2 and 3):

███
█ █
███

█████████
█ ██ ██ █
█████████
███   ███
█ █   █ █
███   ███
█████████
█ ██ ██ █
█████████

███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████
███   ██████   ██████   ███
█ █   █ ██ █   █ ██ █   █ █
███   ██████   ██████   ███
███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████
█████████         █████████
█ ██ ██ █         █ ██ ██ █
█████████         █████████
███   ███         ███   ███
█ █   █ █         █ █   █ █
███   ███         ███   ███
█████████         █████████
█ ██ ██ █         █ ██ ██ █
█████████         █████████
███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████
███   ██████   ██████   ███
█ █   █ ██ █   █ ██ █   █ █
███   ██████   ██████   ███
███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████

ES6

Functional composition

(() => {
'use strict';
 
// sierpinskiCarpet :: Int -> String
let sierpinskiCarpet = n => {
 
// carpet :: Int -> [[String]]
let carpet = n => {
let xs = range(0, Math.pow(3, n) - 1);
return xs.map(x => xs.map(y => inCarpet(x, y)));
},
 
// https://en.wikipedia.org/wiki/Sierpinski_carpet#Construction
 
// inCarpet :: Int -> Int -> Bool
inCarpet = (x, y) =>
(!x || !y) ? true : !(
(x % 3 === 1) &&
(y % 3 === 1)
) && inCarpet(
x / 3 | 0,
y / 3 | 0
);
 
return carpet(n)
.map(line => line.map(bool => bool ? '\u2588' : ' ')
.join(''))
.join('\n');
};
 
// GENERIC
 
// range :: Int -> Int -> [Int]
let range = (m, n) =>
Array.from({
length: Math.floor(n - m) + 1
}, (_, i) => m + i);
 
// TEST
 
return [1, 2, 3]
.map(sierpinskiCarpet);
})();
Output:
███
█ █
███

█████████
█ ██ ██ █
█████████
███   ███
█ █   █ █
███   ███
█████████
█ ██ ██ █
█████████

███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████
███   ██████   ██████   ███
█ █   █ ██ █   █ ██ █   █ █
███   ██████   ██████   ███
███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████
█████████         █████████
█ ██ ██ █         █ ██ ██ █
█████████         █████████
███   ███         ███   ███
█ █   █ █         █ █   █ █
███   ███         ███   ███
█████████         █████████
█ ██ ██ █         █ ██ ██ █
█████████         █████████
███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████
███   ██████   ██████   ███
█ █   █ ██ █   █ ██ █   █ █
███   ██████   ██████   ███
███████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ █
███████████████████████████

Kotlin

ASCII Art Version

Translation of: Python
// version 1.1.2
 
fun inCarpet(x: Int, y: Int): Boolean {
var xx = x
var yy = y
while (xx != 0 && yy != 0) {
if (xx % 3 == 1 && yy % 3 == 1) return false
xx /= 3
yy /= 3
}
return true
}
 
fun carpet(n: Int) {
val power = Math.pow(3.0, n.toDouble()).toInt()
for(i in 0 until power) {
for(j in 0 until power) print(if (inCarpet(i, j)) "*" else " ")
println()
}
}
 
fun main(args: Array<String>) = carpet(3)
Output:
***************************
* ** ** ** ** ** ** ** ** *
***************************
***   ******   ******   ***
* *   * ** *   * ** *   * *
***   ******   ******   ***
***************************
* ** ** ** ** ** ** ** ** *
***************************
*********         *********
* ** ** *         * ** ** *
*********         *********
***   ***         ***   ***
* *   * *         * *   * *
***   ***         ***   ***
*********         *********
* ** ** *         * ** ** *
*********         *********
***************************
* ** ** ** ** ** ** ** ** *
***************************
***   ******   ******   ***
* *   * ** *   * ** *   * *
***   ******   ******   ***
***************************
* ** ** ** ** ** ** ** ** *
***************************

Graphical Animated Version

Translation of: Java
// version 1.1.2
 
import java.awt.*
import javax.swing.*
 
public class SierpinskiCarpet : JPanel() {
private val dim = 513
private val margin = 20
private var limit = dim
 
init {
val size = dim + 2 * margin
preferredSize = Dimension(size, size)
background = Color.blue
foreground = Color.yellow
Timer(2000) {
limit /= 3
if (limit <= 3) limit = dim
repaint()
}.start()
}
 
private fun drawCarpet(g: Graphics2D, x: Int, y: Int, s: Int) {
var size = s
if (s < limit) return
size /= 3
for (i in 0 until 9) {
if (i == 4) {
g.fillRect(x + size, y + size, size, size)
}
else {
drawCarpet(g, x + (i % 3) * size, y + (i / 3) * size, size)
}
}
}
 
override fun paintComponent(gg: Graphics) {
super.paintComponent(gg)
val g = gg as Graphics2D
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
g.translate(margin, margin)
drawCarpet(g, 0, 0, dim)
}
}
 
fun main(args: Array<String>) {
SwingUtilities.invokeLater {
val f = JFrame()
f.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
f.title = "Sierpinski Carpet"
f.isResizable = false
f.add(SierpinskiCarpet(), BorderLayout.CENTER)
f.pack()
f.setLocationRelativeTo(null)
f.isVisible = true
}
}

jq

jq does Cartesian products, so the heart of the matter is the line:

inCarpet( range(0; $power) ; range(0; $power), -1 )

This is like a "for" loop within a "for" loop in C-like languages, because range(0;n) generates a stream of n integers beginning at 0. The -1 is used to signal that a newline character is required.

 
def inCarpet(x; y):
x as $x | y as $y |
if $x == -1 or $y == -1 then "\n"
elif $x == 0 or $y == 0 then "*"
elif ($x % 3) == 1 and ($y % 3) == 1 then " "
else inCarpet($x/3 | floor; $y/3 | floor)
end;
 
def ipow(n):
. as $in | reduce range(0;n) as $i (1; . * $in);
 
def carpet(n):
(3|ipow(n)) as $power
| [ inCarpet( range(0; $power) ; range(0; $power), -1 )]
| join("") ;
 
 
carpet(3)
The following command produces the required pattern, and so the output is not repeated here:
jq -n -r -c -f sierpinski.jq

Julia

pprint(matrix) = for i = 1:size(matrix,1) println(join(matrix[i,:])) end
 
spaces(m,n) = [" " for i=1:m, j=1:n]
 
function sierpinski(n, token = "*")
x = [token for i=1:1, j=1:1]
for i = 1:n
t = spaces(size(x)...)
x = [[x x x] ; [x t x] ; [x x x]]
end
x
end
Output:
julia> pprint(sierpinski(2, "#"))
#########
# ## ## #
#########
###   ###
# #   # #
###   ###
#########
# ## ## #
#########

Liberty BASIC

NoMainWin
WindowWidth = 508
WindowHeight = 575
Open "Sierpinski Carpets" For Graphics_nsb_nf As #g
#g "Down; TrapClose [halt]"
 
'labels
#g "Place 90 15;\Order 0"
#g "Place 340 15;\Order 1"
#g "Place 90 286;\Order 2"
#g "Place 340 286;\Order 3"
'carpets
Call carpet 5, 20, 243, 0
Call carpet 253, 20, 243, 1
Call carpet 5, 293, 243, 2
Call carpet 253, 293, 243, 3
#g "Flush"
Wait
 
[halt]
Close #g
End
 
Sub carpet x, y, size, order
#g "Color 0 0 128; BackColor 0 0 128"
#g "Place ";x;" ";y
#g "BoxFilled ";x+size-1;" ";y+size-1
#g "Color white; BackColor white"
side = Int(size/3)
newX = x+side
newY = y+side
#g "Place ";newX;" ";newY
#g "BoxFilled ";newX+side-1;" ";newY+side-1
order = order - 1
If order > -1 Then
Call carpet newX-side, newY-side+1, side, order
Call carpet newX, newY-side+1, side, order
Call carpet newX+side, newY-side+1, side, order
Call carpet newX+side, newY, side, order
Call carpet newX+side, newY+side, side, order
Call carpet newX, newY+side, side, order
Call carpet newX-side, newY+side, side, order
Call carpet newX-side, newY, side, order
End If
End Sub

Mathematica

Replace a empty spot with a 3x3 empty matrix, and replace a full spot with an empty spot surrounded by 8 full spots:

full={{1,1,1},{1,0,1},{1,1,1}}
empty={{0,0,0},{0,0,0},{0,0,0}}
n=3;
Grid[Nest[ArrayFlatten[#/.{0->empty,1->full}]&,{{1}},n]//.{0->" ",1->"#"}]

MATLAB

n = 3;
c = string('#');
for k = 1 : n
c = [c + c + c, c + c.replace('#', ' ') + c, c + c + c];
end
disp(c.join(char(10)))
Output:
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################
#########         #########
# ## ## #         # ## ## #
#########         #########
###   ###         ###   ###
# #   # #         # #   # #
###   ###         ###   ###
#########         #########
# ## ## #         # ## ## #
#########         #########
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################

NetRexx

/* NetRexx */
options replace format comments java crossref symbols nobinary
 
numeric digits 1000
runSample(arg)
return
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method runSample(arg) public static
DARK_SHADE = '\u2593'
parse arg ordr filr .
if ordr = '' | ordr = '.' then ordr = 3
if filr = '' | filr = '.' then filler = DARK_SHADE
else filler = filr
drawSierpinskiCarpet(ordr, filler)
return
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method drawSierpinskiCarpet(ordr, filler = Rexx '@') public static binary
x = long
y = long
powr = 3 ** ordr
loop x = 0 to powr - 1
loop y = 0 to powr - 1
if isSierpinskiCarpetCellFilled(x, y) then cell = filler
else cell = ' '
say cell'\-'
end y
say
end x
return
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method isSierpinskiCarpetCellFilled(x = long, y = long) public static binary returns boolean
isTrue = boolean (1 == 1)
isFalse = \isTrue
isFilled = isTrue
loop label edge while x \= 0 & y \= 0
if x // 3 = 1 & y // 3 = 1 then do
isFilled = isFalse
leave edge
end
x = x % 3
y = y % 3
end edge
return isFilled
 
Output:

Sample shown with order "2".

▓▓▓▓▓▓▓▓▓
▓ ▓▓ ▓▓ ▓
▓▓▓▓▓▓▓▓▓
▓▓▓   ▓▓▓
▓ ▓   ▓ ▓
▓▓▓   ▓▓▓
▓▓▓▓▓▓▓▓▓
▓ ▓▓ ▓▓ ▓
▓▓▓▓▓▓▓▓▓

Nim

Translation of: Python
proc `^`*(base: int, exp: int): int =
var (base, exp) = (base, exp)
result = 1
 
while exp != 0:
if (exp and 1) != 0:
result *= base
exp = exp shr 1
base *= base
 
proc inCarpet(x, y): bool =
var x = x
var y = y
while true:
if x == 0 or y == 0:
return true
if x mod 3 == 1 and y mod 3 == 1:
return false
 
x = x div 3
y = y div 3
 
proc carpet(n) =
for i in 0 .. <(3^n):
for j in 0 .. <(3^n):
if inCarpet(i, j):
stdout.write "* "
else:
stdout.write " "
echo ""
 
carpet(3)

Output:

* * * * * * * * * * * * * * * * * * * * * * * * * * * 
*   * *   * *   * *   * *   * *   * *   * *   * *   * 
* * * * * * * * * * * * * * * * * * * * * * * * * * * 
* * *       * * * * * *       * * * * * *       * * * 
*   *       *   * *   *       *   * *   *       *   * 
* * *       * * * * * *       * * * * * *       * * * 
* * * * * * * * * * * * * * * * * * * * * * * * * * * 
*   * *   * *   * *   * *   * *   * *   * *   * *   * 
* * * * * * * * * * * * * * * * * * * * * * * * * * * 
* * * * * * * * *                   * * * * * * * * * 
*   * *   * *   *                   *   * *   * *   * 
* * * * * * * * *                   * * * * * * * * * 
* * *       * * *                   * * *       * * * 
*   *       *   *                   *   *       *   * 
* * *       * * *                   * * *       * * * 
* * * * * * * * *                   * * * * * * * * * 
*   * *   * *   *                   *   * *   * *   * 
* * * * * * * * *                   * * * * * * * * * 
* * * * * * * * * * * * * * * * * * * * * * * * * * * 
*   * *   * *   * *   * *   * *   * *   * *   * *   * 
* * * * * * * * * * * * * * * * * * * * * * * * * * * 
* * *       * * * * * *       * * * * * *       * * * 
*   *       *   * *   *       *   * *   *       *   * 
* * *       * * * * * *       * * * * * *       * * * 
* * * * * * * * * * * * * * * * * * * * * * * * * * * 
*   * *   * *   * *   * *   * *   * *   * *   * *   * 
* * * * * * * * * * * * * * * * * * * * * * * * * * *

Objeck

Translation of: Python
class SierpinskiCarpet {
function : Main(args : String[]) ~ Nil {
Carpet(3);
}
 
function : InCarpet(x : Int, y : Int) ~ Bool {
while(x<>0 & y<>0) {
if(x % 3 = 1 & y % 3 = 1) {
return false;
};
 
x /= 3;
y /= 3;
};
 
return true;
}
 
function : Carpet(n : Int) ~ Nil {
power := 3.0->Power(n->As(Float));
for(i := 0; i < power; i+=1;) {
for(j := 0; j < power; j+=1;) {
c := InCarpet(i, j) ? '*' : ' ';
c->Print();
};
IO.Console->PrintLine();
};
}
}

OCaml

let rec in_carpet x y =
if x = 0 || y = 0 then true
else if x mod 3 = 1 && y mod 3 = 1 then false
else in_carpet (x / 3) (y / 3)
 
(* I define my own operator for integer exponentiation *)
let rec (^:) a b =
if b = 0 then 1
else if b mod 2 = 0 then let x = a ^: (b / 2) in x * x
else a * (a ^: (b - 1))
 
let carpet n =
for i = 0 to (3 ^: n) - 1 do
for j = 0 to (3 ^: n) - 1 do
print_char (if in_carpet i j then '*' else ' ')
done;
print_newline ()
done
Translation of: Ruby
let nextCarpet carpet =
List.map (fun x -> x ^ x ^ x) carpet @
List.map (fun x -> x ^ String.make (String.length x) ' ' ^ x) carpet @
List.map (fun x -> x ^ x ^ x) carpet
 
let rec sierpinskiCarpet n =
let rec aux n carpet =
if n = 0 then carpet
else aux (n-1) (nextCarpet carpet)
in
aux n ["#"]
 
let () =
List.iter print_endline (sierpinskiCarpet 3)

Oforth

: carpet(n) 
| dim i j k |
3 n pow ->dim
 
0 dim 1 - for: i [
0 dim 1 - for: j [
dim 3 / ->k
while(k) [
i k 3 * mod k / 1 == j k 3 * mod k / 1 == and ifTrue: [ break ]
k 3 / ->k
]
k ifTrue: [ " " ] else: [ "#" ] print
]
printcr
] ;

Order

Since the C Preprocessor cannot print newlines, this Order program produces a string for a simple C program to print:

#include <order/interpreter.h>
 
#define ORDER_PP_DEF_8in_carpet ORDER_PP_FN( \
8fn(8X, 8Y, \
8if(8or(8is_0(8X), 8is_0(8Y)), \
8true, \
8let((8Q, 8quotient(8X, 3)) \
(8R, 8remainder(8X, 3)) \
(8S, 8quotient(8Y, 3)) \
(8T, 8remainder(8Y, 3)), \
8and(8not(8and(8equal(8R, 1), 8equal(8T, 1))), \
8in_carpet(8Q, 8S))))) )

 
#define ORDER_PP_DEF_8carpet ORDER_PP_FN( \
8fn(8N, \
8lets((8R, 8seq_iota(0, 8pow(3, 8N))) \
(8G, 8seq_map(8fn(8Y, 8seq_map(8fn(8X, 8pair(8X, 8Y)), \
8R)), \
8R)), \
8seq_map(8fn(8S, 8seq_map(8fn(8P, 8apply(8in_carpet, 8P)), \
8S)), \
8G))) )

 
#define ORDER_PP_DEF_8carpet_to_string ORDER_PP_FN( \
8fn(8C, \
8seq_fold( \
8fn(8R, 8S, \
8adjoin(8R, \
8seq_fold(8fn(8P, 8B, 8adjoin(8P, 8if(8B, 8("#"), 8(" ")))), \
8nil, 8S), \
8("\n"))), \
8nil, 8C)) )

 
#include <stdio.h>
 
int main(void) {
printf(ORDER_PP( 8carpet_to_string(8carpet(3)) ));
return 0;
}

(This example may take a long time to compile: change the 8carpet parameter to 2 for a much quicker compile time and a smaller graphic.)

The 8carpet function creates a 2-dimensional array of boolean values (i.e. an internal representation of the Sierpinski carpet), and the 8carpet_to_string function then converts this to a C string.

Since the # and space characters are rather difficult for the C Preprocessor to handle (as a result Order can only print them, not concatenate them), this program takes advantage of the fact that two string literals side-by-side in C must be interpreted as a single string. An alternative method might be to pass the carpet to a print function, that prints the carpet string and returns nil, and then use a regular C macro to stringify the entire result of the Order program.

Oz

declare
%% A carpet is a list of lines.
fun {NextCarpet Carpet}
{Flatten
[{Map Carpet XXX}
{Map Carpet X_X}
{Map Carpet XXX}
]}
end
 
fun {XXX X} X#X#X end
fun {X_X X} X#{Spaces {VirtualString.length X}}#X end
fun {Spaces N} if N == 0 then nil else & |{Spaces N-1} end end
 
fun lazy {Iterate F X}
X|{Iterate F {F X}}
end
 
SierpinskiCarpets = {Iterate NextCarpet ["#"]}
in
%% print all lines of the Sierpinski carpet of order 3
{ForAll {Nth SierpinskiCarpets 4} System.showInfo}

PARI/GP

Works with: PARI/GP version 2.9.1 and above
Translation of: Python
File:SierpC5.png
Output SierpC5.png
File:SierpC5a.png
Output SierpC5a.png

Plotting helper functions

Note: wrtmat() can be found here on RC Brownian tree page.

 
\\ Improved simple plotting using matrix mat (color and scaling added).
\\ Matrix should be filled with 0/1. 7/6/16 aev
iPlotmat(mat,clr)={
my(xz=#mat[1,],yz=#mat[,1],vx=List(),vy=vx,xmin,xmax,ymin,ymax,c=0.625);
for(i=1,yz, for(j=1,xz, if(mat[i,j]==0, next, listput(vx,i); listput(vy,j))));
xmin=listmin(vx); xmax=listmax(vx); ymin=listmin(vy); ymax=listmax(vy);
plotinit(0); plotcolor(0,clr);
plotscale(0, xmin,xmax,ymin,ymax);
plotpoints(0, Vec(vx)*c,Vec(vy));
plotdraw([0,xmin,ymin]);
print(" *** matrix: ",xz,"x",yz,", ",#vy," DOTS");
}
\\ iPlotV2(): Improved plotting from a file written by the wrtmat(). (color added)
\\ Saving possibly huge generation time if re-plotting needed.
iPlotV2(fn, clr)={
my(F,nf,vx=List(),vy=vx,Vr,xmin,xmax,ymin,ymax,c=0.625);
F=readstr(fn); nf=#F;
print(" *** Plotting from: ", fn, " - ", nf, " DOTS");
for(i=1,nf, Vr=stok(F[i]," "); listput(vx,eval(Vr[1])); listput(vy,eval(Vr[2])));
xmin=listmin(vx); xmax=listmax(vx); ymin=listmin(vy); ymax=listmax(vy);
plotinit(0); plotcolor(0,clr);
plotscale(0, xmin,xmax,ymin,ymax);
plotpoints(0, Vec(vx)*c,Vec(vy));
plotdraw([0,xmin,ymin]);
}
\\ Are x,y inside Sierpinski carpet? (1-yes, 0-no) 6/10/16 aev
inSC(x,y)={
while(1, if(!x||!y,return(1));
if(x%3==1&&y%3==1, return(0));
x\=3; y\=3;);\\wend
}
 

Sierpinski carpet fractal.

 
\\ Sierpinski carpet fractal (n - order, clr - color, dfn - data file name)
\\ 6/10/16, upgraded 11/29/16 aev
pSierpinskiC(n, clr=5, dfn="")={
my(n3=3^n-1,M,pf=n>=5);
if(pf, M=matrix(n3+1,n3+1));
for(i=0,n3, for(j=0,n3,
if(inSC(i,j),
if(pf, M[i+1,j+1]=1, print1("* ")), if(!pf, print1(" ")));
); if(!pf, print(""));
);\\fend i
if(!pf, return(0));
if(dfn=="", c, wrtmat(M, dfn));
}
{\\ Test:
pSierpinskiC(3);
pSierpinskiC(5,14); \\ SierpC5.png, color - navy
}
{pSierpinskiC(5,,"c:\\pariData\\SC5.dat");
iPlotV2("c:\\pariData\\SC5.dat",10);} \\ SierpC5a.png, color - dark-green
 
Output:
> pSierpinskiC(3);
* * * * * * * * * * * * * * * * * * * * * * * * * * *
*   * *   * *   * *   * *   * *   * *   * *   * *   *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
* * *       * * * * * *       * * * * * *       * * *
*   *       *   * *   *       *   * *   *       *   *
* * *       * * * * * *       * * * * * *       * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
*   * *   * *   * *   * *   * *   * *   * *   * *   *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * *                   * * * * * * * * *
*   * *   * *   *                   *   * *   * *   *
* * * * * * * * *                   * * * * * * * * *
* * *       * * *                   * * *       * * *
*   *       *   *                   *   *       *   *
* * *       * * *                   * * *       * * *
* * * * * * * * *                   * * * * * * * * *
*   * *   * *   *                   *   * *   * *   *
* * * * * * * * *                   * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
*   * *   * *   * *   * *   * *   * *   * *   * *   *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
* * *       * * * * * *       * * * * * *       * * *
*   *       *   * *   *       *   * *   *       *   *
* * *       * * * * * *       * * * * * *       * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
*   * *   * *   * *   * *   * *   * *   * *   * *   *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
> pSierpinskiC(5,14); \\ SierpC5.png, color navy
   *** matrix: 243x243, 32768 DOTS
> {pSierpinskiC(5,,"c:\\pariData\\SC5.dat");
iPlotV2("c:\\pariData\\SC5.dat",10);} \\ SierpC5a.png, color - dark-green
 *** matrix(243x243) 32768 DOTS put in c:\pariData\SC5.dat
 *** Plotting from: c:\pariData\SC5.dat - 32768 DOTS

Pascal

Program SierpinskiCarpet;
 
uses
Math;
 
function In_carpet(a, b: longint): boolean;
 
var
x, y: longint;
 
begin
x := a;
y := b;
while true do
begin
if (x = 0) or (y = 0) then
begin
In_carpet := true;
break;
end
else
if ( (x mod 3) = 1 ) and ((y mod 3) = 1) then
begin
In_carpet := false;
break;
end;
x := x div 3;
y := y div 3;
end;
end;
 
procedure Carpet(n: integer);
 
var
i, j: longint;
 
begin
for i := 0 to 3**n - 1 do
begin
for j := 0 to 3**n - 1 do
if In_carpet(i, j) then
write('*')
else
write(' ');
writeln;
end;
end;
 
begin
Carpet(3);
end.
Output:
:> ./SierpinskiCarpet
***************************
* ** ** ** ** ** ** ** ** *
***************************
***   ******   ******   ***
* *   * ** *   * ** *   * *
***   ******   ******   ***
***************************
* ** ** ** ** ** ** ** ** *
***************************
*********         *********
* ** ** *         * ** ** *
*********         *********
***   ***         ***   ***
* *   * *         * *   * *
***   ***         ***   ***
*********         *********
* ** ** *         * ** ** *
*********         *********
***************************
* ** ** ** ** ** ** ** ** *
***************************
***   ******   ******   ***
* *   * ** *   * ** *   * *
***   ******   ******   ***
***************************
* ** ** ** ** ** ** ** ** *
***************************

Perl

my @c = '##'; 
@c = (map($_ x 3, @c), map($_.(' ' x length).$_, @c), map($_ x 3, @c))
for 1 .. 3;
print join("\n", @c), "\n";

Perl 6

Translation of: Tcl
sub carpet
{
(['#'], -> @c {
[ @c.map({$_ x 3}),
@c.map({ $_ ~ $_.trans('#'=>' ') ~ $_}),
@c.map({$_ x 3}) ]
} ... *).map: { .join("\n") };
}
 
say carpet[3];

Same as above, structured as an array bound to a sequence, with a separate sub for clarity.

sub weave ( @c ) {[
@c.map({ $_ x 3 }),
@c.map({ $_ ~ .trans( '#' => ' ' ) ~ $_ }),
@c.map({ $_ x 3 }),
]}
 
my @carpet := ( ['#'], &weave ... * ).map: { .join: "\n" };
 
say @carpet[3];

Output of both versions matches task exemplar.

Phix

Translation of: Euphoria
constant order = 4
 
function InCarpet(atom x, atom y)
while x!=0 and y!=0 do
if floor(mod(x,3))=1 and floor(mod(y,3))=1 then
return ' '
end if
x /= 3
y /= 3
end while
return '#'
end function
 
for i=0 to power(3,order)-1 do
for j=0 to power(3,order)-1 do
puts(1,InCarpet(i,j))
end for
puts(1,'\n')
end for
Output:
#################################################################################
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
#################################################################################
###   ######   ######   ######   ######   ######   ######   ######   ######   ###
# #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # #
###   ######   ######   ######   ######   ######   ######   ######   ######   ###
#################################################################################
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
#################################################################################
#########         ##################         ##################         #########
# ## ## #         # ## ## ## ## ## #         # ## ## ## ## ## #         # ## ## #
#########         ##################         ##################         #########
###   ###         ###   ######   ###         ###   ######   ###         ###   ###
# #   # #         # #   # ## #   # #         # #   # ## #   # #         # #   # #
###   ###         ###   ######   ###         ###   ######   ###         ###   ###
#########         ##################         ##################         #########
# ## ## #         # ## ## ## ## ## #         # ## ## ## ## ## #         # ## ## #
#########         ##################         ##################         #########
#################################################################################
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
#################################################################################
###   ######   ######   ######   ######   ######   ######   ######   ######   ###
# #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # #
###   ######   ######   ######   ######   ######   ######   ######   ######   ###
#################################################################################
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
#################################################################################
###########################                           ###########################
# ## ## ## ## ## ## ## ## #                           # ## ## ## ## ## ## ## ## #
###########################                           ###########################
###   ######   ######   ###                           ###   ######   ######   ###
# #   # ## #   # ## #   # #                           # #   # ## #   # ## #   # #
###   ######   ######   ###                           ###   ######   ######   ###
###########################                           ###########################
# ## ## ## ## ## ## ## ## #                           # ## ## ## ## ## ## ## ## #
###########################                           ###########################
#########         #########                           #########         #########
# ## ## #         # ## ## #                           # ## ## #         # ## ## #
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #
###   ###         ###   ###                           ###   ###         ###   ###
#########         #########                           #########         #########
# ## ## #         # ## ## #                           # ## ## #         # ## ## #
#########         #########                           #########         #########
###########################                           ###########################
# ## ## ## ## ## ## ## ## #                           # ## ## ## ## ## ## ## ## #
###########################                           ###########################
###   ######   ######   ###                           ###   ######   ######   ###
# #   # ## #   # ## #   # #                           # #   # ## #   # ## #   # #
###   ######   ######   ###                           ###   ######   ######   ###
###########################                           ###########################
# ## ## ## ## ## ## ## ## #                           # ## ## ## ## ## ## ## ## #
###########################                           ###########################
#################################################################################
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
#################################################################################
###   ######   ######   ######   ######   ######   ######   ######   ######   ###
# #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # #
###   ######   ######   ######   ######   ######   ######   ######   ######   ###
#################################################################################
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
#################################################################################
#########         ##################         ##################         #########
# ## ## #         # ## ## ## ## ## #         # ## ## ## ## ## #         # ## ## #
#########         ##################         ##################         #########
###   ###         ###   ######   ###         ###   ######   ###         ###   ###
# #   # #         # #   # ## #   # #         # #   # ## #   # #         # #   # #
###   ###         ###   ######   ###         ###   ######   ###         ###   ###
#########         ##################         ##################         #########
# ## ## #         # ## ## ## ## ## #         # ## ## ## ## ## #         # ## ## #
#########         ##################         ##################         #########
#################################################################################
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
#################################################################################
###   ######   ######   ######   ######   ######   ######   ######   ######   ###
# #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # ## #   # #
###   ######   ######   ######   ######   ######   ######   ######   ######   ###
#################################################################################
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
#################################################################################

PicoLisp

Translation of: Ruby
(de carpet (N)
(let Carpet '("#")
(do N
(setq Carpet
(conc
(mapcar '((S) (pack S S S)) Carpet)
(mapcar
'((S) (pack S (replace (chop S) "#" " ") S))
Carpet )
(mapcar '((S) (pack S S S)) Carpet) ) ) ) ) )
 
(mapc prinl (carpet 3))

PL/I

 
/* Sierpinski carpet */
 
Sierpinski_carpet: procedure options (main); /* 28 January 2013 */
 
call carpet(3);
 
In_carpet: procedure (a, b) returns (bit(1));
declare (a, b) fixed binary nonassignable;
declare (x, y) fixed binary;
declare (true value ('1'b), false value ('0'b)) bit (1);
 
x = a ; y = b;
do forever;
if x = 0 | y = 0 then
return (true);
else if mod(x, 3) = 1 & mod(y, 3) = 1 then
return (false);
x = x / 3;
y = y / 3;
end;
end in_carpet;
 
Carpet: procedure (n);
declare n fixed binary nonassignable;
declare (i, j) fixed binary;
 
do i = 0 to 3**n - 1;
do j = 0 to 3**n - 1;
if In_carpet(i, j) then
put edit ('#') (a);
else
put edit (' ') (a);
end;
put skip;
end;
end Carpet;
end Sierpinski_carpet;
 

The above is a translation of the Fortran version. Output for n=3:

###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################
#########         #########
# ## ## #         # ## ## #
#########         #########
###   ###         ###   ###
# #   # #         # #   # #
###   ###         ###   ###
#########         #########
# ## ## #         # ## ## #
#########         #########
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################

PostScript

%!PS-Adobe-3.0
%%BoundingBox 0 0 300 300
 
/r { moveto 0 -1 1 0 0 1 3 { rlineto } repeat closepath fill } def
/serp { gsave
3 1 roll translate
1 3 div dup scale
1 1 r
dup 1 sub dup 0 eq not {
0 0 0 1 0 2 1 0 1 2 2 0 2 1 2 2 17 -1 roll 8 { serp } repeat
} if pop
grestore
} def
 
300 300 scale 0 0 r 1 setgray
 
0 0 5 serp
 
pop showpage
%%EOF

PowerShell

Text based solution

Works with: PowerShell version 2
function Draw-SierpinskiCarpet ( [int]$N )
{
$Carpet = @( '#' ) * [math]::Pow( 3, $N )
ForEach ( $i in 1..$N )
{
$S = [math]::Pow( 3, $i - 1 )
ForEach ( $Row in 0..($S-1) )
{
$Carpet[$Row+$S+$S] = $Carpet[$Row] * 3
$Carpet[$Row+$S] = $Carpet[$Row] + ( " " * $Carpet[$Row].Length ) + $Carpet[$Row]
$Carpet[$Row] = $Carpet[$Row] * 3
}
}
$Carpet
}
 
Draw-SierpinskiCarpet 3
Output:
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################
#########         #########
# ## ## #         # ## ## #
#########         #########
###   ###         ###   ###
# #   # #         # #   # #
###   ###         ###   ###
#########         #########
# ## ## #         # ## ## #
#########         #########
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################

Graphics based solution

Works with: PowerShell version 3
Function Draw-SierpinskiCarpet ( [int]$N )
{
# Define form
$Form = [System.Windows.Forms.Form]@{ Size = '300, 300' }
$Form.Controls.Add(( $PictureBox = [System.Windows.Forms.PictureBox]@{ Size = $Form.ClientSize; Anchor = 'Top, Bottom, Left, Right' } ))
 
# Main code to draw Sierpinski carpet
$Draw = {
 
# Create graphics objects to use
$PictureBox.Image = ( $Canvas = New-Object System.Drawing.Bitmap ( $PictureBox.Size.Width, $PictureBox.Size.Height ) )
$Graphics = [System.Drawing.Graphics]::FromImage( $Canvas )
 
# Draw single pixel
$Graphics.FillRectangle( [System.Drawing.Brushes]::Black, 0, 0, 1, 1 )
 
# If N was not specified, use an N that will fill the form
If ( -not $N ) { $N = [math]::Ceiling( [math]::Log( [math]::Max( $PictureBox.Size.Height, $PictureBox.Size.Width ) ) / [math]::Log( 3 ) ) }
 
# Define the shape of the fractal
$P = @( @( 0, 0 ), @( 0, 1 ), @( 0, 2 ) )
$P += @( @( 1, 0 ), @( 1, 2 ) )
$P += @( @( 2, 0 ), @( 2, 1 ), @( 2, 2 ) )
 
# For each iteration
ForEach ( $i in 0..$N )
{
# Copy the result of the previous iteration
$Copy = New-Object System.Drawing.TextureBrush ( $Canvas )
 
# Calulate the size of the copy
$S = [math]::Pow( 3, $i )
 
# For each position in the next layer of the fractal
ForEach ( $i in 1..7 )
{
# Adjust the copy for the new location
$Copy.TranslateTransform( - $P[$i-1][0] * $S + $P[$i][0] * $S, - $P[$i-1][1] * $S + $P[$i][1] * $S )
 
# Paste the copy of the previous iteration into the new location
$Graphics.FillRectangle( $Copy, $P[$i][0] * $S, $P[$i][1] * $S, $S, $S )
}
}
}
 
# Add the main drawing code to the appropriate events to be drawn when the form is first shown and redrawn when the form size is changed
$Form.Add_Shown( $Draw )
$Form.Add_Resize( $Draw )
 
# Launch the form
$Null = $Form.ShowDialog()
}
 
Draw-SierpinskiCarpet 4
Output:
This example is incomplete. Upload of files currently blocked. Needs output screenshot once file uploading is again allowed. Please ensure that it meets all task requirements and remove this message.

PureBasic

Translation of: Python
Procedure in_carpet(x,y)
While x>0 And y>0
If x%3=1 And y%3=1
ProcedureReturn #False
EndIf
y/3: x/3
Wend
ProcedureReturn #True
EndProcedure
 
Procedure carpet(n)
Define i, j, l=Pow(3,n)-1
For i=0 To l
For j=0 To l
If in_carpet(i,j)
Print("#")
Else
Print(" ")
EndIf
Next
PrintN("")
Next
EndProcedure

Python

This inserts a space after every character; but this makes the spacing look better anyway.

def in_carpet(x, y):
while True:
if x == 0 or y == 0:
return True
elif x % 3 == 1 and y % 3 == 1:
return False
 
x /= 3
y /= 3
 
def carpet(n):
for i in xrange(3 ** n):
for j in xrange(3 ** n):
if in_carpet(i, j):
print '*',
else:
print ' ',
print

This version is elegant:

Translation of: Ruby
def sierpinski_carpet(n):
carpet = ["#"]
for i in xrange(n):
carpet = [x + x + x for x in carpet] + \
[x + x.replace("#"," ") + x for x in carpet] + \
[x + x + x for x in carpet]
return "\n".join(carpet)
 
print sierpinski_carpet(3)

R

Version #1.

Note: Find plotmat() here on RC R Helper Functions page.

Translation of: PARI/GP
Works with: R version 3.3.3 and above
File:SierpCRo5.png
Output SierpCRo5.png
 
## Are x,y inside Sierpinski carpet (and where)? (1-yes, 0-no)
inSC <- function(x, y) {
while(TRUE) {
if(!x||!y) {return(1)}
if(x%%3==1&&y%%3==1) {return(0)}
x=x%/%3; y=y%/%3;
} return(0);
}
## Plotting Sierpinski carpet fractal. aev 4/1/17
## ord - order, fn - file name, ttl - plot title, clr - color
pSierpinskiC <- function(ord, fn="", ttl="", clr="navy") {
m=640; abbr="SCR"; dftt="Sierpinski carpet fractal";
n=3^ord-1; M <- matrix(c(0), ncol=n, nrow=n, byrow=TRUE);
cat(" *** START", abbr, date(), "\n");
if(fn=="") {pf=paste0(abbr,"o", ord)} else {pf=paste0(fn, ".png")};
if(ttl!="") {dftt=ttl}; ttl=paste0(dftt,", order ", ord);
cat(" *** Plot file:", pf,".png", "title:", ttl, "\n");
for(i in 0:n) {
for(j in 0:n) {if(inSC(i,j)) {M[i,j]=1}
}}
plotmat(M, pf, clr, ttl);
cat(" *** END", abbr, date(), "\n");
}
## Executing:
pSierpinskiC(5);
 
Output:
> pSierpinskiC(5);
 *** START SCR Sun Apr 02 12:39:21 2017 
 *** Plot file: SCRo5 .png title: Sierpinski carpet fractal, order 5 
 *** Matrix( 242 x 242 ) 32283 DOTS
 *** END SCR Sun Apr 02 12:39:28 2017 

Version #2.

Note: Find plotmat() here on RC R Helper Functions page.

Works with: R version 3.3.3 and above
File:SierpCR2o5.png
Output SierpCR2o5.png
 
## Plotting Sierpinski carpet fractal v.2. aev 4/2/17
## ord - order, fn - file name, ttl - plot title, clr - color
pSierpinskiC2 <- function(ord, fn="", ttl="", clr="brown") {
m=640; abbr="SCR2"; dftt="Sierpinski carpet fractal v.2";
cat(" *** START", abbr, date(), "\n");
if(fn=="") {pf=paste0(abbr,"o", ord)} else {pf=paste0(fn, ".png")};
if(ttl!="") {dftt=ttl}; ttl=paste0(dftt,", order ", ord);
cat(" *** Plot file:", pf,".png", "title:", ttl, "\n");
S = matrix(1,1,1);
for (i in 1:ord) {
Q = cbind(S,S,S); R = cbind(S,0*S,S); S = rbind(Q,R,Q);
}
plotmat(S, pf, clr, ttl);
cat(" *** END", abbr, date(), "\n");
}
## Executing:
pSierpinskiC2(5);
 
Output:
> pSierpinskiC2(5);
 *** START SCR2 Sun Apr 02 14:44:17 2017 
 *** Plot file: SCR2o5 .png title: Sierpinski carpet fractal v.2, order 5 
 *** Matrix( 243 x 243 ) 32768 DOTS
 *** END SCR2 Sun Apr 02 14:44:24 2017 

REXX

/*REXX program draws any order Sierpinski carpet (order 20 would be ≈ 3.4Gx3.4G carpet).*/
parse arg N char . /*get the order of the carpet. */
if N=='' | N=="," then N=3 /*if none specified, then assume 3. */
if char=='' then char="*" /*use the default of an asterisk (*). */
if length(char)==2 then char=x2c(char) /*it was specified in hexadecimal char.*/
if length(char)==3 then char=d2c(char) /* " " " " decimal character*/
width=linesize() /*the width of the terminal screen. */
if N>18 then numeric digits 100 /*just in case the user went ka─razy. */
nnn=3**N /* [↓] NNN is the cube of N. */
 
do j=0 for nnn; z= /*Z: is the line to be displayed. */
do k=0 for nnn; jj=j; kk=k; x=char
do while jj\==0 & kk\==0 /*one symbol for a not (¬) is a \ */
if jj//3==1 then if kk//3==1 then do /*in REXX: // ≡ division remainder*/
x=' ' /*use a blank for this display line. */
leave /*LEAVE terminates this DO WHILE. */
end
jj=jj%3; kk=kk%3 /*in REXX:  % ≡ integer division. */
end /*while*/
 
z=z || x /*xChar is either black or white. */
end /*k*/ /* [↑] " " " " blank. */
 
if length(z)<width then say z /*display the line if it fits on screen*/
call lineout 'Sierpinski.'N, z /*also, write the line to a (disk) file*/
end /*j*/ /*stick a fork in it, we're all done. */

This REXX program makes use of   linesize   REXX program (or BIF) which is used to determine the screen width (or linesize) of the terminal (console).

Some REXXes don't have this BIF, so the   linesize.rex   REXX program is included here   ──►   LINESIZE.REX.


output   (when using the default for input):

***************************
* ** ** ** ** ** ** ** ** *
***************************
***   ******   ******   ***
* *   * ** *   * ** *   * *
***   ******   ******   ***
***************************
* ** ** ** ** ** ** ** ** *
***************************
*********         *********
* ** ** *         * ** ** *
*********         *********
***   ***         ***   ***
* *   * *         * *   * *
***   ***         ***   ***
*********         *********
* ** ** *         * ** ** *
*********         *********
***************************
* ** ** ** ** ** ** ** ** *
***************************
***   ******   ******   ***
* *   * ** *   * ** *   * *
***   ******   ******   ***
***************************
* ** ** ** ** ** ** ** ** *
***************************

output   when using for input:   2   db

█████████
█ ██ ██ █
█████████
███   ███
█ █   █ █
███   ███
█████████
█ ██ ██ █
█████████

Racket

 
#lang racket
(define (carpet n)
(if (zero? n)
'("#")
(let* ([prev (carpet (sub1 n))]
[spaces (regexp-replace* #rx"#" (car prev) " ")])
(append (map (λ(x) (~a x x x)) prev)
(map (λ(x) (~a x spaces x)) prev)
(map (λ(x) (~a x x x)) prev)))))
(for-each displayln (carpet 3))
 

Ring

 
load "guilib.ring"
 
new qapp
{
win1 = new qwidget() {
etwindowtitle("drawing using qpainter")
setgeometry(100,100,500,500)
label1 = new qlabel(win1) {
setgeometry(10,10,400,400)
settext("")
}
new qpushbutton(win1) {
setgeometry(200,450,100,30)
settext("draw")
setclickevent("draw()")
}
show()
}
exec()
}
 
func draw
p1 = new qpicture()
color = new qcolor() {
setrgb(0,0,255,255)
}
pen = new qpen() {
setcolor(color)
setwidth(1)
}
new qpainter() {
begin(p1)
setpen(pen)
 
order = 3
side = pow(3,order)
for y = 0 to side-1
for x = 0 to side-1
if carpet(self,x,y)
drawpoint(x*16,y*16+15)
drawpoint(x*16+1,y*16+16)
drawpoint(x*16+2,y*16+17) ok
next
next
 
endpaint()
}
label1 { setpicture(p1) show() }
 
func carpet myObj,x,y
myObj{while x!=0 and y!=0
if x % 3 = 1 if y % 3 = 1 return false ok ok
x = floor(x/3)
y = floor(y/3)
end
return true}
 

Output: CalmoSoftCarpet.jpg

Ruby

Translation of: Tcl
def sierpinski_carpet(n)
carpet = ["#"]
n.times do
carpet = carpet.collect {|x| x + x + x} +
carpet.collect {|x| x + x.tr("#"," ") + x} +
carpet.collect {|x| x + x + x}
end
carpet
end
 
4.times{|i| puts "\nN=#{i}", sierpinski_carpet(i)}
Output:
N=0
#

N=1
###
# #
###

N=2
#########
# ## ## #
#########
###   ###
# #   # #
###   ###
#########
# ## ## #
#########

N=3
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################
#########         #########
# ## ## #         # ## ## #
#########         #########
###   ###         ###   ###
# #   # #         # #   # #
###   ###         ###   ###
#########         #########
# ## ## #         # ## ## #
#########         #########
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################

Scala

Translation of: Ruby
def nextCarpet(carpet: List[String]): List[String] = (
carpet.map(x => x + x + x) :::
carpet.map(x => x + x.replace('#', ' ') + x) :::
carpet.map(x => x + x + x))
 
def sierpinskiCarpets(n: Int) = (Iterator.iterate(List("#"))(nextCarpet) drop n next) foreach println

Scheme

(define (carpet n)
(define (in-carpet? x y)
(cond ((or (zero? x) (zero? y))
#t)
((and (= 1 (remainder x 3)) (= 1 (remainder y 3)))
#f)
(else
(in-carpet? (quotient x 3) (quotient y 3)))))
 
(do ((i 0 (+ i 1))) ((not (< i (expt 3 n))))
(do ((j 0 (+ j 1))) ((not (< j (expt 3 n))))
(display (if (in-carpet? i j)
#\*
#\space)))
(newline)))

Seed7

$ include "seed7_05.s7i";
 
const func boolean: inCarpet (in var integer: x, in var integer: y) is func
result
var boolean: result is TRUE;
begin
while result and x <> 0 and y <> 0 do
if x rem 3 = 1 and y rem 3 = 1 then
result := FALSE;
else
x := x div 3;
y := y div 3;
end if;
end while;
end func;
 
const proc: carpet (in integer: n) is func
local
var integer: i is 0;
var integer: j is 0;
begin
for i range 0 to pred(3 ** n) do
for j range 0 to pred(3 ** n) do
if inCarpet(i, j) then
write("#");
else
write(" ");
end if;
end for;
writeln;
end for;
end func;
 
const proc: main is func
begin
carpet(3);
end func;

Sidef

var c = ['##']
3.times {
c = (c.map{|x| x * 3 } +
c.map{|x| x + ' '*x.len + x } +
c.map{|x| x * 3 })
}
say c.join("\n")

Swift

Translation of: Ruby
import Foundation
func sierpinski_carpet(n:Int) -> String {
func middle(str:String) -> String {
let spacer = str.stringByReplacingOccurrencesOfString("#", withString:" ", options:nil, range:nil)
return str + spacer + str
}
 
var carpet = ["#"]
for i in 1...n {
let a = carpet.map{$0 + $0 + $0}
let b = carpet.map(middle)
carpet = a + b + a
}
return "\n".join(carpet)
}
 
println(sierpinski_carpet(3))

Tcl

package require Tcl 8.5
 
proc map {lambda list} {
foreach elem $list {
lappend result [apply $lambda $elem]
}
return $result
}
 
proc sierpinski_carpet n {
set carpet [list "#"]
for {set i 1} {$i <= $n} {incr i} {
set carpet [concat \
[map {x {subst {$x$x$x}}} $carpet] \
[map {x {subst {$x[string map {"#" " "} $x]$x}}} $carpet] \
[map {x {subst {$x$x$x}}} $carpet] \
]
}
return [join $carpet \n]
}
 
puts [sierpinski_carpet 3]

uBasic/4tH

Input "Carpet order: ";n
 
l = (3^n) - 1
For i = 0 To l
For j = 0 To l
Push i,j
Gosub 100
If Pop() Then
Print "#";
Else
Print " ";
EndIf
Next
Print
Next
End
 
100 y = Pop(): x = Pop() : Push 1
 
Do While (x > 0) * (y > 0)
If (x % 3 = 1) * (y % 3 = 1) Then
Push (Pop() - 1)
Break
EndIf
y = y / 3
x = x / 3
Loop
 
Return

UNIX Shell

Works with: Bash

Doesn't pretend to be efficient.

Note that this code inserts a space between characters; some versions of paste(1) (notably the one that ships with OS X) won't allow an empty delimiter. If yours does, you can replace the -d ' ' in the function body with -d ' ' for more compact output.

#!/bin/bash
 
sierpinski_carpet() {
local -i n="${1:-3}"
local carpet="${2:-#}"
while (( n-- )); do
local center="${carpet//#/ }"
carpet="$(paste -d ' ' <(echo "$carpet"$'\n'"$carpet"$'\n'"$carpet") <(echo "$carpet"$'\n'"$center"$'\n'"$carpet") <(echo "$carpet"$'\n'"$carpet"$'\n'"$carpet"))"
done
echo "$carpet"
}

Sample run:

$ sierpinski_carpet 3
# # # # # # # # # # # # # # # # # # # # # # # # # # #
#   # #   # #   # #   # #   # #   # #   # #   # #   #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
# # #       # # # # # #       # # # # # #       # # #
#   #       #   # #   #       #   # #   #       #   #
# # #       # # # # # #       # # # # # #       # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
#   # #   # #   # #   # #   # #   # #   # #   # #   #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # #                   # # # # # # # # #
#   # #   # #   #                   #   # #   # #   #
# # # # # # # # #                   # # # # # # # # #
# # #       # # #                   # # #       # # #
#   #       #   #                   #   #       #   #
# # #       # # #                   # # #       # # #
# # # # # # # # #                   # # # # # # # # #
#   # #   # #   #                   #   # #   # #   #
# # # # # # # # #                   # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
#   # #   # #   # #   # #   # #   # #   # #   # #   #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
# # #       # # # # # #       # # # # # #       # # #
#   #       #   # #   #       #   # #   #       #   #
# # #       # # # # # #       # # # # # #       # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
#   # #   # #   # #   # #   # #   # #   # #   # #   #
# # # # # # # # # # # # # # # # # # # # # # # # # # #

Ursala

The carpet function works for any natural number n and is tested on 0,1,2, and 3. The carpet is stored as a list of lists of booleans but converted to characters for display.

#import std
#import nat
 
carpet = ~&a^?\<<&>>! (-*<7,5,7>; *=DS ~&K7+ ~&B**DS*=rlDS)^|R/~& predecessor
 
#show+
 
test = mat0 ~&?(`#!,` !)*** carpet* <0,1,2,3>
Output:
#

###
# #
###

#########
# ## ## #
#########
###   ###
# #   # #
###   ###
#########
# ## ## #
#########

###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################
#########         #########
# ## ## #         # ## ## #
#########         #########
###   ###         ###   ###
# #   # #         # #   # #
###   ###         ###   ###
#########         #########
# ## ## #         # ## ## #
#########         #########
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################

VBScript

Function InCarpet(i,j)
If i > 0 And j > 0 Then
Do While i > 0 And j > 0
If i Mod 3 = 1 And j Mod 3 = 1 Then
InCarpet = " "
Exit Do
Else
InCarpet = "#"
End If
i = Int(i / 3)
j = Int(j / 3)
Loop
Else
InCarpet = "#"
End If
End Function
 
Function Carpet(n)
k = 3^n - 1
x2 = 0
y2 = 0
For y = 0 To k
For x = 0 To k
x2 = x
y2 = y
WScript.StdOut.Write InCarpet(x2,y2)
Next
WScript.StdOut.WriteBlankLines(1)
Next
End Function
 
Carpet(WScript.Arguments(0))
Output:
F:\VBScript>cscript /nologo RosettaCode-Sierpinski_Carpet.vbs 3
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################
#########         #########
# ## ## #         # ## ## #
#########         #########
###   ###         ###   ###
# #   # #         # #   # #
###   ###         ###   ###
#########         #########
# ## ## #         # ## ## #
#########         #########
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################

X86 Assembly

Uses magic number division to avoid repeatedly using the div instruction in a loop.

;x86-64 assembly code for Microsoft Windows
;Tested in windows 7 Enterprise Service Pack 1 64 bit
;With the AMD FX(tm)-6300 processor
;Assembled with NASM version 2.11.06
;Linked to C library with gcc version 4.9.2 (x86_64-win32-seh-rev1, Built by MinGW-W64 project)
 
;Assembled and linked with the following commands:
;nasm -f win64 <filename>.asm -o <filename>.obj
;gcc <filename>.obj -o <filename>
 
;Takes magnitude of Sierpinski Carpet as command line argument.
 
extern atoi,puts,putchar,exit
 
section .data
errmsg_noarg: db "Magnitude of Sierpinski Carpet was not specified.",0
errmsg_argnumber: db "There should be no more than one argument.",0
 
section .bss
 
section .text
global main
 
main:
 
;check for argument
cmp rcx,1
jle err_noarg
 
;ensure that only one argument was entered
cmp rcx,2
jg err_argnumber
 
;column in rsi
;row in rdi
;x in r8
;y in r9
;width in r13
;magic number in r14
 
mov r14,2863311531
 
;get magnitude in rbx from first arg
mov rcx,[rdx + 8]
call atoi
mov rbx,rax
 
cmp rbx,0
jz magnitude_zero
 
 
;determine dimensions of square
mov rax,1
 
find_width:
 
lea rax,[rax * 3]
 
dec rbx
jg find_width
 
sub rax,1
 
mov r13,rax
mov rdi,rax
 
 
next_row:
 
mov rsi,r13
 
fill_row:
 
;x in r8, y in r9
mov r8,rsi
mov r9,rdi
 
is_filled:
 
;if(x%3==1 && y%3==1)
;x%3 in rbx
mov rax,r8
mov rbx,r8
mul r14
shr rax,33
mov r8,rax
lea rax,[rax * 3]
sub rbx,rax
 
;y%3 in rcx
mov rax,r9
mov rcx,r9
mul r14
shr rax,33
mov r9,rax
lea rax,[rax * 3]
sub rcx,rax
 
;x%3==1 && y%3==1
xor rbx,1
xor rcx,1
or rbx,rcx
mov rcx,' '
cmp rbx,0
jz dont_fill
 
;x>0 || y>0
mov rax,r8
or rax,r9
cmp rax,0
jg is_filled
 
mov rcx,'#'
dont_fill:
 
call putchar
 
dec rsi
jge fill_row
 
;put newline at the end of each row
mov rcx,0xa
call putchar
 
dec rdi
jge next_row
 
xor rcx,rcx
call exit
 
magnitude_zero:
 
mov rcx,'#'
call putchar
 
mov rcx,0xa
call putchar
 
xor rcx,rcx
call exit
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;error message
 
err_noarg:
 
mov rcx,errmsg_noarg
call puts
 
mov rcx,1
call exit
 
 
err_argnumber:
 
mov rcx,errmsg_argnumber
call puts
 
mov rcx,1
call exit
Sample:
F:\>asciisierpinski.exe
Magnitude of Sierpinski Carpet was not specified.

F:\>asciisierpinski.exe 1 1 1
There should be no more than one arguement.

F:\>asciisierpinski.exe 0
#

F:\>asciisierpinski.exe 1
###
# #
###

F:\>asciisierpinski.exe 2
#########
# ## ## #
#########
###   ###
# #   # #
###   ###
#########
# ## ## #
#########

F:\>asciisierpinski.exe 3
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################
#########         #########
# ## ## #         # ## ## #
#########         #########
###   ###         ###   ###
# #   # #         # #   # #
###   ###         ###   ###
#########         #########
# ## ## #         # ## ## #
#########         #########
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################

XPL0

CarpetXPL0.gif
include c:\cxpl\codes;          \intrinsic 'code' declarations
 
proc DrawPat(X0, Y0, S); \Draw 3x3 pattern with hole in middle
int X0, Y0, S; \coordinate of upper-left corner, size
int X, Y;
[for Y:= 0 to 2 do
for X:= 0 to 2 do
if X#1 or Y#1 then \don't draw middle pattern
[if S>1 then \recurse
DrawPat(X*S+X0, Y*S+Y0, S/3)
else Point(X+X0, Y+Y0, 4\red\);
];
];
 
[SetVid($13); \set 320x200 graphic video mode
DrawPat(0, 0, 3*3*3); \draw Sierpinski carpet
if ChIn(1) then []; \wait for keystroke
SetVid($3); \restore normal text mode
]

zkl

Sierpinski carpet.zkl.gif
Translation of: XPL0

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

fcn drawPat(x0,y0,s,img){  // Draw 3x3 pattern with hole in middle
foreach y,x in (3,3){
if(x.isEven or y.isEven){ // don't draw middle pattern
if(s>1) self.fcn(x*s + x0, y*s + y0, s/3, img); // recurse
else img[x + x0, y + y0]=0xff0000; // red
}
}
}
img:=PPM(800,800);
drawPat(0,0,(3).pow(5),img);
img.write(File("foo.ppm","wb"));