Sierpinski triangle
From Rosetta Code
Programming Task
This is a programming task. It lays out a problem which Rosetta Code users are encouraged to solve, using languages they know.
Produce an ASCII representation of a Sierpinski triangle of order N. For example, the Sierpinski triangle of order 4 should look like this:
*
* *
* *
* * * *
* *
* * * *
* * * *
* * * * * * * *
* *
* * * *
* * * *
* * * * * * * *
* * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
See also Sierpinski carpet
Contents |
[edit] Ada
This Ada example creates a string of the binary value for each line, converting the '0' values to spaces.
with Ada.Text_Io; use Ada.Text_Io; with Ada.Strings.Fixed; with Interfaces; use Interfaces; procedure Sieteri_Triangles is subtype Practical_Order is Unsigned_32 range 0..4; function Pow(X : Unsigned_32; N : Unsigned_32) return Unsigned_32 is begin if N = 0 then return 1; else return X * Pow(X, N - 1); end if; end Pow; procedure Print(Item : Unsigned_32) is use Ada.Strings.Fixed; package Ord_Io is new Ada.Text_Io.Modular_Io(Unsigned_32); use Ord_Io; Temp : String(1..36) := (others => ' '); First : Positive; Last : Positive; begin Put(To => Temp, Item => Item, Base => 2); First := Index(Temp, "#") + 1; Last := Index(Temp(First..Temp'Last), "#") - 1; for I in reverse First..Last loop if Temp(I) = '0' then Put(' '); else Put(Temp(I)); end if; end loop; New_Line; end Print; procedure Sierpinski (N : Practical_Order) is Size : Unsigned_32 := Pow(2, N); V : Unsigned_32 := Pow(2, Size); begin for I in 0..Size - 1 loop Print(V); V := Shift_Left(V, 1) xor Shift_Right(V,1); end loop; end Sierpinski; begin for N in Practical_Order loop Sierpinski(N); end loop; end Sieteri_Triangles;
[edit] BASIC
Works with: FreeBASIC
Works with: RapidQ
SUB triangle (x AS Integer, y AS Integer, length AS Integer, n AS Integer) IF n = 0 THEN LOCATE y,x: PRINT "*"; ELSE triangle (x, y+length, length/2, n-1) triangle (x+length, y, length/2, n-1) triangle (x+length*2, y+length, length/2, n-1) END IF END SUB CLS triangle 1,1,16,5
Note: The total height of the triangle is 2 * parameter length. It should be power of two so that the pattern matches evenly with the character cells. Value 16 will thus create pattern of 32 lines.
[edit] Common Lisp
(defun print-sierpinski (order)
(loop with size = (expt 2 order)
repeat size
for v = (expt 2 (1- size)) then (logxor (ash v -1) (ash v 1))
do (fresh-line)
(loop for i below (integer-length v)
do (princ (if (logbitp i v) "*" " ")))))
Printing each row could also be done by printing the integer in base 2 and replacing zeroes with spaces: (princ (substitute #\Space #\0 (format nil "~%~2,vR" (1- (* 2 size)) v)))
Replacing the iteration with for v = 1 then (logxor v (ash v 1)) produces a "right" triangle instead of an "equilateral" one.
[edit] D
Adapted from Java version (this version is slower than the Python one).
import std.stdio, std.string; string[] sierpinski(int n) { string[] parts = ["*"]; string space = " "; for (int i; i < n; i++) { string[] parts2; foreach (x; parts) parts2 ~= space ~ x ~ space; foreach (x; parts) parts2 ~= x ~ " " ~ x; parts = parts2; space ~= space; } return parts; } void main() { writefln(sierpinski(4).join("\n")); }
That sierpinski() function can run at compile time too, so with a compile-time join it can compute the whole result at compile-time:
string[] sierpinski(int n) { string[] parts = ["*"]; string space = " "; for (int i; i < n; i++) { string[] parts2; foreach (x; parts) parts2 ~= space ~ x ~ space; foreach (x; parts) parts2 ~= x ~ " " ~ x; parts = parts2; space ~= space; } return parts; } string joinCT(string[] parts, char sep) { string result; if (parts.length) { foreach (part; parts[0 .. $-1]) { result ~= part; result ~= sep; } result ~= parts[$-1]; } return result; } pragma(msg, sierpinski(4).joinCT('\n')); void main() {}
[edit] Forth
: stars ( mask -- )
begin
dup 1 and if [char] * else bl then emit
1 rshift dup
while space repeat drop ;
: triangle ( order -- )
1 swap lshift ( 2^order )
1 over 0 do
cr over i - spaces dup stars
dup 2* xor
loop 2drop ;
5 triangle
[edit] Haskell
sierpinski 0 = ["*"]
sierpinski (n+1) = map ((space ++) . (++ space)) down
++ map (unwords . replicate 2) down
where down = sierpinski n
space = replicate (2^n) ' '
printSierpinski = mapM_ putStrLn . sierpinski
[edit] IDL
The only 'special' thing here is that the math is done in a byte array, filled with the numbers 32 and 42 and then output through a "string(array)" which prints the ascii representation of each individual element in the array.
pro sierp,n
s = (t = bytarr(3+2^(n+1))+32b)
t[2^n+1] = 42b
for lines = 1,2^n do begin
print,string( (s = t) )
for i=1,n_elements(t)-2 do if s[i-1] eq s[i+1] then t[i]=32b else t[i]=42b
end
end
[edit] J
There are any number of succinct ways to produce this in J. Here's one that exploits self-similarity:
|._31]\,(,.~,])^:4,:'* '
Here's one that leverages the relationship between Sierpinski's and Pascal's triangles:
' *'{~'1'=(-|."_1[:":2|!/~)i.-16
[edit] Java
Translation of: JavaScript
public static void triangle(int n){ n= 1 << n; StringBuilder line= new StringBuilder(); //use a "mutable String" char t= 0; char u= 0; // avoid warnings for(int i= 0;i <= 2 * n;++i) line.append(" "); //start empty line.setCharAt(n, '*'); //with the top point of the triangle for(int i= 0;i < n;++i){ System.out.println(line); u= '*'; for(int j= n - i;j < n + i + 1;++j){ t= (line.charAt(j - 1) == line.charAt(j + 1) ? ' ' : '*'); line.setCharAt(j - 1, u); u= t; } line.setCharAt(n + i, t); line.setCharAt(n + i + 1, '*'); } }
Translation of: Haskell
import java.util.*; public class Sierpinski { public static List<String> sierpinski(int n) { List<String> down = Arrays.asList("*"); String space = " "; for (int i = 0; i < n; i++) { List<String> newDown = new ArrayList<String>(); for (String x : down) newDown.add(space + x + space); for (String x : down) newDown.add(x + " " + x); down = newDown; space += space; } return down; } public static void main(String[] args) { for (String x : sierpinski(4)) System.out.println(x); } }
[edit] JavaScript
function triangle(o) { var n = 1<<o, line = new Array(2*n), i,j,t,u; for (i=0; i<line.length; ++i) line[i] = ' '; line[n] = '*'; for (i=0; i<n; ++i) { document.write(line.join('')+"\n"); u ='*'; for(j=n-i; j<n+i+1; ++j) { t = (line[j-1] == line[j+1] ? ' ' : '*'); line[j-1] = u; u = t; } line[n+i] = t; line[n+i+1] = '*'; } } document.write("<pre>\n"); triangle(6); document.write("</pre>");
[edit] Logo
This will draw a graphical Sierpinski gasket using turtle graphics.
to sierpinski :n :length if :n = 0 [stop] repeat 3 [sierpinski :n-1 :length/2 fd :length rt 120] end seth 30 sierpinski 5 200
[edit] OCaml
let sierpinski n = let rec loop down space n = if n = 0 then down else loop (List.map (fun x -> space ^ x ^ space) down @ List.map (fun x -> x ^ " " ^ x) down) (space ^ space) (n - 1) in loop ["*"] " " n let () = List.iter print_endline (sierpinski 4)
[edit] Perl
sub sierpinski { my ($n) = @_; my @down = '*'; my $space = ' '; foreach (1..$n) { @down = (map("$space$_$space", @down), map("$_ $_", @down)); $space = "$space$space"; } return @down; } print "$_\n" foreach sierpinski 4;
[edit] Pop11
Solution using line buffer in an integer array oline, 0 represents ' ' (space), 1 represents '*' (star).
define triangle(n);
lvars k = 2**n, j, l, oline, nline;
initv(2*k+3) -> oline;
initv(2*k+3) -> nline;
for l from 1 to 2*k+3 do 0 -> oline(l) ; endfor;
1 -> oline(k+2);
0 -> nline(1);
0 -> nline(2*k+3);
for j from 1 to k do
for l from 1 to 2*k+3 do
printf(if oline(l) = 0 then ' ' else '*' endif);
endfor;
printf('\n');
for l from 2 to 2*k+2 do
(oline(l-1) + oline(l+1)) rem 2 -> nline(l);
endfor;
(oline, nline) -> (nline, oline);
endfor;
enddefine;
triangle(4);
Alternative solution, keeping all triangle as list of strings
define triangle2(n);
lvars acc = ['*'], spaces = ' ', j;
for j from 1 to n do
maplist(acc, procedure(x); spaces >< x >< spaces ; endprocedure)
<> maplist(acc, procedure(x); x >< ' ' >< x ; endprocedure) -> acc;
spaces >< spaces -> spaces;
endfor;
applist(acc, procedure(x); printf(x, '%p\n'); endprocedure);
enddefine;
triangle2(4);
[edit] Python
def sierpinski(n): d = ["*"] for i in xrange(n): sp = " " * (2 ** i) d = [sp+x+sp for x in d] + [x+" "+x for x in d] return d print "\n".join(sierpinski(4))
[edit] Ruby
From the command line:
ruby -le'16.times{|y|print" "*(15-y),(0..y).map{|x|~y&x>0?" ":" *"}}'
[edit] Scheme
Translation of: Haskell
(define (sierpinski n) (for-each (lambda (x) (display (list->string x)) (newline)) (let loop ((acc (list (list #\*))) (spaces (list #\ )) (n n)) (if (zero? n) acc (loop (append (map (lambda (x) (append spaces x spaces)) acc) (map (lambda (x) (append x (list #\ ) x)) acc)) (append spaces spaces) (- n 1))))))
[edit] Vedit macro language
[edit] Iterative
Translation of: JavaScript
The macro writes the fractal into an edit buffer where it can be viewed and saved to file if required. This allows creating images larger than screen, the size is only limited by free disk space.
#3 = 16 // size (height) of the triangle
Buf_Switch(Buf_Free) // Open a new buffer for output
Ins_Char(' ', COUNT, #3*2+2) // fill first line with spaces
Ins_Newline
Line(-1) Goto_Col(#3)
Ins_Char('*', OVERWRITE) // the top of triangle
for (#10=0; #10 < #3-1; #10++) {
BOL Reg_Copy(9,1) Reg_Ins(9) // duplicate the line
#20 = '*'
for (#11 = #3-#10; #11 < #3+#10+1; #11++) {
Goto_Col(#11-1)
if (Cur_Char==Cur_Char(2)) { #21=' ' } else { #21='*' }
Ins_Char(#20, OVERWRITE)
#20 = #21
}
Ins_Char(#21, OVERWRITE)
Ins_Char('*', OVERWRITE)
}
[edit] Recursive
Translation of: BASIC
Vedit macro language does not have recursive functions, so some pushing and popping is needed to implement recursion.
#1 = 1 // x
#2 = 1 // y
#3 = 16 // length (height of the triangle / 2)
#4 = 5 // depth of recursion
Buf_Switch(Buf_Free) // Open a new buffer for output
Ins_Newline(#3*2) // Create as many empty lines as needed
Call("Triangle") // Draw the triangle
BOF
Return
:Triangle:
if (#4 == 0) {
Goto_Line(#2)
EOL Ins_Char(' ', COUNT, #1-Cur_Col+1) // add spaces if needed
Goto_Col(#1)
Ins_Char('*', OVERWRITE)
} else {
Num_Push(1,4)
#2 += #3; #3 /= 2; #4--; Call("Triangle")
Num_Pop(1,4)
Num_Push(1,4)
#1 += #3; #3 /= 2; #4--; Call("Triangle")
Num_Pop(1,4)
Num_Push(1,4)
#1 += 2*#3; #2 += #3; #3 /= 2; #4--; Call("Triangle")
Num_Pop(1,4)
}
Return
Categories: Programming Tasks | Fractals | Ada | BASIC | Common Lisp | D | Forth | Haskell | IDL | J | Java | JavaScript | Logo | OCaml | Perl | Pop11 | Python | Ruby | Scheme | Vedit macro language

