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
-
Fun with multi-dimension arrays
by Dave Whipp