daverave:

I had a bit of time on my lunch break, so I whipped a little something up. It's pretty close, but there are still a few tweaks I have in mind for it...

#!/usr/bin/perl use strict; use warnings; my @universe = (1, 10); my @ranges = ( [ 1, 3 ], [2, 7], [10, 2] ); # Normalize the lists my @nrm_rng = map { ($$_[0] < $$_[1]) ? $_ : ( [ $$_[0]-$universe[1], $$_[1] ], [ $$_[0], $$_[1] + $universe[1]-$universe[0] ] + ) } @ranges; # Dump lists printf("% 2u ",$_) for $universe[0] .. $universe[1]; print "\n"; print "-- " for $universe[0] .. $universe[1]; print "\n"; for my $R (@nrm_rng) { printf("%2s ", ($_>= $$R[0] and $_<=$$R[1]) ? "XX" : "") for $universe[0] .. $universe[1]; print ": ($$R[0], $$R[1])\n"; } my $arMax; my @out; my @working; for my $col ($universe[0] .. $universe[1]) { $arMax=undef; # Add and remove working lists based on column position push @working, grep { $col>=$$_[0] } @nrm_rng; @nrm_rng = grep { $col < $$_[0] } @nrm_rng; @working = grep { $col<=$$_[1] } @working; # Compute result for each list for (@working) { $$_[2] = 3+2*min(abs($col-$$_[0]),abs($col-$$_[1])); if (!defined($arMax) or ($$arMax[2]<$$_[2]) or ($$arMax[2]==$$_[2] and $$arMax[1]<$$_[1]) +) { $arMax=$_; } } $out[$col] = defined($arMax) ? sprintf("% 2u",$$arMax[2]) : ' +1'; # print "$col ", # "wrk: ", join(", ", map { "(".join(",",@$_).")" } @$_, @wo +rking), "\n"; # Remove lists that will no longer give us values @working = grep { $_ eq $arMax or $$arMax[1] < $$_[1] } @worki +ng; } print "FINAL: ", join(' ', @out), "\n"; sub min { my ($l, $r) = (@_); return ($l<$r) ? $l : $r; }

...roboticus

Update:I reformatted one of the lines of code to get rid of an ugly line break.

Update 2: Code edits: (1) Set ranges as per daverave's request, (2) added debug trace (commented out print), (3) bugfix ($arMax=undef at start of loop), (4) bugfix (list normalization). I didn't replace all the code, so I may have made an error, so let me know if you see something wrong. Currently, though, running it shows me:

roboticus@Work: /Work/Perl/PerlMonks $ perl 868827_ranges_and_such.pl 1 2 3 4 5 6 7 8 9 10 -- -- -- -- -- -- -- -- -- -- XX XX XX : (1, 3) XX XX XX XX XX XX : (2, 7) XX XX : (0, 2) XX : (10, 11) 5 5 5 7 7 5 3 1 1 3 : FINAL

In reply to Re^2: Can I speed this up? by roboticus
in thread Can I speed this up? (repetitively scanning ranges in a large array) by daverave

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.