Yin and yang: Difference between revisions

From Rosetta Code
Content added Content deleted
(Go solution)
m (→‎{{header|Prolog}}: size down image)
Line 1,169: Line 1,169:
true.
true.
</pre>
</pre>
[[File:Prolog-yin-yang.png]]
[[File:Prolog-yin-yang.png|center|600px]]

=={{header|PureBasic}}==
=={{header|PureBasic}}==
[[File:Yin And yang.png|350px|thumb|right]]
[[File:Yin And yang.png|350px|thumb|right]]

Revision as of 22:40, 5 November 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.

Asymptote

The resulting EPS, converted to SVG

<lang asymptote>unitsize(1 inch);

fill(scale(6)*unitsquare, invisible);

picture yinyang(pair center, real radius) {

   picture p;
   fill(p, unitcircle, white);
   fill(p, arc(0, S, N) -- cycle, black);
   fill(p, circle(N/2, 1/2), white);
   fill(p, circle(S/2, 1/2), black);
   fill(p, circle(N/2, 1/5), black);
   fill(p, circle(S/2, 1/5), white);
   draw(p, unitcircle, linewidth((1/32) * inch) + gray(0.5));
   return shift(center) * scale(radius) * p;

}

add(yinyang((1 + 1/4, 4 + 3/4), 1)); add(yinyang((3 + 3/4, 2 + 1/4), 2));</lang>

ALGOL 68

Works with: ALGOL 68 version Revision 1 - With Currying extensions to language.
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny.

<lang algol68>INT scale x=2, scale y=1; CHAR black="#", white=".", clear=" ";

PROC print yin yang = (REAL radius)VOID:(

 PROC in circle = (REAL centre x, centre y, radius, x, y)BOOL:
   (x-centre x)**2+(y-centre y)**2 <= radius**2;
 PROC (REAL, REAL)BOOL
   in big circle = in circle(0, 0, radius, , ),
   in white semi circle  = in circle(0, +radius/2, radius/2, , ),
   in small black circle = in circle(0, +radius/2, radius/6, , ),
   in black semi circle  = in circle(0, -radius/2, radius/2, , ),
   in small white circle = in circle(0, -radius/2, radius/6, , );
 FOR sy FROM +ROUND(radius * scale y) BY -1 TO -ROUND(radius * scale y) DO
   FOR sx FROM -ROUND(radius * scale x) TO +ROUND(radius * scale x) DO
     REAL x=sx/scale x, y=sy/scale y;
     print(
       IF in big circle(x, y) THEN
           IF in white semi circle(x, y) THEN
             IF in small black circle(x, y) THEN black ELSE white FI
           ELIF in black semi circle(x, y) THEN
             IF in small white circle(x, y) THEN white ELSE black FI
           ELIF x < 0 THEN white ELSE black FI
       ELSE
         clear
       FI
     )
   OD;
   print(new line)
 OD

);

main:(

 print yin yang(17);
 print yin yang(8)

)</lang> Output:

                                  .                                  
                       ....................###                       
                  ...........................######                  
               ................................#######               
             ....................................#######             
          ........................................#########          
         .......................#####..............#########         
       .......................#########............###########       
      .......................###########...........############      
    .........................###########...........##############    
    ..........................#########............##############    
   .............................#####..............###############   
  ................................................#################  
 ................................................################### 
 ..............................................##################### 
 ............................................####################### 
 ..........................................######################### 
...................................##################################
 .........................########################################## 
 .......................############################################ 
 .....................############################################## 
 ...................################################################ 
  .................################################################  
   ...............##############.....#############################   
    ..............############.........##########################    
    ..............###########...........#########################    
      ............###########...........#######################      
       ...........############.........#######################       
         .........##############.....#######################         
          .........########################################          
             .......####################################             
               .......################################               
                  ......###########################                  
                       ...####################                       
                                  #                                  
                .                
         .............##         
      .................####      
    ...........###......#####    
   ...........#####......#####   
  .............###......#######  
 ......................######### 
 .....................########## 
.................################
 ..........##################### 
 .........###################### 
  .......######...#############  
   .....######.....###########   
    .....######...###########    
      ....#################      
         ..#############         
                #                

BBC BASIC

