sequences of numbers

B

Big Daddy

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.
 
A

Anno Siegel

Big Daddy said:
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+ )\1{3}/, map "$_ ", @array;

Anno
 
J

Julia De Silva

#!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 ?!
 
J

John Bokma

Big said:
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( ?))+/$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.
 
C

Charles DeRykus

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.

Although very klunky, you could use a hash:

my( %h, @new );
for (0..$#array) { push @{ $h{$array[$_]} }, $array[$_] }
for (0..$#array) { push @new, @{ $h{$array[$_]} } if @{ $h{$array[$_]} } < 4 }
 
A

Anno Siegel

Abigail said:
Anno Siegel ([email protected]) wrote on MMMMCXCVII
September MCMXCIII in <URL:[...]

:: > $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+ )\1{3}/, map "$_ ", @array;

You might want to change the regex to:

/\b(\d+ )\1{3}\b/

or it will filter out

"12 2 2 2"

Ah, yes. Thanks.

Anno
 
B

Big Daddy

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?
 
B

Big Daddy

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{chop;$_} grep !/\b(\d+ )\1{3}\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+ )\1{3}\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 said:
Big Daddy rudely spits TOFU in our faces:

[ rudeness corrected ]
Thank you for your help.

Please express your gratitude by _not_ spitting in our faces.
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.
 
B

Brian McCauley

Big Daddy rudely spits TOFU in our faces:

[ rudeness corrected ]
Thank you for your help.

Please express your gratitude by _not_ spitting in our faces.
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.
 
A

Arndt Jonasson

Big Daddy said:
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.
 
A

Anno Siegel

Big Daddy said:
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{chop;$_} grep !/\b(\d+ )\1{3}\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+ )\1{3}\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
 
A

Anno Siegel

Big Daddy said:
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{chop;$_} grep !/\b(\d+ )\1{3}\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+ )\1{3}\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
 
X

xhoster

Abigail said:
Anno Siegel ([email protected]) wrote on MMMMCXCVII
September MCMXCIII in <URL::: > 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+ )\1{3}/, map "$_ ", @array;

You might want to change the regex to:

/\b(\d+ )\1{3}\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
 
A

axel

Big Daddy said:
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{chop;$_} grep !/\b(\d+ )\1{3}\b/,map "$_", @array;
will yield @stack with 2 elements still.
The regular expression /\b(\d+ )\1{3}\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+ )\2{3}|(-\d+ )\3{3})/,
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,169
Messages
2,570,919
Members
47,458
Latest member
Chris#

Latest Threads

Top