Cantor set: Difference between revisions

57,655 bytes added ,  1 month ago
m
→‎Using an L-System: added link to description
mNo edit summary
m (→‎Using an L-System: added link to description)
 
(91 intermediate revisions by 37 users not shown)
Line 1:
{{task}}
 
;Task:
Draw a Cantor set.
See details: [https://en.wikipedia.org/wiki/Cantor_set Cantor set]
 
 
See details at this Wikipedia webpage:   [https://en.wikipedia.org/wiki/Cantor_set Cantor set]
<br><br>
=={{header|11l}}==
{{trans|Python}}
<langsyntaxhighlight lang="11l">V WIDTH = 81
V HEIGHT = 5
 
Line 28 ⟶ 30:
L(i) 0 .< HEIGHT
V beg = WIDTH * i
print((lines[beg .< beg + WIDTH]).join(‘’))</langsyntaxhighlight>
{{out}}
<pre>
Line 37 ⟶ 39:
* * * * * * * * * * * * * * * *
</pre>
=={{header|Action!}}==
<syntaxhighlight lang="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)
OD
RETURN
 
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
OD
RETURN
 
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=$FF
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Cantor_set.png Screenshot from Atari 8-bit computer]
=={{header|Ada}}==
<syntaxhighlight lang="ada">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;</syntaxhighlight>
{{out}}
<pre>*********************************************************************************
*************************** ***************************
********* ********* ********* *********
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *</pre>
=={{header|ALGOL 68}}==
<langsyntaxhighlight lang="algol68">BEGIN
# draw a Cantor Set using ASCII #
INT lines = 5; # number of lines for the set #
Line 65 ⟶ 152:
segment width OVERAB 3
OD
END</langsyntaxhighlight>
{{out}}
<pre>
Line 74 ⟶ 161:
# # # # # # # # # # # # # # # #
</pre>
 
=={{header|ALGOL W}}==
Based on the Algol 68 sample.
<langsyntaxhighlight lang="algolw">begin
% draw a Cantor Set using ASCII %
integer LINES; % number of lines for the set %
Line 110 ⟶ 196:
end for_l
end
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 119 ⟶ 205:
# # # # # # # # # # # # # # # #
</pre>
 
=={{header|Amazing Hopper}}==
{{Trans|C}}
VERSION 1:
<syntaxhighlight lang="c">
#include <basico.h>
 
#define WIDTH 81
#define HEIGHT 5
 
#proto cantor(_X_,_Y_,_Z_)
 
algoritmo
 
decimales '0'
dimensionar(HEIGHT,WIDTH) matriz rellena("#",líneas)
 
_cantor(1, WIDTH, 2)
fijar separador 'NULO', imprimir( líneas, NL)
 
terminar
 
subrutinas
 
cantor(inicio, largo, índice)
seg=0
#( seg:=(int(largo/3))), no es cero?, entonces{
#basic{
líneas[índice:HEIGHT, (inicio+seg):((inicio+seg*2)-1)] = " ")
cantor( inicio, seg, índice+1 ) )
cantor( (inicio+(seg*2)), seg, índice+1 ) )
}
}
retornar
</syntaxhighlight>
{{out}}
<pre>
#################################################################################
########################### ###########################
######### ######### ######### #########
### ### ### ### ### ### ### ###
# # # # # # # # # # # # # # # #
</pre>
{{Trans|Ruby}}
VERSION 2:
<syntaxhighlight lang="c">
#include <basico.h>
 
#define HEIGHT 5
 
algoritmo
 
