Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Copying two-dimensional arrays

by Not_a_Number (Prior)
on May 17, 2003 at 20:14 UTC ( [id://258900]=perlquestion: print w/replies, xml ) Need Help??

Not_a_Number has asked for the wisdom of the Perl Monks concerning the following question:

Hello, all. This is my first post, please don’t judge me too severely if I mess up :-) Here we go:

I have found out, after much headbanging and looking for errors in the wrong parts of my code, that:
@y = @x;
works differently for one- and two-dimensional arrays, presumably because the latter are arrays of references and, well, er...

The difference is that changing an element in @x will not affect @y if both are 1D arrays, while for 2D arrays, doing something like:
$x[0][2] = ‘foo’
changes both arrays, as illustrated by:
my @x; push @x, [ 0 .. 3 ] for 0 .. 3; # creates a basic 2D array my @y = @x; $x[0][2] = 'foo'; print $y[0][2];
which outputs “foo”.


This is where my code breaks:
use strict; use warnings; my @word = qw ( F O O B A R ); my $letter = 'X'; # no prob with FOOBAR if $letter = ‘A’ # Two dimensional: doesn't work my @matrix2D; push @matrix2D, [ split '', '.......' ] for 0 .. 2; $matrix2D[0][4] = $letter; my @temp_matrix2D = @matrix2D; for my $i ( 0 .. $#word ) { unless ( $temp_matrix2D[0][$i] =~ /[.$word[$i]]/ ) { print 'Error!: '; @temp_matrix2D = @matrix2D; last; } $temp_matrix2S[0][$i] = $word[$i]; } @matrix2D = @temp_matrix2D; print "@{$matrix2D[0]}\n"; # prints “Error: F O O B X . .’, which I don’t want # One dimensional: works, but no good to me... my @matrix = split '', '.......'; $matrix[4] = $letter; my @temp_matrix = @matrix; for my $i ( 0 .. $#word ) { unless ( $temp_matrix[$i] =~ /[.$word[$i]]/ ) { print 'Error!: '; @temp_matrix = @matrix; last; } $temp_matrix[$i] = $word[$i]; } @matrix = @temp_matrix; print "@matrix\n"; # prints “Error!: . . . . X . .’, which is what I want


As might|mightn’t be obvious from the above, I am endeavouring to write a crossword/scrabble type programme. This extract simulates my attempt to check whether the user-entered word (simplified here to @word) fits in the existing (already partially filled) grid, given the user-entered coordinates (simplified here to [0,0,h] where ‘h’ is horizontal). If the word fits with the letters already in the matrix, no problem, let’s change the grid to include it and move on (this works, as illustrated by changing $letter to 'A'). If the word doesn’t fit, however, I need to: (a) print a warning (easy); (b) redo (or whatever) a loop that doesn’t concern us here in order to get new user input; (c) crucially, recuperate my matrix as it was previously. That is to say, based on the above snippet, I want the first ‘line’ of @matrix2 to be ‘. . . . X .’ and not ‘F O O B X .’.

So, on to my question (at last):
- Is there an obvious workaround for this? I’ve scoured perllol, perldsc, perlreftut, and (to the best of my limited capacities) perlref; have I missed something?
- Or should I pursue my current idea of looping over the same data twice (which seems a waste...), first to check validity and second to insert the new word?
- Or should I use some other type of data structure, which would seem unfortunate, since an AoA appeared to be ideal for my purposes?

Thank you, knowledgeable Monks, for your input.
Dave

Replies are listed 'Best First'.
Re: Copying two-dimensional arrays
by tall_man (Parson) on May 17, 2003 at 20:48 UTC
    The dclone method of Storable can be used for deep copies of array references:
    use Storable qw(dclone); my $y = dclone(\@x);
    Another option is FreezeThaw.
Re: Copying two-dimensional arrays
by broquaint (Abbot) on May 17, 2003 at 21:53 UTC
    And here's a 2D array copying solution using map
    use Data::Dumper; my @aoa = ( [ 1 .. 5 ], [ 6 .. 10 ] ); my @new = map [@$_], @aoa; $aoa[0] = [ qw/ one two three four five / ]; print "aoa - ", map(@$_, @aoa), $/; print "new - ", map(@$_, @new), $/; __output__ aoa - onetwothreefourfive678910 new - 12345678910

    HTH

    _________
    broquaint

•Re: Copying two-dimensional arrays
by merlyn (Sage) on May 17, 2003 at 22:55 UTC
Re: Copying two-dimensional arrays
by graff (Chancellor) on May 17, 2003 at 21:02 UTC
    Welcome to the Monastery! You have nice puzzle, where I think I would use a different approach. Basically, when a user comes up with a starting grid coordinate, and a word to insert (horizontally or vertically) at that point, all you want to do really is to determine the length of the user's proposed word, and do two things:
    • check that the word does not extend past the edge of the grid, and
    • extract just the list of current grid contents from the cells affected by the word, join those contents into a string, and -- given that empty cells are initialized with period characters -- see whether that string matches the proposed word.
    # Assume this is a subroutine, called with these args: my ($grid_size); # number of rows, columns (square grid, right?) my ($bgnX,$bgnY); # user's start coords; my ($new_word); # user's proposed word; my ($direction); # down or across my $newlen = length( $new_word ); if ( $direction eq 'down' ) { if ( $bgnY + $newlen > $grid_size ) { return "$new_word doesn't fit going down from $bgnY\n"; } my $ongrid = ""; for ($bgnY .. $grid_size-1) { $ongrid .= $board[$bgnX][$_]; } return "$new_word doen't match existing tiles\n" unless ( $new_word =~ /^$ongrid$/ ); } else { # left as an exercise... }
Re: Copying two-dimensional arrays
by Not_a_Number (Prior) on May 18, 2003 at 10:30 UTC
    I'm impressed. Three answers and a complete explanation of my problem while I slept.
    Thx to all.
    Dave

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://258900]
Approved by graff
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (7)
As of 2024-04-24 11:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found