Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

Re^4: Comparing Lines within a Word List

by dominick_t (Acolyte)
on Apr 30, 2016 at 14:06 UTC ( #1161950=note: print w/replies, xml ) Need Help??

in reply to Re^3: Comparing Lines within a Word List
in thread Comparing Lines within a Word List

Thanks hippo, I will give this a shot. I'm reading the documentation on the /g modifier but do not see yet how this will work.

If the issue was that there were two a's in 'lama', what does it mean that when I ran the original code, 'aaron' successfully matched 'baron' as it should have? Guessing it's to do with the fact that in this latter case, the repeated instance of 'a' comes after rather than before the a/b swap position, unlike 'lama' and 'lamb'. How this plays into the regex though, I don't yet see.

Replies are listed 'Best First'.
Re^5: Comparing Lines within a Word List
by graff (Chancellor) on Apr 30, 2016 at 15:27 UTC
    Note that hippo's addition of the g modifier brings up the issue that I raised earlier about having more than one character difference between two words. Here's what happens when I add a couple more examples to hippo's verson:
    #!/usr/bin/perl use strict; use warnings; my @words = <DATA>; chomp @words; while ( @words >= 2 ) { my $model = my $regex = shift @words; if ( $regex =~ s/(.*?)[ab](.*?)/$1\[ab\]$2/g ) { my @hits = grep /^$regex$/, @words; if ( @hits ) { print join( " ", $model, "matches", @hits, "using", $regex +, "\n" ); } } } __DATA__ lama lamb able bale
    lama matches lamb using l[ab]m[ab] able matches bale using [ab][ab]le
    The output shows how the g modifier affects the creation of the regex to be used for searching the array; without it, the first regex would be l[ab]ma (which would not match "lamb"), and the next would be l[ab]mb (which would not match "lama" if it were to show up later in the list).

    But when using the g modifier, the search pattern for "able" and "bale" come out the same, and they match each other, because the regex [ab][ab]le allows up to two characters to differ.

    To solve that, you could to compare the current "model" word against each of the matches from the array, using the tr/// operator as described in previous replies, to see how many characters are different in each paired set of words, and keep only those matches that differ by a single character.

    (UPDATE: It's also worth noting that using g this way is effectively equivalent to using "split", "map" and "join" to build the multi-match regex, like I showed in this previous reply - which just goes to show that "there's more than one way to do it."

Re^5: Comparing Lines within a Word List
by hippo (Chancellor) on Apr 30, 2016 at 14:26 UTC

    If you cannot work out in your head what the substitution actually does (and it's not an easy thing if you are new to all this) then give it a try in some code. The lack of boilerplate in perl really helps when coding up trivial scripts for testing. eg:

    #!/usr/bin/env perl use strict; use warnings; for my $word ('lama', 'aaron') { print "Word is $word\n"; print "without /g the regex becomes: "; my $r = $word; $r =~ s/(.*?)[ab](.*?)/$1\[ab\]$2/; print "$r\n"; print "with /g the regex becomes: "; $r = $word; $r =~ s/(.*?)[ab](.*?)/$1\[ab\]$2/g; print "$r\n"; }

    Hopefully running this code will illustrate to you how the substitutions differ because of the /g modifier.

      Right, I'm still too new to regular expressions to make head or tails of this, but with enough time I'll be able to parse it. At the moment I'm just hoping to get something that works so that I can meet my deadline; after that I'll be able to focus on the actual learning.

      I'm noticing now that this new code is calling pairs matches that shouldn't be, such as 'baa' and 'bbb'. These shouldn't match because there are two positions where the words differ. I think I have enough correct matches to finish the puzzle I'm working on, so I wouldn't call it urgent, but soon it will be an important thing for me to look at and figure out.

        All of the approaches in this subthread are based upon graff's original statement about his interpretation of your problem:

        OTOH, if you're looking for words that contain a particular pair of characters, and differ only in terms of using one vs. the other of those two (e.g. you really just want "bare/base", etc., but not "foot/fool"), you would probably want to use a regex like this ...

        Having computed set of "matches" for each term you can choose to refine that such that they differ by only one character using the other approaches (bitwise OR, Levenshtein, etc) mentioned elsewhere in the thread.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1161950]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (2)
As of 2021-04-17 00:05 GMT
Find Nodes?
    Voting Booth?

    No recent polls found