my @ends = map{ [$_->[0], $_, 'S'], [$_->[-1], $_, 'E'] } @data;
####
@ends = sort{
$b->[0]{X} <=> $a->[0]{X}
||
$b->[0]{Y} <=> $a->[0]{Y}
||
$b->[2] cmp $a->[2]
} @ends;
####
sub mapAdjPairs (&@) {
my $code = shift;
map { local ($a, $b) = (shift, $_[0]); $code->() } 0 .. @_-2;
}
####
my @merged = mapAdjPairs{
if ($a->[2] eq 'S') { # $a is a start point
if ( $b->[2] eq 'E'
and $a->[0]{X} == $b->[0]{X} # Introduce FP fudge factor if needed
and $a->[0]{Y} == $b->[0]{Y}
) { # $b is and end and we found a coincident end/start pair
push @{ $b->[1] }, @{ $a->[1] }[1.. $#{$a->[1]} ];
return; # we merged two sections so don't add to result
}
else { # We have a start point and didn't merge so add to the results
return $a->[1];
}
}
return;
} @ends, $ends[0]; # Note:Repeat first element last to complete cycle
####
c:\test>240810
X 11 Y 12 X 12 Y 13 X 13 Y 14 X 14 Y 15 X 15 Y 16 X 16 Y 17 X 17 Y 18 X 18 Y 19 X 19 Y 20
X 10 Y 10 X 11 Y 11 X 12 Y 12 X 13 Y 13 X 14 Y 14 X 15 Y 15 X 16 Y 16 X 17 Y 17 X 18 Y 18 X 19 Y 19 X 20 Y 20 X 21 Y 21 X 22 Y 22 X 23 Y 23 X 24 Y 24
X 1 Y 2 X 1 Y 3 X 1 Y 4
c:\test>
####
#! perl -slw
use strict;
# Steps through an array two at a time [0,1], the [1,2] etc
sub mapAdjPairs (&@) {
my $code = shift;
map { local ($a, $b) = (shift, $_[0]); $code->() } 0 .. @_-2;
}
my @data = (
[ {X=>10, Y=>10}, {X=>11, Y=>11}, {X=>12, Y=>12}, ],
[ {X=>11, Y=>12}, {X=>12, Y=>13}, {X=>13, Y=>14}, {X=>14, Y=>15}, ],
[ {X=>20, Y=>20}, {X=>21, Y=>21}, {X=>22, Y=>22}, {X=>23, Y=>23}, {X=>24, Y=>24}, ],
[ {X=>17, Y=>17}, {X=>18, Y=>18}, {X=>19, Y=>19}, {X=>20, Y=>20}, ],
[ {X=>01, Y=>02}, {X=>01, Y=>03}, {X=>01, Y=>04}, ],
[ {X=>12, Y=>12}, {X=>13, Y=>13}, {X=>14, Y=>14}, {X=>15, Y=>15}, {X=>16, Y=>16}, {X=>17, Y=>17}, ],
[ {X=>14, Y=>15}, {X=>15, Y=>16}, {X=>16, Y=>17}, {X=>17, Y=>18}, {X=>18, Y=>19}, {X=>19, Y=>20}, ],
);
my @ends = sort{
$b->[0]{X} <=> $a->[0]{X}
||
$b->[0]{Y} <=> $a->[0]{Y}
||
$b->[2] cmp $a->[2]
} map{ [$_->[0], $_, 'S'], [$_->[-1], $_, 'E'] } @data;
my @merged = mapAdjPairs{
if ($a->[2] eq 'S') { # $a is a start point
if ( $b->[2] eq 'E'
and $a->[0]{X} == $b->[0]{X} # Introduce FP fudge factor if needed
and $a->[0]{Y} == $b->[0]{Y}
) { # $b is and end and we found a coincident end/start pair
push @{ $b->[1] }, @{ $a->[1] }[1.. $#{$a->[1]} ];
return; # we merged two sections so don't add to result
}
else { # We have a start point and didn't merge so add to the results
return $a->[1];
}
}
return;
} @ends, $ends[0]; # Note: repeat the first element as the last to complete the cycle
# Display the results.
print qq[ @{[ map{ qq[ @{[ %$_ ]} ] } @$_ ]} ] for @merged;
__END__
c:\test>240810
X 11 Y 12 X 12 Y 13 X 13 Y 14 X 14 Y 15 X 15 Y 16 X 16 Y 17 X 17 Y 18 X 18 Y 19 X 19 Y 20
X 10 Y 10 X 11 Y 11 X 12 Y 12 X 13 Y 13 X 14 Y 14 X 15 Y 15 X 16 Y 16 X 17 Y 17 X 18 Y 18 X 19 Y 19 X 20 Y 20 X 21 Y 21 X 22 Y 22 X 23 Y 23 X 24 Y 24
X 1 Y 2 X 1 Y 3 X 1 Y 4