import time
import random
import linked_list as ll
import hash_table as ht
import bst
import sys

sys.setrecursionlimit(20000)

def generate_records(n=10000):
    records =[]
    for i in range(n):
        name = f"User_{i:05d}"
        phone = f"+7{random.randint(9000000000, 9999999999)}"
        records.append((name, phone))
        
    records_sorted = list(records)       
    records_shuffled = list(records)
    random.shuffle(records_shuffled)
        
    return records_sorted, records_shuffled

records_sorted, records_shuffled = generate_records()

#SORTE
print("Sorte:")

#Linked list

print("Linked list")

#Вставка
head = None
start = time.perf_counter()
for name, phone in records_sorted:
    head = ll.ll_insert(head, name, phone)
end = time.perf_counter()
print(f"Insert: {end - start:.4f} sec")

#Поиск
existing = random.sample(records_sorted, 100)
missing = [f"None_{i}" for i in range(10)]
start = time.perf_counter()
for name, _ in existing:
    ll.ll_find(head, name)
for name in missing:
    ll.ll_find(head, name)
end = time.perf_counter()
print(f"Find (110): {end - start:.6f} sec")

#Удаление
to_delete = random.sample(records_sorted, 50)

start = time.perf_counter()
for name, _ in to_delete:
    head = ll.ll_delete(head, name)
end = time.perf_counter()
print(f"Delete (50): {end - start:.6f} sec")

#Hash table

print("Hash table")

#Вставка
table = ht.ht_create()
start = time.perf_counter()
for name, phone in records_sorted:
    ht.ht_insert(table, name, phone)
end = time.perf_counter()
print(f"Insert: {end - start:.4f} sec")

#Поиск
start = time.perf_counter()
for name, _ in existing:
    ht.ht_find(table, name)
for name in missing:
    ht.ht_find(table, name)
end = time.perf_counter()
print(f"Find (110): {end - start:.6f} sec")

#УДаление
start = time.perf_counter()
for name, _ in to_delete:
    ht.ht_delete(table, name)
end = time.perf_counter()
print(f"Delete (50): {end - start:.6f} sec")

#BST

print("BST")

#Вставка
root = None
start = time.perf_counter()
for name, phone in records_sorted:
    root = bst.bst_insert(root, name, phone)
end = time.perf_counter()
print(f"Insert: {end - start:.4f} sec")

#Поиск
start = time.perf_counter()
for name, _ in existing:
    bst.bst_find(root, name)
for name in missing:
    bst.bst_find(root, name)
end = time.perf_counter()
print(f"Find (110): {end - start:.6f} sec")

#Удаление
start = time.perf_counter()
for name, _ in to_delete:
    root = bst.bst_delete(root, name)
end = time.perf_counter()
print(f"Delete (50): {end - start:.6f} sec")

#SHUFFLE
print("Shuffle:")

#Linked list

print("Linked list")

#Вставка
head = None
start = time.perf_counter()
for name, phone in records_shuffled:
    head = ll.ll_insert(head, name, phone)
end = time.perf_counter()
print(f"Insert: {end - start:.4f} sec")

#Поиск
existing = random.sample(records_shuffled, 100)
missing = [f"None_{i}" for i in range(10)]
start = time.perf_counter()
for name, _ in existing:
    ll.ll_find(head, name)
for name in missing:
    ll.ll_find(head, name)
end = time.perf_counter()
print(f"Find (110): {end - start:.6f} sec")

#Удаление
to_delete = random.sample(records_shuffled, 50)

start = time.perf_counter()
for name, _ in to_delete:
    head = ll.ll_delete(head, name)
end = time.perf_counter()
print(f"Delete (50): {end - start:.6f} sec")

#Hash table

print("Hash table")

#Вставка
table = ht.ht_create()
start = time.perf_counter()
for name, phone in records_shuffled:
    ht.ht_insert(table, name, phone)
end = time.perf_counter()
print(f"Insert: {end - start:.4f} sec")

#Поиск
start = time.perf_counter()
for name, _ in existing:
    ht.ht_find(table, name)
for name in missing:
    ht.ht_find(table, name)
end = time.perf_counter()
print(f"Find (110): {end - start:.6f} sec")

#УДаление
start = time.perf_counter()
for name, _ in to_delete:
    ht.ht_delete(table, name)
end = time.perf_counter()
print(f"Delete (50): {end - start:.6f} sec")

#BST

print("BST")

#Вставка
root = None
start = time.perf_counter()
for name, phone in records_shuffled:
    root = bst.bst_insert(root, name, phone)
end = time.perf_counter()
print(f"Insert: {end - start:.4f} sec")

#Поиск
start = time.perf_counter()
for name, _ in existing:
    bst.bst_find(root, name)
for name in missing:
    bst.bst_find(root, name)
end = time.perf_counter()
print(f"Find (110): {end - start:.6f} sec")

#Удаление
start = time.perf_counter()
for name, _ in to_delete:
    root = bst.bst_delete(root, name)
end = time.perf_counter()
print(f"Delete (50): {end - start:.6f} sec")