Cantor set: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added Java)
(Added modula-2)
Line 349: Line 349:
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
</pre>
</pre>

=={{header|Modula-2}}==
{{trans|Kotlin}}
<lang modula2>MODULE Cantor;
FROM Terminal IMPORT Write,WriteLn,ReadChar;

CONST
WIDTH = 81;
HEIGHT = 5;
VAR
lines : ARRAY[0..HEIGHT] OF ARRAY[0..WIDTH] OF CHAR;

PROCEDURE Init;
VAR i,j : CARDINAL;
BEGIN
FOR i:=0 TO HEIGHT DO
FOR j:=0 TO WIDTH DO
lines[i,j] := '*'
END
END
END Init;

PROCEDURE Cantor(start,len,index : CARDINAL);
VAR i,j,seg : CARDINAL;
BEGIN
seg := len DIV 3;
IF seg=0 THEN RETURN END;
FOR i:=index TO HEIGHT-1 DO
j := start+seg;
FOR j:=start+seg TO start+seg*2-1 DO
lines[i,j] := ' '
END
END;
Cantor(start, seg, index+1);
Cantor(start+seg*2, seg, index+1)
END Cantor;

PROCEDURE Print;
VAR i,j : CARDINAL;
BEGIN
FOR i:=0 TO HEIGHT-1 DO
FOR j:=0 TO WIDTH-1 DO
Write(lines[i,j])
END;
WriteLn
END
END Print;

BEGIN
Init;
Cantor(0,WIDTH,1);
Print;

ReadChar;
END Cantor.</lang>


=={{header|Perl 6}}==
=={{header|Perl 6}}==

Revision as of 20:48, 24 June 2018

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

Draw Cantor set. See details: Cantor set


ALGOL 68

<lang algol68>BEGIN

   # draw a Cantor Set using ASCII                                            #
   INT    lines     = 5; # number of lines for the set                        #
   # we must choose the line width so that the width of each segment is       #
   # divisible by 3 ( except for the final line where the segment width will  #
   # be 1 )                                                                   #
   INT    set width = 3 ^ ( lines - 1 );
   [ set width ]CHAR set;
   # start with a complete line #
   FOR i TO set width DO set[ i ] := "#" OD;
   print( ( set, newline ) );
   # repeatedly modify the line, replacing the middle third of each segment   #
   # with blanks                                                              #
   INT   segment width := set width OVER 3;
   WHILE segment width > 0 DO
       INT   set pos := 1;
       WHILE set pos < ( set width - segment width ) DO
           set pos   +:= segment width;
           FOR char pos FROM set pos TO ( set pos + segment width ) - 1 DO
               set[ char pos ] := " "
           OD;
           set pos +:= segment width
       OD;
       print( ( set, newline ) );
       segment width OVERAB 3
   OD

END</lang>

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

ALGOL W

Based on the Algol 68 sample. <lang algolw>begin

   % draw a Cantor Set using ASCII                                            %
   integer LINES;        % number of lines for the set                        %
   integer setWidth;     % width of each line of the set                      %
   % we must choose the line width so that the width of each segment is       %
   % divisible by 3 ( except for the final line where the segment width will  %
   % be 1 )                                                                   %
   LINES    := 5;
   setWidth := round( 3 ** ( LINES - 1 ) );
   begin % start new block so the array can have computed bounds              %
       logical array set ( 1 :: setWidth );
       integer segmentWidth;
       % start with a complete line %
       for i := 1 until setWidth do set( i ) := true;
       segmentWidth := setWidth;
       for l := 1 until LINES do begin
           % print the latest line, all lines start with a "#"                %
           write( "#" );
           for i := 2 until setWidth do writeon( if set( i ) then "#" else " " );
           % modify the line, replacing the middle third of each segment      %
           % with blanks, unless this was the last line                       %
           if l < LINES then begin
               integer   setPos;
               segmentWidth := segmentWidth div 3;
               setPos := 1;
               while setPos < ( setWidth - segmentWidth ) do begin
                   setPos := setPos + segmentWidth;
                   for charPos := setPos until ( setPos + segmentWidth ) - 1 do set( charPos ) := false;
                   setPos := setPos + segmentWidth
               end while_setPos_in_range ;
           end if_l_lt_LINES
       end for_l
   end

end.</lang>

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

AWK

