develooper Front page | perl.perl6.language | Postings from April 2003

Fun with multi-dimension arrays

Thread Next
From:
Dave Whipp
Date:
April 26, 2003 17:49
Subject:
Fun with multi-dimension arrays
Message ID:
20030427004929.88458.qmail@onion.perl.org
I was having fun with a game of life over on perl monks (node_id=253366) 
-- writing "real" Perl6 code -- and I realised there were a few things 
that I wanted arrays/loops to do, that I'm not entirely sure that they can.

Lets start with something simple:

   for @x.kv -> $k,$v { print "$k = $v\n" }

That works fine. But can I do

   for @x -> $v { print "$v.key = $v\n" }

I.e. does a loop variable maintain a connection to its iterator. C<Fo> 
being a builtin, the compiler could easily do that behind the scenes. 
For namespace reasons, we might require an explicit trait:

   for @x -> $v is keyed { print "$v.key = $v\n" }

Presumably a keyed value could also have .prev and .next methods. 
Perhaps C<keyed> is spelt C<iterator>.

Thats the 1-d case. Now what about 2-d arrays:

   for *@AofA -> $cell is keyed
   {
      my ($x, $y) = $cell.key;
      print "cell value at ($x,$y) is $cell\n";
   }

The issue here is whether the lasily flattened array remembers its 
original index, rather than its flattenned one.

If we've got this far, what about 3-d arrays. Is It possible to iterate 
a 3-d grid without using nested loops?



The next thing that I wanted to do was to get all the sum of the 
neighboring points around a cell (remember, this was Game Of Life).

Going back to 2-d a moment:

First the offsets:

   my $offsets_2d = [ -1|0|1, -1|0|1 ] & none([0,0]);

Will this work. Will the junction reach outward to make a junction of 
array-refs?

For the multi-d (dimension $N) case, would this work?

   my $offsets_1d = -1|0|1;

   my $offsets = [ ($offsets_1d) x $N ] & none( [ (0) x $N ] );


OK, having got this far, lets apply out offsets to get coords:

   my @neighbors = ( $offsets_2d >>+<< [$x,$y] ).states;

I think Ive got this right: both sides of the hyper-plus will 
dereference their arrays, and elements will be summed. Because the lhs 
is a junction, the result of the hyper operator will be a junction of 
corrdinates. I then .states that junction to get the neighborhood: an 
array of points



OK, so thats the junctions. What about access? Given @cell[$x][$y][$z], 
how do I pass around an index to a cell?

   $point = [10, 3, 9];
   print @cell[$point]; # is this an array slice, or a single point?

Having to write

   @cell[$point[0]][$point[1]][$point[2]];

could get stale somewhat quick.


So lets assume it works. Hopefully I can now sum my neighborhood by doing:

   my $sum = @neighbors
                ==> map { @cells[$^coordinate }
                ==> sum;


Putting this all together, my code the the game-of-life update loop 
could be:

class Life
{
   has @.grid is array dim(20) of array dim(20) of bit is default(0);

   method update
   {
      my @new_grid is like @.grid;
      for *@new_grid -> $cell is rw is keyed
      {
        $cell = .next_state($cell.key)
      }
      @.grid = @new_grid;
   }

   method next_state(int @point) returns bit;
   {
     my $offsets is const = [ (-1|0|1) x 2 ] & none [0,0];
     my $sum = ( $offsets >>+<< @point ).states )
           ==> map { @.grid[$^coord] }
           ==> sum;

     @.grid[[@point]] ?? $sum == 2|3 :: $sum == 3;
   }
}

It would be really cool if all this could really work. But I'm pretty 
sure it falls flat on its face somewhere along the road.


Dave.


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About