Constrained random points on a circle: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 699: Line 699:
procedure main(A) # points, inside r, outside r in pixels - default to task values
procedure main(A) # points, inside r, outside r in pixels - default to task values


if \A[1] == "help" then stop("Usage: plot #points inside-radius outside-radius")
points := \A[1] | 100
points := \A[1] | 100
outside := \A[2] | 15
outside := \A[2] | 15
inside := \A[3] | 10
inside := \A[3] | 10
if inside > outside then inside :=: outside


wsize := integer(2.2*outside)
wsize := integer(2.2*outside)

Revision as of 03:33, 10 May 2011

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.

Generate 100 <x,y> coordinate pairs such that x and y are integers sampled from the uniform distribution with the condition that . Then display/plot them. The outcome should be a "fuzzy" circle. The actual number of points plotted may be less than 100, given that some pairs may be generated more than once.

There are several possible approaches to accomplish this. Here are two possible algorithms.

1) Generate random pairs of integers and filter out those that don't satisfy this condition:

.

2) Precalculate the set of all possible points (there are 404 of them) and select randomly from this set.

Ada

<lang Ada>with Ada.Text_IO; with Ada.Numerics.Discrete_Random; procedure Circle is

  -- extreme coordinate values are -15:0, 15:0, 0:-15, 0:15
  subtype Coordinate is Integer range -15 .. 15;
  type Point is record
     X, Y : Coordinate;
  end record;
  type Point_List is array (Positive range <>) of Point;
  function Acceptable (Position : Point) return Boolean is
     Squared_Sum : Natural := Position.X ** 2 + Position.Y ** 2;
  begin
     return 10 ** 2 <= Squared_Sum and Squared_Sum <= 15 ** 2;
  end Acceptable;
  -- first algorithm
  function Generate_Random_Points
    (Count : Positive := 100)
     return  Point_List
  is
     package RNG is new Ada.Numerics.Discrete_Random (Coordinate);
     Generator  : RNG.Generator;
     Next_Point : Point;
     Result     : Point_List (1 .. Count);
  begin
     RNG.Reset (Generator);
     for N in Result'Range loop
        loop
           Next_Point.X := RNG.Random (Generator);
           Next_Point.Y := RNG.Random (Generator);
           exit when Acceptable (Next_Point);
        end loop;
        Result (N) := Next_Point;
     end loop;
     return Result;
  end Generate_Random_Points;
  -- second algorithm
  function Choose_Precalculated
    (Count : Positive := 100)
     return  Point_List
  is
     subtype Possible_Points is Positive range 1 .. 404;
     package RNG is new Ada.Numerics.Discrete_Random (Possible_Points);
     Generator  : RNG.Generator;
     Point_Pool : Point_List (Possible_Points);
     Next_Point : Point;
     Next_Index : Possible_Points := 1;
     Result     : Point_List (1 .. Count);
  begin
     -- precalculate
     Precalculate : for X in Coordinate'Range loop
        Next_Point.X := X;
        for Y in Coordinate'Range loop
           Next_Point.Y := Y;
           if Acceptable (Next_Point) then
              Point_Pool (Next_Index) := Next_Point;
              exit Precalculate when Next_Index = Possible_Points'Last;
              Next_Index := Next_Index + 1;
           end if;
        end loop;
     end loop Precalculate;
     -- choose
     RNG.Reset (Generator);
     for N in Result'Range loop
        Result (N) := Point_Pool (RNG.Random (Generator));
     end loop;
     return Result;
  end Choose_Precalculated;
  procedure Print_Points (Points : Point_List) is
     Output_String : array (Coordinate, Coordinate) of Character :=
       (others => (others => ' '));
  begin
     for N in Points'Range loop
        Output_String (Points (N).X, Points (N).Y) := '*';
     end loop;
     for Line in Output_String'Range (2) loop
        for Column in Output_String'Range (1) loop
           Ada.Text_IO.Put (Output_String (Column, Line));
        end loop;
        Ada.Text_IO.New_Line;
     end loop;
  end Print_Points;
  My_Circle_Randomly      : Point_List := Generate_Random_Points;
  My_Circle_Precalculated : Point_List := Choose_Precalculated;

begin

  Ada.Text_IO.Put_Line ("Randomly generated:");
  Print_Points (My_Circle_Randomly);
  Ada.Text_IO.Put_Line ("Chosen from precalculated:");
  Print_Points (My_Circle_Precalculated);

