Draw circle in console using python

I want to draw a circle in the console using characters instead of pixels, for this I need to know how many pixels are in each row. The diameter is given as input, you need to output a list with the width in pixels of each line of the picture

For example:

input: 7

output: [3, 5, 7, 7, 7, 5, 3]

enter image description here

input: 12

output: [4, 8, 10, 10, 12, 12, 12, 12, 10, 10, 8, 4]

enter image description here

How can this be implemented?


Solution 1:

This was a good reminder for me to be careful when mixing zero-based and one-based computations. In this case, I had to account for the for loops being zero-based, but the quotient of the diameter divided by 2 being one-based. Otherwise, the plots would have been over or under by 1.

By the way, while I matched your answer for 7, I didn't come up with the same exact plot for 12:

NOTE - Tested using Python 3.9.6

pixels_in_line = 0
pixels_per_line = []

diameter = int(input('Enter the diameter of the circle: '))

# You must account for the loops being zero-based, but the quotient of the diameter / 2 being
# one-based. If you use the exact radius, you will be short one column and one row.
offset_radius = (diameter / 2) - 0.5

for i in range(diameter):
    for j in range(diameter):
        x = i - offset_radius
        y = j - offset_radius
        if x * x + y * y <= offset_radius * offset_radius + 1:
            print('*', end='  ')
            pixels_in_line += 1
        else:
            print(' ', end='  ')
    pixels_per_line.append(pixels_in_line)
    pixels_in_line = 0
    print()

print('The pixels per line are {0}.'.format(pixels_per_line))

Output for 7:

Enter the diameter of the circle: 7
      *  *  *        
   *  *  *  *  *     
*  *  *  *  *  *  *  
*  *  *  *  *  *  *  
*  *  *  *  *  *  *  
   *  *  *  *  *     
      *  *  *        
The pixels per line are [3, 5, 7, 7, 7, 5, 3].

Output for 12:

Enter the diameter of the circle: 12
               *  *                 
         *  *  *  *  *  *           
      *  *  *  *  *  *  *  *        
   *  *  *  *  *  *  *  *  *  *     
   *  *  *  *  *  *  *  *  *  *     
*  *  *  *  *  *  *  *  *  *  *  *  
*  *  *  *  *  *  *  *  *  *  *  *  
   *  *  *  *  *  *  *  *  *  *     
   *  *  *  *  *  *  *  *  *  *     
      *  *  *  *  *  *  *  *        
         *  *  *  *  *  *           
               *  *                 
The pixels per line are [2, 6, 8, 10, 10, 12, 12, 10, 10, 8, 6, 2].

Solution 2:

Based on Rob's solution (all credits to Rob!) I've managed to tweak the code for 12x12 pixel grid as well:

diameter = 12

radius = diameter / 2 - .5
r = (radius + .25)**2 + 1

result = ''

for i in range(diameter):
    y = (i - radius)**2
    for j in range(diameter):
        x = (j - radius)**2
        if x + y <= r:
            result = result + '*  '
        else:
            result = result + '   '
    result = result + '\n'

print(result)

result = result.split('\n')[:-1]
pixels_per_line = [x.count('*') for x in result]

print(f'The pixels per line are {pixels_per_line}.')

Output:

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

The pixels per line are [4, 8, 10, 10, 12, 12, 12, 12, 10, 10, 8, 4].

If you need the empty area inside the circle it can be done with minimal changes:

diameter = 7

radius = diameter / 2 - .5
r = (radius + .25)**2 + 1
r_min = (radius - 1)**2 + 1 # <-------- here

result = ''

for i in range(diameter):
    y = (i - radius)**2
    for j in range(diameter):
        x = (j - radius)**2
        if r_min <= x + y <= r: # <----- here
            result = result + '*  '
        else:
            result = result + '   '
    result = result + '\n'

print(result)

Output:

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