class Circle def initialize(radius) @radius = radius end def draw unless @canvas diameter = 2 * @radius @canvas = Array.new(diameter + 1){ ' ' * (2 * (diameter + 1)) } key_points.each do |kx, ky| [kx, diameter - kx].product([ky, diameter - ky]).each do |x, y| @canvas[x][2 * y] = @canvas[y][2 * x] = '*' end end end puts @canvas.join "\n" end private def key_points q = (1 - 0.5 * (2 ** 0.5)) * @radius # (1 - cos45) * radius [*q.floor..@radius].product([*0..q.ceil]).select{|x, y| lies_on_circle? x, y } end # Detects if point is closest to the circle edge by checking the devitaion of points above and below def lies_on_circle?(x, y) cx, cy = @radius, @radius # central point dx2, r2 = (x - cx) ** 2, @radius ** 2 [y - 1, y, y + 1].min_by {|y| (dx2 + (y - cy) ** 2 - r2) ** 2 } == y end end Circle.new(ARGV[0].to_i).draw # ruby circle.rb 7 # * * * * * # * * * * # * * # * * # * * # * * # * * # * * # * * # * * # * * # * * # * * # * * * * # * * * * *