did things

This commit is contained in:
Aaro Koivukangas
2026-04-15 10:39:02 +03:00
parent 2ce94f46ca
commit 140b24dbb5
9 changed files with 529 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
import time
import random
class BellmanFord:
def __init__(self, nodes):
self.nodes = nodes
self.edges = []
def add_edge(self, node_a, node_b, weight):
self.edges.append((node_a, node_b, weight))
def find_distances(self, start_node):
distances = {}
for node in self.nodes:
distances[node] = float("inf")
distances[start_node] = 0
num_rounds = len(self.nodes) - 1
for _ in range(num_rounds):
for edge in self.edges:
node_a, node_b, weight = edge
new_distance = distances[node_a] + weight
if new_distance < distances[node_b]:
distances[node_b] = new_distance
return distances
if __name__ == "__main__":
start = time.time()
ls = [x for x in range(1, 5000 + 1)]
random.shuffle(ls)
bf = BellmanFord(ls)
for i in range(1, 5000 + 1):
for j in range(1, i):
if i - j < 10:
bf.add_edge(j, i, random.randint(1, 1000))
distances = bf.find_distances(1)
end = time.time()
print(f"Time: {end - start:.2f}s")
+56
View File
@@ -0,0 +1,56 @@
import math
import heapq
class BestRoute:
def __init__(self, nodes: int):
self.nodes = [x for x in range(1, nodes+1)]
self.graph = {node: [] for node in self.nodes}
def add_road(self, node_a, node_b, weight):
self.graph[node_a].append((node_b, weight))
self.graph[node_b].append((node_a, weight))
def find_distances(self, start_node):
distances = {}
for node in self.nodes:
distances[node] = float("inf")
distances[start_node] = 0
queue = []
heapq.heappush(queue, (0, start_node))
visited = set()
while queue:
node_a = heapq.heappop(queue)[1]
if node_a in visited:
continue
visited.add(node_a)
for node_b, weight in self.graph[node_a]:
new_distance = distances[node_a] + weight
if new_distance < distances[node_b]:
distances[node_b] = new_distance
new_pair = (new_distance, node_b)
heapq.heappush(queue, new_pair)
return distances
def find_route(self, start_n, end_n):
distances = self.find_distances(start_n)
# print(distances, distances[end_n])
if distances[end_n] == math.inf:
return -1
return distances[end_n]
if __name__ == "__main__":
routes = BestRoute(3)
routes.add_road(1, 2, 2)
print(routes.find_route(1, 3)) # -1
routes.add_road(3, 1, 5)
print(routes.find_route(1, 3)) # 5
routes.add_road(2, 3, 1)
print(routes.find_route(1, 3)) # 3
+53
View File
@@ -0,0 +1,53 @@
import time
import random
import heapq
class Dijkstra:
def __init__(self, nodes):
self.nodes = nodes
self.graph = {node: [] for node in nodes}
def add_edge(self, node_a, node_b, weight):
self.graph[node_a].append((node_b, weight))
def find_distances(self, start_node):
distances = {}
for node in self.nodes:
distances[node] = float("inf")
distances[start_node] = 0
queue = []
heapq.heappush(queue, (0, start_node))
visited = set()
while queue:
node_a = heapq.heappop(queue)[1]
if node_a in visited:
continue
visited.add(node_a)
for node_b, weight in self.graph[node_a]:
new_distance = distances[node_a] + weight
if new_distance < distances[node_b]:
distances[node_b] = new_distance
new_pair = (new_distance, node_b)
heapq.heappush(queue, new_pair)
return distances
if __name__ == "__main__":
start = time.time()
ls = [x for x in range(1, 5000 + 1)]
random.shuffle(ls)
d = Dijkstra(ls)
for i in range(1, 5000 + 1):
for j in range(1, i):
if i - j < 10:
d.add_edge(j, i, random.randint(1, 1000))
distances = d.find_distances(1)
end = time.time()
print(f"Time: {end - start:.2f}s")
+62
View File
@@ -0,0 +1,62 @@
import math
import heapq
class Dijkstra:
def __init__(self, nodes):
self.nodes = nodes
self.graph = {node: [] for node in range(len(nodes))}
def add_edge(self, node_a, node_b, weight):
self.graph[node_a].append((node_b, weight))
def find_distances(self, start_node):
distances = {}
for i in range(len(self.nodes)):
distances[i] = float("inf")
distances[start_node] = 0
queue = []
heapq.heappush(queue, (0, start_node))
visited = set()
while queue:
node_a = heapq.heappop(queue)[1]
if node_a in visited:
continue
visited.add(node_a)
for node_b, weight in self.graph[node_a]:
new_distance = distances[node_a] + weight
if new_distance < distances[node_b]:
distances[node_b] = new_distance
new_pair = (new_distance, node_b)
heapq.heappush(queue, new_pair)
return distances
def find_steps(numbers):
d = Dijkstra(numbers)
for i in range(len(numbers)):
# left
if i-numbers[i] >= 0:
d.add_edge(i, i - numbers[i], numbers[i])
# right
if i+numbers[i] < len(numbers):
d.add_edge(i, i+numbers[i], numbers[i])
distances = d.find_distances(0)
# print(distances, distances[len(numbers)-1])
if distances[len(numbers)-1] == math.inf:
return -1
return distances[len(numbers)-1]
if __name__ == "__main__":
print(find_steps([1, 1, 1, 1])) # 3
print(find_steps([3, 2, 1])) # -1
print(find_steps([3, 5, 2, 2, 2, 3, 5])) # 10
print(find_steps([7, 5, 3, 1, 4, 2, 4, 6, 1])) # 32
numbers = []
for i in range(10**5):
numbers.append(1337 * i % 100 + 1)
print(find_steps(numbers)) # 100055
+90
View File
@@ -0,0 +1,90 @@
import math
class TrainPrices:
def __init__(self):
self.nodes = []
self.graph = {}
for a in self.nodes:
for b in self.nodes:
distance = 0 if a == b else float("inf")
self.graph[(a, b)] = distance
def add_city(self, name):
self.nodes.append(name)
self.nodes.sort()
for a in self.nodes:
for b in self.nodes:
distance = 0 if a == b else float("inf")
self.graph[(a, b)] = distance
def add_train(self, a, b, w):
self.graph[(a, b)] = min(self.graph[(a, b)], w)
self.graph[(b, a)] = min(self.graph[(a, b)], w)
def find_prices(self):
distances = self.graph.copy()
for k in self.nodes:
for a in self.nodes:
for b in self.nodes:
distance = min(
distances[(a, b)], distances[(a, k)] + distances[(k, b)]
)
distances[(a, b)] = distance
result = []
result.append([None] + [x for x in self.nodes])
for x in self.nodes:
row = [x]
for y in self.nodes:
row.append(-1 if distances[(x,y)] == math.inf else distances[(x,y)])
result.append(row)
# print(distances)
# for x in result:
# print(x)
return result
class TrainPrices2:
def __init__(self):
pass
def add_city(self, name):
pass
def add_train(self, city1, city2, price):
pass
def find_prices(self):
pass
if __name__ == "__main__":
prices = TrainPrices()
prices.add_city("Helsinki")
prices.add_city("Turku")
prices.add_city("Tampere")
prices.add_city("Oulu")
prices.add_train("Helsinki", "Tampere", 20)
prices.add_train("Helsinki", "Turku", 10)
prices.add_train("Tampere", "Turku", 50)
print(prices.find_prices())
print()
prices = TrainPrices()
prices.add_city("Helsinki")
prices.add_city("Oulu")
prices.add_train("Helsinki", "Oulu", 14)
print(prices.find_prices())
# metodin haluttu tulos:
# [[None, 'Helsinki', 'Oulu', 'Tampere', 'Turku'],
# ['Helsinki', 0, -1, 20, 10],
# ['Oulu', -1, 0, -1, -1],
# ['Tampere', 20, -1, 0, 30],
# ['Turku', 10, -1, 30, 0]]
+46
View File
@@ -0,0 +1,46 @@
class UnionFind:
def __init__(self, nodes):
self.link = {node: None for node in nodes}
self.size = {node: 1 for node in nodes}
def find(self, x):
while self.link[x]:
x = self.link[x]
return x
def union(self, a, b):
a = self.find(a)
b = self.find(b)
if a == b:
return
if self.size[a] > self.size[b]:
a, b = b, a
self.link[a] = b
self.size[b] += self.size[a]
class Components:
def __init__(self, n):
self.uf = UnionFind([x for x in range(1, n + 1)])
def add_road(self, a, b):
self.uf.union(a, b)
def count(self):
return list(self.uf.link.values()).count(None)
if __name__ == "__main__":
components = Components(5)
print(components.count()) # 5
components.add_road(1, 2)
components.add_road(1, 3)
print(components.count()) # 3
components.add_road(2, 3)
print(components.count()) # 3
components.add_road(4, 5)
print(components.count()) # 2
+57
View File
@@ -0,0 +1,57 @@
class UnionFind:
def __init__(self, nodes):
self.link = {node: None for node in nodes}
self.size = {node: 1 for node in nodes}
self.longest = 1
def find(self, x):
while self.link[x]:
x = self.link[x]
return x
def union(self, a, b):
a = self.find(a)
b = self.find(b)
if a == b:
return
if self.size[a] > self.size[b]:
a, b = b, a
self.link[a] = b
self.size[b] += self.size[a]
self.longest = max(self.size[b], self.longest)
def get_max(self):
return self.longest
class MaxSet:
def __init__(self, n):
self.uf = UnionFind([x for x in range(1, n + 1)])
def merge(self, a, b):
self.uf.union(a, b)
def get_max(self):
return self.uf.get_max()
if __name__ == "__main__":
max_set = MaxSet(5)
print(max_set.get_max()) # 1
max_set.merge(1, 2)
max_set.merge(3, 4)
max_set.merge(3, 5)
print(max_set.get_max()) # 3
max_set.merge(1, 5)
print(max_set.get_max()) # 5
max_set.merge(2, 3)
print(max_set.get_max()) # 5
max_set = MaxSet(10**5)
for i in range(2, 10**5 + 1):
max_set.merge(1, i)
print(max_set.get_max())
+62
View File
@@ -0,0 +1,62 @@
class UnionFind:
def __init__(self, nodes):
self.link = {node: None for node in nodes}
self.size = {node: 1 for node in nodes}
def find(self, x: int):
while self.link.get(x):
x = self.link.get(x)
return x
def union(self, a, b):
a = self.find(a)
b = self.find(b)
if a == b:
return
if self.size[a] > self.size[b]:
a, b = b, a
self.link[a] = b
self.size[b] += self.size[a]
class NewRoads:
def __init__(self, nodes):
nodes = [x for x in range(1, nodes + 1)]
self.nodes = nodes
self.edges = []
def add_road(self, node_a, node_b, weight):
self.edges.append((node_a, node_b, weight))
def min_cost(self):
self.edges.sort(key=lambda x: x[2])
uf = UnionFind(self.nodes)
edges_count = 0
tree_weight = 0
for edge in self.edges:
node_a, node_b, weight = edge
if uf.find(node_a) != uf.find(node_b):
uf.union(node_a, node_b)
edges_count += 1
tree_weight += weight
if edges_count != len(self.nodes) - 1:
return -1
return tree_weight
if __name__ == "__main__":
new_roads = NewRoads(4)
new_roads.add_road(1, 2, 2)
new_roads.add_road(1, 3, 5)
print(new_roads.min_cost()) # -1
new_roads.add_road(3, 4, 4)
print(new_roads.min_cost()) # 11
new_roads.add_road(2, 3, 1)
print(new_roads.min_cost()) # 7
+60
View File
@@ -0,0 +1,60 @@
class UnionFind:
def __init__(self, nodes):
self.link = {node: None for node in nodes}
self.size = {node: 1 for node in nodes}
def find(self, x):
while self.link[x]:
x = self.link[x]
return x
def union(self, a, b):
a = self.find(a)
b = self.find(b)
if a == b:
return
if self.size[a] > self.size[b]:
a, b = b, a
self.link[a] = b
self.size[b] += self.size[a]
class Kruskal:
def __init__(self, nodes):
self.nodes = nodes
self.edges = []
def add_edge(self, node_a, node_b, weight):
self.edges.append((node_a, node_b, weight))
def construct(self):
self.edges.sort(key=lambda x: -x[2])
uf = UnionFind(self.nodes)
edges_count = 0
tree_weight = 0
for edge in self.edges:
node_a, node_b, weight = edge
if uf.find(node_a) != uf.find(node_b):
print(node_a, node_b)
uf.union(node_a, node_b)
edges_count += 1
tree_weight += weight
if edges_count != len(self.nodes) - 1:
return None
return tree_weight
def main():
nodes = [x for x in range(1,1000+1)]
k = Kruskal(nodes)
for i in nodes:
for j in range(1,i):
k.add_edge(j, i, min(i, j))
print(k.construct())
if __name__ == "__main__":
main()