<lang bbcbasic> PROCyinyang(200, 200, 100)

     PROCyinyang(700, 400, 300)
     END
     
     DEF PROCyinyang(xpos%, ypos%, size%)
     CIRCLE xpos%, ypos%, size%
     LINE xpos%, ypos%+size%, xpos%, ypos%-size%
     FILL xpos%+size%/2, ypos%
     CIRCLE FILL xpos%, ypos%-size%/2, size%/2+2
     GCOL 15
     CIRCLE FILL xpos%, ypos%+size%/2, size%/2+2
     CIRCLE FILL xpos%, ypos%-size%/2, size%/6+2
     GCOL 0
     CIRCLE FILL xpos%, ypos%+size%/2, size%/6+2
     CIRCLE xpos%, ypos%, size%
     ENDPROC</lang>

C

Writes to stdout a SVG file with two yin-yangs (no, it's really just that big): <lang C>#include <stdio.h>

void draw_yinyang(int trans, double scale) { printf("<use xlink:href='#y' transform='translate(%d,%d) scale(%g)'/>", trans, trans, scale); }

int main() { printf( "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" "<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN'\n" " 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>\n" "<svg xmlns='http://www.w3.org/2000/svg' version='1.1'\n" " xmlns:xlink='http://www.w3.org/1999/xlink'\n" " width='30' height='30'>\n" " <defs><g id='y'>\n" " <circle cx='0' cy='0' r='200' stroke='black'\n" " fill='white' stroke-width='1'/>\n" " <path d='M0 -200 A 200 200 0 0 0 0 200\n" " 100 100 0 0 0 0 0 100 100 0 0 1 0 -200\n" " z' fill='black'/>\n" " <circle cx='0' cy='100' r='33' fill='white'/>\n" " <circle cx='0' cy='-100' r='33' fill='black'/>\n" " </g></defs>\n"); draw_yinyang(20, .05); draw_yinyang(8, .02); printf("</svg>"); return 0; }</lang>

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:

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

Delphi

This example does not show the output mentioned in the task description on this page (or a page linked to from here). Please ensure that it meets all task requirements and remove this message.
Note that phrases in task descriptions such as "print and display" and "print and show" for example, indicate that (reasonable length) output be a part of a language's solution.


<lang delphi>procedure TForm1.ButtonCreateClick(Sender: TObject); begin

  DrawYinAndYang(StrToInt(EditSize.Text), Canvas, GetClientRect);

end;

procedure DrawYinandYang(size: Word; DrawArea: TCanvas; R: TRect); begin

  DrawArea.Brush.Color := clGray;
  DrawArea.FillRect(R);
  DrawArea.Brush.Color := clwhite;
  DrawArea.Pen.Color := clwhite;
  DrawArea.Pie(10, 10, 10 + size, 10 + size, 10 + (size div 2), 10, 10 + (size div 2), 10 + size);
  DrawArea.Brush.Color := clblack;
  DrawArea.Pen.Color := clblack;
  DrawArea.Pie(10, 10, 10 + size, 10 + size, 10 + (size div 2), 10 + size, 10 + (size div 2), 10);
  DrawArea.Brush.Color := clwhite;
  DrawArea.Pen.Color := clwhite;
  DrawArea.Ellipse(10 + (size div 4), 10, 10 + 3 * (size div 4),10 + (size div 2));
  DrawArea.Brush.Color := clblack;
  DrawArea.Pen.Color := clblack;
  DrawArea.Ellipse(10 + (size div 4), 10 + (size div 2), 10 + 3 * (size div 4), 10 + size);
  DrawArea.Brush.Color := clwhite;
  DrawArea.Pen.Color := clwhite;
  DrawArea.Ellipse(10 + 7 * (size div 16), 10 + 11 * (size div 16), 10 + 9 * (size div 16),10 + 13 * (size div 16));
  DrawArea.Brush.Color := clblack;
  DrawArea.Pen.Color := clblack;
  DrawArea.Ellipse(10 + 7 * (size div 16), 10 + 3 * (size div 16), 10 + 9 * (size div 16),10 + 5 * (size div 16));

end;</lang>


DWScript

Translation of: D

<lang delphi> type

  TColorFuncX = function (x : Integer) : Integer;

type

  TSquareBoard = class
     Scale : Integer;
     Pix : array of array of Integer;
     constructor Create(aScale : Integer);
     begin
        Scale := aScale;
        Pix := new Integer[aScale*12+1, aScale*12+1];
     end;
     method Print;
     begin
        var i, j : Integer;
        for i:=0 to Pix.High do begin
           for j:=0 to Pix.High do begin
              case Pix[j, i] of
                 1 : Print('.');
                 2 : Print('#');
              else
                 Print(' ');
              end;
           end;
           PrintLn();
        end;
     end;
     method DrawCircle(cx, cy, cr : Integer; color : TColorFuncX);
     begin
        var rr := Sqr(cr*Scale);
        var x, y : Integer;
        for x := 0 to Pix.High do begin
           for y := 0 to Pix.High do begin
              if Sqr(x-cx*Scale)+Sqr(y-cy*Scale)<=rr then
                 Pix[x, y] := color(x);
           end;
        end;
     end;
     method ColorHalf(x : Integer) : Integer;
     begin
        if (x<6*Scale) then
           Result:=1
        else Result:=2;
     end;
     method ColorYin(x : Integer) : Integer;
     begin
        Result:=2;
     end;
     method ColorYang(x : Integer) : Integer;
     begin
        Result:=1;
     end;
     method YinYang;
     begin
        DrawCircle(6, 6, 6, ColorHalf);
        DrawCircle(6, 3, 3, ColorYang);
        DrawCircle(6, 9, 3, ColorYin);
        DrawCircle(6, 9, 1, ColorYang);
        DrawCircle(6, 3, 1, ColorYin);
     end;
  end;

var sq := new TSquareBoard(2); sq.YinYang; sq.Print;

sq := new TSquareBoard(1); sq.YinYang; sq.Print; </lang> Output:

            .            
        ........#        
      ...........##      
     .............##     
    ........#.....###    
   ........###....####   
  ........#####....####  
  .........###....#####  
 ...........#.....###### 
 .................###### 
 ................####### 
 ...............######## 
............#############
 ........############### 
 .......################ 
 ......################# 
 ......#####.########### 
  .....####...#########  
  ....####.....########  
   ....####...########   
    ...#####.########    
     ..#############     
      ..###########      
        .########        
            #            
      .      
   ......#   
  ....#..##  
 ....###..## 
 .....#..### 
 ........### 
......#######
 ...######## 
 ...##.##### 
 ..##...#### 
  ..##.####  
   .######   
      #      

Go

There are some emerging third-party 2D graphics libraries for Go; meanwhile, here is an SVG solution using only standard libraries. <lang go>package main

import (

   "fmt"
   "os"
   "template"

)

var tmpl = `<?xml version="1.0"?> <svg xmlns="http://www.w3.org/2000/svg"

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

<symbol id="yy" viewBox="0 0 200 200"> <circle stroke="black" stroke-width="2" fill="white"

   cx="100" cy="100" r="99" />

<path fill="black"

   d="M100 100 a49 49 0 0 0 0 -98
   v-1 a99 99 0 0 1 0 198
   v-1 a49 49 0 0 1 0 -98" />

<circle fill="black" cx="100" cy="51" r="17" /> <circle fill="white" cx="100" cy="149" r="17" /> </symbol> Template:Range .<use xlink:href="#yy"

   x="Template:.X" y="Template:.Y" width="Template:.Sz" height="Template:.Sz"/>

Template:End</svg> `

// structure specifies position and size to draw symbol type xysz struct {

   X, Y, Sz int

}