<lang AWK>

  1. syntax: GAWK -f CANTOR_SET.AWK
  2. converted from C

BEGIN {

   WIDTH = 81
   HEIGHT = 5
   for (i=0; i<HEIGHT; ++i) {
     for (j=0; j<WIDTH; ++j) {
       lines[i][j] = "*"
     }
   }
   cantor(0,WIDTH,1)
   for (i=0; i<HEIGHT; ++i) {
     for (j=0; j<WIDTH; ++j) {
       printf("%s",lines[i][j])
     }
     printf("\n")
   }
   exit(0)

} function cantor(start,leng,indx, i,j,seg) {

   seg = int(leng/3)
   if (seg == 0) { return }
   for (i=indx; i<HEIGHT; ++i) {
     for (j=start+seg; j<start+seg*2; ++j) {
       lines[i][j] = " "
     }
   }
   cantor(start,seg,indx+1)
   cantor(start+seg*2,seg,indx+1)

} </lang>

Output:
*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *

C

Translation of: Kotlin

<lang c>#include <stdio.h>

  1. define WIDTH 81
  2. define HEIGHT 5

char lines[HEIGHT][WIDTH];

void init() {

   int i, j;
   for (i = 0; i < HEIGHT; ++i) {
       for (j = 0; j < WIDTH; ++j) lines[i][j] = '*';
   }

}

void cantor(int start, int len, int index) {

   int i, j, seg = len / 3;
   if (seg == 0) return;
   for (i = index; i < HEIGHT; ++i) {
       for (j = start + seg; j < start + seg * 2; ++j) lines[i][j] = ' ';
   }
   cantor(start, seg, index + 1);
   cantor(start + seg * 2, seg, index + 1);

}

void print() {

   int i, j;
   for (i = 0; i < HEIGHT; ++i) {
       for (j = 0; j < WIDTH; ++j) printf("%c", lines[i][j]);
       printf("\n");
   }

}

int main() {

   init();
   cantor(0, WIDTH, 1);
   print();
   return 0;

}</lang>

Output:
*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *

D

Translation of: C

<lang d>import std.stdio;

enum WIDTH = 81; enum HEIGHT = 5;

char[WIDTH*HEIGHT] lines;

void cantor(int start, int len, int index) {

   int seg = len / 3;
   if (seg == 0) return;
   for (int i=index; i<HEIGHT; i++) {
       for (int j=start+seg; j<start+seg*2; j++) {
           int pos = i*WIDTH + j;
           lines[pos] = ' ';
       }
   }
   cantor(start, seg, index+1);
   cantor(start+seg*2, seg, index+1);

}

void main() {

   // init
   lines[] = '*';
   // calculate
   cantor(0, WIDTH, 1);
   // print
   for (int i=0; i<HEIGHT; i++) {
       int beg = WIDTH * i;
       writeln(lines[beg..beg+WIDTH]);
   }

}</lang>

Output:
*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *

Go

Translation of: Kotlin

<lang go>package main

import "fmt"

const (

   width = 81
   height = 5

)

var lines [height][width]byte

func init() {

   for i := 0; i < height; i++ {
       for j := 0; j < width; j++ {
           lines[i][j] = '*'
       }
   }

}

func cantor(start, len, index int) {

   seg := len / 3
   if seg == 0 {
       return
   }
   for i := index; i < height; i++ {
       for j := start + seg; j < start + 2 * seg; j++ {
           lines[i][j] = ' '
       }
   }
   cantor(start, seg, index + 1)
   cantor(start + seg * 2, seg, index + 1)

}

func main() {

   cantor(0, width, 1)
   for _, line := range lines {
       fmt.Println(string(line[:]))
   }

}</lang>

Output:
*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *

Java

Translation of: Kotlin

<lang java>public class App {

   private static final int WIDTH = 81;
   private static final int HEIGHT = 5;
   private static char[][] lines;
   static {
       lines = new char[HEIGHT][WIDTH];
       for (int i = 0; i < HEIGHT; i++) {
           for (int j = 0; j < WIDTH; j++) {
               lines[i][j] = '*';
           }
       }
   }
   private static void cantor(int start, int len, int index) {
       int seg = len / 3;
       if (seg == 0) return;
       for (int i = index; i < HEIGHT; i++) {
           for (int j = start + seg; j < start + seg * 2; j++) {
               lines[i][j] = ' ';
           }
       }
       cantor(start, seg, index + 1);
       cantor(start + seg * 2, seg, index + 1);
   }
   public static void main(String[] args) {
       cantor(0, WIDTH, 1);
       for (int i = 0; i < HEIGHT; i++) {
           for (int j = 0; j < WIDTH; j++) {
               System.out.print(lines[i][j]);
           }
           System.out.println();
       }
   }

} </lang>

