http://qs321.pair.com?node_id=1231457


in reply to circular area in a coordinates grid (AoA)

Try this (some slight changes to see a better circle)

#!/usr/bin/perl use strict; use warnings; use List::Util qw( max min ); my $max = 40; my @aoa = map { [ ( 'o' ) x ($max + 1) ] } 0..$max ; display( @aoa ); # @to_change will contain [y1,x1],[y2,x2]... #my @to_change = illuminate( 5, 4, 6 ); my @to_change = illuminate( $max >> 1, $max >> 1, $max - 2 >> 1 ); print "\n"; $aoa[$_->[0]][$_->[1]] = 'x' for @to_change; display( @aoa ); sub illuminate { my @to_change; my $center_r = shift; my $center_c = shift; my $radius = shift; #... for my $row ( 0 .. $#aoa ) { my $delta_x = eval { int sqrt $radius ** 2 - ($center_r - $row) ** + 2 }; if( defined $delta_x ) { my $low = max 0, $center_c - $delta_x; my $high = min $#{ $aoa[$row] }, $center_c + $delta_x; push @to_change, map [ $row, $_ ], $low .. $high; } } return @to_change; } sub display { foreach my $row ( @_ ) { foreach my $col ( @$row ) { print $col; } print "\n" } }

Replies are listed 'Best First'.
Re^2: circular area in a coordinates grid (AoA) -- updated
by Discipulus (Canon) on Mar 19, 2019 at 22:44 UTC
    Fantastic!

    I suppose i can optimize it using for my $row ( $center_r - $radius .. $center_r + $radius ) instead of processing the whole AoA

    I never seen >> before: seems a int( $_ / 2) operator.. thanks for this too!

    L*

    update

    I adapted to return a hash instead. I feel happy with it. Thanks again

    #!/usr/bin/perl use strict; use warnings; use List::Util qw( max min ); my $max = 19; #from OP my @aoa = map { [ ( 'o' ) x ($max + 1) ] } 0..$max; #from OP my %illu = illuminate( 0,0,12 ); display(@aoa); %illu = illuminate( 0,10,4 ); display(@aoa); %illu = illuminate( 10,10,6 ); display(@aoa); %illu = illuminate( 10,0,5.5 ); display(@aoa); sub illuminate{ my $center_r = shift; my $center_c = shift; my $radius = shift; my %ret; foreach my $row ( $center_r - $radius .. $center_r + $radius ){ my $delta_x = $radius ** 2 - ($center_r - $row) ** 2; if( $delta_x >= 0 ){ $delta_x = int sqrt $delta_x; my $low = max 0, $center_c - $delta_x; my $high = min $#{ $aoa[$row] }, $center_c + $delta_x; map { $ret{ $row.'_'.$_ }++ } $low .. $high; } } return %ret; } sub display{ print "\n"; foreach my $row ( 0..$#aoa ){ foreach my $col ( 0..$#{$aoa[$row]} ){ print $illu{$row.'_'.$col} ? ' ' : $aoa[$row][$col] ; + } print "\n" } }

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re^2: circular area in a coordinates grid (AoA)
by bliako (Monsignor) on Mar 19, 2019 at 23:34 UTC

    Cool! But that eval poked my eye.

    The following can potentially save on some sqrt's too:

    my $delta_x = $radius ** 2 - ($center_r - $row) ** 2; if( $delta_x >= 0 ){ $delta_x = int sqrt $delta_x; ...

    bw, bliako

      you can also get rid of both squares

      x² = r²-y²

      now increment y2=y+1

      x2² = r²-(y+1)²

      x2² = r²-y² - 2y - 1

      x2² = x² - 2y -1

      I'm too tired to get rid of the sqrt too now :)

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      Just having some fun :)

      Nothing wrong with having a little fun in a "proof-of-concept" example, is there?
      It's not like it's production code :)

        sorry maybe my comment sounded a bit aggresive (but it wasn't meant to be).