I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Cantor set

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

Draw a Cantor set.

See details at this Wikipedia webpage:   Cantor set

## 11l

Translation of: Python
`V WIDTH = 81V HEIGHT = 5 F cantor(start, len, index)   V seg = len I/ 3   I seg == 0      R   L(it) 0 .< :HEIGHT - index      V i = index + it      L(jt) 0 .< seg         V j = start + seg + jt         V pos = i * :WIDTH + j         :lines[pos] = ‘ ’   cantor(start, seg, index + 1)   cantor(start + seg * 2, seg, index + 1) V lines = [‘*’] * (WIDTH * HEIGHT)cantor(0, WIDTH, 1) L(i) 0 .< HEIGHT   V beg = WIDTH * i   print((lines[beg .< beg + WIDTH]).join(‘’))`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *
```

## Action!

`PROC FillRect(INT x,y,w,h)  INT i   FOR i=y TO y+h-1  DO    Plot(x,i)    DrawTo(x+w-1,i)  ODRETURN PROC DrawCantor(INT x0,y0,h,level)  INT x,y,i,j,w,w2,h2   w=1  FOR i=0 TO level-1  DO w==*3 OD   Color=1  y=y0  FOR i=0 TO level  DO    FillRect(x0,y,w,h)    y==+h*2  OD   Color=0  w2=1 h2=h*2  FOR i=0 TO level-1  DO    x=w2 y=(level-i)*(h*2)    WHILE x<w    DO      FillRect(x0+x,y0+y,w2,h2)      x==+w2*2    OD    w2==*3    h2==+h*2  ODRETURN PROC Main()  BYTE CH=\$02FC,COLOR1=\$02C5,COLOR2=\$02C6   Graphics(8+16)  COLOR1=\$0C  COLOR2=\$02   DrawCantor(38,48,8,5)   DO UNTIL CH#\$FF OD  CH=\$FFRETURN`
Output:

`with Ada.Text_IO; procedure Cantor_Set is    subtype Level_Range is Integer range 1 .. 5;   Image : array (Level_Range) of String (1 .. 81) := (others => (others => ' '));    procedure Cantor (Level : Natural; Length : Natural; Start : Natural) is   begin      if Level in Level_Range then         Image (Level) (Start .. Start + Length - 1) := (others => '*');         Cantor (Level + 1, Length / 3, Start);         Cantor (Level + 1, Length / 3, Start + 2 * Length / 3);      end if;   end Cantor;begin   Cantor (Level  => Level_Range'First,           Length => 81,           Start  => 1);    for L in Level_Range loop      Ada.Text_IO.Put_Line (Image (L));   end loop;end Cantor_Set;`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

## ALGOL 68

`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    ODEND`
Output:
```#################################################################################
###########################                           ###########################
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #
```

## ALGOL W

Based on the Algol 68 sample.

`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    endend.`
Output:
```#################################################################################
###########################                           ###########################
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #
```

## AppleScript

Using composable library functions whenever possible, for better productivity:

`------------------------- CANTOR SET ----------------------- -- cantor :: [String] -> [String]on cantor(xs)    script go        on |λ|(s)            set m to (length of s) div 3            set blocks to text 1 thru m of s             if "█" = text 1 of s then                {blocks, replicate(m, space), blocks}            else                {s}            end if        end |λ|    end script    concatMap(go, xs)end cantor  ---------------------------- TEST --------------------------on run    showCantor(5)end run -- showCantor :: Int -> Stringon showCantor(n)    unlines(map(my concat, ¬        take(n, iterate(cantor, ¬            {replicate(3 ^ (n - 1), "█")}))))end showCantor  --------------------- GENERIC FUNCTIONS -------------------- -- concat :: [[a]] -> [a]-- concat :: [String] -> Stringon concat(xs)    set lng to length of xs    if 0 < lng and string is class of (item 1 of xs) then        set acc to ""    else        set acc to {}    end if    repeat with i from 1 to lng        set acc to acc & item i of xs    end repeat    accend concat  -- concatMap :: (a -> [b]) -> [a] -> [b]on concatMap(f, xs)    set lng to length of xs    set acc to {}    tell mReturn(f)        repeat with i from 1 to lng            set acc to acc & |λ|(item i of xs, i, xs)        end repeat    end tell    return accend concatMap  -- 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 |λ|(item i of xs, i, xs)        end repeat        return lst    end tellend map  -- Lift 2nd class handler function into 1st class script wrapper -- mReturn :: First-class m => (a -> b) -> m (a -> b)on mReturn(f)    if class of f is script then        f    else        script            property |λ| : f        end script    end ifend mReturn  -- iterate :: (a -> a) -> a -> Gen [a]on iterate(f, x)    script        property v : missing value        property g : mReturn(f)'s |λ|        on |λ|()            if missing value is v then                set v to x            else                set v to g(v)            end if            return v        end |λ|    end scriptend iterate  -- replicate :: Int -> String -> Stringon replicate(n, s)    set out to ""    if n < 1 then return out    set dbl to s     repeat while (n > 1)        if (n mod 2) > 0 then set out to out & dbl        set n to (n div 2)        set dbl to (dbl & dbl)    end repeat    return out & dblend replicate  -- take :: Int -> [a] -> [a]-- take :: Int -> String -> Stringon take(n, xs)    set c to class of xs    if list is c then        if 0 < n then            items 1 thru min(n, length of xs) of xs        else            {}        end if    else if string is c then        if 0 < n then            text 1 thru min(n, length of xs) of xs        else            ""        end if    else if script is c then        set ys to {}        repeat with i from 1 to n            set v to xs's |λ|()            if missing value is v then                return ys            else                set end of ys to v            end if        end repeat        return ys    else        missing value    end ifend take  -- unlines :: [String] -> Stringon unlines(xs)    set {dlm, my text item delimiters} to ¬        {my text item delimiters, linefeed}    set str to xs as text    set my text item delimiters to dlm    strend unlines`
Output:
```█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █```

## Arturo

`width: 81height: 5 lines: array.of: height repeat `*` width cantor: function [start length idx].export:[lines][    seg: length / 3    if seg = 0 -> return null     loop idx..dec height 'i [        loop (start + seg).. dec start + 2 * seg 'j             -> set lines\[i] j ` `    ]    cantor start seg idx+1    cantor start + 2 * seg seg idx+1] cantor 0 width 1 loop lines 'line     -> print join line`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

## AWK

` # syntax: GAWK -f CANTOR_SET.AWK# converted from CBEGIN {    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)} `
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *
```

## BASIC

`10 DEFINT A-Z20 N = 430 W = 3^(N-1)40 S = W50 L\$ = STRING\$(W, "#")60 PRINT L\$70 IF S = 1 THEN END80 S = S\390 P = 1100 IF P >= W-S GOTO 60110 P = P+S120 MID\$(L\$,P,S) = SPACE\$(S)130 P = P+S140 GOTO 100`
Output:
```###########################
#########         #########
###   ###         ###   ###
# #   # #         # #   # #```

## BASIC256

Translation of: FreeBASIC
` global ancho, alto, intervaloancho = 81 : alto = 5dim intervalo(alto, ancho) subroutine Cantor()	for i = 0 to alto - 1		for j = 0 to ancho - 1			intervalo[i, j] = "■"		next j	next iend subroutine subroutine ConjCantor(inicio, longitud, indice)	segmento = longitud / 3	if segmento = 0 then return	for i = indice to alto - 1		for j = inicio + segmento to inicio + segmento * 2 - 1			intervalo[i, j] = " "		next j	next i	call ConjCantor(inicio, segmento, indice + 1)	call ConjCantor(inicio + segmento * 2, segmento, indice + 1)end subroutine call Cantor()call ConjCantor(0, ancho, 1)for i = 0 to alto - 1	for j = 0 to ancho - 1		print intervalo[i, j];	next j	printnext iEnd `
Output:
```Igual que la entrada de FreeBASIC.
```

## BQN

`Cantor ← {" •" ⊏˜ >⥊¨(¯1⊸⊏⊢¨¨⊢)1‿0‿1∧⌜⍟(↕𝕩)1}`
Output:
```   Cantor 5
┌─
╵"•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
•••••••••••••••••••••••••••                           •••••••••••••••••••••••••••
•••••••••         •••••••••                           •••••••••         •••••••••
•••   •••         •••   •••                           •••   •••         •••   •••
• •   • •         • •   • •                           • •   • •         • •   • •"
┘
```

## C