end Circle;</lang>

Output:

Randomly generated:

              **
          *  *    * *
               * * *  **
     *     * *      *
    **  *              * *
   *     *           *  *
      *              *   * *
   *                   **
  *    *               *
    *
    *                       *
   *                      * *
  * *                        *
                             *

   * *                       *
  *
     *                       *
  ***                      *
     *                  *    *
                            *
   *                       *
                     **    *
         **
     *        *   **     *
         * *        * *
      ***  * *         **
        * *   * ***
               *  *

Chosen from precalculated:

            *
            *    *   *
           * **   ** ** *
           * *  * *
                      *
   *  ** *              *
    *    *               * *
  *    *                ***
  *  ***                 *
                        *  * *
                            *

  *                       * *
    *                      **

   *
 *  **                     ***
                           *
                         *   *
  * **
   *                     *
     *
    *   *
         **           *
    *  *     *  *       * *
       **  *       *  * *
      *   **
        *
           *    * ***

ALGOL 68

Translation of: C

- note: This specimen retains the original C coding style.

Works with: ALGOL 68 version Revision 1 - no extensions to language used - requires ansi/xterm & ascii
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny

<lang algol68>PROC clrscr = VOID:

       printf(($g"[2J"$,REPR 27)); # ansi.sys #

PROC gotoxy = (INT x,y)VOID:

       printf(($g"["g(0)";"g(0)"H"$,REPR 27, y,x)); # ansi.sys #

MODE POINT = STRUCT(

   INT x,y

);

INT radius = 15; INT inside radius = 10;

POINT center = (radius+1, radius+1);

FLEX[0]POINT set;

PROC swap with last set = (INT position,INT where last set)VOID: (

       INT temp := x OF set[position];
       x OF set[position]:=x OF set[where last set];
       x OF set[where last set] := temp;
       temp := y OF set[position];
       y OF set[position]:=y OF set[where last set];
       y OF set[where last set] := temp

);

PROC create set = VOID: (

       set := HEAP[(2*radius+1)**2]POINT;
       INT x,y,i:=LWB set;
       FOR x FROM -radius TO radius DO
               FOR y FROM -radius TO radius DO
                       IF sqrt(x*x+y*y)>=inside radius AND sqrt(x*x+y*y)<=radius THEN
                               x OF set[i] := x;
                               y OF set[i] := y;
                               i+:=1
                       FI
               OD
       OD;
       set:=set[:i-1]

);

PROC plot fuzzy set = (CHAR ch)VOID: (

       INT pos,i;
       TO UPB set DO
               pos := ENTIER(random * UPB set) + 1;
               gotoxy(x OF center + x OF set[pos],y OF center + y OF set[pos]);
               print(ch);
               swap with last set(pos,UPB set)
       OD

);

main: (

       # srand((INT)time(NIL)); #
       clrscr;
       create set;
       plot fuzzy set("*");
       gotoxy(2*radius+1, 2*radius+1);
       newline(stand in)

)</lang> Sample output:

           *  * **
        * * *  * ** **
      ***** **   ***** **
     ** **  *  * * * ***
      *  ******** *** *** *
   ** *****         ** * ***
        *            ***** *
   ** **               **** *
   * * *               ****
  ****                  * ****
 * **                    *** *
 ** **                    **
 **                      * * *
  ****                   **  *
 ** *                    ****
 ****                     ** *
 *  **                   *  **
  * **                    *  *
 * ***                    *  *
 ******                 * * **
  * * **               **** *
   ** *                ***  *
   **** **           *    **
    ** ***            * ***
    * *  *** * **  *** ***
      *  *  ** ***** ****
      ** ******* *  *
        * ** ** *******
          *  ****** *
               *

C

The general scheme is :

    • 1. All points satisfying the inequality are enumerated.
    • 2. 100 points are chosen at random from this set and plotted.
    • 3. To ensure that the same point is not picked twice and hence speed up the plotting, the chosen point is swapped with the last point after plotting. The new point is then chosen from the new set minus the last element. The position of this last element moves towards the head as the loop progresses.

<lang C>

  1. include<stdlib.h>
  2. include<stdio.h>
  3. include<conio.h>
  4. include<math.h>

typedef struct{ int x,y; }points;

points set[500]; int last;

