81 lines
2.4 KiB
Python

def solution(banana_list):
loop_memo = {}
edge_map = {i: [] for i in range(len(banana_list))}
for i in range(len(banana_list)):
for j in range(i+1, len(banana_list)):
if check_loop(banana_list[i], banana_list[j], loop_memo):
edge_map[i] += [j]
edge_map[j] += [i]
return len(banana_list) - len(find_maximum_matching(edge_map))
def find_maximum_matching(edge_map):
exposed_vertex_list = [i for i in edge_map]
matching = {}
while len(exposed_vertex_list) >= 2:
start = exposed_vertex_list.pop()
path, end = find_new_path(edge_map, start, exposed_vertex_list, matching, {})
if end in exposed_vertex_list:
update_matching(matching, start, path, end)
exposed_vertex_list.remove(end)
return matching
import copy
def find_new_path(edge_map, curr, end_list, matching, color):
for neighbor in edge_map[curr]:
if neighbor in end_list:
return [], neighbor
color[curr] = True
for neighbor in edge_map[curr]:
if neighbor in color:
continue
temp_color = copy.deepcopy(color)
temp_color[neighbor] = True
new_path, end = find_new_path(edge_map, matching[neighbor], end_list, matching, temp_color)
return [(curr, neighbor)] + new_path, end
return [], None
def update_matching(matching, start, path, end):
new_left = start
for left, right in path:
matching[new_left] = left
matching[left] = new_left
new_left = right
matching[new_left] = end
matching[end] = new_left
# How check_loop works
# 1. (ac, bc) => (2ac, bc-ac) = (a, b) => (2a, b-a)
# * a < b
# 1. (ac, bc+d) => (2ac, bc+d-ac) = (2ac, (b-a)c+d)
# * a < b and 0 < d < c
# 1. (a, 2n-a) => (2a, 2n-2a) = (a, n-a)
# * a < n
# 1. therefore, (x, y) will loop iff (x + y) % 2 == 1
# * x and y are relative prime number
def check_loop(x, y, memo):
if (x, y) in memo:
return memo[(x, y)]
return bin((x + y)/gcd(x, y)).count('1') != 1
def gcd(m, n):
while n != 0:
t = m % n
m, n = n, t
return m
tests = [
([1], 1),
([1, 1], 2),
([1, 7, 3, 21, 13, 19], 0),
#([1 for i in range(100)], 100),
#([2**(i+1) - 1 for i in range(10)], 2),
#([2**(i+1) - 1 for i in range(20)], 2),
]
for i, o in tests:
result = solution(i)
print(i, result == o, result, o)