decimales '0'
cantor="", j=0
iterar
i=0
cadenas 's,v'
iterar grupo ( ++i, #(i< (3^j)),\
#( v = occurs("1", dectobase(i,3)) ? " " : "#"; )\
#( s = s $ replicate(v, 3^(HEIGHT-j-1) )) )
#(cantor = cantor $ s $ NL)
mientras ' #(j<=HEIGHT); ++j '
imprimir(cantor)
 
terminar
</syntaxhighlight>
{{out}}
<pre>
#################################################################################
########################### ###########################
######### ######### ######### #########
### ### ### ### ### ### ### ###
# # # # # # # # # # # # # # # #
</pre>
 
=={{header|AppleScript}}==
 
<lang applescript>-- cantor :: [String] -> [String]
Using composable library functions whenever possible, for better productivity:
<syntaxhighlight lang="applescript">------------------------- CANTOR SET -----------------------
 
-- cantor :: [String] -> [String]
on cantor(xs)
script go
Line 137 ⟶ 303:
end cantor
 
 
---------------------------- TEST --------------------------
on run
showCantor(5)
end run
 
-- showCantor :: Int -> String
Line 146 ⟶ 317:
 
 
-- TEST ------------------------------- GENERIC FUNCTIONS --------------------
on run
showCantor(5)
end run
 
 
-- GENERIC ------------------------------------------------
 
-- concat :: [[a]] -> [a]
Line 168 ⟶ 333:
acc
end concat
 
 
-- concatMap :: (a -> [b]) -> [a] -> [b]
Line 180 ⟶ 346:
return acc
end concatMap
 
 
-- map :: (a -> b) -> [a] -> [b]
Line 192 ⟶ 359:
end tell
end map
 
 
-- Lift 2nd class handler function into 1st class script wrapper
Line 204 ⟶ 372:
end if
end mReturn
 
 
-- iterate :: (a -> a) -> a -> Gen [a]
Line 268 ⟶ 437:
end if
end take
 
 
-- unlines :: [String] -> String
Line 276 ⟶ 446:
set my text item delimiters to dlm
str
end unlines</langsyntaxhighlight>
{{Out}}
<pre>█████████████████████████████████████████████████████████████████████████████████
Line 283 ⟶ 453:
███ ███ ███ ███ ███ ███ ███ ███
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █</pre>
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">width: 81
height: 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</syntaxhighlight>
 
{{out}}
 
<pre>*********************************************************************************
*************************** ***************************
********* ********* ********* *********
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *</pre>
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f CANTOR_SET.AWK
# converted from C
Line 316 ⟶ 516:
cantor(start+seg*2,seg,indx+1)
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 326 ⟶ 526:
</pre>
 
=={{header|BASIC256BASIC}}==
{{works with|QBasic}}
{{works with|GW-BASIC}}
{{works with|MSX BASIC}}
<syntaxhighlight lang="gwbasic">10 DEFINT A-Z
20 N = 4
30 W = 3^(N-1)
40 S = W
50 L$ = STRING$(W, "#")
60 PRINT L$
70 IF S = 1 THEN END
80 S = S\3
90 P = 1
100 IF P >= W-S GOTO 60
110 P = P+S
120 MID$(L$,P,S) = SPACE$(S)
130 P = P+S
140 GOTO 100</syntaxhighlight>
{{out}}
<pre>###########################
######### #########
### ### ### ###
# # # # # # # #</pre>
 
==={{header|BASIC256}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vb">global ancho, alto, intervalo
<lang BASIC256>
global ancho, alto, intervalo
ancho = 81 : alto = 5
dim intervalo(alto, ancho)
Line 336 ⟶ 559:
for i = 0 to alto - 1
for j = 0 to ancho - 1
intervalo[i, j] = chr(254)"■"
next j
next i
Line 346 ⟶ 569:
for i = indice to alto - 1
for j = inicio + segmento to inicio + segmento * 2 - 1
intervalo[i, j] = chr(32)" "
next j
next i
Line 361 ⟶ 584:
print
next i
end</syntaxhighlight>
End
 
</lang>
==={{header|Chipmunk Basic}}===
{{trans|FreeBASIC}}
{{works with|Chipmunk Basic|3.6.4}}
<syntaxhighlight lang="qbasic">100 cls
110 ancho = 81
120 alto = 5
130 dim intervalo$(alto,ancho)
140 '
150 sub cantor()
160 for i = 0 to alto-1
170 for j = 0 to ancho-1
180 intervalo$(i,j) = chr$(254)
190 next j
200 next i
210 end sub
220 '
230 sub conjcantor(inicio,longitud,indice)
240 segmento = longitud/3
250 if segmento = 0 then exit sub
260 for i = indice to alto-1
270 for j = inicio+segmento to inicio+segmento*2-1
280 intervalo$(i,j) = chr$(32)
290 next j
300 next i
310 conjcantor(inicio,segmento,indice+1)
320 conjcantor(inicio+segmento*2,segmento,indice+1)
330 end sub
340 '
350 cantor()
360 conjcantor(0,ancho,1)
370 for i = 0 to alto-1
380 for j = 0 to ancho-1
390 print intervalo$(i,j);
400 next j
410 print
420 next i
430 end</syntaxhighlight>
 
==={{header|GW-BASIC}}===
{{works with|PC-BASIC|any}}
{{works with|BASICA}}
The [[#BASIC|BASIC]] solution works without any changes.
 
==={{header|MSX Basic}}===
{{works with|MSX BASIC|any}}
The [[#BASIC|BASIC]] solution works without any changes.
 
==={{header|QBasic}}===
{{trans|FreeBASIC}}
{{works with|QBasic|1.1}}
{{works with|QuickBasic|4.5}}
<syntaxhighlight lang="qbasic">SUB Cantor
FOR i = 0 TO alto - 1
FOR j = 0 TO ancho - 1
intervalo$(i, j) = CHR$(254) '"#"
NEXT j
NEXT i
END SUB
 
SUB ConjCantor (inicio, longitud, indice)
segmento = INT(longitud / 3)
IF segmento = 0 THEN EXIT SUB
FOR i = indice TO alto - 1
FOR j = inicio + segmento TO inicio + segmento * 2 - 1
intervalo$(i, j) = CHR$(32) '" "
NEXT j
NEXT i
CALL ConjCantor(inicio, segmento, indice + 1)
CALL ConjCantor(inicio + segmento * 2, segmento, indice + 1)
END SUB
 
CONST ancho = 81
CONST alto = 5
DIM SHARED intervalo$(alto, ancho)
 
CLS
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
PRINT
NEXT i
END</syntaxhighlight>
 
==={{header|True BASIC}}===
{{trans|QBasic}}
<syntaxhighlight lang="qbasic">LET ancho = 81
LET alto = 5
DIM intervalo$(0,0)
MAT REDIM intervalo$(0 TO alto, 0 TO ancho)
 
SUB cantor
FOR i = 0 TO alto-1
FOR j = 0 TO ancho-1
LET intervalo$(i, j) = "#" !CHR$(254)
NEXT j
NEXT i
END SUB
 
SUB conjcantor (inicio,longitud,indice)
LET segmento = INT(longitud/3)
IF segmento = 0 THEN EXIT SUB
FOR i = indice TO alto-1
FOR j = inicio+segmento TO inicio+segmento*2-1
LET intervalo$(i, j) = CHR$(32) !" "
NEXT j
NEXT i
CALL conjcantor (inicio, segmento, indice+1)
CALL conjcantor (inicio+segmento*2, segmento, indice+1)
END SUB
 
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
PRINT
NEXT i
END</syntaxhighlight>
 
==={{header|Yabasic}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vb">ancho = 81
alto = 5
dim intervalo$(alto, ancho)
 
Cantor()
ConjCantor(0, ancho, 1)
for i = 0 to alto - 1
for j = 0 to ancho - 1
print intervalo$(i, j);
next j
print
next i
end
 
sub Cantor()
for i = 0 to alto - 1
for j = 0 to ancho - 1
intervalo$(i, j) = chr$(254) //"#"
next j
next i
end sub
 
sub ConjCantor(inicio, longitud, indice)
segmento = longitud / 3
if segmento = 0 return
for i = indice to alto - 1
for j = inicio + segmento to inicio + segmento * 2 - 1
intervalo$(i, j) = " "
next j
next i
ConjCantor(inicio, segmento, indice + 1)
ConjCantor(inicio + segmento * 2, segmento, indice + 1)
end sub</syntaxhighlight>
 
=={{header|BQN}}==
<syntaxhighlight lang="bqn">Cantor ← {" •" ⊏˜ >⥊¨(¯1⊸⊏⊢¨¨⊢)1‿0‿1∧⌜⍟(↕𝕩)1}</syntaxhighlight>
 
{{out}}
 
<pre>
Cantor 5
Igual que la entrada de FreeBASIC.
┌─
╵"•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
••••••••••••••••••••••••••• •••••••••••••••••••••••••••
••••••••• ••••••••• ••••••••• •••••••••
••• ••• ••• ••• ••• ••• ••• •••
• • • • • • • • • • • • • • • •"
</pre>
 
=={{header|C}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="c">#include <stdio.h>
 
#define WIDTH 81
Line 407 ⟶ 799:
print();
return 0;
}</langsyntaxhighlight>
 
{{output}}
Line 417 ⟶ 809:
* * * * * * * * * * * * * * * *
</pre>
=={{header|C sharp|C#}}==
{{trans|Java}}
<syntaxhighlight lang="csharp">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();
}
}
}
}</syntaxhighlight>
{{out}}
<pre>*********************************************************************************
*************************** ***************************
********* ********* ********* *********
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *</pre>
=={{header|C++}}==
{{trans|D}}
<langsyntaxhighlight lang="cpp">#include <iostream>
 
const int WIDTH = 81;
Line 455 ⟶ 893:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>*********************************************************************************
Line 462 ⟶ 900:
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *</pre>
=={{header|CLU}}==
<syntaxhighlight lang="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)
=={{header|C#|C sharp}}==
seg: int := len / 3
{{trans|Java}}
if seg = 0 then return end
<lang csharp>using System;
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_step
end cantor
 
start_up = proc ()
namespace CantorSet {
po: stream := stream$primary_output()
class Program {
cs: string := cantor$make(81, 5, '*')
const int WIDTH = 81;
stream$puts(po, cs)
const int HEIGHT = 5;
end start_up</syntaxhighlight>
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();
}
}
}
}</lang>
{{out}}
<pre>*********************************************************************************
Line 510 ⟶ 940:
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *</pre>
=={{header|COBOL}}==
 
<syntaxhighlight lang="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.</syntaxhighlight>
{{out}}
<pre>#################################################################################
########################### ###########################
######### ######### ######### #########
### ### ### ### ### ### ### ###
# # # # # # # # # # # # # # # #</pre>
=={{header|D}}==
{{trans|C}}
<langsyntaxhighlight lang="d">import std.stdio;
 
enum WIDTH = 81;
Line 545 ⟶ 1,029:
writeln(lines[beg..beg+WIDTH]);
}
}</langsyntaxhighlight>
{{out}}
<pre>*********************************************************************************
Line 552 ⟶ 1,036:
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *</pre>
=={{header|Delphi}}==
{{Trans|Java}}
<syntaxhighlight lang="delphi">
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.
</syntaxhighlight>
 
{{out}}
Same result of Java
 
=={{header|EasyLang}}==
 
[https://easylang.dev/show/#cod=S87PyS9SMDU15Sooyk9WSE7MKwHyKxQqFYqrFPQU9LgUFBQy00AcOwUDPUMQFwiKq4wVbEGC+grGUKHc/LJUsD5dkCxUsCg1uQSkDCGCZAFYITYpbQUjBS2wJJoiPS49LqgqAwULAwVDAwMuAA== Run it]
 
<syntaxhighlight>
color 555
proc cantor x y sz . .
if sz > 0.1
sz3 = sz / 3
move x y - sz3
rect sz sz3
cantor x y - sz3 sz3
cantor x + 2 * sz3 y - sz3 sz3
.
.
cantor 0 80 100
</syntaxhighlight>
 
=={{header|Elixir}}==
<syntaxhighlight lang="elixir">
defmodule Cantor do
@pos "█"
@neg " "
 
def run(lines) do
Enum.map(0..lines, fn line ->
segment_size = 3 ** (lines - line - 1)
chars = (3 ** line)
 
Enum.map(0..chars, fn char ->
char
|> Integer.digits(3)
|> Enum.any?(fn x -> x === 1 end)
|> case do
true -> @neg
false -> @pos
end
end)
|> Enum.reduce([], fn el, acc -> duplicate_char(acc, el, segment_size) end)
|> Enum.join()
|> String.trim_trailing()
end)
|> Enum.filter(fn line -> line !== "" end)
end
 
def duplicate_char(acc, el, segment_size) when segment_size >= 1, do: acc ++ [String.duplicate(el, segment_size)]
def duplicate_char(acc, _el, segment_size) when segment_size < 1, do: acc
end
 
Cantor.run(5) |> IO.inspect()
</syntaxhighlight>
{{out}}
<pre>["█████████████████████████████████████████████████████████████████████████████████",
"███████████████████████████ ███████████████████████████",
"█████████ █████████ █████████ █████████",
"███ ███ ███ ███ ███ ███ ███ ███",
"█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █"]</pre>
 
=={{header|EMal}}==
<syntaxhighlight lang="emal">
int WIDTH = 81
int HEIGHT = 5
List lines = text[].with(HEIGHT) # a list with HEIGHT empty texts
for each int i in range(0, HEIGHT) do lines[i] = text("█", WIDTH) end
fun cantor = void by int start, int len, int index
int seg = len / 3
if seg == 0 do return end
for int i = index; i < HEIGHT; i++
for int j = start + seg; j < start + seg * 2; j++
lines[i][j] = " "
end
end
cantor(start, seg, index + 1)
cantor(start + seg * 2, seg, index + 1)
end
cantor(0, WIDTH, 1)
for each text line in lines do writeLine(line) end
</syntaxhighlight>
{{out}}
<pre>
█████████████████████████████████████████████████████████████████████████████████
███████████████████████████ ███████████████████████████
█████████ █████████ █████████ █████████
███ ███ ███ ███ ███ ███ ███ ███
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
</pre>
 
=={{header|Excel}}==
===LAMBDA===
Binding names to the following lambda expressions in the Name Manager of the Excel WorkBook:
 
(See [https://www.microsoft.com/en-us/research/blog/lambda-the-ultimatae-excel-worksheet-function/ LAMBDA: The ultimate Excel worksheet function])
 
{{Works with|Office 365 betas 2021}}
<syntaxhighlight lang="lisp">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)
),
""
)
)
)
)</syntaxhighlight>
 