void swapWithLast(int position,int whereLast) { int temp = set[position].x; set[position].x=set[whereLast].x; set[whereLast].x = temp;

temp = set[position].y; set[position].y=set[whereLast].y; set[whereLast].y = temp; }

void createSet() { int x,y,i=0;

for(x=-15;x<=15;x++) { for(y=-15;y<=15;y++) { if(sqrt(x*x+y*y)>=10.0 && sqrt(x*x+y*y)<=15.0) { set[i].x = x; set[i].y = y; i++; } } }

last = i; }

void plotFuzzySet(char ch) { int pos,i;

for(i=0;i<100;i++) { pos = rand()%last;

gotoxy(40 + set[pos].x,30 + set[pos].y);

printf("%c",ch);

swapWithLast(pos,last-1);

last--; } }

int main() { srand((unsigned int)time(NULL));

clrscr(); createSet(); plotFuzzySet('*');

getch(); return 0; } </lang>

Output will differ from system to system. A better rendering would be to use graphics libraries like OpenGL or Turbo BGI.



                                   *  *     *
                                   * **   *
                                    *  *** ** *
                               **  *        **   *
                               ** *    *   *    *
                               *   *         *   **
                            *    **                 *
                                *                  * *
                               **               * **
                             *
                            * *
                                                    **
                          *                        *
                                                    **
                         *   **                        *
                             *                        *
                             *                      *
                             **                   *
                              *                   *
                               *                   * *
                              *
                               **               *  *
                            * *                *  ***
                                *              * *
                                        **  *
                              *  *    **    * *
                                        * * *
                                  *  **
                                         * **

Clojure

<lang Clojure>(import '[java.awt Color Graphics Dimension] '[javax.swing JFrame JPanel])

(let [points (->> (for [x (range -15 16) y (range -15 16) :when (<= 10 (Math/sqrt (+ (* x x) (* y y))) 15)] [(+ x 15) (+ y 15)]) shuffle (take 100 ,))]

 (doto (JFrame.)
   (.add (doto (proxy [JPanel] []

(paint [^Graphics g] (doseq [[x y] points] (.fillRect g (* 10 x) (* 10 y) 10 10)))) (.setPreferredSize (Dimension. 310 310))))

   (.setResizable false)
   (.setDefaultCloseOperation JFrame/DISPOSE_ON_CLOSE)
   .pack
   .show))</lang>

D

<lang d>import std.stdio, std.random, std.math;

void main() {

   char[31][31] table = ' ';
   foreach (i; 0 .. 100) {
       int x, y;
       do {
           x = uniform(-15, 16);
           y = uniform(-15, 16);
       } while(abs(12.5 - abs(x + y * 1i)) > 2.5);
       table[x + 15][y + 15] = '*';
   }
   foreach (row; table)
       writeln(row);

}</lang>

                               
                   *           
          * **  *              
                  * *          
     **  * *   **  *  *        
    *    *            **  *    
        **            **  *    
                       *   *   
                        *      
       *                 ***   
 *  * *                        
   * *                     *   
   *                        *  
     *                      *  
   **                    * *   
  *                       *    
                            *  
                             * 
  *                          * 
                               
   *                           
     *                     **  
    * *                  *     
         *           * *  *    
   *     *             **      
    *     *  *  *     * *      
     **     *  **   **   *     
          **                   
        *     *  *  *          
               **              

F#

This version uses method 1 from the task description and just calculates 100 suitable points to plot. The INTERACTIVE bit just permits this code in a .fsx file to be run with the interactive interpreter or compiled to an exe. <lang fsharp>module CirclePoints =

   let main args =
       let rnd = new System.Random()
       let rand size = rnd.Next(size) - size/2
       let size = 30
       let gen n =
           let rec f (x,y) =
               let t = (int (sqrt (float (x*x + y*y)) ))
               if 10 <= t && t <= 15 then (x,y) else f (rand size, rand size)
           f (rand size, rand size)
       let plot = Array.init 100 (fun n -> gen n)
       for row in 0 .. size-1 do
           let chars = Array.create (size+1) ' '
           Array.choose (fun (x,y) -> if y = (row-size/2) then Some(x) else None) plot
           |> Array.iter (fun x -> chars.[x+size/2] <- 'o')
           printfn "%s" (new string(chars))
       0
   
  1. if INTERACTIVE

CirclePoints.main fsi.CommandLineArgs

  1. else

