From 6385c443db8bf4ea8c1b3f4eacfa9f9a50dc5057 Mon Sep 17 00:00:00 2001 From: Aaro Koivukangas Date: Wed, 17 Jun 2026 23:09:20 +0300 Subject: [PATCH] Did week 16 --- viikko16/ball.py | 83 ++++++++++++++++++++++++++++++++++++++++++++ viikko16/download.py | 63 +++++++++++++++++++++++++++++++++ viikko16/max_flow.py | 59 +++++++++++++++++++++++++++++++ viikko16/planets.py | 80 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 285 insertions(+) create mode 100644 viikko16/ball.py create mode 100644 viikko16/download.py create mode 100644 viikko16/max_flow.py create mode 100644 viikko16/planets.py diff --git a/viikko16/ball.py b/viikko16/ball.py new file mode 100644 index 0000000..f674996 --- /dev/null +++ b/viikko16/ball.py @@ -0,0 +1,83 @@ +import math + + +class MaximumFlow: + def __init__(self, nodes): + self.nodes = nodes + self.graph = {} + for i in self.nodes: + for j in self.nodes: + self.graph[(i, j)] = 0 + + def add_edge(self, node_a, node_b, capacity): + self.graph[(node_a, node_b)] += capacity + + def add_flow(self, node, sink, flow): + if node in self.seen: + return 0 + self.seen.add(node) + if node == sink: + return flow + for next_node in self.nodes: + if self.flow[(node, next_node)] > 0: + new_flow = min(flow, self.flow[(node, next_node)]) + inc = self.add_flow(next_node, sink, new_flow) + if inc > 0: + self.flow[(node, next_node)] -= inc + self.flow[(next_node, node)] += inc + return inc + return 0 + + def construct(self, source, sink): + self.flow = self.graph.copy() + total = 0 + while True: + self.seen = set() + add = self.add_flow(source, sink, float("inf")) + if add == 0: + break + total += add + return total + + +class Ball: + def __init__(self, n): + nodes = [] + for x in range(1, n+1): + nodes.append("a" + str(x)) + nodes.append("b" + str(x)) + nodes.append("0") + nodes.append(str(n+1)) + self.n = n + self.mf = MaximumFlow(nodes) + self.unique = { "a": set(), "b": set()} + + def add_pair(self, a: int, b: int): + if a not in self.unique["a"]: + self.unique["a"].add(a) + self.mf.add_edge("0", "a" + str(a), 1) + if b not in self.unique["b"]: + self.unique["b"].add(b) + self.mf.add_edge("b" + str(b), str(self.n + 1), 1) + + self.mf.add_edge("a" + str(a), "b" + str(b), 1) + # print(self.mf.graph) + + def max_pairs(self): + return self.mf.construct("0", str(self.n + 1)) + + +if __name__ == "__main__": + ball = Ball(4) + + print(ball.max_pairs()) # 0 + + ball.add_pair(1, 2) + print(ball.max_pairs()) # 1 + + ball.add_pair(1, 3) + ball.add_pair(3, 2) + print(ball.max_pairs()) # 2 + + ball.add_pair(2, 1) + print(ball.max_pairs()) # 3 diff --git a/viikko16/download.py b/viikko16/download.py new file mode 100644 index 0000000..b965653 --- /dev/null +++ b/viikko16/download.py @@ -0,0 +1,63 @@ +class MaximumFlow: + def __init__(self, nodes): + self.nodes = nodes + self.graph = {} + for i in self.nodes: + for j in self.nodes: + self.graph[(i, j)] = 0 + + def add_edge(self, node_a, node_b, capacity): + self.graph[(node_a, node_b)] += capacity + + def add_flow(self, node, sink, flow): + if node in self.seen: + return 0 + self.seen.add(node) + if node == sink: + return flow + for next_node in self.nodes: + if self.flow[(node, next_node)] > 0: + new_flow = min(flow, self.flow[(node, next_node)]) + inc = self.add_flow(next_node, sink, new_flow) + if inc > 0: + self.flow[(node, next_node)] -= inc + self.flow[(next_node, node)] += inc + return inc + return 0 + + def construct(self, source, sink): + self.flow = self.graph.copy() + total = 0 + while True: + self.seen = set() + add = self.add_flow(source, sink, float("inf")) + if add == 0: + break + total += add + return total + + +class Download: + def __init__(self, n): + self.mf = MaximumFlow([x for x in range(1, n + 1)]) + + def add_link(self, a, b, x): + self.mf.add_edge(a, b, x) + + def max_data(self, a, b): + return self.mf.construct(a, b) + + +if __name__ == "__main__": + download = Download(4) + + print(download.max_data(1, 4)) # 0 + + download.add_link(1, 2, 5) + download.add_link(2, 4, 6) + download.add_link(1, 4, 2) + print(download.max_data(1, 4)) # 7 + + download.add_link(1, 3, 4) + download.add_link(3, 2, 2) + print(download.max_data(1, 4)) # 8 diff --git a/viikko16/max_flow.py b/viikko16/max_flow.py new file mode 100644 index 0000000..3f5830b --- /dev/null +++ b/viikko16/max_flow.py @@ -0,0 +1,59 @@ +class MaximumFlow: + def __init__(self, nodes): + self.nodes = nodes + self.graph = {} + for i in self.nodes: + for j in self.nodes: + self.graph[(i, j)] = 0 + + def add_edge(self, node_a, node_b, capacity): + self.graph[(node_a, node_b)] += capacity + + def add_flow(self, node, sink, flow): + if node in self.seen: + return 0 + self.seen.add(node) + if node == sink: + return flow + for next_node in self.nodes: + if self.flow[(node, next_node)] > 0: + new_flow = min(flow, self.flow[(node, next_node)]) + inc = self.add_flow(next_node, sink, new_flow) + if inc > 0: + self.flow[(node, next_node)] -= inc + self.flow[(next_node, node)] += inc + return inc + return 0 + + def construct(self, source, sink): + self.flow = self.graph.copy() + total = 0 + while True: + self.seen = set() + add = self.add_flow(source, sink, float("inf")) + if add == 0: + break + total += add + return total + +if __name__ == "__main__": + mf = MaximumFlow([x for x in range(1,7+1)]) + mf.add_edge(1,2,7) + mf.add_edge(1,5,15) + + mf.add_edge(2,3,3) + mf.add_edge(2,4,2) + + mf.add_edge(3,7,8) + + mf.add_edge(4,3,4) + mf.add_edge(4,7,3) + + mf.add_edge(5,4,3) + mf.add_edge(5,6,9) + + mf.add_edge(6,4,5) + mf.add_edge(6,7,5) + + print(mf.construct(1,7)) + diff --git a/viikko16/planets.py b/viikko16/planets.py new file mode 100644 index 0000000..b8e3b08 --- /dev/null +++ b/viikko16/planets.py @@ -0,0 +1,80 @@ +class MaximumFlow: + def __init__(self, nodes): + self.nodes = nodes + self.graph = {} + for i in self.nodes: + for j in self.nodes: + self.graph[(i, j)] = 0 + + def add_edge(self, node_a, node_b, capacity): + self.graph[(node_a, node_b)] += capacity + + def add_flow(self, node, sink, flow): + if node in self.seen: + return 0 + self.seen.add(node) + if node == sink: + return flow + for next_node in self.nodes: + if self.flow[(node, next_node)] > 0: + new_flow = min(flow, self.flow[(node, next_node)]) + inc = self.add_flow(next_node, sink, new_flow) + if inc > 0: + self.flow[(node, next_node)] -= inc + self.flow[(next_node, node)] += inc + return inc + return 0 + + def construct(self, source, sink): + self.flow = self.graph.copy() + total = 0 + while True: + self.seen = set() + add = self.add_flow(source, sink, float("inf")) + if add == 0: + break + total += add + return total + + +class Planets: + def __init__(self, n): + self.n = n + self.mf = MaximumFlow([x for x in range(1, n + 1)]) + + def add_teleport(self, a, b): + self.mf.add_edge(a, b, 1) + + def min_removals(self): + return self.mf.construct(1, self.n) + + +class Planets2: + def __init__(self, n): + self.n = n + self.nodes = [x for x in range(1, n + 1)] + self.graph = {} + + def add_teleport(self, a, b): + self.graph[b] = self.graph[b].append(a) if self.graph.get(b) else [a] + + def min_removals(self): + nodes = self.graph[self.n] + lowest_teleports = 0 + for x in nodes: + pass + + return lowest_teleports + + +if __name__ == "__main__": + planets = Planets(5) + + print(planets.min_removals()) # 0 + + planets.add_teleport(1, 2) + planets.add_teleport(2, 5) + print(planets.min_removals()) # 1 + + planets.add_teleport(1, 5) + print(planets.min_removals()) # 2