and also assuming the following generic bindings in the Name Manager for the WorkBook:
 
<syntaxhighlight lang="lisp">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)
)
)
)</syntaxhighlight>
 
{{Out}}
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:
{| class="wikitable"
|-
|||style="text-align:right; font-family:serif; font-style:italic; font-size:120%;"|fx
! colspan="2" style="text-align:left; vertical-align: bottom; font-family:Arial, Helvetica, sans-serif !important;"|=SHOWCANTOR(CANTOR(1))
|- style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff;"
|
| A
| B
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 1
| style="text-align:right; " | SHOWCANTOR(CANTOR(0))
| style="text-align:left; font-weight:bold" | <syntaxhighlight lang="text">█</syntaxhighlight>
 
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 2
| style="text-align:right; " | SHOWCANTOR(CANTOR(1))
| style="text-align:left; background-color:#cbcefb;" | <syntaxhighlight lang="text">███
█ █</syntaxhighlight>
 
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 3
| style="text-align:right; " | SHOWCANTOR(CANTOR(2))
| style="text-align:left; font-weight:bold" | <syntaxhighlight lang="text">█████████
███ ███
█ █ █ █</syntaxhighlight>
 
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 4
| style="text-align:right; " | SHOWCANTOR(CANTOR(3))
| style="text-align:left; font-weight:bold" | <syntaxhighlight lang="text">███████████████████████████
█████████ █████████
███ ███ ███ ███
█ █ █ █ █ █ █ █</syntaxhighlight>
 
|}
 
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.'')
 
{| class="wikitable"
|-
|||style="text-align:right; font-family:serif; font-style:italic; font-size:120%;"|fx
! colspan="17" style="text-align:left; vertical-align: bottom; font-family:Arial, Helvetica, sans-serif !important;"|=IFNA(CANTOR(3), "")
|- style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff;"
|
| A
| B
| C
| D
| E
| F
| G
| H
| I
| J
| K
| L
| M
| N
| O
| P
| Q
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 2
| style="text-align:right; font-weight:bold" | Unit range
| style="text-align:left; background-color:#cbcefb" | 0
| style="text-align:left" | 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 3
| style="text-align:right; font-weight:bold" | Cantor 1
| style="text-align:left" | 0
| style="text-align:left" | 1/3
| style="text-align:left" | 2/3
| style="text-align:left" | 1
|
|
|
|
|
|
|
|
|
|
|
|
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 4
| style="text-align:right; font-weight:bold" | Cantor 2
| style="text-align:left" | 0
| style="text-align:left" | 1/9
| style="text-align:left" | 2/9
| style="text-align:left" | 1/3
| style="text-align:left" | 2/3
| style="text-align:left" | 7/9
| style="text-align:left" | 8/9
| style="text-align:left" | 1
|
|
|
|
|
|
|
|
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 5
| style="text-align:right; font-weight:bold" | Cantor 3
| style="text-align:left" | 0
| style="text-align:left" | 1/27
| style="text-align:left" | 2/27
| style="text-align:left" | 1/9
| style="text-align:left" | 2/9
| style="text-align:left" | 7/27
| style="text-align:left" | 8/27
| style="text-align:left" | 1/3
| style="text-align:left" | 2/3
| style="text-align:left" | 19/27
| style="text-align:left" | 20/27
| style="text-align:left" | 7/9
| style="text-align:left" | 8/9
| style="text-align:left" | 25/27
| style="text-align:left" | 26/27
| style="text-align:left" | 1
|}
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: grouping.extras io kernel math sequences
sequences.repeating ;
IN: rosetta-code.cantor-set
Line 576 ⟶ 1,626:
concat print ;
depth <iota> [ print-cantor ] each</langsyntaxhighlight>
{{out}}
<pre>
Line 585 ⟶ 1,635:
# # # # # # # # # # # # # # # #
</pre>
 
=={{header|Forth}}==
Where is says <code>[email protected]</code> it should say <code>c&#64;</code>, but I'm not keen on writing it as <code>c&amp;#64;</code> in the actual code.
<langsyntaxhighlight Forthlang="forth">warnings off
 
4 \ iterations
Line 613 ⟶ 1,662:
: go print BEGIN step done? UNTIL ;
 
go bye</langsyntaxhighlight>
Output:
<pre>#################################################################################
Line 620 ⟶ 1,669:
### ### ### ### ### ### ### ###
# # # # # # # # # # # # # # # #</pre>
 
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">
Const ancho = 81
Const alto = 5
Line 660 ⟶ 1,707:
Next i
End
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 669 ⟶ 1,716:
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
</pre>
 
 
 
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
_window = 1
 
_width = 81
_height = 5
 
window _window, @"FutureBasic Cantor Set", ( 0, 0, 695, 100 )
WindowSetBackgroundColor( _window, fn ColorWhite )
text @"Menlo", 14.0, fn ColorRed
 
begin globals
CFStringRef gInterval( _height, _width )
end globals
 
local fn Init
NSInteger i, j
for i = 0 to _height - 1
for j = 0 to _width - 1
gInterval( i, j ) = @"◼︎"
next
next
end fn
 
local fn CantorSet( start as NSInteger, length as NSInteger, index as NSInteger )
NSInteger i, j, segment = length / 3
if segment == 0 then exit fn
for i = index to _height - 1
for j = start + segment to start + segment * 2 - 1
gInterval( i, j ) = @" "
next
next
fn CantorSet( start, segment, index + 1 )
fn CantorSet( start + segment * 2, segment, index + 1 )
end fn
 
NSInteger i, j
 
fn Init
fn CantorSet ( 0, _width, 1 )
for i = 0 to _height - 1
for j = 0 to _width - 1
print gInterval( i, j );
next
print
next
 
HandleEvents
</syntaxhighlight>
{{output}}
[[File:FutureBasic Cantor Set.png]]
 
=={{header|Fōrmulæ}}==
 