Translation of: Kotlin
`#include <stdio.h> #define WIDTH 81#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;}`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *
```

## C#

Translation of: Java
`using System; namespace CantorSet {    class Program {        const int WIDTH = 81;        const int HEIGHT = 5;        private static char[,] lines = new char[HEIGHT, WIDTH];         static Program() {            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);        }         static void Main(string[] args) {            Cantor(0, WIDTH, 1);            for (int i = 0; i < HEIGHT; i++) {                for (int j = 0; j < WIDTH; j++) {                    Console.Write(lines[i,j]);                }                Console.WriteLine();            }        }    }}`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

## C++

Translation of: D
`#include <iostream> const int WIDTH = 81;const int HEIGHT = 5; char lines[WIDTH*HEIGHT]; 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 + 2 * seg, seg, index + 1);} int main() {	// init	for (int i = 0; i < WIDTH*HEIGHT; i++) {		lines[i] = '*';	} 	// calculate	cantor(0, WIDTH, 1); 	// print	for (int i = 0; i < HEIGHT*WIDTH; i += WIDTH) {		printf("%.*s\n", WIDTH, lines + i);	} 	return 0;}`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

## CLU

`cantor = cluster is make    rep = null    ac = array[char]    aac = array[array[char]]     make = proc (width, height: int, ch: char) returns (string)        lines: aac := aac\$fill_copy(0, height, ac\$fill(0, width, ch))        cantor_step(lines, 0, width, 1)        s: stream := stream\$create_output()        for line: ac in aac\$elements(lines) do            stream\$putl(s, string\$ac2s(line))        end        return(stream\$get_contents(s))    end make     cantor_step = proc (lines: aac, start, len, index: int)        seg: int := len / 3        if seg = 0 then return end        for i: int in int\$from_to(index, aac\$high(lines)) do            for j: int in int\$from_to(start+seg, start+seg*2-1) do                lines[i][j] := ' '            end        end        cantor_step(lines, start, seg, index+1)        cantor_step(lines, start+seg*2, seg, index+1)    end cantor_stepend cantor start_up = proc ()    po: stream := stream\$primary_output()    cs: string := cantor\$make(81, 5, '*')    stream\$puts(po, cs)end start_up`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

## COBOL

`       IDENTIFICATION DIVISION.       PROGRAM-ID. CANTOR.        DATA DIVISION.       WORKING-STORAGE SECTION.       01 SETTINGS.          03 NUM-LINES     PIC 9 VALUE 5.          03 FILL-CHAR     PIC X VALUE '#'.       01 VARIABLES.          03 CUR-LINE.             05 CHAR       PIC X OCCURS 81 TIMES.          03 WIDTH         PIC 99.          03 CUR-SIZE      PIC 99.          03 POS           PIC 99.          03 MAXPOS        PIC 99.          03 NEXTPOS       PIC 99.          03 I             PIC 99.        PROCEDURE DIVISION.       BEGIN.           COMPUTE WIDTH = 3 ** (NUM-LINES - 1).           PERFORM INIT.           MOVE WIDTH TO CUR-SIZE.           DISPLAY CUR-LINE.           PERFORM DO-LINE UNTIL CUR-SIZE IS EQUAL TO 1.           STOP RUN.        INIT.           PERFORM INIT-CHAR VARYING I FROM 1 BY 1                UNTIL I IS GREATER THAN WIDTH.        INIT-CHAR.           MOVE FILL-CHAR TO CHAR(I).        DO-LINE.           DIVIDE 3 INTO CUR-SIZE.           MOVE 1 TO POS.           SUBTRACT CUR-SIZE FROM WIDTH GIVING MAXPOS.           PERFORM BLANK-REGIONS UNTIL POS IS GREATER THAN MAXPOS.           DISPLAY CUR-LINE.        BLANK-REGIONS.           ADD CUR-SIZE TO POS.           PERFORM BLANK-CHAR CUR-SIZE TIMES.        BLANK-CHAR.           MOVE SPACE TO CHAR(POS).           ADD 1 TO POS.`
Output:
```#################################################################################
###########################                           ###########################
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #```

## D

Translation of: C
`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]);    }}`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

## Delphi

Translation of: Java
` program Cantor_set; {\$APPTYPE CONSOLE} const  WIDTH: Integer = 81;  HEIGHT: Integer = 5; var  Lines: TArray<TArray<Char>>; procedure Init;var  i, j: Integer;begin  SetLength(lines, HEIGHT, WIDTH);  for i := 0 to HEIGHT - 1 do    for j := 0 to WIDTH - 1 do      lines[i, j] := '*';end; procedure Cantor(start, len, index: Integer);var  seg, i, j: Integer;begin  seg := len div 3;  if seg = 0 then    Exit;  for i := index to HEIGHT - 1 do    for j := start + seg to start + seg * 2 - 1 do      lines[i, j] := ' ';  Cantor(start, seg, index + 1);  Cantor(start + seg * 2, seg, index + 1);end; var  i, j: Integer; begin  Init;  Cantor(0, WIDTH, 1);  for i := 0 to HEIGHT - 1 do  begin    for j := 0 to WIDTH - 1 do      Write(lines[i, j]);    Writeln;  end;  Readln;end. `
Output:

Same result of Java

## Excel

### LAMBDA

Binding names to the following lambda expressions in the Name Manager of the Excel WorkBook:

`CANTOR=LAMBDA(n,    APPLYN(n)(        LAMBDA(grid,            APPENDROWS(grid)(                CANTOROW(                    LASTROW(grid)                )            )        )    )({0,1}))  CANTOROW=LAMBDA(xys,    LET(        nCols, COLUMNS(xys),         IF(2 > nCols,            xys,            IF(3 < nCols,                APPENDCOLS(                    CANTORSLICES(TAKECOLS(2)(xys))                )(                    CANTOROW(DROPCOLS(2)(xys))                ),                CANTORSLICES(TAKECOLS(2)(xys))            )        )    ))  CANTORSLICES=LAMBDA(ab,    LET(        a, INDEX(ab, 1),        b, INDEX(ab, 2),        third, (b - a) / 3,         CHOOSE({1,2,3,4}, a, a + third, b - third, b)    ))  SHOWCANTOR=LAMBDA(grid,    LET(        leaves, LASTROW(grid),        leafWidth, INDEX(leaves, 1, 2) - INDEX(leaves, 1, 1),        leafCount, 1 / leafWidth,         SHOWCANTROWS(leafCount)(grid)    ))  SHOWCANTROWS=LAMBDA(leafCount,    LAMBDA(grid,        LET(            xs, FILTERP(               LAMBDA(x, NOT(ISNA(x)))            )(                HEADCOL(grid)            ),             runLengths, LAMBDA(x,                 CEILING.MATH(leafCount * x))(                    SUBTRACT(TAILROW(xs))(INITROW(xs)                )            ),             iCols, SEQUENCE(1, COLUMNS(runLengths)),             CONCAT(                REPT(                    IF(ISEVEN(iCols), " ", "█"),                     runLengths                )            ) & IF(1 < ROWS(grid),                CHAR(10) & SHOWCANTROWS(leafCount)(                    TAILCOL(grid)                ),                ""            )        )    ))`

and also assuming the following generic bindings in the Name Manager for the WorkBook:

`APPENDCOLS=LAMBDA(xs,    LAMBDA(ys,        LET(            nx, COLUMNS(xs),            ny, COLUMNS(ys),            colIndexes, SEQUENCE(1, nx + ny),            rowIndexes, SEQUENCE(MAX(ROWS(xs), ROWS(ys))),             IFERROR(                IF(nx < colIndexes,                    INDEX(ys, rowIndexes, colIndexes - nx),                    INDEX(xs, rowIndexes, colIndexes)                ),                NA()            )        )    ))  APPENDROWS=LAMBDA(xs,    LAMBDA(ys,        LET(            nx, ROWS(xs),            rowIndexes, SEQUENCE(nx + ROWS(ys)),            colIndexes, SEQUENCE(                1,                MAX(COLUMNS(xs), COLUMNS(ys))            ),             IFERROR(                IF(rowIndexes <= nx,                    INDEX(xs, rowIndexes, colIndexes),                    INDEX(ys, rowIndexes - nx, colIndexes)                ),                NA()            )        )    ))  APPLYN=LAMBDA(n,    LAMBDA(f,        LAMBDA(x,            IF(0 < n,                APPLYN(n - 1)(f)(                    f(x)                ),                x            )        )    ))  DROPCOLS=LAMBDA(n,    LAMBDA(xs,        INDEX(            xs,            SEQUENCE(ROWS(xs), 1),            SEQUENCE(1, (COLUMNS(xs) - n), 1 + n, 1)        )    ))  FILTERP=LAMBDA(p,    LAMBDA(xs,        FILTER(xs, p(xs))    ))  HEADCOL=LAMBDA(xs,    LET(REM, "The first item of each column in xs",         INDEX(xs, 1, SEQUENCE(1, COLUMNS(xs)))    ))  INITROW=LAMBDA(xs,    INDEX(        xs,        SEQUENCE(            1,            COLUMNS(xs) - 1,            1, 1        )    ))  LASTROW=LAMBDA(xs,    INDEX(        xs,        ROWS(xs),        SEQUENCE(1, COLUMNS(xs), 1, 1)    ))  SUBTRACT=LAMBDA(a,    LAMBDA(b, a - b))  TAILCOL=LAMBDA(cols,    LET(REM, "The tail of each column in the grid.",         INDEX(            cols,            SEQUENCE(ROWS(cols) - 1, 1, 2, 1),            SEQUENCE(1, COLUMNS(cols))        )    ))  TAILROW=LAMBDA(xs,    LET(REM,"The tail of each row in the grid",        n, COLUMNS(xs) - 1,         IF(0 < n,            INDEX(                xs,                SEQUENCE(ROWS(xs), 1, 1, 1),                SEQUENCE(1, n, 2, 1)            ),            NA()        )    ))  TAKECOLS=LAMBDA(n,    LAMBDA(xs,        INDEX(            xs,            SEQUENCE(ROWS(xs)),            SEQUENCE(1, n)        )    ))`
Output:

