Yin and yang: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|SVG}}: Added a rendering.)
(Simplified D code)
Line 5: Line 5:


=={{header|D}}==
=={{header|D}}==
<lang d>import std.stdio, std.string, std.algorithm, std.array;
{{incorrect|D|The output does not sufficiently resemble a Yin-yang symbol.}}

<lang d>import std.stdio, std.string, std.algorithm ;
struct SquareBoard {
enum { Void = 0, Yan = 1, Yin = 2, I = 3} ;
enum W : char { Void=' ', Yan='.', Yin='#', I='?' };

enum Tiles = [" ","·","#","?"] ;
immutable int scale;
W[][] pix;
alias int delegate(int) Draw ;

this(int s) {
struct Board { // a square board
immutable int scale ;
scale = s;
pix = new W[][](s * 12 + 1, s * 12 + 1);
immutable int size ;
}
int[][] pix ;

this(int s) {
string toString() {
scale = s ;
auto rows = map!q{ (cast(char[])a).idup }(pix);
size = s*12 ;
return join(array(rows), "\n");
pix = new int[][](size + 1,size + 1) ;
}
}

alias pix this ;
void drawCircle(Draw)(int cx, int cy, int cr, Draw action) {
auto rr = (cr * scale) ^^ 2;
static string str(int v) { return Tiles[(v % 4)] ; }
foreach (y, ref r; pix)
string toString() {
foreach (x, ref v; r) {
string[] s ;
auto dx = x - cx * scale;
foreach( r ; pix)
auto dy = y - cy * scale;
s ~= reduce!"a~b"(map!str(r)) ;
if (dx ^^ 2 + dy ^^ 2 <= rr)
return s.join("\n") ;
v = action(x);
}
}
}

void drawCircle(int cx, int cy, int cr, Draw action) {
SquareBoard yanYin() {
auto rr = (cr*scale)^^2 ;
foreach(y, ref r ; pix)
foreach (r; pix) // clear
foreach( x , ref v ; r) {
r[] = W.Void;
drawCircle(6, 6, 6,
auto dx = x - cx*scale ;
auto dy = y - cy*scale ;
(int x){ return (x < 6*scale) ? W.Yan : W.Yin; });
if(dx^^2 + dy^^2 <= rr)
drawCircle(6, 3, 3, (int x){ return W.Yan; });
drawCircle(6, 9, 3, (int x){ return W.Yin; });
v = action(x) ;
}
drawCircle(6, 9, 1, (int x){ return W.Yan; });
drawCircle(6, 3, 1, (int x){ return W.Yin; });
}
return this;
}
Board yanYin() {
foreach(r ; pix) // clear
r[] = 0 ;
drawCircle(6,6,6, (int x) { return (x < 6*scale) ? Yan : Yin ; }) ;
drawCircle(6,3,3, (int x) { return Yan ; } ) ;
drawCircle(6,9,3, (int x) { return Yin ; } ) ;
drawCircle(6,9,1, (int x) { return Yan ; } ) ;
drawCircle(6,3,1, (int x) { return Yin ; } ) ;
return this ;
}
}
}

void main(string[] args) {
void main() {
writeln(Board(2).yanYin) ;
writeln(SquareBoard(2).yanYin());
writeln(Board(1).yanYin) ;
writeln(SquareBoard(1).yanYin());
}</lang>
}</lang>
Output:
Output:

Revision as of 11:19, 25 April 2011

Task
Yin and yang
You are encouraged to solve this task according to the task description, using any language you may know.

Create a function that given a variable representing size, generates a Yin and yang also known as a Taijitu symbol scaled to that size.

Generate and display the symbol generated for two different (small) sizes.

D

<lang d>import std.stdio, std.string, std.algorithm, std.array;

struct SquareBoard {

 enum W : char { Void=' ', Yan='.', Yin='#', I='?' };
 immutable int scale;
 W[][] pix;
 this(int s) {
   scale = s;
   pix = new W[][](s * 12 + 1, s * 12 + 1);
 }
 string toString() {
   auto rows = map!q{ (cast(char[])a).idup }(pix);
   return join(array(rows), "\n");
 }
 void drawCircle(Draw)(int cx, int cy, int cr, Draw action) {
   auto rr = (cr * scale) ^^ 2;
   foreach (y, ref r; pix)
     foreach (x, ref v; r) {
       auto dx = x - cx * scale;
       auto dy = y - cy * scale;
       if (dx ^^ 2 + dy ^^ 2 <= rr)
         v = action(x);
     }
 }
 SquareBoard yanYin() {
   foreach (r; pix) // clear
     r[] = W.Void;
   drawCircle(6, 6, 6,
              (int x){ return (x < 6*scale) ? W.Yan : W.Yin; });
   drawCircle(6, 3, 3, (int x){ return W.Yan; });
   drawCircle(6, 9, 3, (int x){ return W.Yin; });
   drawCircle(6, 9, 1, (int x){ return W.Yan; });
   drawCircle(6, 3, 1, (int x){ return W.Yin; });
   return this;
 }

}