[<EntryPoint>] let main args = CirclePoints.main args

  1. endif</lang>

An example of the output:

          o  o oo
              o       o

         o o        o o
    o   o o oo o o       o o
   o                      o
     o  oo             oooo
     o                  oo
                       o  o
   oo                      o
  oooo                   o  o
 o                         o
    o
  o
  o                       oo
 o                          o
   o
     o
                         o
      o
   oo                    oo  o
                           o
   o  o  o                o
    o                   o o
    o         o  o  oo
       oo         o oo    o
     o   o      o  o
      o o      o oo   o
              o   o

Fortran

Works with: Fortran version 90 and later

<lang fortran>program Constrained_Points

 implicit none

 integer, parameter :: samples = 100
 integer :: i, j, n, randpoint
 real :: r

 type points
   integer :: x, y
 end type
 type(points) :: set(500), temp

! Create set of valid points

 n = 0
 do i = -15, 15
   do j = -15, 15
     if(sqrt(real(i*i + j*j)) >= 10.0 .and. sqrt(real(i*i + j*j)) <= 15.0) then
       n = n + 1
       set(n)%x = i
       set(n)%y = j
     end if
   end do
 end do

! create 100 random points ! Choose a random number between 1 and n inclusive and swap point at this index with point at index 1 ! Choose a random number between 2 and n inclusive and swap point at this index with point at index 2 ! Continue in this fashion until 100 points have been selected

 call random_seed
 do i = 1, samples
   call random_number(r)
   randpoint = r * (n + 1 - i) + i
   temp = set(i)
   set(i) = set(randpoint)
   set(randpoint) = temp
 end do

! In order to facilitate printing sort random points into ascending order ! sort x in ascending order

 do i = 2, samples
    j = i - 1
    temp = set(i)
       do while (j>=1 .and. set(j)%x > temp%x)
          set(j+1) = set(j)
          j = j - 1
       end do
    set(j+1) = temp
 end do

! sort y in ascending order for same x

 do i = 2, samples
    j = i - 1
    temp = set(i)
       do while (j>=1 .and. set(j)%x == temp%x .and. set(j)%y > temp%y)
          set(j+1) = set(j)
          j = j - 1
       end do
    set(j+1) = temp
 end do
 

! print circle

 write(*,"(a,a)", advance="no") repeat(" ", set(1)%y+15), "*"
 do i = 2, samples
   if(set(i)%x == set(i-1)%x) then
     write(*,"(a,a)", advance="no") repeat(" ", set(i)%y - set(i-1)%y-1), "*"
   else
     n = set(i)%x - set(i-1)%x
     do j = 1, n
       write(*,*)
     end do
     write(*,"(a,a)", advance="no") repeat(" ", set(i)%y+15), "*"
   end if
 end do

end program</lang> Output

                  * * 
        *   *         * 
      ** **    * **    * 
                ** 
     *  **   * **    * 
   ***   **               * 
    *    *           * 
                           * 
  *                      *  * 
     **                   * 
   *                      * 
  *  *                   * 
    *                        * 
    * 
    **                   ***  * 
    *                    * 
    **                   * 
    *                    * 
   *                      * 
  *   *                      * 
      **                 *  * 
    * *                *  ** 
   ** * *               * 
     * 
          ***         * * * 
     **         *   *    * 
         *  * * * 
         *     *  ** * 
            *

Haskell

Using Knuth Shuffle <lang haskell>import Data.List import Control.Monad import Control.Arrow import Rosetta.Knuthshuffle

task = do

 let blanco = replicate (31*31) "  "
     cs = sequence [[-15,-14..15],[-15,-14..15]] :: Int
     constraint = uncurry(&&).((<= 15*15) &&& (10*10 <=)). sum. map (join (*))

-- select and randomize all circle points

 pts <- knuthShuffle $ filter constraint cs

-- 'paint' first 100 randomized circle points on canvas

 let canvas = foldl (\cs [x,y] -> replaceAt (31*(x+15)+y+15) "/ " cs ) blanco (take 100 pts)

-- show canvas

 mapM_ (putStrLn.concat). takeWhile(not.null). map (take 31) $ iterate (drop 31) canvas</lang>