As a string, with the format of the cell set to a mono-spaced font, and with Format > Cells > Alignment > Wrap text = True, to allow for the display of Excel's (platform - independent) CHAR(10) line breaks:

 =SHOWCANTOR(CANTOR(1)) fx A B 1 SHOWCANTOR(CANTOR(0)) `█` 2 SHOWCANTOR(CANTOR(1)) `████ █` 3 SHOWCANTOR(CANTOR(2)) `████████████ ████ █ █ █` 4 SHOWCANTOR(CANTOR(3)) `████████████████████████████████████ ████████████ ███ ███ ████ █ █ █ █ █ █ █`

The diagrams above are drawn from the array of underlying fractions defined by CANTOR(n).

(The expression in B2 below defines the values which populate the grid B2:Q5)

The enclosing application of the built-in IFNA function maps undefined numeric cells in that grid (with the Excel value #N/A) to empty strings, for a more readable display.

(The number format for the numeric cells is set to Fraction > Up to three digits.)

 =IFNA(CANTOR(3), "") fx A B C D E F G H I J K L M N O P Q 1 2 Unit range 0 1 3 Cantor 1 0 1/3 2/3 1 4 Cantor 2 0 1/9 2/9 1/3 2/3 7/9 8/9 1 5 Cantor 3 0 1/27 2/27 1/9 2/9 7/27 8/27 1/3 2/3 19/27 20/27 7/9 8/9 25/27 26/27 1

## Factor

`USING: grouping.extras io kernel math sequencessequences.repeating ;IN: rosetta-code.cantor-set CONSTANT: width 81CONSTANT: depth 5 : cantor ( n -- seq )    dup 0 = [ drop { 0 1 } ]    [ 1 - cantor [ 3 / ] map dup [ 2/3 + ] map append ] if ; ! Produces a sequence of lengths from a Cantor set, depending on! width. Even indices are solid; odd indices are blank.! e.g. 2 cantor gaps -> { 9 9 9 27 9 9 9 }!: gaps ( seq -- seq )    [ width * ] map [ - abs ] 2clump-map ; : print-cantor ( n -- )    cantor gaps [ even? "#" " " ? swap repeat ] map-index    concat print ; depth <iota> [ print-cantor ] each`
Output:
```#################################################################################
###########################                           ###########################
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #
```

## Forth

Where is says `[email protected]` it should say `c@`, but I'm not keen on writing it as `c&#64;` in the actual code.

`warnings off 4  \ iterations: **        1 swap  0 ?DO over * LOOP  nip ;3 swap **  constant width  \ Make smallest step 1 create string  here width char # fill  width allot: print     string width type cr ; \  Overwrite string with new holes of size 'length'.\  Pointer into string at TOS.create length  width ,: reduce    length dup @ 3 / swap ! ;: done?     dup string - width >= ;: hole?     dup [email protected] bl = ;: skip      length @ + ;: whipe     dup length @ bl fill  skip ;: step      hole? IF skip skip skip ELSE skip whipe skip THEN ;: split     reduce string BEGIN step done? UNTIL drop ; \  Main: done?     length @ 1 <= ;: step      split print ;: go        print BEGIN step done? UNTIL ; go bye`

Output:

```#################################################################################
###########################                           ###########################
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #```

## FreeBASIC

` Const ancho = 81Const alto = 5Dim Shared intervalo(alto, ancho) As StringDim As Integer i, j Sub Cantor()    Dim As Integer i, j    For i = 0 To alto - 1        For j = 0 To ancho - 1            intervalo(i, j) = Chr(254)        Next j    Next iEnd Sub Sub ConjCantor(inicio As Integer, longitud As Integer, indice As Integer)    Dim As Integer i, j    Dim segmento As Integer = longitud / 3    If segmento = 0 Then Return    For i = indice To alto - 1        For j = inicio + segmento To inicio + segmento * 2 - 1            intervalo(i, j) = Chr(32)        Next j    Next i    ConjCantor(inicio, segmento, indice + 1)    ConjCantor(inicio + segmento * 2, segmento, indice + 1)End Sub Cantor()ConjCantor(0, ancho, 1)For i = 0 To alto - 1    For j = 0 To ancho - 1        Print intervalo(i, j);    Next j    PrintNext iEnd `
Output:
```█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █
```

## Go

Translation of: Kotlin
`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[:]))    }}`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *
```

## Groovy

Translation of: Java
`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 = (int) (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)    }     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()        }    }}`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

### Interval bars

Translation of: Python
(Functional version)
`-------------------------- CANTOR ------------------------ cantor :: [(Bool, Int)] -> [(Bool, Int)]cantor = (go =<<)  where    go (bln, n)      | bln && 1 < n = [(True, m), (False, m), (True, m)]      | otherwise = [(bln, n)]      where        m = quot n 3 --------------------------- TEST -------------------------main :: IO ()main = putStrLn \$ cantorLines 5 ------------------------- DISPLAY ------------------------cantorLines :: Int -> StringcantorLines n =  unlines \$    showCantor      <\$> take n (iterate cantor [(True, 3 ^ pred n)]) showCantor :: [(Bool, Int)] -> StringshowCantor = (go =<<)  where    go (True, n) = replicate n '*'    go (False, n) = replicate n ' '`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

Or, using strings for the model as well as the display:

`-------------------------- CANTOR ------------------------ cantor :: [String] -> [String]cantor = (go =<<)  where    go x      | '█' == head x = [block, replicate m ' ', block]      | otherwise = [x]      where        m = quot (length x) 3        block = take m x  --------------------------- TEST -------------------------main :: IO ()main = putStrLn \$ cantorLines 5  ------------------------- DISPLAY ------------------------cantorLines :: Int -> StringcantorLines =  unlines . (concat <\$>)    . ( take          <*> ( iterate cantor                  . return                  . flip replicate '█'                  . (3 ^)                  . pred              )      )`
Output:
```█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █```

### Dual representation

Intervals as fraction pairs, and intervals as graphic bars:

`import Control.Monad (join)import Data.Bifunctor (bimap)import Data.List (intercalate, mapAccumL, maximumBy)import Data.Ratio (Ratio, denominator, numerator, (%)) -------------------------- CANTOR ------------------------ cantor :: (Rational, Rational) -> [[(Rational, Rational)]]cantor = iterate (>>= go) . return  where    go (x, y) = [(x, x + r), (y - r, y)]      where        r = (y - x) / 3 --------------------------- TEST ------------------------- main :: IO ()main =  ( ( (>>)        . putStrLn        . unlines        . fmap intervalRatios    )      <*> (putStrLn . intervalBars)  )    \$ take 4 \$ cantor (0, 1) ------------------------- DISPLAY ------------------------ intervalBars :: [[(Rational, Rational)]] -> StringintervalBars xs = unlines \$ go (d % 1) <\$> xs  where    d = maximum \$ denominator . fst <\$> last xs    go w xs =      concat . snd \$        mapAccumL          ( \a (rx, ry) ->              let (wy, wx) = (w * ry, w * rx)               in ( wy,                    replicate (floor (wx - a)) ' '                      <> replicate (floor (wy - wx)) '█'                  )          )          0          xs intervalRatios :: [(Rational, Rational)] -> StringintervalRatios =  ('(' :) . (<> ")")    . intercalate ") ("    . fmap      (uncurry ((<>) . (<> ", ")) . join bimap showRatio) showRatio :: Rational -> StringshowRatio = ((<>) . show . numerator) <*> (go . denominator)  where    go x      | 1 /= x = '/' : show x      | otherwise = []`
Output:
```(0, 1)
(0, 1/3) (2/3, 1)
(0, 1/9) (2/9, 1/3) (2/3, 7/9) (8/9, 1)
(0, 1/27) (2/27, 1/9) (2/9, 7/27) (8/27, 1/3) (2/3, 19/27) (20/27, 7/9) (8/9, 25/27) (26/27, 1)