// example data to specify drawing the symbol twice, // with different position and size. var yys = []xysz{

   {20, 20, 100},
   {140, 30, 60},

}

func main() {

   xt := template.New("")
   template.Must(xt.Parse(tmpl))
   f, err := os.Create("yy.svg")
   if err != nil {
       fmt.Println(err)
       return
   }
   if err := xt.Execute(f, yys); err != nil {
       fmt.Println(err)
   }
   f.Close()

}</lang>

Haskell

Yin and Yang Haskell SVG output.

This program uses the diagrams package to produce the Yin and Yang image. The package implements an embedded DSL for producing vector graphics. Depending on the command-line arguments, the program can generate SVG, PNG, PDF or PostScript output. The sample output was created with the command yinyang -o YinYang-Haskell.svg. <lang haskell>{-# LANGUAGE NoMonomorphismRestriction #-}

import Diagrams.Prelude import Diagrams.Backend.Cairo.CmdLine

yinyang = lw 0 $

         perim # lw 0.003 <>
         torus white black # xform id <>
         torus black white # xform negate <>
         clipBy perim base
 where perim      = arc 0 (360 :: Deg) # scale (1/2)
       torus c c' = circle (1/3) # fc c' <> circle 1 # fc c
       xform f    = translateY (f (1/4)) . scale (1/4)
       base       = rect (1/2) 1 # fc white ||| rect (1/2) 1 # fc black

main = defaultMain $

      pad 1.1 $ 
      beside (2,-1) yinyang (yinyang # scale (1/4))</lang>

Icon and Unicon

Sample Output

<lang Icon>link graphics

procedure main() YinYang(100) YinYang(40,"blue","yellow","white") WDone() # quit on Q/q end

procedure YinYang(R,lhs,rhs,bg) # draw YinYang with radius of R pixels and ... /lhs := "white" # left hand side /rhs := "black" # right hand side /bg  := "grey" # background

wsize  := 2*(C := R + (margin := R/5))

W := WOpen("size="||wsize||","||wsize,"bg="||bg) | stop("Unable to open Window") WAttrib(W,"fg="||lhs) & FillCircle(W,C,C,R,+dtor(90),dtor(180)) # main halves WAttrib(W,"fg="||rhs) & FillCircle(W,C,C,R,-dtor(90),dtor(180)) WAttrib(W,"fg="||lhs) & FillCircle(W,C,C+R/2,R/2,-dtor(90),dtor(180)) # sub halves WAttrib(W,"fg="||rhs) & FillCircle(W,C,C-R/2,R/2,dtor(90),dtor(180)) WAttrib(W,"fg="||lhs) & FillCircle(W,C,C-R/2,R/8) # dots WAttrib(W,"fg="||rhs) & FillCircle(W,C,C+R/2,R/8) end </lang>

graphics.icn provides graphical procedures

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>

Liberty BASIC

Liberty BASIC Graphic Output

<lang lb> WindowWidth =410

   WindowHeight =440
   open "Yin & Yang" for graphics_nf_nsb as #w
   #w "trapclose [quit]"
   call YinYang 200, 200, 200
   call YinYang 120,  50,  50
   wait
   sub YinYang x, y, size
   #w "up ; goto "; x; " "; y
   #w "backcolor black ; color black"
   #w "down ; circlefilled "; size /2
   #w "color 255 255 255 ; backcolor 255 255 255"
   #w "up   ; goto ";      x -size /2; " "; y -size /2
   #w "down ; boxfilled "; x;          " "; y +size /2
   #w "up ; goto "; x; " "; y -size /4
   #w "down ; backcolor black ; color black   ; circlefilled "; size  /4
   #w "up ; goto "; x; " "; y -size /4
   #w "down ; backcolor white ; color white ; circlefilled "; size /12
   #w "up ; goto "; x; " "; y +size /4
   #w "down ; backcolor white ; color white ; circlefilled "; size  /4
   #w "up ; goto "; x; " "; y +size /4
   #w "down ; backcolor black ; color black ; circlefilled "; size /12
   #w "up ; goto "; x; " "; y
   #w "down ; color black ; circle "; size /2
   #w "flush"
   end sub
   scan
   wait
 [quit]
   close #w
   end

</lang>

UCB Logo Graphic Output
Works with: UCB_Logo version 5.5
Works with: MSW_Logo version 6.5b

<lang logo>to taijitu :r

 ; Draw a classic Taoist taijitu of the given radius centered on the current
 ; turtle position. The "eyes" are placed along the turtle's heading, the
 ; filled one in front, the open one behind.

 ; don't bother doing anything if the pen is not down
 if not pendown? [stop]

 ; useful derivative values
 localmake "r2 (ashift :r  -1)
 localmake "r4 (ashift :r2 -1)
 localmake "r8 (ashift :r4 -1)

 ; remember where we started
 localmake "start  pos

 ; draw outer circle
 pendown
 arc 360 :r

 ; draw upper half of S
 penup
 forward :r2
 pendown
 arc 180 :r2

 ; and filled inner eye
 arc 360 :r8
 fill

 ; draw lower half of S
 penup
 back :r
 pendown
 arc -180 :r2

 ; other inner eye
 arc  360 :r8

 ; fill this half of the symbol 
 penup
 forward :r4
 fill

 ; put the turtle back where it started
 setpos :start
 pendown

end

demo code to produce image at right

clearscreen pendown hideturtle taijitu 100 penup forward 150 left 90 forward 150 pendown taijitu 75 </lang>

Mathematica

Mathematica's ability to symbolically build up graphics is often underrated. The following function will create a yin-yang symbol with the parameter size indicating the diameter in multiples of 40 pixels. <lang Mathematica> YinYang[size_] :=

Graphics[{{Circle[{0, 0}, 2]}, {Disk[{0, 0}, 
    2, {90 Degree, -90 Degree}]}, {White, Disk[{0, 1}, 1]}, {Black, 
   Disk[{0, -1}, 1]}, {Black, Disk[{0, 1}, 1/4]}, {White, 
   Disk[{0, -1}, 1/4]}}, ImageSize -> 40 size]

</lang>

Metapost

Metapost output (once converted to jpg)

The "function" yinyang returns a picture (a primitive type) that can be drawn (and transformed of course in any way) <lang metapost>vardef yinyang(expr u) =

 picture pic_;
 path p_;
 p_ := halfcircle scaled 2u rotated -90 --
   halfcircle scaled u rotated 90 shifted (0, 1/2u) reflectedabout ((0,1), (0,-1)) --
   halfcircle scaled u rotated -270 shifted (0, -1/2u) -- cycle;
 
 pic_ := nullpicture;
 addto pic_ contour fullcircle scaled 2u withcolor black;
 addto pic_ contour p_ withcolor white;
 addto pic_ doublepath p_ withcolor black withpen pencircle scaled 0.5mm;
 addto pic_ contour fullcircle scaled 1/3u shifted (0, 1/2u) withcolor white;
 addto pic_ contour fullcircle scaled 1/3u shifted (0, -1/2u) withcolor black;
 pic_

enddef;

beginfig(1)

 % let's create a Yin Yang symbol with a radius of 5cm
 draw yinyang(5cm) shifted (5cm, 5cm);
 % and another one, radius 2.5cm, rotated 180 degrees and translated
 draw yinyang(2.5cm) rotated 180 shifted (11cm, 11cm);

endfig;

end.</lang>

NetRexx

Writes an SVG document to standard output:

Translation of: C

<lang NetRexx>/* NetRexx */

options replace format comments java crossref savelog symbols binary

say "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" say "<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN'" say " 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>" say "<svg xmlns='http://www.w3.org/2000/svg' version='1.1'" say " xmlns:xlink='http://www.w3.org/1999/xlink'" say " width='30' height='30'>" say " <defs><g id='y'>" say " <circle cx='0' cy='0' r='200' stroke='black'" say " fill='white' stroke-width='1'/>" say " <path d='M0 -200 A 200 200 0 0 0 0 200" say " 100 100 0 0 0 0 0 100 100 0 0 1 0 -200" say " z' fill='black'/>" say " <circle cx='0' cy='100' r='33' fill='white'/>" say " <circle cx='0' cy='-100' r='33' fill='black'/>" say " </g></defs>"

say draw_yinyang(20, 0.05) say draw_yinyang(8, 0.02)

say "</svg>"

return

method draw_yinyang(trans = int, scale = double) inheritable static returns String

 yy = String.format("  <use xlink:href='#y' transform='translate(%d,%d) scale(%g)'/>", -
      [Object Integer(trans), Integer(trans), Double(scale)])
 return yy

</lang>

OCaml

<lang ocaml>open Graphics

let draw_yinyang x y radius black white =

 let hr = radius / 2 in
 let sr = radius / 6 in
 set_color black;
 set_line_width 6;
 draw_circle x y radius;
 set_line_width 0;
 set_color black;
 fill_arc x y radius radius 270 450;
 set_color white;
 fill_arc x y radius radius 90 270;
 fill_arc x (y + hr) hr hr 270 450;
 set_color black;
 fill_arc x (y - hr) hr hr 90 270;
 fill_circle x (y + hr) sr;
 set_color white;
 fill_circle x (y - hr) sr

let () =

 open_graph "";
 let width = size_x()
 and height = size_y() in
 set_color (rgb 200 200 200);
 fill_rect 0 0 width height;
 let w = width / 3
 and h = height / 3 in
 let r = (min w h) / 3 in
 draw_yinyang w (h*2) (r*2) black white;
 draw_yinyang (w*2) h r blue magenta;
 ignore(read_key())</lang>

run with:

$ ocaml graphics.cma yinyang.ml

Perl

<lang perl>sub circle {

       my ($radius, $cx, $cy, $fill, $stroke) = @_;
       print   "<circle cx='$cx' cy='$cy' r='$radius' ",
               "fill='$fill' stroke='$stroke' stroke-width='1'/>\n";

}

sub yin_yang {

       my ($rad, $cx, $cy, %opt) = @_;
       my ($c, $w) = (1, 0);
       $opt{fill}   //= 'white';
       $opt{stroke} //= 'black';
       $opt{recurangle} //= 0;
       print "<g transform='rotate($opt{angle}, $cx, $cy)'>"   if ($opt{angle});
       if ($opt{flip}) { ($c, $w) = ($w, $c) };
       circle($rad, $cx, $cy, $opt{fill}, $opt{stroke});
       print "<path d='M $cx ", $cy + $rad, "A ",
               $rad/2, " ", $rad/2, " 0 0 $c $cx $cy ",
               $rad/2, " ", $rad/2, " 0 0 $w $cx ", $cy - $rad, " ",
               $rad,   " ", $rad,   " 0 0 $c $cx ", $cy + $rad, " ",
               "z' fill='$opt{stroke}' stroke='none' />";
       if ($opt{recur} and $rad > 1) {
               # recursive "eyes" are slightly larger
               yin_yang($rad/4, $cx, $cy + $rad/2, %opt,
                               angle   => $opt{recurangle},
                               fill    => $opt{stroke},
                               stroke  => $opt{fill}   );
               yin_yang($rad/4, $cx, $cy - $rad/2, %opt,
                               angle   => 180 + $opt{recurangle});
       } else {
               circle($rad/5, $cx, $cy + $rad/2, $opt{fill}, $opt{stroke});
               circle($rad/5, $cx, $cy - $rad/2, $opt{stroke}, $opt{fill});
       }
       print "</g>" if $opt{angle};

}

print <<'HEAD'; <?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">

HEAD

yin_yang(200, 250, 250, recur=>1, angle=>0, recurangle=>90, fill=>'white', stroke=>'black'); yin_yang(100, 500, 500);

print "</svg>"</lang>

Messy code. Note that the larger yin-yang is drawn recursively.

Perl 6

Translation / Modification of C and Perl examples.

<lang perl6>sub circle ($rad, $cx, $cy, $fill = 'white', $stroke = 'black' ){

   say "<circle cx='$cx' cy='$cy' r='$rad' fill='$fill' stroke='$stroke' stroke-width='1'/>";

}

sub yin_yang ($rad, $cx, $cy, :$fill = 'white', :$stroke = 'black', :$angle = 90) {

   my ($c, $w) = (1, 0);
   say "<g transform='rotate($angle, $cx, $cy)'>" if $angle;
   circle($rad, $cx, $cy, $fill, $stroke);
   say "<path d='M $cx {$cy + $rad}A {$rad/2} {$rad/2} 0 0 $c $cx $cy ",
       "{$rad/2} {$rad/2} 0 0 $w $cx {$cy - $rad} $rad $rad 0 0 $c $cx ",
       "{$cy + $rad} z' fill='$stroke' stroke='none' />";
   circle($rad/5, $cx, $cy + $rad/2, $fill, $stroke);
   circle($rad/5, $cx, $cy - $rad/2, $stroke, $fill);
   say "</g>" if $angle;

}

say '<?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">';

yin_yang(40, 50, 50); yin_yang(20, 120, 120);

say '</svg>';</lang>

Seems like something of a cheat since it relies on a web browser / svg image interpreter to actually view the output image. If that's the case, we may as well cheat harder. ;-)

<lang perl6>sub cheat_harder ($scale) {

    "";

}

say '



', cheat_harder(700), cheat_harder(350), '

';</lang>



PostScript

Output:

<lang PostScript>%!PS-Adobe-3.0 %%BoundingBox: 0 0 400 400

/fs 10 def /ed { exch def } def /dist { 3 -1 roll sub dup mul 3 1 roll sub dup mul add sqrt } def /circ {

   /r exch def
   [r neg 1 r {
       /y exch def
       [ r 2 mul neg 1 r 2 mul {
           /x ed x 2 div y 0 0 dist r .05 add gt {( )}{
               x 2 div y 0 r 2 div dist dup
               r 5 div le { pop (.) } {
                   r 2 div le { (@) }{
                       x 2 div y 0 r 2 div neg dist dup
                       r 5 div le { pop (@)} {
                           r 2 div le {(.)}{
                               x 0 le {(.)}{(@)}ifelse
                           } ifelse
                       } ifelse
                   } ifelse
               } ifelse
           } ifelse
       } for]
   } for]

} def

/dis { moveto gsave

       {       grestore 0 fs 1.15 mul neg rmoveto gsave
               {show} forall
       } forall grestore

} def

/Courier findfont fs scalefont setfont

11 circ 10 390 dis 6 circ 220 180 dis showpage %%EOF</lang>

POV-Ray

<lang POV-Ray> // ====== General Scene setup ======

  1. version 3.7;

global_settings { assumed_gamma 2.2 }

camera{ location <0,2.7,4> look_at <0,.1,0> right x*1.6

       aperture .2 focal_point <1,0,0> blur_samples 200 variance 1/10000 }

light_source{<2,4,8>, 1 spotlight point_at 0 radius 10} sky_sphere {pigment {granite scale <1,.1,1> color_map {[0 rgb 1][1 rgb <0,.4,.6>]}}}

  1. default {finish {diffuse .9 reflection {.1 metallic} ambient .3}
         normal {granite scale .2}}

plane { y, -1 pigment {hexagon color rgb .7 color rgb .75 color rgb .65}

       normal {hexagon scale 5}}

// ====== Declare one side of the symbol as a sum and difference of discs ======

  1. declare yang =

difference {

 merge {
   difference {
     cylinder {0 <0,.1,0> 1}               // flat disk
     box {-1 <1,1,0>}                      // cut in half
     cylinder {<.5,-.1,0> <.5,.2,0> .5}    // remove half-cicle on one side
   }
   cylinder {<-.5,0,0> <-.5,.1,0> .5}      // add on the other side
   cylinder {<.5,0,0> <.5,.1,0> .15}       // also add a little dot
 }
 cylinder {<-.5,-.1,0> <-.5,.2,0> .15}     // and carve out a hole
 pigment{color rgb 0.1}

}

// ====== The other side is white and 180-degree turned ======

  1. declare yin =

object {

 yang
 rotate <0,180,0>
 pigment{color rgb 1}

}

// ====== Here we put the two together: ======

  1. macro yinyang( ysize )
 union {
   object {yin}
   object {yang}
   scale ysize   
 }
  1. end

// ====== Here we put one into a scene: ======

object { yinyang(1)

        translate -y*1.08 }

// ====== And a bunch more just for fun: ======

  1. declare scl=1.1;
  2. while (scl > 0.01)
 object { yinyang(scl) 
       rotate <0,180,0> translate <-scl*4,scl*2-1,0> 
       rotate <0,scl*360,0> translate <-.5,0,0>}
       
 object { yinyang(scl) 
       translate <-scl*4,scl*2-1,0> 
       rotate <0,scl*360+180,0> translate <.5,0,0>}
 #declare scl = scl*0.85;
  1. end

</lang>

PicoLisp

<lang PicoLisp>(de circle (X Y C R)

  (>=
     (* R R)
     (+
        (* (setq X (/ X 2)) X)
        (* (dec 'Y C) Y) ) ) )

(de yinYang (R)

  (for Y (range (- R) R)
     (for X (range (- 0 R R) (+ R R))
        (prin
           (cond
              ((circle X Y (- (/ R 2)) (/ R 6))
                 "#" )
              ((circle X Y (/ R 2) (/ R 6))
                 "." )
              ((circle X Y (- (/ R 2)) (/ R 2))
                 "." )
              ((circle X Y (/ R 2) (/ R 2))
                 "#" )
              ((circle X Y 0 R)
                 (if (lt0 X) "." "#") )
              (T " ") ) ) )
     (prinl) ) )</lang>

Test:

: (yinYang 18)
                                   ...
                         .....................##
                   .............................######
                 .................................######
             .......................................########
           ...........................................########
         ..........................###................##########
       ........................###########............############
       ........................###########............############
     ........................###############............############
   ............................###########............################
   ............................###########............################
   ................................###................################
 .....................................................##################
 ...................................................####################
 .................................................######################
 ...............................................########################
 .............................................##########################
......................................###################################
 ..........................#############################################
 ........................###############################################
 ......................#################################################
 ....................###################################################
 ..................#####################################################
   ................################...################################
   ................############...........############################
   ................############...........############################
     ............############...............########################
       ............############...........########################
       ............############...........########################
         ..........################...##########################
           ........###########################################
             ........#######################################
                 ......#################################
                   ......#############################
                         ..#####################
                                   ###

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.

PureBasic

<lang PureBasic>Procedure Yin_And_Yang(x, y, radius)

 DrawingMode(#PB_2DDrawing_Outlined)
 Circle(x, y, 2 * radius, #Black)               ;outer circle
 DrawingMode(#PB_2DDrawing_Default)
 LineXY(x, y - 2 * radius, x, y + 2 * radius, #Black)
 FillArea(x + 1, y, #Black, #Black)
 Circle(x, y - radius, radius - 1, #White)
 Circle(x, y + radius, radius - 1, #Black)
 Circle(x, y - radius, radius / 3, #Black)       ;small contrasting inner circles
 Circle(x, y + radius, radius / 3, #White)

EndProcedure

If CreateImage(0, 700, 700) And StartDrawing(ImageOutput(0))

   FillArea(1, 1, -1, #White)
   Yin_And_Yang(105, 105, 50)
   Yin_And_Yang(400, 400, 148)
 StopDrawing()
 ;
 UsePNGImageEncoder()
 path$ = SaveFileRequester("Save image", "Yin And yang.png", "*.png", 0)
 If path$ <> "": SaveImage(0, path$, #PB_ImagePlugin_PNG, 0, 2): EndIf

EndIf</lang>

Python

Text

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))
      ·      
   ······*   
  ····*··**  
 ····***··** 
 ·····*··*** 
 ········*** 
·······******
 ···******** 
 ···**·***** 
 ··**···**** 
  ··**·****  
   ·******   
      *      
>>> 

Turtle Graphics

This was inspired by the Logo example but diverged as some of the Python turtle graphics primitives such as filling and the drawing of arcs work differently.

Python turtle graphics program output

<lang python>from turtle import *

mode('logo')

def taijitu(r):

 \
 Draw a classic Taoist taijitu of the given radius centered on the current
 turtle position. The "eyes" are placed along the turtle's heading, the
 filled one in front, the open one behind.
 
 # useful derivative values
 r2, r4, r8 = (r >> s for s in (1, 2, 3))
 # remember where we started
 x0, y0 = start = pos()
 startcolour = color()
 startheading = heading()
 color('black', 'black')
 # draw outer circle
 pendown()
 circle(r)
 # draw two 'fishes'
 begin_fill(); circle(r, 180); circle(r2, 180); circle(-r2, 180); end_fill()
 # black 'eye'  
 setheading(0); penup(); goto(-(r4 + r8) + x0, y0); pendown()
 begin_fill(); circle(r8); end_fill()
 # white 'eye'
 color('white', 'white'); setheading(0); penup(); goto(-(r+r4+r8) + x0, y0); pendown()
 begin_fill(); circle(r8); end_fill() 
 # put the turtle back where it started
 penup()
 setpos(start)
 setheading(startheading)
 color(*startcolour)


if __name__ == '__main__':

 # demo code to produce image at right
 reset()
 #hideturtle()
 penup()
 goto(300, 200)
 taijitu(200)
 penup()
 goto(-150, -150)
 taijitu(100)
 hideturtle()</lang>

Seed7

Output of the Seed7 program

<lang seed7>$ include "seed7_05.s7i";

 include "float.s7i";
 include "math.s7i";
 include "draw.s7i";
 include "keybd.s7i";

const proc: yinYang (in integer: xPos, in integer: yPos, in integer: size) is func

 begin
   pieslice(xPos, yPos, size, 3.0 * PI / 2.0, PI, black);
   pieslice(xPos, yPos, size, PI / 2.0, PI, white);
   fcircle(xPos, yPos - size div 2, size div 2, white);
   fcircle(xPos, yPos + size div 2, size div 2, black);
   fcircle(xPos, yPos - size div 2, size div 6, black);
   fcircle(xPos, yPos + size div 2, size div 6, white);
   circle(xPos, yPos, size, black);
 end func;

const proc: main is func

 begin
   screen(640, 480);
   clear(white);
   KEYBOARD := GRAPH_KEYBOARD;
   yinYang(100, 100, 80);
   yinYang(400, 250, 200);
   readln(KEYBOARD);
 end func;</lang>

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>

Visual Basic .NET

Output of this VB.Net program

This version is based behind a Windows Form Application project in Visual Studio, single form with base values. <lang vbnet> Public Class Form1

   Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
       Dim g As Graphics = e.Graphics
       g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
       DrawTaijitu(g, New Point(50, 50), 200, True)
       DrawTaijitu(g, New Point(10, 10), 60, True)
   End Sub
   Private Sub DrawTaijitu(ByVal g As Graphics, ByVal pt As Point, ByVal width As Integer, ByVal hasOutline As Boolean)
       g.FillPie(Brushes.Black, pt.X, pt.Y, width, width, 90, 180)
       g.FillPie(Brushes.White, pt.X, pt.Y, width, width, 270, 180)
       g.FillEllipse(Brushes.Black, CSng(pt.X + (width * 0.25)), CSng(pt.Y), CSng(width * 0.5), CSng(width * 0.5))
       g.FillEllipse(Brushes.White, CSng(pt.X + (width * 0.25)), CSng(pt.Y + (width * 0.5)), CSng(width * 0.5), CSng(width * 0.5))
       g.FillEllipse(Brushes.White, CSng(pt.X + (width * 0.4375)), CSng(pt.Y + (width * 0.1875)), CSng(width * 0.125), CSng(width * 0.125))
       g.FillEllipse(Brushes.Black, CSng(pt.X + (width * 0.4375)), CSng(pt.Y + (width * 0.6875)), CSng(width * 0.125), CSng(width * 0.125))
       If hasOutline Then g.DrawEllipse(Pens.Black, pt.X, pt.Y, width, width)
   End Sub

End Class </lang>