Output (added a trailing space per 'pixel'

*Main> task
                                                              
                      /             / /                       
                          /     /       /                                       
              /                 /                                               
          /     /               /       / / /   /                               
            /                 / /       /                                       
      /     /     /                       /   /                                 
      /         /                           /                                   
        /   / /                                     /   /                       
        / / /                                 /       / /                       
                                                    /                           
    /     /                                       /                             
      / /                                             /                         
      /                                               /   /                     
        /                                                                       
/ /                                                   /     / 
                                                      /   /                     
                                                      /   /                     
      /                                                                         
      /                                             /                           
  /                                                   /       
                                                /     /                         
    /     /                                       /           
              / /                         / /         /       
        /   /       /                             /           
                          / /     / / /   / /                 
          / /             /                   /               
                            / /                               
                /   /   / / /   /       / /                   
                      /             / /

Icon and Unicon

Generate random points in the bounded by the outside edge. Reject any found out of the prescribed bounds and stop when the required numbers of points have been generated. <lang Icon>link graphics

procedure main(A) # points, inside r, outside r in pixels - default to task values

if \A[1] == "help" then stop("Usage: plot #points inside-radius outside-radius") points  := \A[1] | 100 outside := \A[2] | 15 inside  := \A[3] | 10 if inside > outside then inside :=: outside

wsize  := integer(2.2*outside) wsize <:= 150 center  := wsize/2

WOpen("size="||wsize||","||wsize,"bg=black","fg=white") | stop("Unable to open window")

until(points -:= 1) <= 0 do {

  x := ?(2*outside)-outside   # random x
  y := ?(2*outside)-outside   # and y
  if (inside <= integer(sqrt(x^2+y^2)) ) <= outside then 
     DrawPoint(x + center,y + center)
  }

WDone()

end</lang>

J

This version deals 100 distinct coordinates from the set of acceptable coordinates (much like dealing cards from a shuffled deck):

<lang j>gen=: ({~ 100?#)bind((#~ 1=99 225 I.+/"1@:*:),/,"0/~i:15)</lang>

Example use (gen'' generates the points, the rest of the example code deals with rendering them as a text array): <lang j> '*' (<"1]15+gen )} 31 31$' '

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

Liberty BASIC

<lang lb>' RC Constrained Random Points on a Circle

nomainwin

WindowWidth =400 WindowHeight =430

open "Constrained Random Points on a Circle" for graphics_nsb as #w

  1. w "trapclose [quit]"
  2. w "down ; size 7 ; color red ; fill black"

for i =1 to 1000

 do
    x =int( 30 *rnd( 1)) -15
    y =int( 30 *rnd( 1)) -15
 loop until IsInRange( x, y) =1
 #w "set "; 200 +10 *x; " "; 200 - 10 *y

next

wait

function IsInRange( x, y)

 z =sqr( x*x +y*y)
 if 10 <=z and z <=15 then IsInRange =1 else IsInRange =0

end function

[quit] close #w end</lang>

Locomotive Basic

<lang locobasic>10 MODE 1:RANDOMIZE TIME 20 FOR J=1 TO 100 30 X=INT(RND*30-15) 40 Y=INT(RND*30-15) 50 D=X*X+Y*Y 60 IF D<100 OR D>225 THEN GOTO 40 70 PLOT 320+10*X,200+10*Y:LOCATE 1,1:PRINT J 80 NEXT 90 CALL &BB06</lang>

MATLAB

Uses the Monte-Carlo method described above.

<lang MATLAB>function [xCoordinates,yCoordinates] = randomDisc(numPoints)

   xCoordinates = [];
   yCoordinates = [];
   %Helper function that samples a random integer from the uniform
   %distribution between -15 and 15.
   function nums = randInt(n)
       nums = round((31*rand(n,1))-15.5);
   end
   n = numPoints;
   while n > 0
       
       x = randInt(n);
       y = randInt(n);
       norms = sqrt((x.^2) + (y.^2));
       inBounds = find((10 <= norms) & (norms <= 15));
       
       xCoordinates = [xCoordinates; x(inBounds)];
       yCoordinates = [yCoordinates; y(inBounds)];
       
       n = numPoints - numel(xCoordinates);
   end
   
   xCoordinates(numPoints+1:end) = [];
   yCoordinates(numPoints+1:end) = [];
   

end</lang>

Output: <lang MATLAB>>> [x,y] = randomDisc(100); >> plot(x,y,'.')</lang>


OCaml

<lang ocaml>let p x y =

 let d = sqrt(x ** 2.0 +. y ** 2.0) in
 10.0 <= d && d <= 15.0

let () =

 Random.self_init();
 let rec aux i acc =
   if i >= 100 then acc else
     let x = (Random.float 40.0) -. 20.0
     and y = (Random.float 40.0) -. 20.0 in
     if (p x y)
     then aux (succ i) ((x,y)::acc)
     else aux i acc
 in
 let points = aux 0 [] in
 let g = Array.init 40 (fun _ -> String.make 40 ' ') in
 List.iter (fun (x,y) ->
   let x = (int_of_float x) + 20
   and y = (int_of_float y) + 20 in
   g.(y).[x] <- 'o'
 ) points;
 Array.iter print_endline g</lang>


                o   o     o
                o
           oo      oo     oooo
               o      o   oo o
        oo
          o                o   o
         o
      oo  o
       oo o                 oo  o
                              oo
                              oo
         o                     o
      oooo                     o o
        oo                  o o
        o                    oo
                                 o
      o  o                  o  o
        o  o                 o o
       o  o
          o                   o
        o    o              oo
            o             oo
         o            o
             ooo o o       o
             o  ooo     o
              o
                 oo  o

PARI/GP

<lang>crpc()={

 my(v=vector(404),t=0,i=0,vx=vy=vector(100));
 for(x=1,14,for(y=1,14,
   t=x^2+y^2;
   if(t>99&t<226,
     v[i++]=[x,y];
     v[i++]=[x,-y];
     v[i++]=[-x,y];
     v[i++]=[-x,-y]
   )
 ));
 for(x=10,15,
   v[i++]=[x,0];
   v[i++]=[-x,0];
   v[i++]=[0,x];
   v[i++]=[0,-x]
 );
 for(i=1,#vx,
   t=v[random(#v)+1];
   vx[i]=t[1];
   vy[i]=t[2];
 );
 plothraw(vx,vy)

};</lang>

Perl 6

<lang perl6>my @range = -15..16;

my @points = gather for @range X @range -> $x, $y {

   take [$x,$y] if 10 <= sqrt($x*$x+$y*$y) <= 15

} my @samples = @points.roll(100); # or .pick(100) to get distinct points

  1. format and print

my %matrix; for @range X @range -> $x, $y { %matrix{$y}{$x} = ' ' } %matrix{$_[1]}{$_[0]} = '*' for @samples; %matrix{$_}{@range}.join(' ').say for @range;</lang>

Turning that program completely inside-out and reducing to a single statement with a single non-parameter variable, we get this version, which also works:

<lang perl6>(say ~.map: { $_ // ' ' } for my @matrix) given do

   -> [$x, $y] { @matrix[$x][$y] = '*' } for pick 100, do
       for ^32 X ^32 -> $x, $y {
           [$x,$y] when 100..225 given [+] ($x,$y X- 15) X** 2;
       }

</lang>

This uses, among other things, a 0-based matrix rather than a hash, a given on the first line that allows us to print the final value of the matrix straight from its initial declaration, a for statement feeding a for statement modifier, a lambda that unpacks a single x-y argument into two variables, the functional form of pick rather than the method form, a quasi-list comprehension in the middle loop that filters each given with a when, precalculated squared limits so we don't have to take the square root, use of X- and X** to subtract and exponentiate both $x and $y in parallel.

After the given do has loaded up @matrix with our circle, the map on the first line substitutes a space for any undefined matrix element, and the extra space between elements is supplied by the stringification of the list value, performed by the prefix ~ operator, the unary equivalent of concatenation in Perl 6.

At this point you would be justified in concluding that we are completely mad. :-)

PicoLisp

<lang PicoLisp>(let Area (make (do 31 (link (need 31 " "))))

  (use (X Y)
     (do 100
        (until
           (>=
              15
              (sqrt
                 (+
                    (* (setq X (rand -15 15)) X)
                    (* (setq Y (rand -15 15)) Y) ) )
              10 ) )
        (set (nth Area (+ 16 X) (+ 16 Y)) "#") ) )
  (mapc prinl Area) )</lang>

Output:

           #
        ##
           #  #  #  #
         ## #    #  #   #
       #      #   # # #
    #       #     # #   #
      #   #         #    #
      #                #   #
                       #
       #               #
     ##                      #
                          #
   #                      # #
  ###                      #
 #                         # #
##                          # #
  #                        #
 #                        #
 ## #
                           #
   #
     #                 #
     #
   ###                  #   #
      ###           # #    #
    #      #
         #  #   ##
                 # #
      #     #           #
                # #  #

Prolog

Works with SWI-Prolog <lang Prolog>:- use_module(library(clpfd)).

circle :- bagof([X,Y], init(X,Y), BL), length(BL, N), length(L, 100), maplist(choose(BL, N), L), draw_circle(L).


% point selection choose(BL, N, V) :- I is random(N), nth0(I, BL, V).

% to find all couples of numbers verifying % 100 <= x^2 + y^2 <= 225 init(X1, Y1) :- X in -15..15, Y in -15..15, X*X + Y*Y #>= 100, X*X + Y*Y #=< 225, label([X,Y]), X1 is 10 * X + 200, Y1 is 10 * Y + 200.


draw_circle(L) :- new(D, window('Circle')), send(D, size,size(400,400)), forall(member([X,Y], L), ( new(C, circle(4)), send(C, fill_pattern, colour(@default, 0, 0, 0)), send(C, center(point(X,Y))), send(D, display, C))), send(D, open). </lang>

PureBasic

<lang PureBasic>CreateImage(0,31,31) StartDrawing(ImageOutput(0))

 For i=1 To 100
   Repeat
     x=Random(30)-15
     y=Random(30)-15
     R.f=Sqr(x*x+y*y)
   Until 10<=R And R<=15
   Plot(x+15,y+15,#Red)
 Next

StopDrawing()

Title$="PureBasic Plot" Flags=#PB_Window_SystemMenu OpenWindow(0,#PB_Ignore,#PB_Ignore,ImageWidth(0),ImageHeight(0),Title$,Flags) ImageGadget(0,0,0,ImageWidth(0),ImageHeight(0),ImageID(0)) Repeat: Until WaitWindowEvent()=#PB_Event_CloseWindow</lang>

Python

Note that the diagram shows the number of points at any given position (up to a maximum of 9 points). <lang python>>>> from collections import defaultdict >>> from random import choice >>> world = defaultdict(int) >>> possiblepoints = [(x,y) for x in range(-15,16) for y in range(-15,16) if 10 <= abs(x+y*1j) <= 15] >>> for i in range(100): world[choice(possiblepoints)] += 1

>>> for x in range(-15,16): print(.join(str(min([9, world[(x,y)]])) if world[(x,y)] else ' ' for y in range(-15,16)))


            1     1           
         1 1                  
     11 1     1  1     1      
    111  1     1211           
     1   2    1 1    11       
     1  11         21         
    1   1            11  1    
  1  2                1 1     
                              
1  2                          
  1 1                      1  
  1 1                         
  2                      11   
 1                         1  
                        1     
                              
                              
 1                          1 
                        1     
                        2     
                           1  
    1                  1 1    
     1                2   1   
  1   3            11  2      
   11   1    1      1   2     
           1   1    2         
       1  1                   
        1      1     1        
         2 2   1              
              1               </lang>

If the number of samples is increased to 1100: <lang python>>>> for i in range(1000): world[choice(possiblepoints)] += 1

>>> for x in range(-15,16): print(.join(str(min([9, world[(x,y)]])) if world[(x,y)] else ' ' for y in range(-15,16)))


              2               
         41341421333          
       5133333131253 1        
     5231514 14214721 24      
    326 21222143234122322     
   54235153132123344125 22    
  32331432         2422 33    
  5453135           4144344   
 132595               323123  
 4 6353               432224  
5 4323                 3 5313 
23214                   41433 
42454                   33342 
332 4                   34314 
142 1                   35 53 

124211 53131

22221                   152 4 
22213                   34562 
654 4                   4 212 
24354                   52232 
544222                 283323 
 411123               453325  
 251321               124332  
  2124134           2443226   
  2 113315         64324334   
   2412452 324 32121132363    
     4222434324635 5433       
     3113333123432112633      
       2131181233  424        
         47414232164          
              4               </lang>

Ruby

<lang Ruby>points = (1...100).map {

   # choose a random radius and angle
   angle = rand * 2.0 * Math::PI
   rad   = rand * 5.0 + 10.0
   # convert back from polar to cartesian coordinates
   [rad * Math::cos(angle), rad * Math::sin(angle)].map(&:round)
 }

(-15..15).each do |row|

 puts((-15..15).map { |col| points.include?([row, col]) ? "X" : " " }.join)

end</lang>

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