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

Wassup Monks, heres an interesting (to some) problem i need help with...

I have a some code that splits a diagram into 2 arrays @leftCon & @rightCon. In their respective arrays, left and right connectors are contained.

e.g.
@leftCon = (left123, left456); @rightCon = (right123, right456, right789);

I also have a file that shows the ping connectivity between them, which looks like this:

left123:right123
left123:right456
right123:right456
right789:left456
right789:left123

Note that the left & right connectors can be on either side of the ':', i.e. left connectors are not always on the left and right connectors are not always on the right, which i have tried to show (they are from and to).

What i want to do is recursively get each element of the @leftCon and find it in the file, replace/output it with the with the element number (+1) and "L", then do the same with @rightCon, except <elementno.+1>R.

So in the example i will take the first element of @leftCon, which is left123, find left123 in the file and replace it with 1L. I will then get the next element of @leftCon, which is left456, find left456 in the file and replace that with 2L. I will then do the same with @rightCon, so the final output will look like:

1L:1R 1L:2R 1R:2R 3R:2L 3R:1L

There is one thing i want to try an avoid, which is why i am having so much trouble, i dont want to use any perl extensions. The reason being is that i am using perl2exe to create an exe out of all my scripts, and it doesnt seem to like file extensions. I have set the path to point to where the modules are kept and used the 'lib' command to set the path in the script. The exe is created but then says it cant find the modules?! Whether its a problem with perl2exe or I have set it up wrongly (which is probably & usually the case) i would still like it to be done without using a perl extension if it can be.

This is the code that gets the connector IDs...it reads in a text file containing a diagram.

my @leftCon; my @rightCon; while (<>) { /^\s*\[([^]]+)\]/ and push @leftCon, $1; /\[([^]]+)\]\s*$/ and push @rightCon, $1; } my $leftnoel = @leftCon; my $rightnoel = @rightCon; for (my $x = 0; $x <= $leftnoel-1; $x++) { # remove leading tab $leftCon[$x] =~ s/\t//g; $leftCon[$x] =~ s/\s+//g; } for (my $y = 0; $y <= $rightnoel-1; $y++) { # remove leading space char $rightCon[$y] =~ s/\s+//g; }

And this is my attempt at the problem, but clearly the result produced is in the wrong order, as it will find all the left connectors first, then the right connectors. To get the from & to connectors i have read in the file and split at the :

for ( my $x = 0; $x < $numFrom; $x++) { for (my $y = 0; $y < $leftCon-1; $y++) { if (@fromCon[$x] eq @leftCon[$y]) { my $fromConv = @fromCon[$x]; $fromConv = $leftcounter."L"; push @fromConv, $fromConv; } if (@toCon[$x] eq @leftCon[$y]) { my $toConv = @toCon[$y]; $toConv = $leftcounter."L"; push @toConv, $toConv; } $leftcounter++; } for (my $y = 0; $y < $rightConnectors-1; $y++) { if (@fromCon[$x] eq @rightCon[$y]) { my $fromConv = @fromCon[$x]; $fromConv = $leftcounter."R"; push @fromConv, $fromConv; } if (@toCon[$x] eq @rightCon[$y]) { my $toConv = @toCon[$y]; $toConv = $leftcounter."R"; push @toConv, $toConv; } $rightcounter++; } } print @fromConv; print @toConv;

Hopefully someone out there can help me solve this problem and maybe shed some light on whats wrong perl2exe (or possibly me ;-))? Cheers, Steve

Replies are listed 'Best First'.
Re: string manipulation with arrays
by jmcnamara (Monsignor) on Oct 22, 2003 at 10:46 UTC

    Here is one approach.
    #!/usr/bin/perl -w use strict; my @leftCon = qw(left123 left456); my @rightCon = qw(right123 right456 right789); my %l_con; my %r_con; @l_con{@leftCon} = (1 .. @leftCon); @r_con{@rightCon} = (1 .. @rightCon); while (<DATA>) { next unless /:/; chomp; my ($ping1, $ping2) = split /:/; $ping1 =~ s/(?<=\d\d\d)\d+$//; $ping2 =~ s/(?<=\d\d\d)\d+$//; s/$ping1/$l_con{$ping1}."L"/e if defined $l_con{$ping1}; s/$ping2/$l_con{$ping2}."L"/e if defined $l_con{$ping2}; s/$ping1/$r_con{$ping1}."R"/e if defined $r_con{$ping1}; s/$ping2/$r_con{$ping2}."R"/e if defined $r_con{$ping2}; print $_," "; } print "\n"; __DATA__ left1232:right4562 right1234:right4563 right7895:left4565 right7891:left1232
    Prints:
    1L2:2R2 1R4:2R3 3R5:2L5 3R1:1L2

    One aspect of the problem that wasn't well defined was whether left12345 can be interpreted as both left123 45 and left1234 5. I took the statement above that the connection names would contain 3 digits as the defining case.

    Also, there is some duplicated code here that could probably be simplified upon further clarification.

    --
    John.

Re: string manipulation with arrays
by TomDLux (Vicar) on Oct 22, 2003 at 15:54 UTC

    My first thought was to generate a pair of hashes, like jmcnamara did. It's the standard Perl mechanism for translating a set of strings to some other encoding.

    But in this case left and right are purely arbitrary labels. left123 is as likely to occur on the left as on the right.

    So instead of placing the tags into two hashes, %L_tags and %R_tags, I would simply use one hash, %tags.

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

Re: string manipulation with arrays
by Anonymous Monk on Oct 22, 2003 at 09:26 UTC
    Hi, theres something i did leave out...
    The pings also have an actual ping number as well, next to the connector so it would look like this...
    left1231:right1231 left1232:right4562 right1234:right4563 right7895:left4565 right7891:left1232

    and i want the output to just have these number appended so it would look like...

    1L1:1R1 1L2:2R2 1R4:2R3 3R5:2L5 3R1:1L2

    Note that the connector name can be of different length and often do not start with left or right and have 3 digits after it.