Constrained random points on a circle

From Rosetta Code
Revision as of 10:56, 3 September 2010 by rosettacode>Dkf (Use the power of math, remove assumption about exactly how points are generated (saying 100 random ones is enough))
Task
Constrained random points on a circle
You are encouraged to solve this task according to the task description, using any language you may know.

The task is to generate 100 uniformly distributed random points (x,y integer pairs) that lie in a circular disc at 10 to 15 units from its center; and then display/plot them to show a fuzzy circle.

There are several possible approaches, depending on your language. One is simply to generate random pairs of integers and filter out those that don't satisfy the equation

Another is to precalculate the set of all possible points (there are 404 of them) and select from this set. Yet another is to use real-valued polar coordinates then snap to integer Cartesian coordinates. I'm sure there are others.

SystemVerilog

<lang SystemVerilog>program main;

 bit [39:0] bitmap [40];
 class Point;
   rand bit signed [4:0] x;
   rand bit signed [4:0] y;
   constraint on_circle_edge {
     (10*10) <= (x*x + y*y);
     (x*x + y*y) <= (15*15);
   };
   function void do_point();
     randomize;
     bitmap[x+20][y+20] = 1;
   endfunction
 endclass
 initial begin
   Point p = new;
   repeat (100) p.do_point;
   foreach (bitmap[row]) $display( "%b", bitmap[row]);
 end

endprogram</lang>

Piping the output through sed to improve the contrast of the output:

% vcs -sverilog -R circle.sv | sed 's/0/ /g'
                                        
                   1                    
                11 1  1                 
            1 1  1    11                
          1     1   1   11              
            1           1  1            
             1      1      1            
            1                           
       1   1                  1         
      1    1               1            
                             1          
       11                               
                                11      
         1                              
     11  1                     1 1      
         1                   1          
    1   1                    1   1      
     1                        1  1      
     11 1                       1       
                             11         
     1111                        1      
      1 111                  1          
       11 1                111  1       
       11                               
                          1  1          
            1            1   1          
                   1                    
             1  11                      
                          1             
                   1    1               
               11  1 1                  
                                        

Tcl

<lang tcl>package require Tcl 8.5

  1. Generate random point at specified distance from the centre

proc getPoint {range from to} {

   set r2 [expr {$range / 2}]
   set f2 [expr {$from ** 2}]
   set t2 [expr {$to ** 2}]
   while 1 {

set x [expr {int($range * rand())}] set y [expr {int($range * rand())}] set d2 [expr {($x-$r2)**2 + ($y-$r2)**2}] if {$d2 >= $f2 && $d2 <= $t2} { return [list $y $x] }

   }

}

  1. Make somewhere to store the counters

set ary [lrepeat 31 [lrepeat 31 0]]

  1. Generate 100 random points

for {set i 0} {$i < 100} {incr i} {

   set location [getPoint 31 10 15]
   # Increment the counter for the point
   lset ary $location [expr {1 + [lindex $ary $location]}]

}

  1. Simple renderer

foreach line $ary {

   foreach c $line {

puts -nonewline [expr {$c == 0 ? " " : $c > 9 ? "X" : $c}]

   }
   puts ""

}</lang> Example output:

               1               
           1  1                
                               
         1 1 1   2   1 1       
        11   1        1  1     
       11 1            1  1    
   1     1                     
   1    12               1     
     1 1               1       
  1 1                    1     
      1                    1   
   1                       1 1 
                          1  2 
                           1   
 1                         1   
 2   1                    2    
  2                         1  
                             1 
    1                    11    
     1                   1     
      1                        
  1                       1    
     2                 1    1  
   1                     1     
   1 1   1          11     1   
     2  1  1        11         
        11      1      1 1     
      1 2   1       11         
         121   1  1            
           1  1   1            
               1