Yin and yang

From Rosetta Code
Yin and yang is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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

This example is incorrect. Please fix the code and remove this message.

Details: The output does not sufficiently resemble a Yin-yang symbol.

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

enum { Void = 0, Yan = 1, Yin = 2, I = 3} ; enum Tiles = [" ","·","#","?"] ;

alias int delegate(int) Draw ;

struct Board { // a square board

   immutable int scale ;
   immutable int size ;
   int[][] pix ;
   this(int s) {
       scale = s ;
       size = s*12 ;
       pix = new int[][](size + 1,size + 1) ;
   }
   alias pix this ;

   static string str(int v) { return Tiles[(v % 4)] ; }

   string toString() {
       string[] s ;
       foreach( r ; pix)
           s ~= reduce!"a~b"(map!str(r)) ;
       return s.join("\n") ;
   }

   void drawCircle(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) ;
           }
   }

   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) {

   writeln(Board(2).yanYin) ;
   writeln(Board(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
 ccords=. ({:radii) +each circles #&(,/)each squares
 M=. ' *.' {~  circles (*  1 + 0 >: {:"1)&(_1&{::) squares
 offset=. 3*y,0
 M=. '*' ((_2 {:: ccords) <@:+"1 offset)} M
 M=. '.' ((_2 {:: ccords) <@:-"1 offset)} M
 M=. '.' ((_3 {:: ccords) <@:+"1 offset)} M
 M=. '*' ((_3 {:: ccords) <@:-"1 offset)} M

)</lang>

Example use:

<lang> yinyang 1

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

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

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

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

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

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