Cantor set: Difference between revisions
(Added modula-2) |
(→{{header|REXX}}: added the REXX computer programming language.) |
||
Line 470: | Line 470: | ||
*** *** *** *** *** *** *** *** |
*** *** *** *** *** *** *** *** |
||
* * * * * * * * * * * * * * * * |
* * * * * * * * * * * * * * * * |
||
</pre> |
|||
=={{header|EWXX}}== |
|||
<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 /*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. */</lang> |
|||
{{out|output|text= when using the default size of the terminal width of 100:}} |
|||
(Shown at half size.) |
|||
<pre style="font-size:50%"> |
|||
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ |
|||
■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ |
|||
■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■ |
|||
■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ |
|||
■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ |
|||
</pre> |
|||
{{out|output|text= when using the default size of the terminal width of 250:}} |
|||
(Shown at half size.) |
|||
<pre style="font-size:50%"> |
|||
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ |
|||
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ |
|||
■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ |
|||
■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■ |
|||
■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ ■■■ |
|||
■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ |
|||
</pre> |
</pre> |
||
Revision as of 19:28, 25 June 2018
Draw Cantor set. See details: Cantor set
ALGOL 68
<lang algol68>BEGIN
# draw a Cantor Set using ASCII # INT lines = 5; # number of lines for the set # # we must choose the line width so that the width of each segment is # # divisible by 3 ( except for the final line where the segment width will # # be 1 ) # INT set width = 3 ^ ( lines - 1 ); [ set width ]CHAR set; # start with a complete line # FOR i TO set width DO set[ i ] := "#" OD; print( ( set, newline ) ); # repeatedly modify the line, replacing the middle third of each segment # # with blanks # INT segment width := set width OVER 3; WHILE segment width > 0 DO INT set pos := 1; WHILE set pos < ( set width - segment width ) DO set pos +:= segment width; FOR char pos FROM set pos TO ( set pos + segment width ) - 1 DO set[ char pos ] := " " OD; set pos +:= segment width OD; print( ( set, newline ) ); segment width OVERAB 3 OD
END</lang>
- Output:
################################################################################# ########################### ########################### ######### ######### ######### ######### ### ### ### ### ### ### ### ### # # # # # # # # # # # # # # # #
ALGOL W
Based on the Algol 68 sample. <lang algolw>begin
% draw a Cantor Set using ASCII % integer LINES; % number of lines for the set % integer setWidth; % width of each line of the set % % we must choose the line width so that the width of each segment is % % divisible by 3 ( except for the final line where the segment width will % % be 1 ) % LINES := 5; setWidth := round( 3 ** ( LINES - 1 ) ); begin % start new block so the array can have computed bounds % logical array set ( 1 :: setWidth ); integer segmentWidth; % start with a complete line % for i := 1 until setWidth do set( i ) := true; segmentWidth := setWidth; for l := 1 until LINES do begin % print the latest line, all lines start with a "#" % write( "#" ); for i := 2 until setWidth do writeon( if set( i ) then "#" else " " ); % modify the line, replacing the middle third of each segment % % with blanks, unless this was the last line % if l < LINES then begin integer setPos; segmentWidth := segmentWidth div 3; setPos := 1; while setPos < ( setWidth - segmentWidth ) do begin setPos := setPos + segmentWidth; for charPos := setPos until ( setPos + segmentWidth ) - 1 do set( charPos ) := false; setPos := setPos + segmentWidth end while_setPos_in_range ; end if_l_lt_LINES end for_l end
end.</lang>
- Output:
################################################################################# ########################### ########################### ######### ######### ######### ######### ### ### ### ### ### ### ### ### # # # # # # # # # # # # # # # #
AWK
<lang AWK>
- syntax: GAWK -f CANTOR_SET.AWK
- converted from C
BEGIN {
WIDTH = 81 HEIGHT = 5 for (i=0; i<HEIGHT; ++i) { for (j=0; j<WIDTH; ++j) { lines[i][j] = "*" } } cantor(0,WIDTH,1) for (i=0; i<HEIGHT; ++i) { for (j=0; j<WIDTH; ++j) { printf("%s",lines[i][j]) } printf("\n") } exit(0)
} function cantor(start,leng,indx, i,j,seg) {
seg = int(leng/3) if (seg == 0) { return } for (i=indx; i<HEIGHT; ++i) { for (j=start+seg; j<start+seg*2; ++j) { lines[i][j] = " " } } cantor(start,seg,indx+1) cantor(start+seg*2,seg,indx+1)
} </lang>
- Output:
********************************************************************************* *************************** *************************** ********* ********* ********* ********* *** *** *** *** *** *** *** *** * * * * * * * * * * * * * * * *
C
<lang c>#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;
}</lang>
- Output:
********************************************************************************* *************************** *************************** ********* ********* ********* ********* *** *** *** *** *** *** *** *** * * * * * * * * * * * * * * * *
D
<lang d>import std.stdio;
enum WIDTH = 81; enum HEIGHT = 5;
char[WIDTH*HEIGHT] lines;
void cantor(int start, int len, int index) {
int seg = len / 3; if (seg == 0) return; for (int i=index; i<HEIGHT; i++) { for (int j=start+seg; j<start+seg*2; j++) { int pos = i*WIDTH + j; lines[pos] = ' '; } } cantor(start, seg, index+1); cantor(start+seg*2, seg, index+1);
}
void main() {
// init lines[] = '*';
// calculate cantor(0, WIDTH, 1);
// print for (int i=0; i<HEIGHT; i++) { int beg = WIDTH * i; writeln(lines[beg..beg+WIDTH]); }
}</lang>
- Output:
********************************************************************************* *************************** *************************** ********* ********* ********* ********* *** *** *** *** *** *** *** *** * * * * * * * * * * * * * * * *
Go
<lang go>package main
import "fmt"
const (
width = 81 height = 5
)
var lines [height][width]byte
func init() {
for i := 0; i < height; i++ { for j := 0; j < width; j++ { lines[i][j] = '*' } }
}
func cantor(start, len, index int) {
seg := len / 3 if seg == 0 { return } for i := index; i < height; i++ { for j := start + seg; j < start + 2 * seg; j++ { lines[i][j] = ' ' } } cantor(start, seg, index + 1) cantor(start + seg * 2, seg, index + 1)
}
func main() {
cantor(0, width, 1) for _, line := range lines { fmt.Println(string(line[:])) }
}</lang>
- Output:
********************************************************************************* *************************** *************************** ********* ********* ********* ********* *** *** *** *** *** *** *** *** * * * * * * * * * * * * * * * *
Java
<lang java>public class App {
private static final int WIDTH = 81; private static final int HEIGHT = 5;
private static char[][] lines; static { lines = new char[HEIGHT][WIDTH]; for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { lines[i][j] = '*'; } } }
private static void cantor(int start, int len, int index) { int seg = len / 3; if (seg == 0) return; for (int i = index; i < HEIGHT; i++) { for (int j = start + seg; j < start + seg * 2; j++) { lines[i][j] = ' '; } } cantor(start, seg, index + 1); cantor(start + seg * 2, seg, index + 1); }
public static void main(String[] args) { cantor(0, WIDTH, 1); for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { System.out.print(lines[i][j]); } System.out.println(); } }
} </lang>
- Output:
********************************************************************************* *************************** *************************** ********* ********* ********* ********* *** *** *** *** *** *** *** *** * * * * * * * * * * * * * * * *
Kotlin
Simple terminal drawing. <lang scala>// Version 1.2.31
const val WIDTH = 81 const val HEIGHT = 5
val lines = List(HEIGHT) { CharArray(WIDTH) { '*' } }
fun cantor(start: Int, len: Int, index: Int) {
val seg = len / 3 if (seg == 0) return for (i in index until HEIGHT) { for (j in start + seg until start + seg * 2) lines[i][j] = ' ' } cantor(start, seg, index + 1) cantor(start + seg * 2, seg, index + 1)
}
fun main(args: Array<String>) {
cantor(0, WIDTH, 1) lines.forEach { println(it) }
}</lang>
- Output:
********************************************************************************* *************************** *************************** ********* ********* ********* ********* *** *** *** *** *** *** *** *** * * * * * * * * * * * * * * * *
Modula-2
<lang modula2>MODULE Cantor; FROM Terminal IMPORT Write,WriteLn,ReadChar;
CONST
WIDTH = 81; HEIGHT = 5;
VAR
lines : ARRAY[0..HEIGHT] OF ARRAY[0..WIDTH] OF CHAR;
PROCEDURE Init; VAR i,j : CARDINAL; BEGIN
FOR i:=0 TO HEIGHT DO FOR j:=0 TO WIDTH DO lines[i,j] := '*' END END
END Init;
PROCEDURE Cantor(start,len,index : CARDINAL); VAR i,j,seg : CARDINAL; BEGIN
seg := len DIV 3; IF seg=0 THEN RETURN END; FOR i:=index TO HEIGHT-1 DO j := start+seg; FOR j:=start+seg TO start+seg*2-1 DO lines[i,j] := ' ' END END; Cantor(start, seg, index+1); Cantor(start+seg*2, seg, index+1)
END Cantor;
PROCEDURE Print; VAR i,j : CARDINAL; BEGIN
FOR i:=0 TO HEIGHT-1 DO FOR j:=0 TO WIDTH-1 DO Write(lines[i,j]) END; WriteLn END
END Print;
BEGIN
Init; Cantor(0,WIDTH,1); Print;
ReadChar;
END Cantor.</lang>
Perl 6
<lang perl6>sub cantor ( Int $height ) {
my $width = 3 ** ($height - 1);
my @lines = ( "\c[FULL BLOCK]" x $width ) xx $height;
my sub _trim_middle_third ( $len, $start, $index ) { my $seg = $len div 3 or return;
for ( $index ..^ $height ) X ( 0 ..^ $seg ) -> ( $i, $j ) { @lines[$i].substr-rw( $start + $seg + $j, 1 ) = ' '; }
_trim_middle_third( $seg, $start + $_, $index + 1 ) for 0, $seg * 2; }
_trim_middle_third( $width, 0, 1 ); return @lines;
}
.say for cantor(5);</lang>
- Output:
█████████████████████████████████████████████████████████████████████████████████ ███████████████████████████ ███████████████████████████ █████████ █████████ █████████ █████████ ███ ███ ███ ███ ███ ███ ███ ███ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
Racket
<lang racket>#lang racket/base
- {trans|Kotlin}}
(define current-width (make-parameter 81))
(define current-height (make-parameter 5))
(define (Cantor_set (w (current-width)) (h (current-height)))
(define lines (build-list h (λ (_) (make-bytes w (char->integer #\#))))) (define (cantor start len index) (let* ((seg (quotient len 3)) (seg-start (+ start seg)) (seg-end (+ seg-start seg))) (unless (zero? seg) (for* ((i (in-range index h)) (j (in-range seg-start seg-end))) (bytes-set! (list-ref lines i) j (char->integer #\space))) (cantor start seg (add1 index)) (cantor seg-end seg (add1 index))))) (cantor 0 w 1) lines)
(module+ main
(for-each displayln (Cantor_set)))
</lang>
- Output:
********************************************************************************* *************************** *************************** ********* ********* ********* ********* *** *** *** *** *** *** *** *** * * * * * * * * * * * * * * * *
EWXX
<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 /*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. */</lang>
- 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
<lang ring>
- Project : Cantor set
- Date : 2018/04/20
- Author : Gal Zsolt [~ CalmoSoft ~]
- Email : <calmosoft@gmail.com>
load "guilib.ring" paint = null
new qapp
{ win1 = new qwidget() { setwindowtitle("") setgeometry(100,100,800,600) label1 = new qlabel(win1) { setgeometry(10,10,800,600) settext("") } new qpushbutton(win1) { setgeometry(150,500,100,30) settext("draw") setclickevent("draw()") } show() } exec() }
func draw
p1 = new qpicture() color = new qcolor() { setrgb(0,0,255,255) } pen = new qpen() { setcolor(color) setwidth(10) } paint = new qpainter() { begin(p1) setpen(pen)
cantor(10,20,600)
endpaint() } label1 { setpicture(p1) show() } return
func cantor(x,y,lens)
if lens >= 10 paint.drawline(x,y,x+lens,y) y = y + 20 cantor(x,y,floor(lens/3)) cantor(x+floor(lens*2/3),y,floor(lens/3)) ok
</lang> Output image:
Scala
Imperative Programming (Q&D)
<lang Scala>object CantorSetQD extends App {
val (width, heigth) = (81, 5)
val lines = Seq.fill[Array[Char]](heigth)(Array.fill[Char](width)('*'))
def cantor(start: Int, len: Int, index: Int) { val seg = len / 3
println(start, len, index)
if (seg != 0) { for (i <- index until heigth; j <- (start + seg) until (start + seg * 2)) lines(i)(j) = ' '
cantor(start, seg, index + 1) cantor(start + seg * 2, seg, index + 1) } }
cantor(0, width, 1) lines.foreach(l => println(l.mkString))
}</lang>
- Output:
See it in running in your browser by (JavaScript)
or by Scastie (JVM).
Functional Programming (Recommended)
<lang Scala>object CantorSetFP extends App {
val (width, heigth) = (81, 5)
def lines = (1 to heigth).map(_ => (0 until width).toSet)
def cantorSet(pre: Seq[Set[Int]], start: Int, len: Int, index: Int): Seq[Set[Int]] = { val seg = len / 3
def cantorSet1(pre: Seq[Set[Int]], start: Int, index: Int): Seq[Set[Int]] = { def elementsStuffing(pre: Set[Int], start: Int): Set[Int] = pre -- ((start + seg) until (start + seg * 2))
for (n <- 0 until heigth) yield if (index to heigth contains n) elementsStuffing(pre(n), start) else pre(n) }
if (seg == 0) pre else { def version0 = cantorSet1(pre, start, index) def version1 = cantorSet(cantorSet1(pre, start, index), start, seg, index + 1)
cantorSet(version1, start + seg * 2, seg, index + 1) } }
def output: Seq[Set[Int]] = cantorSet(lines, 0, width, 1)
println( output.map(l => (0 to width).map(pos => if (l contains pos) '*' else ' ').mkString) .mkString("\n"))
}</lang>
- Output:
See it in running in your browser by (JavaScript)
or by Scastie (JVM).
Sidef
<lang ruby>func cantor (height) {
var width = 3**(height - 1) var lines = height.of { "\N{FULL BLOCK}" * width }
func trim_middle_third (len, start, index) { var seg = (len // 3) || return()
for i, j in ((index ..^ height) ~X (0 ..^ seg)) { lines[i].replace!(Regex("^.{#{start + seg + j}}\\K."), ' ') }
[0, 2*seg].each { |k| trim_middle_third(seg, start + k, index + 1) } }
trim_middle_third(width, 0, 1) return lines
}
cantor(5).each { .say }</lang>
- Output:
█████████████████████████████████████████████████████████████████████████████████ ███████████████████████████ ███████████████████████████ █████████ █████████ █████████ █████████ ███ ███ ███ ███ ███ ███ ███ ███ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
zkl
<lang zkl>const WIDTH=81, HEIGHT=5; var lines=HEIGHT.pump(List,List.createLong(WIDTH,"\U2588;").copy); // full block
fcn cantor(start,len,index){
(seg:=len/3) or return(); foreach i,j in ([index..HEIGHT-1], [start + seg .. start + seg*2 - 1]){ lines[i][j]=" "; } cantor(start, seg, index + 1); cantor(start + seg*2, seg, index + 1);
}(0,WIDTH,1);
lines.pump(Console.println,"concat");</lang>
- Output:
█████████████████████████████████████████████████████████████████████████████████ ███████████████████████████ ███████████████████████████ █████████ █████████ █████████ █████████ ███ ███ ███ ███ ███ ███ ███ ███ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █