in reply to searching for strings

There are two things that make this much easier. One, is to iterate over the data twice, the first time to set up your relationships, the second time to report their existance. And two, rely solely on incrementing +1, as it is the easier of the relationships to calculate because of the special magic of ++ on strings.

You still must define the characteristics of your boundary conditions though. Ideally, we want the increment and decrement relationships to be one to one. What is the increment of "Bar999"? If it is "Bar1000", then your relationship is no longer 1 to 1 as there is also "Bar0999".

Anyway, here is an implementation without the boundary conditions fully defined. I've added two data entries for lines that do not match:
use Fcntl qw(SEEK_SET); use strict; # Calculate Relationships. # - Rely on increment, as it's the easier of the two to calculate. my %decrement; my %increment; # Synonymous with existance. my $start_of_DATA = tell DATA; while (<DATA>) { chomp; my $item = $_; # Note concerning parsing # - This regex requires that a prefix exist. if ($item =~ m{ (\w+) ( (?<!\d)\d+ | (?<![A-Z])[A-Z]+ ) \z}x) { my ($prefix, $suffix) = ($1, $2); # Note: this is the primary spot where there might be changes +in rules. # - What happens when the character ends in 'Z'? Currently # That would translate to 'AA'. # - What happens when number is 999? Currently that would tra +nslate # to '1000'. # Fix the rules here, and everything else will translate. (my $suffix_next = $suffix)++; my $item_next = $prefix . $suffix_next; $increment{$item} = $item_next; $decrement{$item_next} = $item; } else { die "Invalid data: $_"; } } # Reparse DATA seek(DATA, $start_of_DATA, SEEK_SET); while (<DATA>) { chomp; print; if ($increment{ $decrement{ $_ } }) { print ";$decrement{$_}"; } elsif ($increment{ $increment{ $_ } }) { print ";$increment{$_}"; } print "\n"; } __DATA__ AAA30 BBC5 SHT12H DAL33B BBC49 AAA31 BBC8 BBC3 DAL33A BBC6 SHT12G BBC50
And the output is:
>perl scratch.pl AAA30;AAA31 BBC5;BBC6 SHT12H;SHT12G DAL33B;DAL33A BBC49;BBC50 AAA31;AAA30 BBC8 BBC3 DAL33A;DAL33B BBC6;BBC5 SHT12G;SHT12H BBC50;BBC49
- Miller

Replies are listed 'Best First'.
Re^2: searching for strings
by wind (Priest) on Aug 10, 2007 at 08:32 UTC

    steph_bow asked "could you tell me what is the signification of (?<!\d) in your code ?"

    The purpose of the negative look behind assertions in my regular expression was to ensure that there was a key included in the data value. This was not strictly part of your stated requirement, but it seemed implied and therefore should be enforced.

    If this didn't matter, than we could simply rely on non-greedy matching in order to separate the key from the suffix.

    while (<DATA>) { chomp; if (m{\A (.*?) (\d+ | [A-Z]+) \z}x) { printf "Key = %-6s - Suffix = %s\n", $1, $2; } else { die "Invalid data: $_"; } } __DATA__ AAA30 BBC5 SHT12H DAL33B BBC49 AAA31 BBC8 BBC3 DAL33A BBC6 SHT12G BBC50

    However, what about the case of a value of '123456' or 'ABCDEF'? Currently those two values would validate to a key of the empty string "", and a suffix of the entire string. To avoid this, we start by changing the key matching from * (0 or more) to + (1 or more). However, this will just eat up 1 character of our suffix. We therefore add negative look behind assertions to the suffix matching in order to ensure that the suffix is matched on a boundary.

    This might have been a little obsessive, but it's always a good idea to validate your data so that you are absolutely sure that the rules of your logic are being followed.

    - Miller