# [SOLVED] Using definition on elements of a list to decide which give smallest answer

## Issue

In the code below I have calculated which triangles cover a certain point. Now I am trying to let the function `perimeter` calculate the perimeter of the left over triangles which can be found in `triangle_fit`. And when I know the perimeters of these triangles I want to chose the smallest triangle. I did some attempts but the function will only recognize `x1`, `y1`, `x2`, `...`.

``````import itertools
import math

def area(x1, y1, x2, y2, x3, y3):
return abs((x1 * (y2 - y3) + x2 * (y3 - y1)
+ x3 * (y1 - y2)) / 2.0)

def isInside(x1, y1, x2, y2, x3, y3, x, y):
A = area (x1, y1, x2, y2, x3, y3)
A1 = area (x, y, x2, y2, x3, y3)
A2 = area (x1, y1, x, y, x3, y3)
A3 = area (x1, y1, x2, y2, x, y)
if(A == A1 + A2 + A3):
return True
else:
return False

def perimeter (x1, y1, x2, y2, x3, y3):
return abs(math.sqrt((x1-x2)**2+(y1-y2)**2)+math.sqrt((x2-x3)^2
+(y2-y3)**2)+math.sqrt((x3-x1)**2+(y3-y1)**2))

points = [(0,10), (0,0), (10,0), (10,10), (5,2), (2,2)]
P = (5,1)
triangle_fit = []

for triangle in itertools.combinations(points, 3):
p1, p2, p3 = triangle
if isInside(*p1, *p2, *p3, *P):
triangle_fit.append(triangle)

print(triangle_fit)
``````

## Solution

You can do it by sorting the list of triangles by their perimeter which will move the smaller ones to the beginning (note there can be more than one that is smallest if they have the same perimeter).

To make doing this easier I changed the calling sequence of your `perimeter()` function to accept a sequence of three points to match the format of the contents of the `triangle_fit` list. I also changed it to use the `math.hypot()` function to compute the Euclidean-distance between each pair points. Doing this not only makes it a little faster, it also fixed a bug in your code I noticed where you used `^` instead of `**` for exponentiation.

``````import itertools
import math

def area(x1, y1, x2, y2, x3, y3):
return abs((x1 * (y2 - y3) +
x2 * (y3 - y1) +
x3 * (y1 - y2)) / 2.0)

def is_inside(x1, y1, x2, y2, x3, y3, x, y):
A = area(x1, y1, x2, y2, x3, y3)
A1 = area(x, y, x2, y2, x3, y3)
A2 = area(x1, y1, x, y, x3, y3)
A3 = area(x1, y1, x2, y2, x, y)
return A == A1 + A2 + A3

def perimeter(points):
(x1, y1), (x2, y2), (x3, y3) = points
return (math.hypot(x1-x2, y1-y2) +
math.hypot(x2-x3, y2-y3) +
math.hypot(x3-x1, y3-y1))

points = [(0,10), (0,0), (10,0), (10,10), (5,2), (2,2)]
P = (5,1)
triangle_fit = []

for triangle in itertools.combinations(points, 3):
p1, p2, p3 = triangle
if is_inside(*p1, *p2, *p3, *P):
triangle_fit.append(triangle)

triangle_fit.sort(key=perimeter)  # Sort by perimeter.

for points in triangle_fit:
print(f'{points}: area={area(*points[0], *points[1], *points[2]):.2f}')

``````