Output:
*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *

Kotlin

Simple terminal drawing. <lang scala>// Version 1.2.31

const val WIDTH = 81 const val HEIGHT = 5

val lines = List(HEIGHT) { CharArray(WIDTH) { '*' } }

fun cantor(start: Int, len: Int, index: Int) {

   val seg = len / 3
   if (seg == 0) return
   for (i in index until HEIGHT) {
       for (j in start + seg until start + seg * 2) lines[i][j] = ' '
   }
   cantor(start, seg, index + 1)
   cantor(start + seg * 2, seg, index + 1)

}

fun main(args: Array<String>) {

   cantor(0, WIDTH, 1)
   lines.forEach { println(it) }

}</lang>

Output:
*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *

Modula-2

Translation of: Kotlin

<lang modula2>MODULE Cantor; FROM Terminal IMPORT Write,WriteLn,ReadChar;

CONST

   WIDTH = 81;
   HEIGHT = 5;

VAR

   lines : ARRAY[0..HEIGHT] OF ARRAY[0..WIDTH] OF CHAR;

PROCEDURE Init; VAR i,j : CARDINAL; BEGIN

   FOR i:=0 TO HEIGHT DO
       FOR j:=0 TO WIDTH DO
           lines[i,j] := '*'
       END
   END

END Init;

PROCEDURE Cantor(start,len,index : CARDINAL); VAR i,j,seg : CARDINAL; BEGIN

   seg := len DIV 3;
   IF seg=0 THEN RETURN END;
   FOR i:=index TO HEIGHT-1 DO
       j := start+seg;
       FOR j:=start+seg TO start+seg*2-1 DO
           lines[i,j] := ' '
       END
   END;
   Cantor(start, seg, index+1);
   Cantor(start+seg*2, seg, index+1)

END Cantor;

PROCEDURE Print; VAR i,j : CARDINAL; BEGIN

   FOR i:=0 TO HEIGHT-1 DO
       FOR j:=0 TO WIDTH-1 DO
           Write(lines[i,j])
       END;
       WriteLn
   END

END Print;

BEGIN

   Init;
   Cantor(0,WIDTH,1);
   Print;
   ReadChar;

END Cantor.</lang>

Perl 6

Translation of: Kotlin

<lang perl6>sub cantor ( Int $height ) {

   my $width = 3 ** ($height - 1);
   my @lines = ( "\c[FULL BLOCK]" x $width ) xx $height;
   my sub _trim_middle_third ( $len, $start, $index ) {
       my $seg = $len div 3
           or return;
       for ( $index ..^ $height ) X ( 0 ..^ $seg ) -> ( $i, $j ) {
           @lines[$i].substr-rw( $start + $seg + $j, 1 ) = ' ';
       }
       _trim_middle_third( $seg, $start + $_, $index + 1 ) for 0, $seg * 2;
   }
   _trim_middle_third( $width, 0, 1 );
   return @lines;

}

.say for cantor(5);</lang>

Output:
█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █

Racket

Translation of: Kotlin

<lang racket>#lang racket/base

{trans|Kotlin}}

(define current-width (make-parameter 81))

(define current-height (make-parameter 5))