void main() {

 writeln(SquareBoard(2).yanYin());
 writeln(SquareBoard(1).yanYin());

}</lang> Output:

            ·            
        ········#        
      ···········##      
     ·············##     
    ········#·····###    
   ········###····####   
  ········#####····####  
  ·········###····#####  
 ···········#·····###### 
 ·················###### 
 ················####### 
 ···············######## 
············#############
 ········############### 
 ·······################ 
 ······################# 
 ······#####·########### 
  ·····####···#########  
  ····####·····########  
   ····####···########   
    ···#####·########    
     ··#############     
      ··###########      
        ·########        
            #            
      ·      
   ······#   
  ····#··##  
 ····###··## 
 ·····#··### 
 ········### 
······#######
 ···######## 
 ···##·##### 
 ··##···#### 
  ··##·####  
   ·######   
      #      

J

Based on the Python implementation:

<lang j>yinyang=:3 :0

 radii=. y*1 3 6
 ranges=. i:each radii
 squares=. ,"0/~each ranges
 circles=. radii ([ >: +/"1&.:*:@])each squares
 cInds=. ({:radii) +each circles #&(,/)each squares
 M=. ' *.' {~  circles (*  1 + 0 >: {:"1)&(_1&{::) squares
 offset=. 3*y,0
 M=. '*' ((_2 {:: cInds) <@:+"1 offset)} M
 M=. '.' ((_2 {:: cInds) <@:-"1 offset)} M
 M=. '.' ((_3 {:: cInds) <@:+"1 offset)} M
 M=. '*' ((_3 {:: cInds) <@:-"1 offset)} M

)</lang>

Note: although the structure of this program is based on the python implementation, some details are different. In particular, in the python implementation, the elements of squares and circles have no x,y structure -- they are flat list of coordinates.

Here, the three squares are each 3 dimensional arrays. The first two dimensions correspond to the x and y values and the last dimension is 2 (the first value being the y coordinate and the second being the x coordinate -- having the dimensions as y,x pairs like this works because in J the first dimension of a matrix is the number of rows and the second dimension is the number of columns).

Also, the three elements in the variable circles are represented by 2 dimensional arrays. The dimensions correspond to x and y values and the values are bits -- 1 if the corresponding coordinate pair in squares is a member of the circle and 0 if not.

Finally, the variable cInds corresponds very closely to the variable circles in the python code. Except, instead of having y and x values, cInds has indices into M. In other words, I added the last value from radii to the y and x values. In other words, instead of having values in the range -18..18, I would have values in the range 0..36 (but replace 18 and 36 with whatever values are appropriate).

Example use:

<lang> yinyang 1

     .      
  ......*   
 ....*..**  
....***..** 
.....*..*** 
........*** 

.......******

...******** 
...**.***** 
..**...**** 
 ..**.****  
  .******   
     *      
  yinyang 2
           .            
       ........*        
     ...........**      
    .............**     
   ........*.....***    
  ........***....****   
 ........*****....****  
 .........***....*****  
...........*.....****** 
.................****** 
................******* 
...............******** 

.............************

........*************** 
.......**************** 
......***************** 
......*****.*********** 
 .....****...*********  
 ....****.....********  
  ....****...********   
   ...*****.********    
    ..*************     
     ..***********      
       .********        
           *            </lang>

Prolog

Works with SWI-Prolog and XPCE.

<lang Prolog>ying_yang(N) :- R is N * 100, sformat(Title, 'Yin Yang ~w', [N]), new(W, window(Title)), new(Wh, colour(@default, 255*255, 255*255, 255*255)), new(Bl, colour(@default, 0, 0, 0)), CX is R + 50, CY is R + 50, R1 is R / 2, R2 is R / 8, CY1 is R1 + 50, CY2 is 3 * R1 + 50,

new(E, semi_disk(point(CX, CY), R, w, Bl)), new(F, semi_disk(point(CX, CY), R, e, Wh)), new(D1, disk(point(CX, CY1), R, Bl)), new(D2, disk(point(CX, CY2), R, Wh)), new(D3, disk(point(CX, CY1), R2, Wh)), new(D4, disk(point(CX, CY2), R2, Bl)),

send_list(W, display, [E, F, D1, D2, D3, D4]),

WD is 2 * R + 100, send(W, size, size(WD, WD )), send(W, open).

- pce_begin_class(semi_disk, path, "Semi disk with color ").

initialise(P, C, R, O, Col) :->

       send(P, send_super, initialise),

get(C, x, CX), get(C, y, CY), choose(O, Deb, End), forall(between(Deb, End, I), ( X is R * cos(I * pi/180) + CX, Y is R * sin(I * pi/180) + CY, send(P, append, point(X,Y)))), send(P, closed, @on), send(P, fill_pattern, Col).

- pce_end_class.

choose(s, 0, 180). choose(n, 180, 360). choose(w, 90, 270). choose(e, -90, 90).

- pce_begin_class(disk, ellipse, "disk with color ").

initialise(P, C, R, Col) :->

       send(P, send_super, initialise, R, R),

send(P, center, C), send(P, pen, 0), send(P, fill_pattern, Col).

- pce_end_class.

</lang> Example of output :

 ?- ying_yang(1).
true.

 ?- ying_yang(2).
true.

Python

For positive integer n > 0, the following generates an ASCII representation of the Yin yang symbol.

Works with: Python version 3.x

<lang python>import math def yinyang(n=3): radii = [i * n for i in (1, 3, 6)] ranges = [list(range(-r, r+1)) for r in radii] squares = [[ (x,y) for x in rnge for y in rnge] for rnge in ranges] circles = [[ (x,y) for x,y in sqrpoints if math.hypot(x,y) <= radius ] for sqrpoints, radius in zip(squares, radii)] m = {(x,y):' ' for x,y in squares[-1]} for x,y in circles[-1]: m[x,y] = '*' for x,y in circles[-1]: if x>0: m[(x,y)] = '·' for x,y in circles[-2]: m[(x,y+3*n)] = '*' m[(x,y-3*n)] = '·' for x,y in circles[-3]: m[(x,y+3*n)] = '·' m[(x,y-3*n)] = '*' return '\n'.join(.join(m[(x,y)] for x in reversed(ranges[-1])) for y in ranges[-1])</lang>

Sample generated symbols for n = 2 and n = 3
>>> print(yinyang(2))
            ·            
        ········*        
      ···········**      
     ·············**     
    ········*·····***    
   ········***····****   
  ········*****····****  
  ·········***····*****  
 ···········*·····****** 
 ·················****** 
 ················******* 
 ···············******** 
·············************
 ········*************** 
 ·······**************** 
 ······***************** 
 ······*****·*********** 
  ·····****···*********  
  ····****·····********  
   ····****···********   
    ···*****·********    
     ··*************     
      ··***********      
        ·********        
            *            
>>> print(yinyang(1))
      ·      
   ······*   
  ····*··**  
 ····***··** 
 ·····*··*** 
 ········*** 
·······******
 ···******** 
 ···**·***** 
 ··**···**** 
  ··**·****  
   ·******   
      *      
>>> 

SVG

A rendering

SVG has no proper functions or variables, but we can translate and rescale a shape after defining it.

<lang xml><?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"

 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg xmlns="http://www.w3.org/2000/svg" version="1.1"

   xmlns:xlink="http://www.w3.org/1999/xlink"
   width="600" height="600">

<symbol id="yinyang">

 <g transform="translate(-0.5, -0.5)">
   <circle cx="0.5" cy="0.5" r="0.5" fill="white"/>
   <path d="M 0.5,0 A 0.5,0.5 0 0,1 0.5,1 z" fill="black"/>
   <circle cx="0.5" cy="0.25" r="0.25" fill="white"/>
   <circle cx="0.5" cy="0.75" r="0.25" fill="black"/>
   <circle cx="0.5" cy="0.25" r="0.1" fill="black"/>
   <circle cx="0.5" cy="0.75" r="0.1" fill="white"/>
   <circle cx="0.5" cy="0.5" r="0.5" fill="none"
     stroke="gray" stroke-width=".01"/>
 </g>

</symbol>

<use xlink:href="#yinyang"

 transform="translate(125, 125) scale(200, 200)"/>

<use xlink:href="#yinyang"

 transform="translate(375, 375) scale(400, 400)"/>

</svg></lang>

Tcl

Output of this Tcl program
Library: Tk

<lang tcl>package require Tcl 8.5 package require Tk

namespace import tcl::mathop::\[-+\]  ;# Shorter coordinate math proc yinyang {c x y r {colors {white black}}} {

   lassign $colors a b
   set tt [expr {$r * 2 / 3.0}]
   set h [expr {$r / 2.0}]
   set t [expr {$r / 3.0}]
   set s [expr {$r / 6.0}]
   $c create arc [- $x $r] [- $y $r] [+ $x $r] [+ $y $r] \

-fill $a -outline {} -extent 180 -start 90

   $c create arc [- $x $r] [- $y $r] [+ $x $r] [+ $y $r] \

-fill $b -outline {} -extent 180 -start 270

   $c create oval [- $x $h] [- $y $r] [+ $x $h] $y \

-fill $a -outline {}

   $c create oval [- $x $h] [+ $y $r] [+ $x $h] $y \

-fill $b -outline {}

   $c create oval [- $x $s] [- $y $tt] [+ $x $s] [- $y $t] \

-fill $b -outline {}

   $c create oval [- $x $s] [+ $y $tt] [+ $x $s] [+ $y $t] \

-fill $a -outline {} }

pack [canvas .c -width 300 -height 300 -background gray50] yinyang .c 110 110 90 yinyang .c 240 240 40</lang>