-
Notifications
You must be signed in to change notification settings - Fork 21
/
j_optimized_hashing.py
48 lines (35 loc) · 1.88 KB
/
j_optimized_hashing.py
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
# Здесь реализована идея проверки на вырожденность через set обратных векторов,
# где ключ вектора считается как произведение его координат со сдвигом.
from collections import defaultdict
# Сдвиг для вычисления уникального значения произведения координат вектора.
# Сдвиг именно такой, потому что если его сделать хотя бы на 1 меньше,
# то начнутся коллизии, можно рассмотреть краевой случай (0, 10**9) и (1, -10**9))
SHIFT = 2 * 10 ** 9 + 1
def triangles(points):
triangles_count = 0
for (x1, y1) in points:
opposite_vectors_xy_product = set()
points_by_distances = defaultdict(int)
for x2, y2 in points:
x = x2 - x1
y = y2 - y1
squared_distance = x ** 2 + y ** 2
triangles_count += points_by_distances[squared_distance]
previous_vectors_xy_product_values = abs(x * SHIFT + y)
if previous_vectors_xy_product_values in opposite_vectors_xy_product:
triangles_count -= 1
else:
opposite_vectors_xy_product.add(previous_vectors_xy_product_values)
points_by_distances[squared_distance] += 1
return triangles_count
assert triangles([(0, 0), (-1, 0), (0, -1), (0, 1), (1, 0)]) == 8
assert triangles([(0, 0), (2, 2), (-2, 2)]) == 1
assert triangles([(0, 0), (2, 2), (-2, -2)]) == 0
assert triangles([(0, 0), (1, 1), (1, 0), (0, 1)]) == 4
assert triangles([(0, 0), (1, 1), (0, 1), (1, 0), (0, -1)]) == 6
def main():
n = int(input())
points = [tuple(map(int, input().split())) for _ in range(n)]
print(triangles(points))
if __name__ == '__main__':
main()