(define (Cantor_set (w (current-width)) (h (current-height)))

 (define lines (build-list h (λ (_) (make-bytes w (char->integer #\#)))))
 (define (cantor start len index)
   (let* ((seg (quotient len 3))
          (seg-start (+ start seg))
          (seg-end (+ seg-start seg)))
     (unless (zero? seg)
       (for* ((i (in-range index h))
              (j (in-range seg-start seg-end)))
         (bytes-set! (list-ref lines i) j (char->integer #\space)))
       (cantor start seg (add1 index))
       (cantor seg-end seg (add1 index)))))
 (cantor 0 w 1)
 lines)

(module+ main

 (for-each displayln (Cantor_set)))

</lang>

Output:
*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *

Ring

<lang ring>

  1. Project : Cantor set
  2. Date  : 2018/04/20
  3. Author : Gal Zsolt [~ CalmoSoft ~]
  4. Email  : <calmosoft@gmail.com>

load "guilib.ring" paint = null

new qapp

       {
       win1 = new qwidget() {
                 setwindowtitle("")
                 setgeometry(100,100,800,600)
                 label1 = new qlabel(win1) {
                             setgeometry(10,10,800,600)
                             settext("")
                 }
                 new qpushbutton(win1) {
                         setgeometry(150,500,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(10)
       }
       paint = new qpainter() {
                 begin(p1)
                 setpen(pen)
       cantor(10,20,600)
       endpaint()
       }
       label1 { setpicture(p1) show() }
       return

func cantor(x,y,lens)

       if lens >= 10
          paint.drawline(x,y,x+lens,y)
          y = y + 20
          cantor(x,y,floor(lens/3))
          cantor(x+floor(lens*2/3),y,floor(lens/3))
       ok

</lang> Output image:

Cantor set

Scala

Imperative Programming (Q&D)

<lang Scala>object CantorSetQD extends App {

 val (width, heigth) = (81, 5)
 val lines = Seq.fill[Array[Char]](heigth)(Array.fill[Char](width)('*'))
 def cantor(start: Int, len: Int, index: Int) {
   val seg = len / 3
   println(start, len, index)
   if (seg != 0) {
     for (i <- index until heigth;
          j <- (start + seg) until (start + seg * 2)) lines(i)(j) = ' '
     cantor(start, seg, index + 1)
     cantor(start + seg * 2, seg, index + 1)
   }
 }
 cantor(0, width, 1)
 lines.foreach(l => println(l.mkString))

}</lang>

Output:

See it in running in your browser by (JavaScript)

or by Scastie (JVM).

Functional Programming (Recommended)

<lang Scala>object CantorSetFP extends App {

 val (width, heigth) = (81, 5)
 def lines = (1 to heigth).map(_ => (0 until width).toSet)
 def cantorSet(pre: Seq[Set[Int]], start: Int, len: Int, index: Int): Seq[Set[Int]] = {
   val seg = len / 3
   def cantorSet1(pre: Seq[Set[Int]], start: Int, index: Int): Seq[Set[Int]] = {
     def elementsStuffing(pre: Set[Int], start: Int): Set[Int] =
       pre -- ((start + seg) until (start + seg * 2))
     for (n <- 0 until heigth)
       yield if (index to heigth contains n) elementsStuffing(pre(n), start)
       else pre(n)
   }
   if (seg == 0) pre
   else {
     def version0 = cantorSet1(pre, start, index)
     def version1 = cantorSet(cantorSet1(pre, start, index), start, seg, index + 1)
     cantorSet(version1, start + seg * 2, seg, index + 1)
   }
 }
 def output: Seq[Set[Int]] = cantorSet(lines, 0, width, 1)
 println(
   output.map(l => (0 to width).map(pos => if (l contains pos) '*' else ' ').mkString)
     .mkString("\n"))

}</lang>

Output:

See it in running in your browser by (JavaScript)

or by Scastie (JVM).

Sidef

Translation of: Perl 6

<lang ruby>func cantor (height) {

   var width = 3**(height - 1)
   var lines = height.of { "\N{FULL BLOCK}" * width }
   func trim_middle_third (len, start, index) {
       var seg = (len // 3) || return()
       for i, j in ((index ..^ height) ~X (0 ..^ seg)) {
           lines[i].replace!(Regex("^.{#{start + seg + j}}\\K."), ' ')
       }
       [0, 2*seg].each { |k|
           trim_middle_third(seg, start + k, index + 1)
       }
   }
   trim_middle_third(width, 0, 1)
   return lines

}

cantor(5).each { .say }</lang>

Output:
█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █

zkl

<lang zkl>const WIDTH=81, HEIGHT=5; var lines=HEIGHT.pump(List,List.createLong(WIDTH,"\U2588;").copy); // full block

fcn cantor(start,len,index){

  (seg:=len/3) or return();
  foreach i,j in ([index..HEIGHT-1], [start + seg .. start + seg*2 - 1]){
     lines[i][j]=" ";
  }
  cantor(start, seg, index + 1);
  cantor(start + seg*2, seg, index + 1);

}(0,WIDTH,1);

lines.pump(Console.println,"concat");</lang>

Output:
█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █