in reply to screen out an untained array from a special array

Have you tried writing any code for that yet? I do understand the question, although the nature of the input is still a bit vague. Are you reading from a file? Is the max value always 31, or will it vary with the input?

If I had to code something like that, the plan would be:

use strict; use warnings; # get the inputs into an array, one "number" or "n:n" range per array +element. # then: my @covered; # an array to track the "coverage" of the inputs # for each input array element { # if the element does not contain ":" # use it as an array index and set $covered[$element] to some va +lue # otherwise # split on ":", sort the pieces numerically and assign to $begin +, $end # $covered[$_] = 'some value' for ( $begin .. $end ); # } # Once that's done, the only thing left to do is: my $uncovered = ''; for ( 0 .. $#covered ) { $uncovered .= "$_, " unless ( defined( $covered[$_] )); } $uncovered =~ s/, $/\n/; print $uncovered;
That output would not exactly match what you said you wanted, but I'm puzzled why you would want your output to be so irregular (some elements shown as single values, some shown as ranges, some ranges have higher value first, etc).

If you really want your output to be as complicated as you say in the OP, go ahead and try writing some code to do that. If it doesn't work and you can't figure out how to fix it, post another thread, and show us what you tried.

Replies are listed 'Best First'.
Re^2: screen out an untained array from a special array
by Hanken (Acolyte) on Feb 08, 2009 at 02:21 UTC
    Thanks for everyone above replied.
    The max value is always 31, and those input are read from a parsed file.
    The output should be (\d+:\d+) so which is required by the Verilog syntax I had to use.
    Here is what I have tried.
    sub get_reserved { my $bits_ref = shift; my @bits = @{$bits_ref}; my @digits = map { chomp; if ( m/(\d+):(\d+)/) { ($1 > $2) ? ($2 .. $1) : ($1 .. $2); } else { $_; } } @bits; my @reg32set = map {0} 0 .. 31; my @index; if (@digits ne '') { map {$reg32set[$_] = 1;} @digits; @index = grep {if ($reg32set[$_] == 0) {$_;}} 0..31; } else { undef @index; } }
      The output should be (\d+:\d+) so which is required by the Verilog syntax I had to use.

      Does the "Verilog syntax" have some sort of specification that says an N1..N2 range should be presented sometimes as "N1:N2" and other times as "N2:N1"? Do you know whether there is some reason for this fluctuation?

      Regarding the code you posted, you are missing some fundamental points of Perl syntax. What do you think  @digits ne '' is supposed to do? (Hint: an array in a scalar context always returns the number of elements in the array, which will never be the same as an empty string.)

      If "Verilog syntax" supports the use of a consistent ordering of range components, I think this will be close to what you're looking for:

      use strict; use warnings; my @test = qw/1 5:10 18:14 21 24:25 31:28/; print get_reserved( \@test ), "\n"; sub get_reserved { my ( $bits_ref ) = @_; # should be an array ref return "bad call to get_reserved()" unless ( ref( $bits_ref ) eq 'ARRAY' and @$bits_ref ); my @reg32set; for my $spec ( @$bits_ref ) { if ( $spec =~ /(\d+):(\d+)/) { my ( $bgn, $end ) = sort {$a<=>$b} ( $1, $2 ); $reg32set[$_] = 1 for ( $bgn .. $end ); } else { $reg32set[$spec] = 1; } } my $verilog_string = ''; for my $seq ( 0 .. $#reg32set ) { if ( defined( $reg32set[$seq] )) { $verilog_string .= ", "; } else { $verilog_string .= "$seq:"; } } return "no intervals to report from get_reserved()" unless ( $verilog_string =~ /\d/ ); $verilog_string =~ s/(?<=\d):[\d:]+:(?=\d)/:/g; # e.g. "2:3:4:5:6 + -> 2:6 $verilog_string =~ s/^(?:, )+//; $verilog_string =~ s/:(?:, )*$//; $verilog_string =~ s/:,(?: ,)*/,/g; return $verilog_string; }
      (updated to add diagnostic messages for a couple of edge conditions)
        Thanks Graff for your patient instruction and comments.
        For the verilog syntax, you can check here: http://www.sutherland-hdl.com/online_verilog_ref_guide/vlog_ref_top.html
        In the section of "6.0 Module Port Declarations" you will know the port size definition.

        my code @digits ne '' might be a mistake, thanks for pointing it out. I supposed to do nothing if @digits contains no vars. You know otherwise, it would be warning msg prompted saying not a number index assign to $reg32set

        Regarding to your code, I think you idear is great. But I had to change the code $#reg32set in  for my $seq (0 .. $#reg32set) to 31 get what I need. The max index is always 32. By the way, you coding style is pretty good and I am trying to learn from you.

        Thanks again for everyone comments, and tolerating my confusing explanation. :)

        Hanken