███████████████████████████
█████████         █████████
███   ███         ███   ███
█ █   █ █         █ █   █ █```

## IS-BASIC

`100 PROGRAM "Cantor.bas"110 GRAPHICS HIRES 2120 SET PALETTE BLACK,WHITE130 CALL CANTOR(28,500,1216,32)140 DEF CANTOR(X,Y,L,HEIGHT)150   IF L>3 THEN160     PLOT X,Y;X+L,Y,X,Y+4;X+L,Y+4170     CALL CANTOR(X,Y-HEIGHT,L/3,HEIGHT)180     CALL CANTOR(X+2*L/3,Y-HEIGHT,L/3,HEIGHT)190   END IF200 END DEF`

## J

The argument to the cantor_dust monad is an integer that describes the depth of the dust. Shown here are results for cantor_dust 2 and for cantor_dust 3 . It works by checking for 1 digits in the base 3 representation of the coordinates. These background coordinates are plotted with # character using ASCII art. 1j1 #"1 expands the lines to improve aspect ratio on character cell (console) display. }:"1 curtails the extra space character line by line. < draws a pretty box.

` odometer =: [: (4 \$. \$.) \$&1 cantor_dust =: monad define shape =. ,~ 3 ^ y a =. shape \$ ' ' i =. odometer shape < (}:"1) 1j1 #"1 '#' (([: <"1 [: ;/"1 (#~ 1 e."1 [: (,/"2) 3 3&#:)) i)}a) `
```   cantor_dust 2
┌─────────────────┐
│  #   # # #   #  │
│# # # # # # # # #│
│  #   # # #   #  │
│# # # # # # # # #│
│# # # # # # # # #│
│# # # # # # # # #│
│  #   # # #   #  │
│# # # # # # # # #│
│  #   # # #   #  │
└─────────────────┘

cantor_dust 3
┌─────────────────────────────────────────────────────┐
│  #   # # #   #     #   # # #   #     #   # # #   #  │
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│  #   # # #   #     #   # # #   #     #   # # #   #  │
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│  #   # # #   #     #   # # #   #     #   # # #   #  │
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│  #   # # #   #     #   # # #   #     #   # # #   #  │
│  #   # # #   #     #   # # #   #     #   # # #   #  │
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│  #   # # #   #     #   # # #   #     #   # # #   #  │
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│  #   # # #   #     #   # # #   #     #   # # #   #  │
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│  #   # # #   #     #   # # #   #     #   # # #   #  │
│  #   # # #   #     #   # # #   #     #   # # #   #  │
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│  #   # # #   #     #   # # #   #     #   # # #   #  │
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│  #   # # #   #     #   # # #   #     #   # # #   #  │
│# # # # # # # # # # # # # # # # # # # # # # # # # # #│
│  #   # # #   #     #   # # #   #     #   # # #   #  │
└─────────────────────────────────────────────────────┘

```

With an `x' argument cantor_dust generalizes to higher dimensions. Try 3 cantor_dust 2

` cantor_dust =: 2&\$: :(dyad define) shape =. x # 3 ^ y a =. shape \$ ' ' i =. odometer shape < (}:"1) 1j1 #"1 '#' (([: <"1 [: ;/"1 (#~ 1 e."1 [: (,/"2) 3 3&#:)) i)} a) `

## Java

Translation of: Kotlin
`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();        }    }} `
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

## JavaScript

### Cantor: (Bool, Int) pairs

Translation of: Python
(Functional version)
`(() => {    "use strict";     // -------------- CANTOR BOOL-INT PAIRS --------------     // cantor :: [(Bool, Int)] -> [(Bool, Int)]    const cantor = xs => {        const go = ([bln, n]) =>            bln && 1 < n ? (() => {                const x = Math.floor(n / 3);                 return [                    [true, x],                    [false, x],                    [true, x]                ];            })() : [                [bln, n]            ];         return xs.flatMap(go);    };     // ---------------------- TEST -----------------------    // main :: IO ()    const main = () =>        cantorLines(5);      // --------------------- DISPLAY ---------------------     // cantorLines :: Int -> String    const cantorLines = n =>        take(n)(            iterate(cantor)([                [true, 3 ** (n - 1)]            ])        )        .map(showCantor)        .join("\n");      // showCantor :: [(Bool, Int)] -> String    const showCantor = xs =>        xs.map(            ([bln, n]) => (                bln ? (                    "*"                ) : " "            ).repeat(n)        )        .join("");     // ---------------- GENERIC FUNCTIONS ----------------     // iterate :: (a -> a) -> a -> Gen [a]    const iterate = f =>        // An infinite list of repeated        // applications of f to x.        function* (x) {            let v = x;             while (true) {                yield v;                v = f(v);            }        };      // take :: Int -> [a] -> [a]    // take :: Int -> String -> String    const take = n =>        // The first n elements of a list,        // string of characters, or stream.        xs => "GeneratorFunction" !== xs        .constructor.constructor.name ? (            xs.slice(0, n)        ) : [].concat(...Array.from({            length: n        }, () => {            const x = xs.next();             return x.done ? [] : [x.value];        }));     // MAIN ---    return main();})();`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

### Cantor: Strings

Using strings for the model as well as the display:

`(() => {    "use strict";     // ----------------- CANTOR STRINGS ------------------     // cantor :: [String] -> [String]    const cantor = xs => {        const go = s => {            const                m = Math.floor(s.length / 3),                blocks = take(m)(s);             return "█" === s[0] ? (                [blocks, " ".repeat(m), blocks]            ) : [s];        };         return xs.flatMap(go);    };     // ---------------------- TEST -----------------------    const main = () =>        showCantor(5);      // --------------------- DISPLAY ---------------------    // showCantor :: Int -> String    const showCantor = n =>        take(n)(            iterate(cantor)([                "█".repeat(3 ** (n - 1))            ])        )        .map(x => x.join(""))        .join("\n");      // ---------------- GENERIC FUNCTIONS ----------------     // iterate :: (a -> a) -> a -> Gen [a]    const iterate = f =>        // An infinite list of repeated        // applications of f to x.        function* (x) {            let v = x;             while (true) {                yield v;                v = f(v);            }        };      // take :: Int -> [a] -> [a]    // take :: Int -> String -> String    const take = n =>        // The first n elements of a list,        // string of characters, or stream.        xs => "GeneratorFunction" !== xs        .constructor.constructor.name ? (            xs.slice(0, n)        ) : [].concat(...Array.from({            length: n        }, () => {            const x = xs.next();             return x.done ? [] : [x.value];        }));     // MAIN ---    return main();})();`
Output:
```█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █```

### Cantor: Rational pairs

Translation of: Python

Cantor ternary intervals rendered both as lists of rational pairs, and as graphic bars. In the case of languages like Javascript which lack a built-in Ratio type, or standard Fraction/Ratio library, rendering stages of the set elaboration as lists of fraction pairs may take more work than rendering them as graphic lines.

`(() => {    "use strict";     // -------------- CANTOR RATIONAL PAIRS --------------     // cantor :: [(Rational, Rational)] ->    //           [(Rational, Rational)]    const cantor = xs => {        const go = ab => {            const [r1, r2] = Array.from(ab).map(rational);            const third = ratioDiv(ratioMinus(r2)(r1))(3);             return [                Tuple(r1)(ratioPlus(r1)(third)),                Tuple(ratioMinus(r2)(third))(r2)            ];        };         return xs.flatMap(go);    };      // ---------------------- TEST -----------------------    // main :: IO ()    const main = () => {        const            xs = take(4)(                iterate(cantor)([Tuple(0)(1)])            );         return [                `\${unlines(xs.map(intervalRatios))}\n`,                intervalBars(xs)            ]            .join("\n\n");    };      // --------------------- DISPLAY ---------------------     // intervalRatios :: [(Rational, Rational)] -> String    const intervalRatios = xs => {        const go = ab =>            Array.from(ab).map(                compose(showRatio, rational)            )            .join(", ");         return `(\${xs.map(go).join(") (")})`;    };     // intervalBars :: [[(Rational, Rational)]] -> String    const intervalBars = rs => {        const go = w => xs =>            snd(mapAccumL(                a => ab => {                    const [wx, wy] = Array.from(ab).map(                        r => ratioMult(w)(                            rational(r)                        )                    );                     return Tuple(wy)(                        replicateString(                            floor(ratioMinus(wx)(a))                        )(" ") + replicateString(                            floor(ratioMinus(wy)(wx))                        )("█")                    );                }            )(0)(xs)).join("");        const d = maximum(            last(rs).map(x => fst(x).d)        );         return unlines(rs.map(            go(Ratio(d)(1))        ));    };      // ---------------- GENERIC FUNCTIONS ----------------     // Ratio :: Integral a => a -> a -> Ratio a    const Ratio = a => b => {        const go = (x, y) =>            0 !== y ? (() => {                const d = gcd(x)(y);                 return {                    type: "Ratio",                    // numerator                    "n": Math.trunc(x / d),                    // denominator                    "d": Math.trunc(y / d)                };            })() : undefined;         return go(a * signum(b), abs(b));    };      // Tuple (,) :: a -> b -> (a, b)    const Tuple = a =>        b => ({            type: "Tuple",            "0": a,            "1": b,            length: 2        });      // abs :: Num -> Num    const abs =        // Absolute value of a given number        // without the sign.        x => 0 > x ? (            -x        ) : x;      // approxRatio :: Float -> Float -> Ratio    const approxRatio = eps =>        n => {            const                gcde = (e, x, y) => {                    const _gcd = (a, b) =>                        b < e ? (                            a                        ) : _gcd(b, a % b);                     return _gcd(Math.abs(x), Math.abs(y));                },                c = gcde(Boolean(eps) ? (                    eps                ) : (1 / 10000), 1, n);             return Ratio(                Math.floor(n / c)            )(                Math.floor(1 / c)            );        };      // floor :: Num -> Int    const floor = x => {        const            nr = (                "Ratio" !== x.type ? (                    properFraction                ) : properFracRatio            )(x),            n = nr[0];         return 0 > nr[1] ? n - 1 : n;    };      // fst :: (a, b) -> a    const fst = ab =>        // First member of a pair.        ab[0];      // gcd :: Integral a => a -> a -> a    const gcd = x =>        y => {            const zero = x.constructor(0);            const go = (a, b) =>                zero === b ? (                    a                ) : go(b, a % b);             return go(abs(x), abs(y));        };      // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c    const compose = (...fs) =>        // A function defined by the right-to-left        // composition of all the functions in fs.        fs.reduce(            (f, g) => x => f(g(x)),            x => x        );      // iterate :: (a -> a) -> a -> Gen [a]    const iterate = f =>        // An infinite list of repeated        // applications of f to x.        function* (x) {            let v = x;             while (true) {                yield v;                v = f(v);            }        };      // last :: [a] -> a    const last = xs =>        // The last item of a list.        0 < xs.length ? (            xs.slice(-1)[0]        ) : null;      // lcm :: Int -> Int -> Int    const lcm = x =>        // The smallest positive integer divisible        // without remainder by both x and y.        y => (x === 0 || y === 0) ? (            0        ) : Math.abs(Math.floor(x / gcd(x)(y)) * y);      // mapAccumL :: (acc -> x -> (acc, y)) ->    // acc -> [x] -> (acc, [y])    const mapAccumL = f =>        // A tuple of an accumulation and a list        // obtained by a combined map and fold,        // with accumulation from left to right.        acc => xs => [...xs].reduce(            (a, x) => {                const ab = f(a[0])(x);                 return [ab[0], a[1].concat(ab[1])];            },            [acc, []]        );      // maximum :: Ord a => [a] -> a    const maximum = xs => (        // The largest value in a non-empty list.        ys => 0 < ys.length ? (            ys.slice(1).reduce(                (a, y) => y > a ? (                    y                ) : a, ys[0]            )        ) : undefined    )(xs);      // properFracRatio :: Ratio -> (Int, Ratio)    const properFracRatio = nd => {        const [q, r] = Array.from(quotRem(nd.n)(nd.d));         return Tuple(q)(Ratio(r)(nd.d));    };      // properFraction :: Real -> (Int, Real)    const properFraction = n => {        const i = Math.floor(n) + (n < 0 ? 1 : 0);         return Tuple(i)(n - i);    };      // quotRem :: Integral a => a -> a -> (a, a)    const quotRem = m =>        // The quotient, tupled with the remainder.        n => Tuple(            Math.trunc(m / n)        )(            m % n        );      // ratioDiv :: Rational -> Rational -> Rational    const ratioDiv = n1 => n2 => {        const [r1, r2] = [n1, n2].map(rational);         return Ratio(r1.n * r2.d)(            r1.d * r2.n        );    };      // ratioMinus :: Rational -> Rational -> Rational    const ratioMinus = n1 => n2 => {        const [r1, r2] = [n1, n2].map(rational);        const d = lcm(r1.d)(r2.d);         return Ratio(            (r1.n * (d / r1.d)) - (r2.n * (d / r2.d))        )(d);    };      // ratioMult :: Rational -> Rational -> Rational    const ratioMult = n1 => n2 => {        const [r1, r2] = [n1, n2].map(rational);         return Ratio(r1.n * r2.n)(            r1.d * r2.d        );    };      // ratioPlus :: Rational -> Rational -> Rational    const ratioPlus = n1 =>        n2 => {            const [r1, r2] = [n1, n2].map(rational);            const d = lcm(r1.d)(r2.d);             return Ratio(                (r1.n * (d / r1.d)) + (                    r2.n * (d / r2.d)                )            )(d);        };      // rational :: Num a => a -> Rational    const rational = x =>        isNaN(x) ? x : Number.isInteger(x) ? (            Ratio(x)(1)        ) : approxRatio(undefined)(x);      // replicateString :: Int -> String -> String    const replicateString = n =>        s => s.repeat(n);      // showRatio :: Ratio -> String    const showRatio = r =>        "Ratio" !== r.type ? (            r.toString()        ) : r.n.toString() + (            1 !== r.d ? (                `/\${r.d}`            ) : ""        );      // signum :: Num -> Num    const signum = n =>        // | Sign of a number.        n.constructor(            0 > n ? (                -1            ) : (                0 < n ? 1 : 0            )        );      // snd :: (a, b) -> b    const snd = ab =>        // Second member of a pair.        ab[1];      // take :: Int -> [a] -> [a]    // take :: Int -> String -> String    const take = n =>        // The first n elements of a list,        // string of characters, or stream.        xs => "GeneratorFunction" !== xs        .constructor.constructor.name ? (            xs.slice(0, n)        ) : [].concat(...Array.from({            length: n        }, () => {            const x = xs.next();             return x.done ? [] : [x.value];        }));      // unlines :: [String] -> String    const unlines = xs =>        // A single string formed by the intercalation        // of a list of strings with the newline character.        xs.join("\n");      // MAIN ---    return main();})();`
Output:
```(0, 1)
(0, 1/3) (2/3, 1)
(0, 1/9) (2/9, 1/3) (2/3, 7/9) (8/9, 1)
(0, 1/27) (2/27, 1/9) (2/9, 7/27) (8/27, 1/3) (2/3, 19/27) (20/27, 7/9) (8/9, 25/27) (26/27, 1)

███████████████████████████
█████████         █████████
███   ███         ███   ███
█ █   █ █         █ █   █ █```

## jq

`# cantor(width; height)def cantor(\$w; \$h):  def init: [range(0; \$h) | [range(0; \$w) | "*"]];   def cantor(\$start; \$leng; \$ix):    (\$leng/3|floor) as \$seg    | if \$seg == 0 then .      else reduce range(\$ix; \$h) as \$i (.;             reduce range(\$start+\$seg; \$start + 2*\$seg) as \$j (.; .[\$i][\$j] = " "))      | cantor(\$start; \$seg; \$ix+1)      | cantor(\$start + 2*\$seg; \$seg; \$ix+1)    end ;  init | cantor(0; \$w; 1); def pp: .[] | join(""); cantor(\$width; \$height)| pp`
Output:

With the above in a file, cantor.jq, the following incantation yields the same output as shown e.g. under `awk`, `julia`, etc.

```   jq -nr --argjson width 81 --argjson height 5 -f cantor.jq
```

## Julia

Translation of: AWK
`const width = 81const height = 5 function cantor!(lines, start, len, idx)    seg = div(len, 3)    if seg > 0        for i in idx+1:height, j in start + seg + 1: start + seg * 2            lines[i, j] = ' '        end        cantor!(lines, start, seg, idx + 1)        cantor!(lines, start + 2 * seg, seg, idx + 1)    endend lines = fill(UInt8('#'), height, width)cantor!(lines, 0, width, 1) for i in 1:height, j in 1:width    print(Char(lines[i, j]), j == width ? "\n" : "")end `
Output:
```#################################################################################
###########################                           ###########################
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #
```

## Kotlin

Simple terminal drawing.

`// Version 1.2.31 const val WIDTH = 81const 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) }}`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *
```

## Lua

Translation of: python
`local WIDTH = 81local HEIGHT = 5local lines = {} function cantor(start, length, index)    -- must be local, or only one side will get calculated    local seg = math.floor(length / 3)    if 0 == seg then        return nil    end     -- remove elements that are not in the set    for it=0, HEIGHT - index do        i = index + it        for jt=0, seg - 1 do            j = start + seg + jt            pos = WIDTH * i + j            lines[pos] = ' '        end    end     -- left side    cantor(start,           seg, index + 1)    -- right side    cantor(start + seg * 2, seg, index + 1)    return nilend -- initialize the linesfor i=0, WIDTH * HEIGHT do    lines[i] = '*'end -- calculatecantor(0, WIDTH, 1) -- print the result setsfor i=0, HEIGHT-1 do    beg = WIDTH * i    for j=beg, beg+WIDTH-1 do        if j <= WIDTH * HEIGHT then            io.write(lines[j])        end    end    print()end`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

## Mathematica/Wolfram Language

`Graphics[MeshPrimitives[CantorMesh[#],1]/.{x_}:>{x,-0.05#}&/@Range[5],ImageSize->600]`
Output:

A graphic of a Cantor set is shown

## Modula-2

Translation of: Kotlin
`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    ENDEND 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    ENDEND Print; BEGIN    Init;    Cantor(0,WIDTH,1);    Print;     ReadChar;END Cantor.`

## Nim

Translation of: Kotlin
`import strutils const  Width = 81  Height = 5 var lines: array[Height, string]for line in lines.mitems: line = repeat('*', Width) proc cantor(start, length, index: Natural) =  let seg = length div 3  if seg == 0: return  for i in index..<Height:    for j in (start + seg)..<(start + seg * 2):      lines[i][j] = ' '  cantor(start, seg, index + 1)  cantor(start + seg * 2, seg, index + 1) cantor(0, Width, 1)for line in lines:  echo line`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

## Objeck

Translation of: Java
`class CantorSet {  WIDTH : static : Int;  HEIGHT : static : Int;  lines : static : Char[,];   function : Init() ~ Nil {    WIDTH := 81;    HEIGHT := 5;    lines := Char->New[HEIGHT, WIDTH];     each(i : HEIGHT) {      each(j : WIDTH) {        lines[i,j] := '*';      };    };  }   function : Cantor(start : Int, len : Int, index : Int) ~ Nil {    seg : Int := len / 3;     if(seg = 0) {      return;    };     for(i := index; i < HEIGHT; i += 1;) {      for(j := start + seg; j < start + seg * 2; j += 1;) {        lines[i,j] := ' ';      };    };     Cantor(start, seg, index + 1);    Cantor(start + seg * 2, seg, index + 1);  }   function : Main(args : String[]) ~ Nil {    Init();     Cantor(0, WIDTH, 1);    each(i : HEIGHT) {      each(j : WIDTH) {        lines[i,j]->Print();      };      ""->PrintLine();    };  }}`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *
```

## Perl

Translation of: Raku
`use strict;use feature 'say'; sub cantor {    our(\$height) = @_;    my \$width = 3 ** (\$height - 1);     our @lines = ('#' x \$width) x \$height;     sub trim_middle_third {        my(\$len, \$start, \$index) = @_;        my \$seg = int \$len / 3            or return;         for my \$i ( \$index .. \$height - 1 ) {          for my \$j ( 0 .. \$seg - 1 ) {            substr \$lines[\$i], \$start + \$seg + \$j, 1, ' ';          }        }         trim_middle_third( \$seg, \$start + \$_, \$index + 1 ) for 0, \$seg * 2;    }     trim_middle_third( \$width, 0, 1 );    @lines;} say for cantor(5);`
Output:
```#################################################################################
###########################                           ###########################
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #```

### regex version

`#!/usr/bin/perl -l use strict; # https://rosettacode.org/wiki/Cantor_setuse warnings; \$_ = '#' x 81; 1 while print, s/(#+)\1\1/ \$1 . \$1 =~ tr!#! !r . \$1 /ge;`
Output:
```#################################################################################
###########################                           ###########################
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #
```

## Phix

Based on Algol 68, but even simpler, shorter, and sweeter!

```integer n = 5,
w = power(3,n-1),
len = w
string line = repeat('#',w)&"\n"

while 1 do
puts(1,line)
if len=1 then exit end if
len /= 3
integer pos = 1
while pos<(w-len) do
pos += len
line[pos..pos+len-1] = ' '
pos += len
end while
end while
```
Output:
```#################################################################################
###########################                           ###########################
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #
```

## Phixmonti

`include ..\Utilitys.pmt 5 >ps3 tps 1 - power var w"#" 1 get nip w repeat var line ps> for    3 swap 1 - power    w over / int var step    true >ps    for var j    	tps not if            step for var k            	line 32 j 1 - step * k + set var line            endfor        endif        ps> not >ps    endfor    cps    line ?endfor`

Other solution

`include ..\Utilitys.pmt 5 >ps3 tps 1 - power var w"#" 1 get nip w repeat var line ( 2 ps> ) for    line ?    3 swap 1 - power    w over / int var step    2 swap 2 3 tolist for var j        step for var k            line 32 j 1 - step * k + set var line        endfor    endforendforline ?`
Output:
```#################################################################################
###########################                           ###########################
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #

=== Press any key to exit ===```

## Python

### Imperative

`WIDTH = 81HEIGHT = 5 lines=[]def cantor(start, len, index):    seg = len / 3    if seg == 0:        return None    for it in xrange(HEIGHT-index):        i = index + it        for jt in xrange(seg):            j = start + seg + jt            pos = i * WIDTH + j            lines[pos] = ' '    cantor(start,           seg, index + 1)    cantor(start + seg * 2, seg, index + 1)    return None lines = ['*'] * (WIDTH*HEIGHT)cantor(0, WIDTH, 1) for i in xrange(HEIGHT):    beg = WIDTH * i    print ''.join(lines[beg : beg+WIDTH])`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

### Functional

Separating (Bool, Int) model from String display:

Works with: Python version 3.7
`'''Cantor set – separating model from display''' from functools import (reduce)import itertools  # cantor :: [(Bool, Int)] -> [(Bool, Int)]def cantor(xs):    '''A Cantor segmentation step.'''    def go(tpl):        (bln, n) = tpl        m = n // 3        return [            (True, m), (False, m), (True, m)        ] if bln and (1 < n) else [tpl]    return concatMap(go)(xs)  # cantorLines :: Int -> Stringdef cantorLines(n):    '''A text block display of n       Cantor-segmented lines.    '''    m = n - 1    repeat = itertools.repeat    return '\n'.join(        [showCantor(x) for x in (            reduce(                lambda a, f: a + [f(a[-1])],                repeat(cantor, m),                [[(True, 3 ** m)]]            )        )]    )  # showCantor :: [(Bool, Int)] -> Stringdef showCantor(xs):    '''A text block display of a list of       Cantor line segments.    '''    return ''.join(        concatMap(lambda tpl: tpl[1] * ('█' if tpl[0] else ' '))(            xs        )    )  # main :: IO ()def main():    '''Testing to depth 5'''     print(        cantorLines(5)    )  # GENERIC ------------------------------------------------------------- # concatMap :: (a -> [b]) -> [a] -> [b]def concatMap(f):    '''A concatenated list over which a function has been mapped.       The list monad can be derived by using a function f which       wraps its output in a list,       (using an empty list to represent computational failure).'''    chain = itertools.chain    return lambda xs: list(        chain.from_iterable(map(f, xs))    )  # MAIN ---if __name__ == '__main__':    main()`
Output:
```█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █```

Or, using strings for both model and display:

Translation of: JavaScript
Works with: Python version 3.7
`'''Cantor set – strings as both model and display.''' from itertools import (chain, islice)  # cantorLines :: Int -> Stringdef cantorLines(n):    '''N levels of cantor segmentation,       obtained and displayed in the       form of lines of block characters.    '''    return '\n'.join(        [''.join(x) for x in islice(            iterate(cantor)(                [3 ** (n - 1) * '█']            ), n        )]    )  # cantor :: [String] -> [String]def cantor(xs):    '''A cantor line derived from its predecessor.'''    def go(s):        m = len(s) // 3        blocks = s[0:m]        return [            blocks, m * ' ', blocks        ] if '█' == s[0] else [s]    return concatMap(go)(xs)  # MAIN ----------------------------------------------------# main :: IO ()def main():    '''Testing cantor line generation to level 5'''     print(        cantorLines(5)    ) # GENERIC -------------------------------------------------  # concatMap :: (a -> [b]) -> [a] -> [b]def concatMap(f):    '''A concatenated list over which a function has been mapped.       The list monad can be derived by using a function f which       wraps its output in a list,       (using an empty list to represent computational failure).'''    return lambda xs: list(        chain.from_iterable(map(f, xs))    )  # iterate :: (a -> a) -> a -> Gen [a]def iterate(f):    '''An infinite list of repeated       applications of f to x.    '''    def go(x):        v = x        while True:            yield v            v = f(v)    return lambda x: go(x)  # MAIN ---if __name__ == '__main__':    main()`
Output:
```█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █```

### Dual representations – fractional and graphic

Works with: Python version 3.7
`'''A Cantor set generator, and two different   representations of its output.''' from itertools import (islice, chain)from fractions import Fractionfrom functools import (reduce)  # ----------------------- CANTOR SET ----------------------- # cantor :: Generator [[(Fraction, Fraction)]]def cantor():    '''A non-finite stream of successive Cantor       partitions of the line, in the form of       lists of fraction pairs.    '''    def go(xy):        (x, y) = xy        third = Fraction(y - x, 3)        return [(x, x + third), (y - third, y)]     return iterate(        concatMap(go)    )(        [(0, 1)]    )  # fractionLists :: [(Fraction, Fraction)] -> Stringdef fractionLists(xs):    '''A fraction pair representation of a       Cantor-partitioned line.    '''    def go(xy):        return ', '.join(map(showRatio, xy))    return ' '.join('(' + go(x) + ')' for x in xs)  # intervalBars :: [(Fraction, Fraction)] -> Stringdef intervalBars(w):    '''A block diagram representation of a       Cantor-partitioned line.    '''    def go(xs):        def show(a, tpl):            [x, y] = [int(w * r) for r in tpl]            return (                y,                (' ' * (x - a)) + ('█' * (y - x))            )        return mapAccumL(show)(0)(xs)    return lambda xs: ''.join(go(xs)[1])  # -------------------------- TEST --------------------------# main :: IO ()def main():    '''Testing the generation of successive       Cantor subdivisions of the line, and       displaying them both as lines of fraction       pairs and as graphic interval bars.    '''    xs = list(islice(cantor(), 4))    w = max(xy[1].denominator for xy in xs[-1])    print(        '\n'.join(map(fractionLists, xs)),        '\n'    )    print(        '\n'.join(map(intervalBars(w), xs))    )  # ------------------------ GENERIC ------------------------- # concatMap :: (a -> [b]) -> [a] -> [b]def concatMap(f):    '''A concatenated list over which a function has been mapped.       The list monad can be derived by using a function f which       wraps its output in a list,       (using an empty list to represent computational failure).'''    return lambda xs: list(        chain.from_iterable(map(f, xs))    )  # iterate :: (a -> a) -> a -> Gen [a]def iterate(f):    '''An infinite list of repeated       applications of f to x.    '''    def go(x):        v = x        while True:            yield v            v = f(v)    return go  # mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])def mapAccumL(f):    '''A tuple of an accumulation and a list derived by a       combined map and fold,       with accumulation from left to right.    '''    def go(a, x):        tpl = f(a[0], x)        return (tpl[0], a[1] + [tpl[1]])    return lambda acc: lambda xs: (        reduce(go, xs, (acc, []))    )  # showRatio :: Ratio -> Stringdef showRatio(r):    '''String representation of the ratio r.'''    d = r.denominator    return str(r.numerator) + (        '/' + str(d) if 1 != d else ''    )  # MAIN ---if __name__ == '__main__':    main()`
Output:
```(0, 1)
(0, 1/3) (2/3, 1)
(0, 1/9) (2/9, 1/3) (2/3, 7/9) (8/9, 1)
(0, 1/27) (2/27, 1/9) (2/9, 7/27) (8/27, 1/3) (2/3, 19/27) (20/27, 7/9) (8/9, 25/27) (26/27, 1)

███████████████████████████
█████████         █████████
███   ███         ███   ███
█ █   █ █         █ █   █ █```

## QB64

Translation of: FreeBASIC

Note: Other languages will need to zero out the a() array. In QB64 all arrays are initialized to zero at program start.

`_Title "Cantor Set" Dim Shared As Integer sw, sh, wide, highsw = 800: sh = 200: wide = 729: high = 7Dim Shared As Integer a(wide, high) Screen _NewImage(sw, sh, 8)Cls , 15: Color 0 Call calc(0, wide, 1)Call CantorSet SleepSystem Sub calc (start As Integer, length As Integer, index As Integer)    Dim As Integer i, j, newLength    newLength = length \ 3    If newLength = 0 Then Exit Sub    For j = index To high - 1        For i = start + newLength To start + newLength * 2 - 1            a(i, j) = 1        Next    Next    Call calc(start, newLength, index + 1)    Call calc(start + newLength * 2, newLength, index + 1)End Sub Sub CantorSet    Dim As Integer i, j, x, y    For y = 0 To high - 1        j = y + 1        For x = 0 To wide - 1            i = x + 34            If a(x, y) = 0 Then Line (i, j * 24 - 5)-(i, j * 24 + 17)        Next    NextEnd Sub`

## Quackery

### Using an L-System

`  [ \$ "" swap witheach       [ nested quackery join ] ] is expand (   \$ --> \$ )   [ \$ "ABA" ]                    is A      (   \$ --> \$ )   [ \$ "BBB" ]                    is B      (   \$ --> \$ )   [ char A = iff      [ char q ] else space    swap of echo\$ ]              is draw   ( n c --> \$ )   81 \$ "A"  5 times    [ dup witheach        [ dip over draw ]      cr      i if        [ expand          dip [ 3 / ] ] ]  2drop `
Output:
```qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
qqqqqqqqqqqqqqqqqqqqqqqqqqq                           qqqqqqqqqqqqqqqqqqqqqqqqqqq
qqqqqqqqq         qqqqqqqqq                           qqqqqqqqq         qqqqqqqqq
qqq   qqq         qqq   qqq                           qqq   qqq         qqq   qqq
q q   q q         q q   q q                           q q   q q         q q   q q
```

## R

` cantorSet <- function() {  depth <- 6L  cs <- vector('list', depth)  cs[[1L]] <- c(0, 1)  for(k in seq_len(depth)) {    cs[[k + 1L]] <- unlist(sapply(seq_len(length(cs[[k]]) / 2L), function(j) {      p <- cs[[k]][2L] / 3      h <- 2L * (j - 1L)      c(        cs[[k]][h + 1L] + c(0, p),        cs[[k]][h + 2L] - c(p, 0)      )    }, simplify = FALSE))  }  cs} cantorSetGraph <- function() {  cs <- cantorSet()   u <- unlist(cs)   df <- data.frame(    x_start = u[seq_along(u) %% 2L == 1L],    x_end   = u[seq_along(u) %% 2L == 0L],    depth   = unlist(lapply(cs, function(e) {      l <- length(e)      n <- 0      while(l > 1) {        n <- n + 1L        l <- l / 2      }      rep(n, length(e) / 2)    }))  )   require(ggplot2)  g <- ggplot(df, aes_string(x = 'x_start', y = 'depth')) +    geom_segment(aes_string(xend = 'x_end', yend = 'depth', size = 3)) +    scale_y_continuous(trans = "reverse") +    theme(      axis.title = element_blank(),      axis.line = element_blank(),      axis.text = element_blank(),      axis.ticks = element_blank(),      legend.position = 'none',      aspect.ratio = 1/5    )     list(graph = g, data = df, set = cs)} `
Output:

Currently, RosettaCode does not seem to accept image upload anymore. So, you will have to run the program under R or RStudio IDE to get the diagram result.

## Racket

Translation of: Kotlin
`#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))) `
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *
```

## Raku

(formerly Perl 6)

Translation of: Kotlin
`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);`
Output:
```█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █```

## REXX

`/*REXX program displays an ASCII diagram of a Canter Set as a set of (character) lines. */w= linesize()                                    /*obtain the width of the display term.*/if w==0  then w= 81                              /*Can't obtain width?  Use the default.*/                   do lines=0;   _ = 3 ** lines  /*calculate powers of three  (# lines).*/                   if _>w  then leave            /*Too large?  We passed the max value. */                   #=_                           /*this value of a width─of─line is OK. */                   end   /*lines*/               /* [↑]  calculate a useable line width.*/w= #                                             /*use the (last) useable line width.   */\$= copies('■', #)                                /*populate the display line with blocks*/                   do j=0  until #==0            /*show Cantor set as a line of chars.  */                   if j>0  then do k=#+1  by  #+#  to w         /*skip 1st line blanking*/                                \$= overlay( left('', #), \$, k)  /*blank parts of a line.*/                                end   /*j*/                   say \$                         /*display a line of the Cantor Set.    */                   #= # % 3                      /*the part (thirds) to be blanked out. */                   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 size of the terminal width of 100:

(Shown at half size.)

```■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■                           ■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■         ■■■■■■■■■                           ■■■■■■■■■         ■■■■■■■■■
■■■   ■■■         ■■■   ■■■                           ■■■   ■■■         ■■■   ■■■
■ ■   ■ ■         ■ ■   ■ ■                           ■ ■   ■ ■         ■ ■   ■ ■
```
output   when using the default size of the terminal width of 250:

(Shown at half size.)

```■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■                                                                                 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■                           ■■■■■■■■■■■■■■■■■■■■■■■■■■■                                                                                 ■■■■■■■■■■■■■■■■■■■■■■■■■■■                           ■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■         ■■■■■■■■■                           ■■■■■■■■■         ■■■■■■■■■                                                                                 ■■■■■■■■■         ■■■■■■■■■                           ■■■■■■■■■         ■■■■■■■■■
■■■   ■■■         ■■■   ■■■                           ■■■   ■■■         ■■■   ■■■                                                                                 ■■■   ■■■         ■■■   ■■■                           ■■■   ■■■         ■■■   ■■■
■ ■   ■ ■         ■ ■   ■ ■                           ■ ■   ■ ■         ■ ■   ■ ■                                                                                 ■ ■   ■ ■         ■ ■   ■ ■                           ■ ■   ■ ■         ■ ■   ■ ■
```

## Ring

` # Project : Cantor set 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 `

Output image:

## Ruby

This works by numbering the segments (starting with 0) in base 3. Print whitespace if this number contains the digit 1; a black square otherwise.

`lines = 5 (0..lines).each do |exp|  seg_size = 3**(lines-exp-1)  chars = (3**exp).times.map{ |n| n.digits(3).any?(1) ? " " : "█"}  puts chars.map{ |c| c * seg_size }.joinend `
Output:
```█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █

```

## Rust

` use convert_base::Convert;use std::fmt; struct CantorSet {    cells: Vec<Vec<bool>>,}fn number_to_vec(n: usize) -> Vec<u32> {    // for the conversion we need the digits in reverse order    // i.e the least significant digit in the first element of the vector    n.to_string()        .chars()        .rev()        .map(|c| c.to_digit(10).unwrap())        .collect()} impl CantorSet {    fn new(lines: usize) -> CantorSet {        // Convert from base 10- to base 3        let mut base = Convert::new(10, 3);        let mut cells: Vec<Vec<bool>> = vec![];         for line in 0..lines {            // calculate how many repeating sequence will be in the given line            let segment_size = 3_usize.pow((lines - line - 1) as u32);            let segment: Vec<bool> = (0..3_usize.pow(line as u32))                .map(|n| {                    let output = base.convert::<u32, u32>(&number_to_vec(n));                    // return false in case the base 3 number contains at least one "1"                    // otherwise return true                    !output.contains(&1)                })                .collect();             // copy the segment "segment_size" time            let mut accum: Vec<bool> = Vec::with_capacity(segment.len() * segment_size);            for c in segment.iter() {                accum.extend(std::iter::repeat(*c).take(segment_size))            }             cells.push(accum);        }         CantorSet { cells }    }} impl fmt::Display for CantorSet {    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {        for line in self.cells.iter() {            for c in line {                write!(f, "{}", if *c { "█" } else { " " })?            }            writeln!(f)?;        }         Ok(())    }}fn main() {    let cs = CantorSet::new(5);    println!("Cantor set:");    println!("{}", cs);}  `
Output:
```Cantor set:
█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █

```

## Scala

### Imperative Programming (Q&D)

`object CantorSetQD extends App {  val (width, height) = (81, 5)   val lines = Seq.fill[Array[Char]](height)(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 height;           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))}`
Output:
See it in running in your browser by (JavaScript)

or by Scastie (JVM).

### Functional Programming (Recommended)

`object CantorSetFP extends App {  val (width, height) = (81, 5)   def lines = (1 to height).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 height)        yield if (index to height 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"))}`
Output:
See it in running in your browser by (JavaScript)

or by Scastie (JVM).

## Sidef

Translation of: Raku
`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 }`
Output:
```█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █
```

## Smalltalk

Works with: GNU Smalltalk

Smalltalk represents Intervals' start and stop values as Fraction, so precision is kept for quilte a while.

`Object subclass: CantorSet [     | intervals |     CantorSet class >> new        [^self basicNew            initialize;            yourself]     initialize        [intervals := Array with: (CantorInterval            from: 0            to: 1)]     split        [intervals := intervals gather: [:each | each split]]     displayOn: aStream atScale: aNumber        [| current |        current := 0.        intervals do:            [:each |            (each start - current) * aNumber timesRepeat: [aStream space].            each length * aNumber timesRepeat: [aStream nextPut: \$#].            current := each stop].        aStream nl]] Interval subclass: CantorInterval [     split        [| oneThird left right |        oneThird := self length / 3.        left := self class            from: start            to: start + oneThird.        right := self class            from: stop - oneThird            to: stop.        ^Array            with: left            with: right]     start  [^start]    stop   [^stop]    length [^stop - start]     printOn: aStream        [aStream << ('%1[%2,%3]' % {self class name. start. stop})]] Object subclass: TestCantor [     TestCantor class >> iterations: anInteger        [| cantorset scale count |        scale := 3 raisedTo: anInteger. "Make smallest interval 1"        count := 0.        cantorset := CantorSet new.         [cantorset            displayOn: Transcript            atScale: scale.        count < anInteger] whileTrue:            [cantorset split.            count := count + 1]]] TestCantor iterations: 4.`

Output:

```#################################################################################
###########################                           ###########################
#########         #########                           #########         #########
###   ###         ###   ###                           ###   ###         ###   ###
# #   # #         # #   # #                           # #   # #         # #   # #```

## Visual Basic .NET

Translation of: C#
`Module Module1     Const WIDTH = 81    Const HEIGHT = 5    Dim lines(HEIGHT, WIDTH) As Char     Sub Init()        For i = 0 To HEIGHT - 1            For j = 0 To WIDTH - 1                lines(i, j) = "*"            Next        Next    End Sub     Sub Cantor(start As Integer, len As Integer, index As Integer)        Dim seg As Integer = len / 3        If seg = 0 Then            Return        End If        For i = index To HEIGHT - 1            For j = start + seg To start + seg * 2 - 1                lines(i, j) = " "            Next        Next        Cantor(start, seg, index + 1)        Cantor(start + seg * 2, seg, index + 1)    End Sub     Sub Main()        Init()        Cantor(0, WIDTH, 1)        For i = 0 To HEIGHT - 1            For j = 0 To WIDTH - 1                Console.Write(lines(i, j))            Next            Console.WriteLine()        Next    End Sub End Module`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *```

## Wren

Translation of: Kotlin
`var width = 81var height = 5 var lines = [[]] * heightfor (i in 0...height) lines[i] = ["*"] * width var cantor // recursive so need to declare variable firstcantor = Fn.new { |start, len, index|    var seg = (len/3).floor    if (seg == 0) return    for (i in index...height) {        for (j in (start+seg)...(start+seg*2)) lines[i][j] = " "    }        cantor.call(start, seg, index + 1)    cantor.call(start + seg*2, seg, index + 1)} cantor.call(0, width, 1)for (i in 0...height) System.print(lines[i].join())`
Output:
```*********************************************************************************
***************************                           ***************************
*********         *********                           *********         *********
***   ***         ***   ***                           ***   ***         ***   ***
* *   * *         * *   * *                           * *   * *         * *   * *
```

## 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");`
Output:
```█████████████████████████████████████████████████████████████████████████████████
███████████████████████████                           ███████████████████████████
█████████         █████████                           █████████         █████████
███   ███         ███   ███                           ███   ███         ███   ███
█ █   █ █         █ █   █ █                           █ █   █ █         █ █   █ █
```