| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Algorithm::RectanglesContainingDot; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
24858
|
use strict; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
39
|
|
|
4
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
1411
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '0.02'; |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
package |
|
9
|
|
|
|
|
|
|
Algorithm::RectanglesContainingDot::Perl; |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $MIN_DIV = 8; |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
sub new { |
|
14
|
2
|
|
|
2
|
|
24
|
my $class = shift; |
|
15
|
2
|
|
|
|
|
7
|
my $self = { rects => [], |
|
16
|
|
|
|
|
|
|
names => [] }; |
|
17
|
2
|
|
|
|
|
9
|
bless $self, $class; |
|
18
|
|
|
|
|
|
|
} |
|
19
|
|
|
|
|
|
|
|
|
20
|
0
|
|
|
0
|
|
0
|
sub _reset { delete shift->{div} } |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub add_rectangle { |
|
23
|
20000
|
|
|
20000
|
|
96153
|
my ($self, $name, $x0, $y0, $x1, $y1) = @_; |
|
24
|
|
|
|
|
|
|
|
|
25
|
20000
|
50
|
|
|
|
37217
|
($x0, $x1) = ($x1, $x0) if $x0 > $x1; |
|
26
|
20000
|
50
|
|
|
|
33355
|
($y0, $y1) = ($y1, $y0) if $y0 > $y1; |
|
27
|
|
|
|
|
|
|
|
|
28
|
20000
|
|
|
|
|
18630
|
push @{$self->{rects}}, ($x0, $y0, $x1, $y1); |
|
|
20000
|
|
|
|
|
44695
|
|
|
29
|
20000
|
|
|
|
|
20793
|
push @{$self->{names}}, $name; |
|
|
20000
|
|
|
|
|
49815
|
|
|
30
|
20000
|
|
|
|
|
44250
|
delete $self->{div}; |
|
31
|
|
|
|
|
|
|
} |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub rectangles_containing_dot { |
|
34
|
2000
|
|
|
2000
|
|
1897373
|
my $self = shift; |
|
35
|
2000
|
|
66
|
|
|
11872
|
my $div = $self->{div} || $self->_init_div; |
|
36
|
2000
|
|
|
|
|
11149
|
@{$self->{names}}[_rectangles_containing_dot($div, $self->{rects}, @_)]; |
|
|
2000
|
|
|
|
|
41840
|
|
|
37
|
|
|
|
|
|
|
} |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub _rectangles_containing_dot_ref { |
|
40
|
2000
|
|
|
2000
|
|
14472
|
my ($self, $x, $y) = @_; |
|
41
|
2000
|
|
|
|
|
4546
|
my $names = $self->{names}; |
|
42
|
2000
|
|
|
|
|
4333
|
my $rects = $self->{rects}; |
|
43
|
2000
|
|
|
|
|
2598
|
my @ret; |
|
44
|
2000
|
|
|
|
|
6905
|
for (0..$#$names) { |
|
45
|
20000000
|
|
|
|
|
18581439
|
my $i0 = $_ * 4; |
|
46
|
20000000
|
100
|
100
|
|
|
53297819
|
if ($rects->[$i0] <= $x and |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
47
|
|
|
|
|
|
|
$rects->[$i0+1] <= $y and |
|
48
|
|
|
|
|
|
|
$rects->[$i0+2] >= $x and |
|
49
|
|
|
|
|
|
|
$rects->[$i0+3] >= $y) { |
|
50
|
37926
|
|
|
|
|
77487
|
push @ret, $names->[$_]; |
|
51
|
|
|
|
|
|
|
} |
|
52
|
|
|
|
|
|
|
} |
|
53
|
2000
|
|
|
|
|
62806
|
@ret; |
|
54
|
|
|
|
|
|
|
} |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# div is: |
|
57
|
|
|
|
|
|
|
# x/y, right_div, left_div, point, all |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub _init_div { |
|
60
|
1
|
|
|
1
|
|
5
|
my $self = shift; |
|
61
|
1
|
|
|
|
|
3
|
$self->{div} = [undef, undef, undef, undef, [0..$#{$self->{names}}]] |
|
|
1
|
|
|
|
|
2254
|
|
|
62
|
|
|
|
|
|
|
} |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub _rectangles_containing_dot { |
|
65
|
2000
|
|
|
2000
|
|
4765
|
my ($div, $rects, $x, $y) = @_; |
|
66
|
|
|
|
|
|
|
# print "."; |
|
67
|
2000
|
|
|
|
|
3678
|
while (1) { |
|
68
|
27750
|
|
66
|
|
|
73827
|
my $dir = $div->[0] || _divide_rects($div, $rects); |
|
69
|
|
|
|
|
|
|
|
|
70
|
27750
|
100
|
|
|
|
61324
|
if ($dir eq 'n') { |
|
71
|
2000
|
|
|
|
|
3322
|
my @ret; |
|
72
|
2000
|
|
|
|
|
3535
|
for (@{$div->[4]}) { |
|
|
2000
|
|
|
|
|
6998
|
|
|
73
|
83175
|
|
|
|
|
130590
|
my ($x0, $y0, $x1, $y1) = @{$rects}[4*$_ .. 4*$_+3]; |
|
|
83175
|
|
|
|
|
158466
|
|
|
74
|
83175
|
100
|
100
|
|
|
456887
|
push @ret, $_ |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
75
|
|
|
|
|
|
|
if ($x >= $x0 and $x <= $x1 and $y >= $y0 && $y <= $y1); |
|
76
|
|
|
|
|
|
|
} |
|
77
|
2000
|
|
|
|
|
11059
|
return @ret; |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
|
|
80
|
25750
|
100
|
|
|
|
78170
|
$div = $div->[(($dir eq 'x') ? ($x <= $div->[3]) : ($y <= $div->[3])) ? 1 : 2]; |
|
|
|
100
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
} |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub _find_best_div { |
|
85
|
2072
|
|
|
2072
|
|
3086
|
my ($dr, $rects, $off) = @_; |
|
86
|
|
|
|
|
|
|
|
|
87
|
2072
|
|
|
|
|
6141
|
my @v0 = map { @{$rects}[$_*4+$off] } @$dr; |
|
|
486478
|
|
|
|
|
504468
|
|
|
|
486478
|
|
|
|
|
960104
|
|
|
88
|
2072
|
|
|
|
|
23031
|
my @v1 = map { @{$rects}[$_*4+2+$off] } @$dr; |
|
|
486478
|
|
|
|
|
515262
|
|
|
|
486478
|
|
|
|
|
740885
|
|
|
89
|
2072
|
|
|
|
|
25341
|
@v0 = sort { $a <=> $b } @v0; |
|
|
3561999
|
|
|
|
|
3273639
|
|
|
90
|
2072
|
|
|
|
|
9657
|
@v1 = sort { $a <=> $b } @v1; |
|
|
3591172
|
|
|
|
|
3195535
|
|
|
91
|
|
|
|
|
|
|
|
|
92
|
2072
|
|
|
|
|
4906
|
my $med = 0.5 * @$dr; |
|
93
|
2072
|
|
|
|
|
3862
|
my $op = 0; |
|
94
|
2072
|
|
|
|
|
2436
|
my $cl = 0; |
|
95
|
2072
|
|
|
|
|
5272
|
my $best = @$dr * @$dr; |
|
96
|
2072
|
|
|
|
|
3038
|
my $bestv; |
|
97
|
|
|
|
|
|
|
# my ($bestop, $bestcl); |
|
98
|
2072
|
|
66
|
|
|
13026
|
while (@v0 and @v1) { |
|
99
|
41563
|
100
|
|
|
|
79962
|
my $v = ($v0[0] <= $v1[0]) ? $v0[0] : $v1[0]; |
|
100
|
41563
|
|
100
|
|
|
153776
|
while (@v0 and $v0[0] == $v) { |
|
101
|
486478
|
|
|
|
|
446388
|
$op++; |
|
102
|
486478
|
|
|
|
|
1803866
|
shift @v0; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
41563
|
|
66
|
|
|
169121
|
while (@v1 and $v1[0] == $v) { |
|
105
|
238343
|
|
|
|
|
223789
|
$cl++; |
|
106
|
238343
|
|
|
|
|
866526
|
shift @v1; |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
|
|
109
|
41563
|
|
|
|
|
56012
|
my $l = $op - $med; |
|
110
|
41563
|
|
|
|
|
55108
|
my $r = @$dr - $cl - $med; |
|
111
|
41563
|
|
|
|
|
57175
|
my $good = $l * $l + $r * $r; |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
#{ no warnings; print STDERR "med: $med, op: $op, cl: $cl, good: $good, best: $best, bestv: $bestv\n"; } |
|
114
|
|
|
|
|
|
|
|
|
115
|
41563
|
100
|
|
|
|
115564
|
if ($good < $best) { |
|
116
|
29536
|
|
|
|
|
28981
|
$best = $good; |
|
117
|
29536
|
|
|
|
|
127082
|
$bestv = $v; |
|
118
|
|
|
|
|
|
|
# $bestop = $op; |
|
119
|
|
|
|
|
|
|
# $bestcl = $cl; |
|
120
|
|
|
|
|
|
|
} |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
# print "off: $off, best: $best, bestv: $bestv, bestop: $bestop, bestcl: $bestcl, size-bestcl: ".(@$dr-$bestcl)."\n"; |
|
123
|
2072
|
|
|
|
|
14692
|
return ($best, $bestv); |
|
124
|
|
|
|
|
|
|
} |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub _divide_rects { |
|
127
|
1036
|
|
|
1036
|
|
2156
|
my ($div, $rects) = @_; |
|
128
|
1036
|
|
|
|
|
1610
|
my $dr = $div->[4]; |
|
129
|
1036
|
50
|
|
|
|
2924
|
return $div->[0] = 'n' if (@$dr <= $MIN_DIV); |
|
130
|
1036
|
|
|
|
|
2363
|
my $bestreq = 0.24 * @$dr * @$dr; |
|
131
|
1036
|
|
|
|
|
2803
|
my ($bestx, $bestxx) = _find_best_div($dr, $rects, 0); |
|
132
|
1036
|
50
|
|
|
|
4716
|
my ($besty, $bestyy) = ($bestx == 0) ? 1 : _find_best_div($dr, $rects, 1); |
|
133
|
|
|
|
|
|
|
# print "bestx: $bestx, bestxx: $bestxx, besty: $besty, bestyy: $bestyy, bestreq: $bestreq\n"; |
|
134
|
1036
|
100
|
|
|
|
4005
|
if ($bestx < $besty) { |
|
135
|
509
|
100
|
|
|
|
2020
|
if ($bestx < $bestreq) { |
|
136
|
365
|
|
|
|
|
1891
|
@{$div}[1,2] = _part_rects($dr, $rects, $bestxx, 0); |
|
|
365
|
|
|
|
|
1238
|
|
|
137
|
365
|
|
|
|
|
775
|
$div->[3] = $bestxx; |
|
138
|
365
|
|
|
|
|
548
|
pop @$div; |
|
139
|
365
|
|
|
|
|
10749
|
return $div->[0] = 'x'; |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
} |
|
142
|
|
|
|
|
|
|
else { |
|
143
|
527
|
100
|
|
|
|
2645
|
if ($besty < $bestreq) { |
|
144
|
327
|
|
|
|
|
1486
|
@{$div}[1,2] = _part_rects($dr, $rects, $bestyy, 1); |
|
|
327
|
|
|
|
|
1261
|
|
|
145
|
327
|
|
|
|
|
755
|
$div->[3] = $bestyy; |
|
146
|
327
|
|
|
|
|
424
|
pop @$div; |
|
147
|
327
|
|
|
|
|
5307
|
return $div->[0] = 'y'; |
|
148
|
|
|
|
|
|
|
} |
|
149
|
|
|
|
|
|
|
} |
|
150
|
344
|
|
|
|
|
2382
|
return $div->[0] = 'n'; |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub _part_rects { |
|
154
|
692
|
|
|
692
|
|
1743
|
my ($dr, $rects, $bestv, $off) = @_; |
|
155
|
692
|
|
|
|
|
1186
|
my (@l, @r); |
|
156
|
692
|
|
|
|
|
2267
|
for (@$dr) { |
|
157
|
202863
|
100
|
|
|
|
484496
|
push @l, $_ if ($bestv >= $rects->[$_ * 4 + $off]); |
|
158
|
202863
|
100
|
|
|
|
463676
|
push @r, $_ if ($bestv < $rects->[$_ * 4 + $off + 2]); |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
# print "off: $off, left: ".scalar(@l).", right: ".scalar(@r)."\n"; |
|
161
|
692
|
|
|
|
|
6013
|
return ([undef, undef, undef, undef, \@l], |
|
162
|
|
|
|
|
|
|
[undef, undef, undef, undef, \@r]) |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
package Algorithm::RectanglesContainingDot; |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
our @ISA; |
|
168
|
|
|
|
|
|
|
if (eval "require Algorithm::RectanglesContainingDot_XS") { |
|
169
|
|
|
|
|
|
|
@ISA = qw(Algorithm::RectanglesContainingDot_XS); |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
else { |
|
172
|
|
|
|
|
|
|
@ISA = qw(Algorithm::RectanglesContainingDot::Perl); |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
1; |
|
176
|
|
|
|
|
|
|
__END__ |