Sierpinski triangle: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Perl}}: ++ pascal)
(add Tcl)
Line 573: Line 573:
(- n 1))))))
(- n 1))))))
</lang>
</lang>

=={{header|Tcl}}==
{{trans|Perl}}
<lang tcl>package require Tcl 8.5

proc map {lambda list} {
foreach elem $list {
lappend result [apply $lambda $elem]
}
return $result
}

proc sierpinski_triangle n {
set down [list *]
set space " "
for {set i 1} {$i <= $n} {incr i} {
set down [concat \
[map [subst -nocommands {x {expr {"$space[set x]$space"}}}] $down] \
[map {x {expr {"$x $x"}}} $down] \
]
append space $space
}
return [join $down \n]
}

puts [sierpinski_triangle 4]</lang>


=={{header|Vedit macro language}}==
=={{header|Vedit macro language}}==

Revision as of 10:48, 1 May 2009

Task
Sierpinski triangle
You are encouraged to solve this task according to the task description, using any language you may 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

Ada

This Ada example creates a string of the binary value for each line, converting the '0' values to spaces. <lang ada>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;</lang>

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

<lang algol>PROC sierpinski = (INT n)[]STRING: (

   FLEX[0]STRING d := "*";
   FOR i TO n DO
       [UPB d * 2]STRING next;
       STRING sp := " " * (2 ** (i-1));
       FOR x TO UPB d DO
         STRING dx = d[x];
         next[x] := sp+dx+sp;
         next[UPB d+x] := dx+" "+dx
       OD;
       d := next
   OD;
   d

);

printf(($gl$,sierpinski(4)))</lang>

BASIC

Works with: FreeBASIC
Works with: RapidQ

<lang freebasic>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</lang>

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.

C

This solution uses a cellular automaton (rule 90) with a proper initial status.

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <stdbool.h>
  3. include <string.h>
  1. ifndef _POSIX_C_SOURCE

char *strdup(char *s) {

 int l = strlen(s);
 char *r = malloc(l+1);
 memcpy(r, s, l+1);
 return r;

}

  1. endif
  1. define truth(X) ((X)=='*'?true:false)

void rule_90(char *evstr) {

 int i;
 int l = strlen(evstr);
 bool s[3];
 char *cp = strdup(evstr);
 for(i=0;i < l; i++) {
   s[1] = truth(cp[i]);
   s[0] = (i-1) < 0 ? false : truth(cp[i-1]);
   s[2] = (i+1) < l ? truth(cp[i+1]) : false;
   if ( (s[0] && !s[2]) || (!s[0] && s[2]) ) {
     evstr[i] = '*';
   } else {
     evstr[i] = ' ';
   }
 }
 free(cp);

}</lang>

<lang c>void sierpinski_triangle(int n) {

 int i;
 int l = 1<<(n+1);
 char *b = malloc(l+1);
 memset(b, ' ', l);
 b[l] = 0;
 b[l>>1] = '*';
 printf("%s\n", b);
 for(i=0; i < l/2-1;i++) {
   rule_90(b);
   printf("%s\n", b);
 }
 free(b);

}</lang>

<lang c>int main() {

 sierpinski_triangle(4);
 return EXIT_SUCCESS;

}</lang>

Common Lisp

<lang 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) "*" " ")))))</lang>

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.

D

Adapted from Java version (this version is slower than the Python one). <lang d>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"));

}</lang>

That sierpinski() function can run at compile time too, so with a compile-time join it can compute the whole result at compile-time:

<lang d> 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() {} </lang>

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

Haskell

<lang 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</lang>

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

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

Java

Translation of: JavaScript

<lang java>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, '*');
       }

}</lang>

Translation of: Haskell

<lang java> 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);
   }

} </lang>

JavaScript

<lang 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("

\n");
 triangle(6);
 document.write("

");

</lang>

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

OCaml

<lang 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)

</lang>

Pascal

Translation of: C
Works with: Free Pascal

<lang pascal>program Sierpinski;

function ipow(b, n : Integer) : Integer; var

  i : Integer;

begin

  ipow := 1;
  for i := 1 to n do
     ipow := ipow * b

end;

function truth(a : Char) : Boolean; begin

  if a = '*' then
     truth := true
  else
     truth := false

end;</lang>

<lang pascal>function rule_90(ev : String) : String; var

  l, i	: Integer;
  cp	: String;
  s	: Array[0..1] of Boolean;

begin

  l := length(ev);
  cp := copy(ev, 1, l);
  for i := 1 to l do begin
     if (i-1) < 1 then

s[0] := false

     else

s[0] := truth(ev[i-1]);

     if (i+1) > l then

s[1] := false

     else

s[1] := truth(ev[i+1]);

     if ( (s[0] and not s[1]) or (s[1] and not s[0]) ) then

cp[i] := '*'

     else

cp[i] := ' ';

  end;
  rule_90 := cp

end;

procedure triangle(n : Integer); var

  i, l	: Integer;
  b	: String;

begin

  l := ipow(2, n+1);
  b := ' ';
  for i := 1 to l do
     b := concat(b, ' ');
  b[round(l/2)] := '*';
  writeln(b);
  for i := 1 to (round(l/2)-1) do begin
     b := rule_90(b);
     writeln(b)
  end

end;</lang>

<lang pascal>begin

  triangle(4)

end.</lang>

Perl

<lang 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; </lang>

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);

Python

<lang 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)) </lang>

Ruby

From the command line: <lang bash> ruby -le'16.times{|y|print" "*(15-y),(0..y).map{|x|~y&x>0?" ":" *"}}' </lang>

Scheme

Translation of: Haskell

<lang scheme> (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))))))

</lang>

Tcl

Translation of: Perl

<lang tcl>package require Tcl 8.5

proc map {lambda list} {

   foreach elem $list {
       lappend result [apply $lambda $elem]
   }
   return $result

}

proc sierpinski_triangle n {

   set down [list *]
   set space " "
   for {set i 1} {$i <= $n} {incr i} {
       set down [concat \
           [map [subst -nocommands {x {expr {"$space[set x]$space"}}}] $down] \
           [map {x {expr {"$x $x"}}} $down] \
       ]
       append space $space
   }
   return [join $down \n]

}

puts [sierpinski_triangle 4]</lang>

Vedit macro language

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)
}

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