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

Hi guys, I have a problem coming up with code to finding matching characters in a 2d array.
i.e.
[b][o][o][k] [r][e][b][o][o][t] [r][o][c][k][e][t]
would return the matching positions of similar characters
b=0,0
b=1,2
o=0,1
o=0,2
o=1,3
o=2,1
this is what I have so far, but I don't think I'm on the right track
#compare the (s)source patterns for ( my $i=0 ; $i<$row ; $i++ ) { #for each column in a row print "number of cols= $#{s1[$i]}\n"; if ($j=0;$j<$#{s1[$i]};$j++) { if (s1[i][j]==s1[i+1][j+1]){print "$i,$j\n"; } }
If anyone could suggest a better way to this, I'd be greatful.

Replies are listed 'Best First'.
Re: ideas needed for finding matching characters in 2d array
by ikegami (Patriarch) on Aug 27, 2008 at 05:11 UTC

    The naïve solution uses four nested loops, two (row+col) to find characters to match, then two (row+col) to find a pairing. That's rather expensive.

    A cheaper solution would track the location of each character.

    my @a = map { [ split // ] } qw( book reboot rocket ); my %locs; for my $i (0..$#a) { my $row = $a[$i]; for my $j (0..$#$row) { push @{ $locs{$a[$i][$j]} }, "$i,$j"; } } for my $c (sort keys %loc) { next if @{ $loc{$c} } <= 1; print("$c: ", join(' ', @{ $locs{$c} }), "\n"); }
Re: ideas needed for finding matching characters in 2d array
by GrandFather (Saint) on Aug 27, 2008 at 05:20 UTC

    Scan the data to find the coordinates for each character and save the results in a hash of arrays (one hash entry for each character encountered). Then run through the hash and generate the report:

    use strict; use warnings; my @words = qw(book reboot rocket); my @chars = map {[split '']} @words; my %matches; for my $row (0 .. $#chars) { for my $column (0 .. $#{$chars[$row]}) { push @{$matches{$chars[$row][$column]}}, [$row, $column]; } } for my $char (sort keys %matches) { next unless @{$matches{$char}} > 1; print "$char=", join (',', @$_), "\n" for @{$matches{$char}}; }

    Prints:

    b=0,0 b=1,2 e=1,1 e=2,4 k=0,3 k=2,3 o=0,1 o=0,2 o=1,3 o=1,4 o=2,1 r=1,0 r=2,0 t=1,5 t=2,5

    Perl reduces RSI - it saves typing
Just in case...
by juster (Friar) on Aug 27, 2008 at 05:50 UTC

    This isn't a solution but just so you know for future reference there was a logic error here:

    print "number of cols= $#{s1[$i]}\n"; if ($j=0;$j<$#{s1[$i]};$j++)

    $# will give you the index/subscript of the last element in the array whereas evaluating in scalar context will give you the number of elements in the array. Something like print scalar @list where the scalar function forces it to be evaluated as scalar.

    I just noticed it's an if, too!.

    # dont put @array in string or it prints the elements print "number of cols=".@{s1[$i]}."\n"; for(my $j=0;$j<scalar @{s1[$i]};$j++) # explicit scalar

    update: also forgot to put my in front of $j=0
Re: ideas needed for finding matching characters in 2d array
by Anonymous Monk on Aug 27, 2008 at 05:08 UTC
    Please post a complete code sample (include definition for your data structures).