# sequences of numbers

#### Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

•  Subject
• Author
• Posted on

If I have an array that has elements of the following form

#!usr/bin/perl

my @array;

\$array[0] = "0 1 2 3 4 4 5";

\$array[1] = "0 2 2 2 3 4 5";

\$array[2] = "0 2 2 2 2 3 4";

\$array[3] = "0 2 6 8 9 10 12";

How would I get rid of any elements of the array that have 4 or more
adjacent alike elements?  For example, in the above array, I would want to
get rid of element 2 because it has the number 2 in 4 adjecent elements.

## Re: sequences of numbers

> If I have an array that has elements of the following form
>
>
> #!usr/bin/perl
>
> my @array;
>
> \$array[0] = "0 1 2 3 4 4 5";
>
> \$array[1] = "0 2 2 2 3 4 5";
>
> \$array[2] = "0 2 2 2 2 3 4";
>
> \$array[3] = "0 2 6 8 9 10 12";
>
> How would I get rid of any elements of the array that have 4 or more
> adjacent alike elements?  For example, in the above array, I would want to

my @sel = map { chop; \$_} grep !/(\d+ )/, map "\$_ ", @array;

Anno

## Re: sequences of numbers

> Anno Siegel (anno4000@lublin.zrz.tu-berlin.de) wrote on MMMMCXCVII

[...]

> :: > \$array[2] = "0 2 2 2 2 3 4";
> :: >
> :: > \$array[3] = "0 2 6 8 9 10 12";
> :: >
> :: > How would I get rid of any elements of the array that have 4 or more
> :: > adjacent alike elements?  For example, in the above array, I would want
to
> ::
> ::      my @sel = map { chop; \$_} grep !/(\d+ )/, map "\$_ ", @array;
>
> You might want to change the regex to:
>
>     /\b(\d+ )\b/
>
> or it will filter out
>
>     "12 2 2 2"

Ah, yes.  Thanks.

Anno

## Re: sequences of numbers