{{FormulaeEntry|page=https://formulae.org/?script=examples/The_Cantor_set}}
 
'''Solution'''
 
Strictly speaking, a visualization of the perfect Cantor set is impossible, it consists of a infinite set of isolated points in the interval [0, 1]. The most we can do is drawing the early steps of its construction.
 
Several ways of visualization of the Cantor set are shown.
 
'''Preliminaries'''
 
Let us start with a definition of the points that define the central points of the intervals of the Cantos set on any step:
 
[[File:Fōrmulæ - Cantor set 01.png]]
 
[[File:Fōrmulæ - Cantor set 02.png]]
 
[[File:Fōrmulæ - Cantor set 03.png]]
 
The followign function defines the segments on each step:
 
[[File:Fōrmulæ - Cantor set 04.png]]
 
[[File:Fōrmulæ - Cantor set 05.png]]
 
[[File:Fōrmulæ - Cantor set 06.png]]
 
=== Plotting the central points ===
 
[[File:Fōrmulæ - Cantor set 07.png]]
 
[[File:Fōrmulæ - Cantor set 08.png]]
 
=== Common method ===
 
[[File:Fōrmulæ - Cantor set 09.png]]
 
[[File:Fōrmulæ - Cantor set 10.png]]
 
[[File:Fōrmulæ - Cantor set 11.png]]
 
=== Cantor dust ===
 
[[File:Fōrmulæ - Cantor set 12.png]]
 
[[File:Fōrmulæ - Cantor set 13.png]]
 
[[File:Fōrmulæ - Cantor set 14.png]]
 
=== [https://en.wikipedia.org/wiki/Knaster%E2%80%93Kuratowski_fan Knaster–Kuratowski fan or "Cantor teepee"] ===
 
[[File:Fōrmulæ - Cantor set 15.png]]
 
[[File:Fōrmulæ - Cantor set 16.png]]
 
[[File:Fōrmulæ - Cantor set 17.png]]
 
 
The following forms of visualization are taken from [https://en.wikipedia.org/wiki/Point-set_topology point-set topology]. They are not intended as forms of visualization of the Cantor set, instead, these structures make use of the Cantor set.
 
=== [https://en.wikipedia.org/wiki/Indecomposable_continuum Brouwer–Janiszewski–Knaster continuum, or "the bucket handle"] ===
 
[[File:Fōrmulæ - Cantor set 18.png]]
 
[[File:Fōrmulæ - Cantor set 19.png]]
 
[[File:Fōrmulæ - Cantor set 20.png]]
 
=== "Double Knaster" ===
 
[[File:Fōrmulæ - Cantor set 21.png]]
 
[[File:Fōrmulæ - Cantor set 22.png]]
 
[[File:Fōrmulæ - Cantor set 23.png]]
 
=={{header|Go}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 710 ⟶ 1,891:
fmt.Println(string(line[:]))
}
}</langsyntaxhighlight>
 
{{out}}
Line 720 ⟶ 1,901:
* * * * * * * * * * * * * * * *
</pre>
=={{header|Groovy}}==
{{trans|Java}}
<syntaxhighlight lang="groovy">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()
}
}
}</syntaxhighlight>
{{out}}
<pre>*********************************************************************************
*************************** ***************************
********* ********* ********* *********
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *</pre>
=={{header|Haskell}}==
===Interval bars===
{{Trans|Python}} (Functional version)
<syntaxhighlight lang="haskell">-------------------------- CANTOR ------------------------
<lang haskell>import Data.Bool (bool)
 
cantor :: [(Bool, Int)] -> [(Bool, Int)]
cantor = (goconcatMap =<<)go
where
go (bln, n) =
let| mbln =&& quot1 < n 3=
in bool [(bln, n)] [(True,let m), (False,= m),quot (True,n m)] (bln && 1 < n)3
in [(True, m), (False, m), (True, m)]
| otherwise = [(bln, n)]
 
--------------------------- TEST -------------------------
main :: IO ()
main = putStrLn $ cantorLines 5
 
------------------------- DISPLAY ------------------------
cantorLines :: Int -> String
cantorLines n =
unlines $
unlines $ showCantor <$> take n (iterate cantor [(True, 3 ^ (n - 1))])
showCantor
<$> take n (iterate cantor [(True, 3 ^ pred n)])
 
showCantor :: [(Bool, Int)] -> String
showCantor = (concatMap $ uncurry (flip replicate . bool ' ' '*') =<<c)
where
 
c True = '*'
main :: IO ()
c False = ' '</syntaxhighlight>
main = putStrLn $ cantorLines 5</lang>
{{Out}}
<pre>*********************************************************************************
Line 751 ⟶ 1,984:
Or, using strings for the model as well as the display:
 
<syntaxhighlight lang="haskell">-------------------------- CANTOR ------------------------
<lang haskell>import Data.Bool (bool)
 
cantor :: [String] -> [String]
cantor = (go =<<)
where
go x =
| '█' == head x = [block, replicate m ' ', block]
let m = quot (length x) 3
| blockotherwise = take m [x]
where
in bool [x] [block, replicate m ' ', block] ('█' == head x)
m = quot (length x) 3
 
block = take m x
cantorLines :: Int -> String
cantorLines n =
unlines $ concat <$> take n (iterate cantor [replicate (3 ^ (n - 1)) '█'])
 
--------------------------- TEST -------------------------
main :: IO ()
main = putStrLn $ cantorLines 5</lang>
 
 
------------------------- DISPLAY ------------------------
cantorLines :: Int -> String
cantorLines =
unlines . (concat <$>)
. ( take
<*> ( iterate cantor
. return
. flip replicate '█'
. (3 ^)
. pred
)
)</syntaxhighlight>
{{Out}}
<pre>█████████████████████████████████████████████████████████████████████████████████
Line 776 ⟶ 2,023:
===Dual representation===
Intervals as fraction pairs, and intervals as graphic bars:
<syntaxhighlight lang ="haskell">import DataControl.RatioMonad (Ratio, (%), numerator, denominatorjoin)
import Data.Bifunctor (bimap)
import Data.List (intercalate, mapAccumL, maximumBy)
import Data.BoolRatio (boolRatio, denominator, numerator, (%))
 
-------------------------- CANTOR ------------------------
 
cantor :: (Rational, Rational) -> [[(Rational, Rational)]]
cantor = iterate (go =<<) . pure
where
let go (x, y) =
go (x, y) = let[(x, rx =+ r), (y - x)r, / 3y)]
where
in [(x, x + r), (y - r, y)]
in iterate (>> r = go(y - x) ./ return3
 
--------------------------- TEST -------------------------
 
main :: IO ()
main = do
( ( (>>)
let xs = take 4 $ cantor (0, 1)
. putStrLn
(putStrLn . unlines) $ intervalRatios <$> xs
. unlines
putStrLn $ intervalBars xs
. fmap intervalRatios
)
<*> (putStrLn . intervalBars)
)
$ take 4 $ cantor (0, 1)
 
------------------------- DISPLAY ------------------------
 
-- DISPLAY FUNCTIONS ---------------------------------------------------
intervalBars :: [[(Rational, Rational)]] -> String
intervalBars xs = unlines $ go (d % 1) <$> xs
where
let go w xs =
d = maximum $ concatdenominator . sndfst <$> last xs
go w xs =
concat . snd $
mapAccumL
( \a (rx, ry) ->
let (wxwy, wywx) = (w * rxry, w * ryrx)
in ( wy -- Accumulator – end of previous interval.,
, replicate (floor (wx - a)) ' ' -- Preceding gap, and
++ <> replicate (floor (wy - wx)) '█'
replicate (floor (wy - wx)) '█' -- interval bar.
))
0
xs
d = maximum $ (denominator . fst) <$> last xs
in unlines $ go (d % 1) <$> xs
 
intervalRatios :: [(Rational, Rational)] -> String
intervalRatios xs =
('(' :) . (<> ")")
let go (rx, ry) = intercalate ", " $ showRatio <$> [rx, ry]
in '(' :. intercalate ") (" (go <$> xs) ++ ")"
. fmap
(uncurry ((<>) . (<> ", ")) . join bimap showRatio)
 
showRatio :: Rational -> String
showRatio = ((<>) . show . numerator) <*> (go . denominator)
showRatio r =
where
let d = denominator r
go x
in show (numerator r) ++ bool [] ('/' : show d) (1 /= d)</lang>
| 1 /= x = '/' : show x
| otherwise = []</syntaxhighlight>
{{Out}}
<pre>(0, 1)
Line 830 ⟶ 2,092:
███ ███ ███ ███
█ █ █ █ █ █ █ █</pre>
 
=={{header|IS-BASIC}}==
<langsyntaxhighlight ISlang="is-BASICbasic">100 PROGRAM "Cantor.bas"
110 GRAPHICS HIRES 2
120 SET PALETTE BLACK,WHITE
Line 842 ⟶ 2,103:
180 CALL CANTOR(X+2*L/3,Y-HEIGHT,L/3,HEIGHT)
190 END IF
200 END DEF</langsyntaxhighlight>
 
=={{header|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.
<syntaxhighlight lang="j">
<lang J>
odometer =: [: (4 $. $.) $&1
 
Line 855 ⟶ 2,115:
< (}:"1) 1j1 #"1 '#' (([: <"1 [: ;/"1 (#~ 1 e."1 [: (,/"2) 3 3&#:)) i)}a
)
</syntaxhighlight>
</lang>
 
<pre>
Line 904 ⟶ 2,164:
</pre>
With an `x' argument cantor_dust generalizes to higher dimensions. Try 3 cantor_dust 2
<syntaxhighlight lang="j">
<lang J>
cantor_dust =: 2&$: :(dyad define)
shape =. x # 3 ^ y
Line 911 ⟶ 2,171:
< (}:"1) 1j1 #"1 '#' (([: <"1 [: ;/"1 (#~ 1 e."1 [: (,/"2) 3 3&#:)) i)} a
)
</syntaxhighlight>
</lang>
 
=={{header|Java}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="java">public class App {
private static final int WIDTH = 81;
private static final int HEIGHT = 5;
Line 951 ⟶ 2,210:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>*********************************************************************************
Line 958 ⟶ 2,217:
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *</pre>
 
=={{header|JavaScript}}==
===Cantor: (Bool, Int) pairs===
{{Trans|Python}} (Functional version)
{{Trans|Haskell}}
<langsyntaxhighlight JavaScriptlang="javascript">(() => {
'"use strict'";
 
// -------------- CANTOR BOOL-INT PAIRS --------------
const main = () => {
 
// cantor :: [(Bool, Int)] -> [(Bool, Int)]
const cantor = xs => {
const go = ([bln, n]) =>
bln && 1 < n ? (() => {
const x = Math.floor(n / 3);
 
// cantor :: [(Bool, Int)] -> [(Bool, Int)] return [
const cantor = xs => { [true, x],
const go = ( [blnfalse, nx]) =>,
bln && 1 < n[true, ? (() => {x]
const lng = Math.floor(n / 3);
return [
[true, lng],
[false, lng],
[true, lng]
]
})() : [
[bln, n]
];
return concatMap})(go, xs); : [
}; [bln, n]
];
 
//return cantorLines :: Int -> Stringxs.flatMap(go);
};
const cantorLines = n =>
unlines(
map(showCantor,
take(n,
iterate(
cantor,
[
[true, Math.pow(3, n - 1)]
]
)
)
)
);
 
// ---------------------- TEST -----------------------
// showCantor :: [(Bool, Int)] -> String
// main :: IO ()
const showCantor = xs =>
const main = () concat(map(=>
cantorLines(5);
([bln, n]) => replicate(n, bln ? '*' : ' '), xs
));
 
console.log(
cantorLines(5)
);
};
 
// GENERIC FUNCTIONS --------------------- DISPLAY ---------------------
 
// concatcantorLines :: [[a]]Int -> [a]String
//const concatcantorLines ::= [String]n -=> String
const concat = xs =>take(n)(
0 < xs.length ? iterate(cantor)() => {[
const unit = 'string' !== typeof xs[0]true, ?3 ** (n - 1)]
[])
) : '';
return unit.concat.applymap(unit, xsshowCantor);
}).join("\n") : [];
 
 
// concatMap :: (a -> [b]) -> [a] -> [b]
const// concatMapshowCantor =:: [(fBool, xsInt)] =-> String
const showCantor = xs =>
xs.reduce((a, x) => a.concat(f(x)), []);
xs.map(
([bln, n]) => (
bln ? (
"*"
) : " "
).repeat(n)
)
.join("");
 
// ---------------- GENERIC FUNCTIONS ----------------
 
// iterate :: (a -> a) -> a -> Gen [a]
function*const iterate(f, x)= f {=>
let// vAn =infinite x;list of repeated
while// (true)applications {of f to x.
function* yield(vx); {
let v = f(v)x;
}
}
 
// map :: (a -> b) -> [a] ->while (true) [b]{
const map = (f, xs) => xs.map(f) yield v;
v = f(v);
}
};
 
// replicate :: Int -> String -> String
const replicate = (n, s) => s.repeat(n);
 
// take :: Int -> [a] -> [a]
// take :: Int -> String -> String
const take = (n, xs) =>
// The first n elements of a list,
'GeneratorFunction' !== xs.constructor.constructor.name ? (
// string of characters, or stream.
xs => "GeneratorFunction" !== xs
.constructor.constructor.name ? (
xs.slice(0, n)
) : [].concat.apply([], ...Array.from({
length: n
}, () => {
const x = xs.next();
 
return x.done ? [] : [x.value];
}));
 
// unlines :: [String] -> String
const unlines = xs => xs.join('\n');
 
// MAIN ---
return main();
})();</langsyntaxhighlight>
{{Out}}
<pre>*********************************************************************************
Line 1,065 ⟶ 2,316:
* * * * * * * * * * * * * * * *</pre>
 
===Cantor: Strings===
Or, using strings for the model as well as the display:
Using strings for the model as well as the display:
{{Trans|Haskell}}
<langsyntaxhighlight lang="javascript">(() => {
'"use strict'";
 
// ----------------- CANTOR STRINGS ------------------
const main = () => showCantor(5);
 
// showCantor :: Int -> String
const showCantor = n =>
unlines(map(concat,
take(n,
iterate(
cantor,
[replicate(Math.pow(3, n - 1), '█')]
)
)
));
 
// cantor :: [String] -> [String]
Line 1,088 ⟶ 2,329:
const
m = Math.floor(s.length / 3),
blocks = take(m, )(s);
 
return '█' === s[0] ? (
return "█" === s[blocks,0] ? replicate(m, ' '), blocks]
[blocks, " ".repeat(m), blocks]
) : [s];
};
 
return concatMap(go, xs);
return xs.flatMap(go);
};
 
// GENERIC FUNCTIONS ---------------------- TEST -----------------------
const main = () =>
showCantor(5);
 
// concat :: [[a]] -> [a]
// concat :: [String] -> String
const concat = xs =>
0 < xs.length ? (() => {
const unit = 'string' !== typeof xs[0] ? (
[]
) : '';
return unit.concat.apply(unit, xs);
})() : [];
 
// --------------------- DISPLAY ---------------------
// concatMap :: (a -> [b]) -> [a] -> [b]
const// concatMapshowCantor =:: (f,Int xs) =-> String
const showCantor = n =>
xs.reduce((a, x) => a.concat(f(x)), []);
take(n)(
iterate(cantor)([
"█".repeat(3 ** (n - 1))
])
)
.map(x => x.join(""))
.join("\n");
 
 
// ---------------- GENERIC FUNCTIONS ----------------
 
// iterate :: (a -> a) -> a -> Gen [a]
function*const iterate(f, x)= f {=>
let// vAn =infinite x;list of repeated
while// (true)applications {of f to x.
function* yield(vx); {
let v = f(v)x;
}
}
 
// map :: (a -> b) -> [a] ->while (true) [b]{
const map = (f, xs) => xs.map(f) yield v;
v = f(v);
}
};
 
// replicate :: Int -> String -> String
const replicate = (n, s) => s.repeat(n);
 
// take :: Int -> [a] -> [a]
// take :: Int -> String -> String
const take = (n, xs) =>
// The first n elements of a list,
'GeneratorFunction' !== xs.constructor.constructor.name ? (
// string of characters, or stream.
xs => "GeneratorFunction" !== xs
.constructor.constructor.name ? (
xs.slice(0, n)
) : [].concat.apply([], ...Array.from({
length: n
}, () => {
const x = xs.next();
 
return x.done ? [] : [x.value];
}));
 
// unlines :: [String] -> String
const unlines = xs => xs.join('\n');
 
// MAIN ---
return main();
})();</langsyntaxhighlight>
{{Out}}
<pre>█████████████████████████████████████████████████████████████████████████████████
Line 1,152 ⟶ 2,398:
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █</pre>
 
===DualCantor: representationRational pairs===
{{Trans|Haskell}}
{{Trans|Python}}
 
 
Cantor ternary intervals rendered both as lists of ratiorational 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.
 
<langsyntaxhighlight lang="javascript">(() => {
'"use strict'";
 
// -------------- CANTOR RATIONAL PAIRS --------------
// main :: IO ()
const main = () => {
 
// cantor :: [(Rational, Rational)] ->
const xs = take(4, iterate(cantor, [Tuple(0, 1)]));
// [(Rational, Rational)]
 
console.log(
unlines(map(intervalRatios, xs)) + '\n',
);
console.log(
intervalBars(xs)
);
};
 
// cantor :: [(Rational, Rational)] -> [(Rational, Rational)]
const cantor = xs => {
const go = tplab => {
const [r1, r2] = map(rational, Array.from(tplab).map(rational);
const third = ratioDiv(ratioMinus(r2, )(r1), )(3);
 
return [
Tuple(r1, )(ratioPlus(r1, )(third)),
Tuple(ratioMinus(r2, )(third), )(r2)
];
};
 
return concatMap(go, xs);
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 = tplab =>
mapArray.from(compose(showRatio, rationalab),.map(
Array.fromcompose(tplshowRatio, rational)
).join(', ');
return '(' + map(go, xs).join(') (') +", '")';
 
return `(${xs.map(go).join(") (")})`;
};
 
// intervalBars :: [[(Rational, Rational)]] -> String
const intervalBars = xsrs => {
const go = w => xs =>
concat(snd(mapAccumL(
(a, tpl)=> ab => {
const [wx, wy] = Array.from(ab).map(
r => ratioMult(w, rational)(r)),
Array.from rational(tplr)
)
);
 
return Tuple(
return Tuple(wy,)(
replicateString(floor(ratioMinus(wx, a)), ' ') +
replicateString( floor(ratioMinus(wy, wx)(a), '█')
)(" ") + replicateString(
floor(ratioMinus(wy)(wx))
)("█")
);
},
)(0, )(xs)).join("");
const d = )));maximum(
const d = maximum last(rs).map(x => fst(x).d, last(xs)));
return unlines(map(go(ratio(d, 1)), xs));
 
return unlines(rs.map(
go(Ratio(d)(1))
));
};
 
 
// GENERIC FUNCTIONS ------------------ 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:b 'Tuple',=> ({
'0' type: a"Tuple",
'1' "0": ba,
length "1": 2b,
length: 2
});
});
 
 
// abs :: Num -> Num
const abs = Math.abs;
// Absolute value of a given number
// without the sign.
x => 0 > x ? (
-x
) : x;
 
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
const compose = (f, g) => x => f(g(x));
 
// concatapproxRatio :: [[a]]Float -> [a]Float -> Ratio
//const concatapproxRatio ::= [String]eps -=> String
const concat = xs n => {
0 < xs.length ? (() => {const
const unit = 'string' !=gcde = typeof(e, xs[0]x, ?y) (=> {
[] const _gcd = (a, b) =>
) : ''; b < e ? (
return unit.concat.apply(unit, xs); 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)
);
};
 
// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = (f, xs) =>
xs.reduce((a, x) => a.concat(f(x)), []);
 
// floor :: Num -> Int
Line 1,254 ⟶ 2,555:
const
nr = (
'"Ratio'" !== x.type ? (
properFraction
) : properFracRatio
)(x),
n = nr[0];
 
return 0 > nr[1] ? n - 1 : n;
};
 
// foldl1 :: (a -> a -> a) -> [a] -> a
const foldl1 = (f, xs) =>
1 < xs.length ? xs.slice(1)
.reduce(f, xs[0]) : xs[0];
 
// fst :: (a, b) -> a
const fst = tplab => tpl[0];
// 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
);
 
// gcd :: Int -> Int -> Int
const gcd = (x, y) => {
const
_gcd = (a, b) => (0 === b ? a : _gcd(b, a % b)),
abs = Math.abs;
return _gcd(abs(x), abs(y));
};
 
// iterate :: (a -> a) -> a -> Gen [a]
function*const iterate(f, x)= f {=>
let// vAn =infinite x;list of repeated
while// (true)applications {of f to x.
function* yield(vx); {
let v = f(v)x;
 
}
while (true) {
}
yield v;
v = f(v);
}
};
 
 
// last :: [a] -> a
const last = xs =>
0// <The xs.lengthlast ?item xs.slice(-1)[0]of :a undefined;list.
0 < xs.length ? (
xs.slice(-1)[0]
) : null;
 
 
// lcm :: Int -> Int -> Int
const lcm = (x, y) =>
// The smallest positive integer divisible
(x === 0 || y === 0) ? 0 : Math.abs(Math.floor(x / gcd(x, y)) * y);
// without remainder by both x and y.
y => (x === 0 || y === 0) ? (
0
) : Math.abs(Math.floor(x / gcd(x)(y)) * y);
 
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
 
// 'The mapAccumL function behaves:: like(acc a-> combinationx of-> map(acc, andy)) foldl;->
// acc -> [x] -> (acc, [y])
// it applies a function to each element of a list, passing an accumulating
const mapAccumL = f =>
// parameter from left to right, and returning a final value of this
// A tuple of an accumulation and a list
// accumulator together with the new list.' (See Hoogle)
// 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, []]
);
 
// mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
const mapAccumL = (f, acc, xs) =>
xs.reduce((a, x, i) => {
const pair = f(a[0], x, i);
return Tuple(pair[0], a[1].concat(pair[1]));
}, Tuple(acc, []));
 
// maximum :: Ord a => [a] -> a
const maximum = xs => (
0// <The xs.lengthlargest ?value (in a non-empty list.
foldl1((a, x)ys => x0 >< ays.length ? x : a, xs)(
) : undefined; 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));
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);
return Tuple(i)(n - i);
};
 
// quot :: Int -> Int -> Int
const quot = (n, m) => Math.floor(n / m);
 
// quotRem :: IntIntegral a => a -> Inta -> (Inta, Inta)
const quotRem = (m, n) =>
// The quotient, tupled with the remainder.
Tuple(Math.floor(m / n), m % n);
n => Tuple(
Math.trunc(m / n)
)(
m % n
);
 
// ratio :: Int -> Int -> Ratio Int
const ratio = (x, y) => {
const go = (x, y) =>
0 !== y ? (() => {
const d = gcd(x, y);
return {
type: 'Ratio',
'n': quot(x, d), // numerator
'd': quot(y, d) // denominator
};
})() : undefined;
return go(x * signum(y), abs(y));
};
 
// ratioDiv :: Rational -> Rational -> Rational
const ratioDiv = (n1, => n2) => {
const [r1, r2] = map(rational, [n1, n2].map(rational);
 
return ratio(r1.n * r2.d, r1.d * r2.n);
return Ratio(r1.n * r2.d)(
r1.d * r2.n
);
};
 
 
// ratioMinus :: Rational -> Rational -> Rational
const ratioMinus = (n1, => n2) => {
const [r1, r2] = map(rational, [n1, n2].map(rational);
const d = lcm(r1.d, )(r2.d);
 
return ratio(
return Ratio(
(r1.n * (d / r1.d)) - (r2.n * (d / r2.d)),
(r1.n * (d / r1.d)) - (r2.n * (d / r2.d))
)(d);
};
 
 
// ratioMult :: Rational -> Rational -> Rational
const ratioMult = (n1, => n2) => {
const [r1, r2] = map(rational, [n1, n2].map(rational);
return ratio(r1.n * r2.n, r1.d * r2.d);
};
 
return Ratio(r1.n * r2.n)(
// ratioPlus :: Rational -> Rational -> Rational
const ratioPlus = (n1, n2) => { r1.d * r2.d
const [r1, r2] = map(rational, [n1, n2]);
const d = lcm(r1.d, r2.d);
return ratio(
(r1.n * (d / r1.d)) + (r2.n * (d / r2.d)),
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 : ratioNumber.isInteger(x, 1); ? (
Ratio(x)(1)
) : approxRatio(undefined)(x);
 
 
// replicateString :: Int -> String -> String
const replicateString = (n, s) => s.repeat(n);
s => s.repeat(n);
 
 
// showRatio :: Ratio -> String
const showRatio = r =>
'"Ratio'" !== r.type ? (
r.toString()
) : r.n.toString() + (
1 !== r.d ? (
'`/' + ${r.d.toString()}`
) : ''""
);
 
 
// signum :: Num -> Num
const signum = n => 0 > n ? -1 : (0 < n ? 1 : 0);
// | Sign of a number.
n.constructor(
0 > n ? (
-1
) : (
0 < n ? 1 : 0
)
);
 
 
// snd :: (a, b) -> b
const snd = tplab => tpl[1];
// Second member of a pair.
ab[1];
 
 
// take :: Int -> [a] -> [a]
// take :: Int -> String -> String
const take = (n, xs) =>
// The first n elements of a list,
'GeneratorFunction' !== xs.constructor.constructor.name ? (
// string of characters, or stream.
xs => "GeneratorFunction" !== xs
.constructor.constructor.name ? (
xs.slice(0, n)
) : [].concat.apply([], ...Array.from({
length: n
}, () => {
const x = xs.next();
 
return x.done ? [] : [x.value];
}));
 
 
// unlines :: [String] -> String
const unlines = xs => xs.join('\n');
// A single string formed by the intercalation
// of a list of strings with the newline character.
xs.join("\n");
 
 
// MAIN ---
return main();
})();</langsyntaxhighlight>
{{Out}}
<pre>(0, 1)
Line 1,432 ⟶ 2,803:
███ ███ ███ ███
█ █ █ █ █ █ █ █</pre>
=={{header|jq}}==
<syntaxhighlight lang="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</syntaxhighlight>
{{out}}
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
=={{header|Julia}}==
{{trans|AWK}}
<langsyntaxhighlight lang="julia">const width = 81
const height = 5
 
Line 1,455 ⟶ 2,848:
print(Char(lines[i, j]), j == width ? "\n" : "")
end
</langsyntaxhighlight>{{out}}
<pre>
#################################################################################
Line 1,463 ⟶ 2,856:
# # # # # # # # # # # # # # # #
</pre>
 
=={{header|Kotlin}}==
Simple terminal drawing.
<langsyntaxhighlight lang="scala">// Version 1.2.31
 
const val WIDTH = 81
Line 1,486 ⟶ 2,878:
cantor(0, WIDTH, 1)
lines.forEach { println(it) }
}</langsyntaxhighlight>
 
{{output}}
Line 1,496 ⟶ 2,888:
* * * * * * * * * * * * * * * *
</pre>
 
=={{header|Lua}}==
{{trans|python}}
<langsyntaxhighlight lang="lua">local WIDTH = 81
local HEIGHT = 5
local lines = {}
Line 1,544 ⟶ 2,935:
end
print()
end</langsyntaxhighlight>
{{out}}
<pre>*********************************************************************************
Line 1,551 ⟶ 2,942:
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *</pre>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">Graphics[MeshPrimitives[CantorMesh[#],1]/.{x_}:>{x,-0.05#}&/@Range[5],ImageSize->600]</syntaxhighlight>
{{out}}
A graphic of a Cantor set is shown
 
=={{header|MiniScript}}==
<syntaxhighlight lang="miniscript">
cantorSet = function(start, length, depth)
if depth == 0 then return [[start, start+length - 1]]
newLen = length / 3
leftInterval = cantorSet(start, newLen, depth - 1)
rightInterval = cantorSet(start + 2 * newLen, newLen, depth - 1)
return leftInterval + rightInterval
end function
 
for depth in range(0, 4)
output =[" "] * 81
segments = cantorSet(1, 81,depth)
for segment in segments
for x in range(segment[0] - 1, segment[1]-1)
output[x] = "#"
end for
end for
print output.join("")
end for
</syntaxhighlight>
{{out}}
<pre>
#################################################################################
########################### ###########################
######### ######### ######### #########
### ### ### ### ### ### ### ###
# # # # # # # # # # # # # # # #
</pre>
 
=={{header|Modula-2}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="modula2">MODULE Cantor;
FROM Terminal IMPORT Write,WriteLn,ReadChar;
 
Line 1,605 ⟶ 3,033:
 
ReadChar;
END Cantor.</langsyntaxhighlight>
=={{header|Nim}}==
{{trans|Kotlin}}
 
<syntaxhighlight lang="nim">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</syntaxhighlight>
 
{{Out}}
<pre>*********************************************************************************
*************************** ***************************
********* ********* ********* *********
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *</pre>
=={{header|Objeck}}==
{{trans|Java}}
<syntaxhighlight lang="objeck">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();
};
}
}</syntaxhighlight>
 
{{Output}}
<pre>
*********************************************************************************
*************************** ***************************
********* ********* ********* *********
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *
</pre>
=={{header|Perl}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight Perllang="perl">use strict;
use feature 'say';
 
Line 1,636 ⟶ 3,151:
}
 
say for cantor(5);</langsyntaxhighlight>
 
{{Out}}
Line 1,645 ⟶ 3,160:
# # # # # # # # # # # # # # # #</pre>
 
===regex version===
=={{header|Perl 6}}==
<syntaxhighlight lang="perl">#!/usr/bin/perl -l
{{trans|Kotlin}}
<lang perl6>sub cantor ( Int $height ) {
my $width = 3 ** ($height - 1);
 
use strict; # https://rosettacode.org/wiki/Cantor_set
my @lines = ( "\c[FULL BLOCK]" x $width ) xx $height;
use warnings;
 
$_ = '#' x 81;
my sub _trim_middle_third ( $len, $start, $index ) {
my $seg = $len div 3
or return;
 
for ( $index ..^ $height ) X ( 0 ..^ $seg ) -> ( $i, $j ) {
@lines[$i].substr-rw( $start + $seg + $j, 1 ) = ' ';
}
 
_trim_middle_third( $seg, $start + $_, $index + 1 ) for 0, $seg * 2;
}
 
_trim_middle_third( $width, 0, 1 );
return @lines;
}
 
.say for cantor(5);</lang>
 
{{Out}}
<pre>█████████████████████████████████████████████████████████████████████████████████
███████████████████████████ ███████████████████████████
█████████ █████████ █████████ █████████
███ ███ ███ ███ ███ ███ ███ ███
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █</pre>
 
1 while print, s/(#+)\1\1/ $1 . $1 =~ tr!#! !r . $1 /ge;</syntaxhighlight>
{{out}}
<pre>
#################################################################################
########################### ###########################
######### ######### ######### #########
### ### ### ### ### ### ### ###
# # # # # # # # # # # # # # # #
</pre>
=={{header|Phix}}==
Based on Algol 68, but even simpler, shorter, and sweeter!
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>integer n = 5,
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span>
w = power(3,n-1),
<span style="color: #000000;">w</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span>
len = w
<span style="color: #000000;">len</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">w</span>
string line = repeat('#',w)&"\n"
<span style="color: #004080;">string</span> <span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'#'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">w</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">"\n"</span>
 
while 1 do
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
puts(1,line)
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span>
if len=1 then exit end if
<span style="color: #008080;">if</span> <span style="color: #000000;">len</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
len /= 3
<span style="color: #000000;">len</span> <span style="color: #0000FF;">/=</span> <span style="color: #000000;">3</span>
integer pos = 1
<span style="color: #004080;">integer</span> <span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
while pos<(w-len) do
<span style="color: #008080;">while</span> <span style="color: #000000;">pos</span><span style="color: #0000FF;"><(</span><span style="color: #000000;">w</span><span style="color: #0000FF;">-</span><span style="color: #000000;">len</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
pos += len
<span style="color: #000000;">pos</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">len</span>
line[pos..pos+len-1] = ' '
<span style="color: #000000;">line</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pos</span><span style="color: #0000FF;">..</span><span style="color: #000000;">pos</span><span style="color: #0000FF;">+</span><span style="color: #000000;">len</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">' '</span>
pos += len
<span style="color: #000000;">pos</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">len</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end while</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,702 ⟶ 3,205:
# # # # # # # # # # # # # # # #
</pre>
=={{header|Phixmonti}}==
<syntaxhighlight lang="phixmonti">include ..\Utilitys.pmt
 
5 >ps
3 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</syntaxhighlight>
Other solution
<syntaxhighlight lang="phixmonti">include ..\Utilitys.pmt
 
5 >ps
3 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
endfor
endfor
line ?</syntaxhighlight>
{{out}}
<pre>#################################################################################
########################### ###########################
######### ######### ######### #########
### ### ### ### ### ### ### ###
# # # # # # # # # # # # # # # #
 
=== Press any key to exit ===</pre>
=={{header|PL/M}}==
{{works with|8080 PL/M Compiler}} ... under CP/M (or an emulator)
<syntaxhighlight lang="plm">
100H: /* DRAW A CANTOR SET USING ASCII */
 
/* BDOS SYSTEM CALL AND I/O ROUTINES */
BDOS: PROCEDURE( F, A ); DECLARE F BYTE, A ADDRESS; GOTO 5; END;
PR$CHAR: PROCEDURE( C ); DECLARE C BYTE; CALL BDOS( 2, C ); END;
PR$NL: PROCEDURE; CALL PR$CHAR( 0DH ); CALL PR$CHAR( 0AH ); END;
 
/* DRAW A CANTOR SET */
 
DECLARE LINES LITERALLY '4';
DECLARE WIDTH LITERALLY '27'; /* MUST BE 3**(LINES-1) */
 
DECLARE LINE (WIDTH)BYTE;
DECLARE ( I, L, C, W, S, SEGMENTS ) BYTE;
 
DO I = 0 TO LAST( LINE );
LINE( I ) = 023H;
CALL PR$CHAR( LINE( I ) );
END;
CALL PR$NL;
W = WIDTH;
SEGMENTS = 1;
DO L = 2 TO LINES;
W = W / 3;
SEGMENTS = SEGMENTS * 3;
C = 0;
DO S = 1 TO SEGMENTS;
DO I = 1 TO W;
IF NOT S THEN LINE( C ) = ' '; /* EVEN SEGMENT - BLANK IT */
CALL PR$CHAR( LINE( C ) );
C = C + 1;
END;
END;
CALL PR$NL;
END;
 
EOF
</syntaxhighlight>
{{out}}
<pre>
###########################
######### #########
### ### ### ###
# # # # # # # #
</pre>
 
=={{header|Processing}}==
<syntaxhighlight lang="java">
//Aamrun, 1st July 2022
 
void cantorSet(int x1,int y1,int x2,int y2,int strWt,int gap,int n){
strokeWeight(strWt);
line(x1,y1,x2,y2);
if(n>0){
cantorSet(x1,gap + y1,(2*x1+x2)/3,gap + (2*y1+y2)/3,strWt,gap,n-1);
cantorSet((2*x2+x1)/3,gap + (2*y2+y1)/3,x2,gap + y2,strWt,gap,n-1);
}
}
 
void setup(){
size(1000,1000);
cantorSet(100,10,900,10,1,10,5);
}
</syntaxhighlight>
 
=={{header|Python}}==
===Imperative===
<langsyntaxhighlight lang="python">WIDTH = 81
HEIGHT = 5
 
Line 1,728 ⟶ 3,346:
for i in xrange(HEIGHT):
beg = WIDTH * i
print ''.join(lines[beg : beg+WIDTH])</langsyntaxhighlight>
{{out}}
<pre>*********************************************************************************
Line 1,738 ⟶ 3,356:
Separating ''(Bool, Int)'' model from ''String'' display:
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">'''Cantor set – separating model from display'''
 
from functools import (reduce)
Line 1,811 ⟶ 3,429:
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>
Line 1,824 ⟶ 3,442:
{{Trans|Haskell}}
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">'''Cantor set – strings as both model and display.'''
 
from itertools import (chain, islice)
Line 1,894 ⟶ 3,512:
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>█████████████████████████████████████████████████████████████████████████████████
Line 1,904 ⟶ 3,522:
===Dual representations – fractional and graphic===
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">'''A Cantor set generator, and two different
representations of its output.
'''
 
from itertools import (islice, chain)
from functools import (reduce)
from fractions import Fraction
from functools import (reduce)
 
 
# ----------------------- CANTOR SET -----------------------
 
# cantor :: Generator [[(Fraction, Fraction)]]
Line 1,924 ⟶ 3,544:
return [(x, x + third), (y - third, y)]
 
xsreturn = [iterate(0, 1)]
concatMap(go)
while True:
yield xs)(
xs[(0, = concatMap(go)(xs1)]
)
 
 
Line 1,949 ⟶ 3,570:
[x, y] = [int(w * r) for r in tpl]
return (
y, # Accumulator - end of previous interval
(' ' * (x - a)) + ('█' * (y - x)) # A gap + an interval bar
)
return mapAccumL(show)(0)(xs)
Line 1,956 ⟶ 3,577:
 
 
# TEST -------------------------- TEST --------------------------
# main :: IO ()
def main():
Line 1,975 ⟶ 3,596:
 
 
# GENERIC ---------------------------- GENERIC -------------------------
 
# concatMap :: (a -> [b]) -> [a] -> [b]
Line 1,986 ⟶ 3,607:
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
 
 
Line 2,013 ⟶ 3,647:
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>(0, 1)
Line 2,024 ⟶ 3,658:
███ ███ ███ ███
█ █ █ █ █ █ █ █</pre>
=={{header|QB64}}==
{{trans|FreeBASIC}}
 
Note: Other languages will need to zero out the a() array. In QB64 all arrays are initialized to zero at program start.
 
<syntaxhighlight lang="qb64">_Title "Cantor Set"
 
Dim Shared As Integer sw, sh, wide, high
sw = 800: sh = 200: wide = 729: high = 7
Dim Shared As Integer a(wide, high)
 
Screen _NewImage(sw, sh, 8)
Cls , 15: Color 0
 
Call calc(0, wide, 1)
Call CantorSet
 
Sleep
System
 
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
Next
End Sub</syntaxhighlight>
=={{header|Quackery}}==
 
===Using an L-System===
 
(Described at [[L-system#Quackery]].)
 
<syntaxhighlight lang="quackery"> [ $ "" 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
</syntaxhighlight>
 
{{out}}
 
<pre>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
</pre>
 
=={{header|R}}==
[https://creativecommons.org/licenses/by-nc-sa/4.0 Attribution-NonCommercial-ShareAlike 4.0 International, CC BY-NC-SA 4.0] to neonira@gmail.com
 
<syntaxhighlight lang="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)
}
</syntaxhighlight>
{{out}}
 
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.
=={{header|Racket}}==
{{trans|Kotlin}}
 
<langsyntaxhighlight lang="racket">#lang racket/base
;; {trans|Kotlin}}
 
Line 2,052 ⟶ 3,825:
(module+ main
(for-each displayln (Cantor_set)))
</syntaxhighlight>
</lang>
{{out}}
<pre>*********************************************************************************
Line 2,060 ⟶ 3,833:
* * * * * * * * * * * * * * * *
</pre>
=={{header|Raku}}==
(formerly Perl 6)
{{trans|Kotlin}}
<syntaxhighlight lang="raku" line>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);</syntaxhighlight>
 
{{Out}}
<pre>█████████████████████████████████████████████████████████████████████████████████
███████████████████████████ ███████████████████████████
█████████ █████████ █████████ █████████
███ ███ ███ ███ ███ ███ ███ ███
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █</pre>
=={{header|REXX}}==
<langsyntaxhighlight lang="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 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. */
Line 2,072 ⟶ 3,875:
$= 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. */</langsyntaxhighlight>
This REXX program makes use of &nbsp; '''linesize''' &nbsp; REXX program (or BIF) which is used to determine the screen width (or linesize) of the terminal (console).
 
Line 2,103 ⟶ 3,906:
■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
</pre>
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Cantor set
 
Line 2,157 ⟶ 3,959:
cantor(x+floor(lens*2/3),y,floor(lens/3))
ok
</syntaxhighlight>
</lang>
Output image:
 
Line 2,163 ⟶ 3,965:
=={{header|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.
<langsyntaxhighlight lang="ruby">lines = 5
 
(0..lines).each do |exp|
Line 2,170 ⟶ 3,972:
puts chars.map{ |c| c * seg_size }.join
end
</syntaxhighlight>
</lang>
{{out}}
<pre>█████████████████████████████████████████████████████████████████████████████████
Line 2,179 ⟶ 3,981:
 
</pre>
=={{header|Rust}}==
<syntaxhighlight lang="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);
}
 
</syntaxhighlight>
{{out}}
<pre>
Cantor set:
█████████████████████████████████████████████████████████████████████████████████
███████████████████████████ ███████████████████████████
█████████ █████████ █████████ █████████
███ ███ ███ ███ ███ ███ ███ ███
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
 
</pre>
=={{header|Scala}}==
===Imperative Programming (Q&D)===
<langsyntaxhighlight Scalalang="scala">object CantorSetQD extends App {
val (width, heigthheight) = (81, 5)
 
val lines = Seq.fill[Array[Char]](heigthheight)(Array.fill[Char](width)('*'))
 
def cantor(start: Int, len: Int, index: Int) {
Line 2,193 ⟶ 4,072:
 
if (seg != 0) {
for (i <- index until heigthheight;
j <- (start + seg) until (start + seg * 2)) lines(i)(j) = ' '
 
Line 2,203 ⟶ 4,082:
cantor(0, width, 1)
lines.foreach(l => println(l.mkString))
}</langsyntaxhighlight>
{{Out}}See it in running in your browser by [https://scalafiddle.io/sf/QrqaHeu/0 (JavaScript)]
or by [https://scastie.scala-lang.org/4JTi1zXzRq6H4yUlAYNTSw Scastie (JVM)].
 
===Functional Programming (Recommended)===
<langsyntaxhighlight Scalalang="scala">object CantorSetFP extends App {
val (width, heigthheight) = (81, 5)
 
def lines = (1 to heigthheight).map(_ => (0 until width).toSet)
 
def cantorSet(pre: Seq[Set[Int]], start: Int, len: Int, index: Int): Seq[Set[Int]] = {
Line 2,220 ⟶ 4,099:
pre -- ((start + seg) until (start + seg * 2))
 
for (n <- 0 until heigthheight)
yield if (index to heigthheight contains n) elementsStuffing(pre(n), start)
else pre(n)
}
Line 2,239 ⟶ 4,118:
output.map(l => (0 to width).map(pos => if (l contains pos) '*' else ' ').mkString)
.mkString("\n"))
}</langsyntaxhighlight>
{{Out}}See it in running in your browser by [https://scalafiddle.io/sf/szUjPWO/7 (JavaScript)]
or by [https://scastie.scala-lang.org/ZaNUtEOcStuBfJImOnEz5Q Scastie (JVM)].
 
=={{header|Sidef}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="ruby">func cantor (height) {
var width = 3**(height - 1)
var lines = height.of { "\N{FULL BLOCK}" * width }
Line 2,265 ⟶ 4,143:
}
 
cantor(5).each { .say }</langsyntaxhighlight>
{{out}}
<pre>
Line 2,274 ⟶ 4,152:
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
</pre>
 
=={{header|Smalltalk}}==
{{works with|GNU Smalltalk}}
Smalltalk represents Intervals' start and stop values as Fraction, so precision is kept for quilte a while.
<langsyntaxhighlight Smalltalklang="smalltalk">Object subclass: CantorSet [
 
| intervals |
Line 2,345 ⟶ 4,222:
]
 
TestCantor iterations: 4.</langsyntaxhighlight>
Output:
<pre>#################################################################################
Line 2,352 ⟶ 4,229:
### ### ### ### ### ### ### ###
# # # # # # # # # # # # # # # #</pre>
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">const (
width = 81
height = 5
)
fn cantor(mut lines [][]u8, start int, len int, index int) {
seg := len / 3
if seg == 0 {
return
}
for i in index.. height {
for j in start + seg..start + 2 * seg {
lines[i][j] = ' '[0]
}
}
cantor(mut lines, start, seg, index + 1)
cantor(mut lines, start + seg * 2, seg, index + 1)
}
fn main() {
mut lines := [][]u8{len:height, init: []u8{len:width, init:'*'[0]}}
cantor(mut lines, 0, width, 1)
for line in lines {
println(line.bytestr())
}
}</syntaxhighlight>
 
{{out}}
<pre>
*********************************************************************************
*************************** ***************************
********* ********* ********* *********
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *
</pre>
 
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<langsyntaxhighlight lang="vbnet">Module Module1
 
Const WIDTH = 81
Line 2,394 ⟶ 4,308:
End Sub
 
End Module</langsyntaxhighlight>
{{out}}
<pre>*********************************************************************************
Line 2,402 ⟶ 4,316:
* * * * * * * * * * * * * * * *</pre>
 
=={{header|VTL-2}}==
<syntaxhighlight lang="vtl2">
1010 L=4
1020 I=1
1030 X=1
1040 I=I+1
1050 X=X*3
1060 #=I<L*1040
2010 I=0
2020 :I)=35
2030 $=:I)
2040 I=I+1
2050 #=I<X*2020
2060 ?=""
2070 W=X
2080 G=1
2090 W=W/3
2100 G=G*3
2110 S=1
2120 C=0
2130 I=1
2140 #=S/2*0+%=1*2160
2150 :C)=32
2160 $=:C)
2170 C=C+1
2180 I=I+1
2190 #=W>I*2140
2200 S=S+1
2210 #=C<X*2130
2220 ?=""
2230 L=L-1
2240 #=1<L*2090
</syntaxhighlight>
{{out}}
<pre>
###########################
######### #########
### ### ### ###
# # # # # # # #
</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
<syntaxhighlight lang="wren">var width = 81
var height = 5
 
var lines = [[]] * height
for (i in 0...height) lines[i] = ["*"] * width
 
var cantor // recursive so need to declare variable first
cantor = 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())</syntaxhighlight>
 
{{out}}
<pre>
*********************************************************************************
*************************** ***************************
********* ********* ********* *********
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * * *
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang="xpl0">proc Cantor(N, LineSeg, Len); \Delete middle third of LineSeg
int N; char LineSeg; int Len, Third, I;
[if N>0 and Len>1 then
[Third:= Len/3;
for I:= Third, 2*Third-1 do LineSeg(I):= ^ ;
Cantor(N-1, LineSeg, Third);
Cantor(N-1, LineSeg+2*Third, Third);
];
];
 
char LineSeg, N;
[LineSeg:=
"#################################################################################
";
for N:= 0 to 4 do
[Cantor(N, LineSeg, 81);
Text(0, LineSeg);
];
]</syntaxhighlight>
 
{{out}}
<pre>
#################################################################################
########################### ###########################
######### ######### ######### #########
### ### ### ### ### ### ### ###
# # # # # # # # # # # # # # # #
</pre>
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">const WIDTH=81, HEIGHT=5;
var lines=HEIGHT.pump(List,List.createLong(WIDTH,"\U2588;").copy); // full block
Line 2,415 ⟶ 4,430:
}(0,WIDTH,1);
 
lines.pump(Console.println,"concat");</langsyntaxhighlight>
{{out}}
<pre>
1,496

edits