1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
"""
Part of the tagit module.
A copy of the license is provided with the project.
Author: Matthias Baumgartner, 2022
"""
# exports
__all__ = (
'by_area',
'by_area_min',
)
## code ##
def by_area(target, candidates):
"""Pick the item from *candidates* whose area is most similar to *target*."""
target_area = target[0] * target[1]
scores = [
(key, abs(target_area - res[0] * res[1]))
for key, res in candidates
]
best_key, best_score = min(scores, key=lambda key_score: key_score[1])
return best_key
def by_area_min(target, candidates):
"""Pick the item from *candidates* whose area is at least that of *target*."""
# rank the candidates by area difference
# a positive score means that the candidate is larger than the target.
target_area = target[0] * target[1]
scores = [(key, res[0] * res[1] - target_area) for key, res in candidates]
# identify the two items with
# a) the smallest positive score (kmin), or
# b) the largest negative score (kmax)
kmin, kmax = None, None
cmin, cmax = float('inf'), float('-inf')
for key, score in scores:
if score >= 0 and score < cmin:
kmin, cmin = key, score
elif score < 0 and score > cmax:
kmax, cmax = key, score
# prefer positive over negative scores
if cmin < float('inf'):
return kmin
if cmax > float('-inf'):
return kmax
# no viable resolution found
raise IndexError('list contains no valid element')
## EOF ##
|