Thank you for your help.  I found this works provided that all my numbers
are positive numbers. (I know, I didn't portray that in my original data).
Can this be easily modified to work for negative numbers as well?

Abigail wrote:

> Anno Siegel (anno4000@lublin.zrz.tu-berlin.de) wrote on MMMMCXCVII
> :: > If I have an array that has elements of the following form
> :: >
> :: >
> :: > #!usr/bin/perl
> :: >
> :: > my @array;
> :: >
> :: > \$array[0] = "0 1 2 3 4 4 5";
> :: >
> :: > \$array[1] = "0 2 2 2 3 4 5";
> :: >
> :: > \$array[2] = "0 2 2 2 2 3 4";
> :: >
> :: > \$array[3] = "0 2 6 8 9 10 12";
> :: >
> :: > How would I get rid of any elements of the array that have 4 or more
> :: > adjacent alike elements?  For example, in the above array, I would
> :: > want to
> ::
> ::      my @sel = map { chop; \$_} grep !/(\d+ )/, map "\$_ ", @array;
>
> You might want to change the regex to:
>
>     /\b(\d+ )\b/
>
> or it will filter out
>
>     "12 2 2 2"
>
>
> Abigail

## Re: sequences of numbers

Big Daddy rudely spits TOFU in our faces:

[ rudeness corrected ]

> Abigail wrote:
>
>>Anno Siegel (anno4000@lublin.zrz.tu-berlin.de) wrote:
>>::
>>::      my @sel = map { chop; \$_} grep !/(\d+ )/,
>>::                  map "\$_ ", @array;
>>
>>You might want to change the regex to:
>>
>>    /\b(\d+ )\b/
>>
>>or it will filter out
>>
>>    "12 2 2 2"
>
> Thank you for your help.

>  I found this works provided that all my numbers
> are positive numbers. (I know, I didn't portray that in my original data).
> Can this be easily modified to work for negative numbers as well?

Actually the regex solution knows nothing of numbers, it works on
_strings_ and happens to constrain itself to strings that consist
entirely of digits.

You could make it handle any non-whitespace string by simply changing
"digit" to "non-whitespace character".

Please try to understand the solutions you are given rather than simply
transcribe them by rote.

## Re: sequences of numbers

Well, no offense, but I thought the original post was quite clear. I
obviously thought the problem was complex, hence the posting. The solution
provided doesn't work. Here's why:

Try it on this:

\$array[0] = ("-10 10 30 30 30 30");
\$array[1] = ("-10 -10 -10 -10 20 30");
\$array[2] = ("-12 2 2 2 20 30");
\$array[3] = ("10 20 30");

Then,

@stack = map grep !/\b(\d+ )\b/,map "\$_", @array;

will yield @stack with 2 elements still.

I do understand the above, I couldn't figure out how to modify it to work
properly.

The regular expression /\b(\d+ )\b/ only works provided there is a
space after the digit, which isn't the case for the last number in the
string.  I never depicted a space after the last number in each string in
the original post and it isn't trivial (at least for me) how to modify this
to work when it is possible that the repeated number in the string could
occur over the last four numbers of the string.

In other words, if the solution was trivial, someone would have figured it
out by now, and they haven't.  In fact, your idea of using a non-whitespace
character doesn't appear to work either. So please don't flame me for
posting a question which has clearly been very difficult for even the best
Perl programmers in the world to figure out.

Thank you

Brian McCauley wrote:

> Big Daddy rudely spits TOFU in our faces:
>
> [ rudeness corrected ]
>
>  > Abigail wrote:
>  >
>  >>Anno Siegel (anno4000@lublin.zrz.tu-berlin.de) wrote:
>  >>::
>  >>::      my @sel = map { chop; \$_} grep !/(\d+ )/,
>  >>::                  map "\$_ ", @array;
>  >>
>  >>You might want to change the regex to:
>  >>
>  >>    /\b(\d+ )\b/
>  >>
>  >>or it will filter out
>  >>
>  >>    "12 2 2 2"
>  >
>> Thank you for your help.
>
>
>>  I found this works provided that all my numbers
>> are positive numbers. (I know, I didn't portray that in my original
>> data). Can this be easily modified to work for negative numbers as well?
>
> Actually the regex solution knows nothing of numbers, it works on
> _strings_ and happens to constrain itself to strings that consist
> entirely of digits.
>
> You could make it handle any non-whitespace string by simply changing
> "digit" to "non-whitespace character".
>
> Please try to understand the solutions you are given rather than simply
> transcribe them by rote.

## Re: sequences of numbers

> In other words, if the solution was trivial, someone would have figured it
> out by now, and they haven't.  In fact, your idea of using a non-whitespace
> character doesn't appear to work either. So please don't flame me for
> posting a question which has clearly been very difficult for even the best
> Perl programmers in the world to figure out.

Even the best Perl programmer in the world can only guess what the
format of the input is when you don't provide a definition, only a few
examples.

## Re: sequences of numbers

> Well, no offense, but I thought the original post was quite clear. I

Clear?

You gave us a problem, we solved it.  Then you come back and tell us
it wasn't your real problem, would we please solve another.  Not what
I call a clear description.

> obviously thought the problem was complex, hence the posting. The solution
> provided doesn't work. Here's why:

It does work with your original data.

> Try it on this:
>
> \$array[0] = ("-10 10 30 30 30 30");
> \$array[1] = ("-10 -10 -10 -10 20 30");
> \$array[2] = ("-12 2 2 2 20 30");
> \$array[3] = ("10 20 30");
>
> Then,
>
> @stack = map grep !/\b(\d+ )\b/,map "\$_", @array;
>
> will yield @stack with 2 elements still.
>
> I do understand the above, I couldn't figure out how to modify it to work
> properly.

No, you don't understand it.  Your rendition above is broken.

> The regular expression /\b(\d+ )\b/ only works provided there is a
> space after the digit, which isn't the case for the last number in the
> string.

That's what the part you broke is taking care of.

> I never depicted a space after the last number in each string in
> the original post and it isn't trivial (at least for me) how to modify this
> to work when it is possible that the repeated number in the string could
> occur over the last four numbers of the string.
>
> In other words, if the solution was trivial, someone would have figured it
> out by now, and they haven't.

We haven't had much time to look at your real problem, have we?

> In fact, your idea of using a non-whitespace
> character doesn't appear to work either. So please don't flame me for
> posting a question which has clearly been very difficult for even the best
> Perl programmers in the world to figure out.

It isn't hard at all when you're not trying to come up with a one-liner.

If a problem is too complex to solve in one go, break it down:

my @stack = grep ! ! has_long_const_seq( \$_, 3), @array;

Now take your time and space to come up with a function
has_long_const_seq() that checks if the number of consecutive elements
in the first argument exceeds the second one.  That's a rather
straight-forward application of split and a counting loop:

sub has_long_const_seq {
my ( \$str, \$max) = @_;
my \$count = 1;
my ( \$last, @rest) = split ' ', \$str;
for ( @rest ) {
if ( \$_ eq \$last ) {
++ \$count <= \$max or return 1;
} else {
\$last = \$_;
\$count = 1;
}
}
0;
}

The regex-only solution (which may still be possible) only looked
attractive because of your over-simplified problem description.

Anno

## Re: sequences of numbers

> Well, no offense, but I thought the original post was quite clear. I

Clear?

You gave us a problem, we solved it.  Then you come back and tell us
it wasn't your real problem, would we please solve another.  Not what
I call a clear description.

> obviously thought the problem was complex, hence the posting. The solution
> provided doesn't work. Here's why:

It does work with your original data.

> Try it on this:
>
> \$array[0] = ("-10 10 30 30 30 30");
> \$array[1] = ("-10 -10 -10 -10 20 30");
> \$array[2] = ("-12 2 2 2 20 30");
> \$array[3] = ("10 20 30");
>
> Then,
>
> @stack = map grep !/\b(\d+ )\b/,map "\$_", @array;
>
> will yield @stack with 2 elements still.
>
> I do understand the above, I couldn't figure out how to modify it to work
> properly.

No, you don't understand it.  Your rendition above is broken.

> The regular expression /\b(\d+ )\b/ only works provided there is a
> space after the digit, which isn't the case for the last number in the
> string.

That's what the part you broke is taking care of.

> I never depicted a space after the last number in each string in
> the original post and it isn't trivial (at least for me) how to modify this
> to work when it is possible that the repeated number in the string could
> occur over the last four numbers of the string.
>
> In other words, if the solution was trivial, someone would have figured it
> out by now, and they haven't.

We haven't had much time to look at your real problem, have we?

> In fact, your idea of using a non-whitespace
> character doesn't appear to work either. So please don't flame me for
> posting a question which has clearly been very difficult for even the best
> Perl programmers in the world to figure out.

It isn't hard at all when you're not trying to come up with a one-liner.

If a problem is too complex to solve in one go, break it down:

my @stack = grep ! has_long_const_seq( \$_, 3), @array;

Now take your time and space to come up with a function
has_long_const_seq() that checks if the number of consecutive elements
in the first argument exceeds the second one.  That's a rather
straight-forward application of split and a counting loop:

sub has_long_const_seq {
my ( \$str, \$max) = @_;
my \$count = 1;
my ( \$last, @rest) = split ' ', \$str;
for ( @rest ) {
if ( \$_ eq \$last ) {
++ \$count <= \$max or return 1;
} else {
\$last = \$_;
\$count = 1;
}
}
0;
}

The regex-only solution (which may still be possible) only looked
attractive because of your over-simplified problem description.

Anno

## Re: sequences of numbers

> Well, no offense, but I thought the original post was quite clear. I
> obviously thought the problem was complex, hence the posting. The solution
> provided doesn't work. Here's why:

Er... top posting is not appreciated as has been pointed out to you a
couple of times a couple of times.

> Try it on this:

> \$array[0] = ("-10 10 30 30 30 30");
> \$array[1] = ("-10 -10 -10 -10 20 30");
> \$array[2] = ("-12 2 2 2 20 30");
> \$array[3] = ("10 20 30");

> @stack = map grep !/\b(\d+ )\b/,map "\$_", @array;

> will yield @stack with 2 elements still.

> The regular expression /\b(\d+ )\b/ only works provided there is a
> space after the digit, which isn't the case for the last number in the
> string.  I never depicted a space after the last number in each string in
> the original post and it isn't trivial (at least for me) how to modify this
> to work when it is possible that the repeated number in the string could
> occur over the last four numbers of the string.

That is because you did not examine Anno's original closely enough
or use cut and paste; the last part of the statement was:

map "\$_ ", @array;    # Note the space within the quotation marks.

Building on Anno's and Abigail's solutions to include negative
integers (which I do not recall being mentioned in the original
statement of the problem)...

#!/usr/bin/perl

use strict;
use warnings;

my @array;
\$array[0] = ("-10 10 30 30 30 30");
\$array[1] = ("-10 -10 -10 -10 20 30");
\$array[2] = ("-12 2 2 2 20 30");
\$array[3] = ("10 20 30");

my @stack = map {chop; \$_}        grep !/(\b(\d+ )|(-\d+ ))/,
map "\$_ ", @array;

\$\ = "\n";
print for @stack;

__END__

Yields:

-12 2 2 2 20 30
10 20 30

It makes no attempt to deal with floating-point values, use of
whitespace between the integers other than a single space, or any other
previously unmentioned requirements.

Axel

## Re: sequences of numbers

axel@white-eagle.invalid.uk (axel@white-eagle.invalid.uk) wrote on MMMMCC
...
...  /(\b(\d+ )|(-\d+ ))/,

I think that's equivalent with:

/((-?\b\d+ ))/

Abigail
--
@;=split//=>"Joel, Preach sartre knuth\n";\$;=chr 65;%;=map
0,22,13,16,5,14,21,1,23,11,2,7,12,6,8,15,3,19,24,14,10,20,18,17,4,25
;print@;[@;];

## Re: sequences of numbers

> Anno Siegel (anno4000@lublin.zrz.tu-berlin.de) wrote on MMMMCXCVII
> :: > If I have an array that has elements of the following form
> :: >
> :: >
> :: > #!usr/bin/perl
> :: >
> :: > my @array;
> :: >
> :: > \$array[0] = "0 1 2 3 4 4 5";
> :: >
> :: > \$array[1] = "0 2 2 2 3 4 5";
> :: >
> :: > \$array[2] = "0 2 2 2 2 3 4";
> :: >
> :: > \$array[3] = "0 2 6 8 9 10 12";
> :: >
> :: > How would I get rid of any elements of the array that have 4 or more
> :: > adjacent alike elements?  For example, in the above array, I would
> :: > want to
> ::
> ::      my @sel = map { chop; \$_} grep !/(\d+ )/, map "\$_ ", @array;
>
> You might want to change the regex to:
>
>     /\b(\d+ )\b/
>
> or it will filter out
>
>     "12 2 2 2"

Actually, it won't filter that out in either case, because the final
2 does not have a space after it.

Xho

--
Usenet Newsgroup Service                        \$9.95/Month 30GB

## Re: sequences of numbers

> #!usr/bin/perl
>
> my @array;
>
> \$array[0] = "0 1 2 3 4 4 5";
>
> \$array[1] = "0 2 2 2 3 4 5";
>
> \$array[2] = "0 2 2 2 2 3 4";
>
> \$array[3] = "0 2 6 8 9 10 12";
>
> How would I get rid of any elements of the array that have 4 or more
> adjacent alike elements?  For example, in the above array, I would want to
> get rid of element 2 because it has the number 2 in 4 adjecent elements.
>

What have you tired so far ? Homework ?!

## Re: sequences of numbers

> If I have an array that has elements of the following form
>
>
> #!usr/bin/perl
>
> my @array;
>
> \$array[0] = "0 1 2 3 4 4 5";
>
> \$array[1] = "0 2 2 2 3 4 5";
>
> \$array[2] = "0 2 2 2 2 3 4";
>
> \$array[3] = "0 2 6 8 9 10 12";
>
> How would I get rid of any elements of the array that have 4 or more
> adjacent alike elements?  For example, in the above array, I would
> want to get rid of element 2 because it has the number 2 in 4 adjecent
> elements.

use strict;
use warnings;

my @array;

\$array[0] = "0 1 2 3 4 4 5";

\$array[1] = "0 2 2 2 3 4 5";

\$array[2] = "0 2 2 2 2 3 4";

\$array[3] = "0 2 6 8 9 10 12";

s/(\d+) (( ?))+/\$1\$3/g for @array;
print map { "[\$_]\n" } @array;

[0 1 2 3 4 5]
[0 2 3 4 5]
[0 2 3 4]
[0 2 6 8 9 10 12]

seems to work, no idea if it's fool proof.

--
John                   Small Perl scripts: http://johnbokma.com/perl/
Perl programmer available:     http://castleamber.com/
Happy Customers: http://castleamber.com/testimonials.html