Re: A string & a list
- From: rob.dixon@xxxxxxx (Rob Dixon)
- Date: Fri, 30 Jun 2006 18:44:04 +0100
Monomachus wrote:
A problem in Perl
You have a string & a list
For ex.: $s = "ADbDCdBabc"; @N=("A","D","C")
You should exclude those elements from the string : first by 1 element, after that by 2 & by 3 ... (If @N would have 5 elements
and by 4 and by 5([$#N+1] elements)), and creating a new list:
by 1:
DbDCdBabc - is excluded A
AbDCdBabc - first D
ADbCdBabc - second D
ADbDdBabc - C
(B doesn't belong to @N list)
by 2:
bDCdBabc - are excluded A,first D
DbCdBabc - A, second D
DbDdBabc - A,C
AbCdBabc - D,D
AbDdBabc - first D,C
ADbdBabc - second D,C
by 3:
bCdBabc - A,first D,second D
bDdBabc - A,first D,C
DbdBabc - A,second D,C
All these elements should be included in new list @Final...
Are there any variants how could I do smth like that ??
And one more thing could u show me variants without using RegEx
Hi Monomachus
I hate answering queries like this with just a solution, but that's what I'm going to do as the stuff I was going to suggest would never have led you to a finished program. I'm also going to ignore the bit about avoiding regular expression, because the problem is best solved using them, and if you /really/ need to take them out then its best done after a working solution is written.
I don't know how much to say about this, as I'm not sure where the sticking points will be, but I'll point out a few bits and then be willing to answer questions.
- The program builds a regex pattern /A|D|C/ out of the characters in the array.
- The solution is a recursive one - reduce() will remove any single occurrence of one of the characters in the pattern from the string. Then, if more elements must be removed, it calls itself to do the same thing to each of its results.
- The array @- is an internal one, storing the offsets of the substrings found by the last regex pattern match. $-[0] is the offset where the whole pattern matched, and can be used with substr() to (in this case) remove the matching character.
- The push of the results of the recursive call is qualified by a call to grep() to make sure the new value isn't already in the list.
- You will see that the program found a fourth case to removing three elements from the string, changing the list to:
by 3:
bCdBabc - A,first D,second D
bDdBabc - A,first D,C
DbdBabc - A,second D,C
AbdBabc - first D,second D,C
- You say that the string should be reduced by up to $#N+1 elements, but in general there are further solutions after this which may be relevant to your application. For instance:
by 4:
bdBabc - A,first D,second D,C
- I've not used the results in @final, but the code puts everything in there as you described it.
I hope I have understood your problem properly, and that this helps you. As I said, if you are determined to do this without regexes than please let us know. I enjoyed coding this: thanks for posting the problem.
Cheers,
Rob
** SOLUTION **
use strict;
use warnings;
my $s = "ADbDCdBabc";
my @N=("A","D","C");
my @final;
for my $depth (1 .. @N) {
printf "\nby %d:\n", $depth;
my @new = reduce($s, $depth);
print $_, "\n" foreach @new;
push @final, @new;
}
sub reduce {
my ($string, $depth) = @_;
my $pattern = join '|', @N;
my @new;
while ($string =~ /$pattern/g) {
substr my $reduction = $string, $-[0], 1, '';
if ($depth > 1) {
foreach my $value (reduce($reduction, $depth - 1)) {
push @new, $value unless grep $value eq $_, @new;
}
}
else {
push @new, $reduction;
}
}
return @new;
}
** OUTPUT **
by 1:
DbDCdBabc
AbDCdBabc
ADbCdBabc
ADbDdBabc
by 2:
bDCdBabc
DbCdBabc
DbDdBabc
AbCdBabc
AbDdBabc
ADbdBabc
by 3:
bCdBabc
bDdBabc
DbdBabc
AbdBabc
.
- References:
- A string & a list
- From: Monomachus
- A string & a list
- Prev by Date: Perl Binary to Perl Code
- Next by Date: Re: A string & a list
- Previous by thread: Re: How to Post/How to Respond (WAS: A string & a list)
- Next by thread: Re: A string & a list
- Index(es):
Relevant Pages
|