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
|