Delete merge_server.py
Browse files- merge_server.py +0 -414
merge_server.py
DELETED
|
@@ -1,414 +0,0 @@
|
|
| 1 |
-
import os
|
| 2 |
-
import pickle
|
| 3 |
-
import torch
|
| 4 |
-
import numpy as np
|
| 5 |
-
import ast
|
| 6 |
-
from flask import Flask, request, jsonify
|
| 7 |
-
from transformers import AutoTokenizer, AutoModel
|
| 8 |
-
|
| 9 |
-
# --- IMPORT ETHAN'S HYBRID ENGINE (Checker 1 & 2) ---
|
| 10 |
-
from codesense.analyzer import analyze_code
|
| 11 |
-
|
| 12 |
-
app = Flask(__name__)
|
| 13 |
-
|
| 14 |
-
# --- CONFIG ---
|
| 15 |
-
MODEL_FILE = 'NEW_BRAIN_MLP.pk2'
|
| 16 |
-
base_dir = os.path.dirname(os.path.abspath(__file__))
|
| 17 |
-
model_path = os.path.join(base_dir, MODEL_FILE)
|
| 18 |
-
|
| 19 |
-
print("⏳ Booting up CodeSense Triple-Checker System...")
|
| 20 |
-
print("⏳ Loading Checker 1 & 2: AST Rule-Engine + CodeT5...")
|
| 21 |
-
|
| 22 |
-
# --- LOAD YOUR SAFETY NET (Checker 3: CodeBERT + pk2) ---
|
| 23 |
-
try:
|
| 24 |
-
print(f"📂 Loading Checker 3: CodeBERT Safety Net ({MODEL_FILE})...")
|
| 25 |
-
tokenizer = AutoTokenizer.from_pretrained("microsoft/codebert-base")
|
| 26 |
-
codebert = AutoModel.from_pretrained("microsoft/codebert-base")
|
| 27 |
-
|
| 28 |
-
with open(model_path, 'rb') as f:
|
| 29 |
-
classifier = pickle.load(f)
|
| 30 |
-
print("✅ All 3 AI Brains Loaded! Server Ready on Port 5000.")
|
| 31 |
-
except Exception as e:
|
| 32 |
-
print(f"❌ WARNING: Could not load Safety Net. {e}")
|
| 33 |
-
classifier = None
|
| 34 |
-
|
| 35 |
-
def get_vector(code):
|
| 36 |
-
inputs = tokenizer(code, return_tensors="pt", truncation=True, max_length=512, padding=True)
|
| 37 |
-
with torch.no_grad():
|
| 38 |
-
outputs = codebert(**inputs)
|
| 39 |
-
return outputs.last_hidden_state[:, 0, :].numpy().flatten()
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
# --- YOUR MAGIC VARIABLE EXTRACTOR & AST LOOP COUNTER ---
|
| 43 |
-
class CodeAnalyzer(ast.NodeVisitor):
|
| 44 |
-
def __init__(self):
|
| 45 |
-
self.max_loop_depth = 0
|
| 46 |
-
self.current_loop_depth = 0
|
| 47 |
-
self.func_name = "optimized_function"
|
| 48 |
-
self.args_string = "data"
|
| 49 |
-
self.first_arg = "data"
|
| 50 |
-
|
| 51 |
-
def visit_FunctionDef(self, node):
|
| 52 |
-
self.func_name = node.name
|
| 53 |
-
arg_names = [arg.arg for arg in node.args.args]
|
| 54 |
-
if arg_names:
|
| 55 |
-
self.args_string = ", ".join(arg_names)
|
| 56 |
-
self.first_arg = arg_names[0]
|
| 57 |
-
self.generic_visit(node)
|
| 58 |
-
|
| 59 |
-
def visit_For(self, node):
|
| 60 |
-
self.current_loop_depth += 1
|
| 61 |
-
if self.current_loop_depth > self.max_loop_depth:
|
| 62 |
-
self.max_loop_depth = self.current_loop_depth
|
| 63 |
-
self.generic_visit(node)
|
| 64 |
-
self.current_loop_depth -= 1
|
| 65 |
-
|
| 66 |
-
def visit_While(self, node):
|
| 67 |
-
self.current_loop_depth += 1
|
| 68 |
-
if self.current_loop_depth > self.max_loop_depth:
|
| 69 |
-
self.max_loop_depth = self.current_loop_depth
|
| 70 |
-
self.generic_visit(node)
|
| 71 |
-
self.current_loop_depth -= 1
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
# --- API ROUTE ---
|
| 75 |
-
@app.route('/predict', methods=['POST'])
|
| 76 |
-
def predict():
|
| 77 |
-
data = request.json
|
| 78 |
-
code = data.get('code', '')
|
| 79 |
-
if not code: return jsonify({"error": "No code provided"}), 400
|
| 80 |
-
|
| 81 |
-
try:
|
| 82 |
-
# 1. Extract your variables & Count Loops
|
| 83 |
-
analyzer = CodeAnalyzer()
|
| 84 |
-
try:
|
| 85 |
-
tree = ast.parse(code)
|
| 86 |
-
analyzer.visit(tree)
|
| 87 |
-
|
| 88 |
-
# --- CALCULATE TIME COMPLEXITY USING AST ---
|
| 89 |
-
loop_depth = analyzer.max_loop_depth
|
| 90 |
-
if loop_depth == 0: dynamic_comp = "O(1) (No loops)"
|
| 91 |
-
elif loop_depth == 1: dynamic_comp = "O(n) (Linear)"
|
| 92 |
-
elif loop_depth == 2: dynamic_comp = "O(n^2) (Nested loops)"
|
| 93 |
-
else: dynamic_comp = f"O(n^{loop_depth}) (Deeply nested)"
|
| 94 |
-
|
| 95 |
-
except Exception:
|
| 96 |
-
dynamic_comp = "Error parsing code structure"
|
| 97 |
-
|
| 98 |
-
# ==========================================
|
| 99 |
-
# 🛡️ THE TRIPLE-CHECKER LOGIC
|
| 100 |
-
# ==========================================
|
| 101 |
-
|
| 102 |
-
# Run Ethan's Engine
|
| 103 |
-
analysis_result = analyze_code(code)
|
| 104 |
-
|
| 105 |
-
algo = analysis_result.get("pattern", "Unknown")
|
| 106 |
-
ethan_summary = analysis_result.get("summary", "")
|
| 107 |
-
t5_raw_conf = analysis_result.get("ml_insights", {}).get("confidence", 0.0)
|
| 108 |
-
|
| 109 |
-
final_conf = t5_raw_conf
|
| 110 |
-
safety_net_triggered = False
|
| 111 |
-
|
| 112 |
-
# Patterns that mean the first engine is slightly confused
|
| 113 |
-
GENERIC_PATTERNS = ["Unknown", "Nested Iterative", "Linear Iterative", "Recursive (Linear)", "Recursive (Exponential)"]
|
| 114 |
-
|
| 115 |
-
# If AST/CodeT5 is confused, trigger YOUR CodeBERT model!
|
| 116 |
-
if (algo in GENERIC_PATTERNS or t5_raw_conf < 0.90) and classifier is not None:
|
| 117 |
-
print(f"⚠️ Primary engine unsure (Confidence: {t5_raw_conf:.2f}). Triggering CodeBERT Safety Net...")
|
| 118 |
-
|
| 119 |
-
try:
|
| 120 |
-
vector = get_vector(code)
|
| 121 |
-
bert_pred = classifier.predict([vector])[0]
|
| 122 |
-
|
| 123 |
-
try:
|
| 124 |
-
bert_probs = classifier.predict_proba([vector])[0]
|
| 125 |
-
bert_conf = float(max(bert_probs))
|
| 126 |
-
except:
|
| 127 |
-
bert_conf = 0.85
|
| 128 |
-
|
| 129 |
-
if bert_conf >= 0.80:
|
| 130 |
-
algo = bert_pred
|
| 131 |
-
final_conf = bert_conf
|
| 132 |
-
safety_net_triggered = True
|
| 133 |
-
print(f"🛡️ Safety Net Override Successful: {algo} ({bert_conf*100:.1f}%)")
|
| 134 |
-
except Exception as e:
|
| 135 |
-
print(f"Safety Net Error: {e}")
|
| 136 |
-
|
| 137 |
-
conf_percentage = (final_conf * 100) if final_conf else 100.0
|
| 138 |
-
|
| 139 |
-
# ==========================================
|
| 140 |
-
# 📚 YOUR FULL UI DICTIONARY
|
| 141 |
-
# ==========================================
|
| 142 |
-
complexity_map = {
|
| 143 |
-
# --- SORTING ---
|
| 144 |
-
"Bubble Sort": {
|
| 145 |
-
"space": "O(1)",
|
| 146 |
-
"explanation": "⚠️ CRITICAL: Bubble Sort is inefficient (O(n^2)) for large datasets. Refactor to Quick Sort or Merge Sort (O(n log n)).",
|
| 147 |
-
"improvements": ["Added a 'swapped' flag to exit early if sorted.", "Shrink inner loop by 'i' each pass."],
|
| 148 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n n = len([FIRST_ARG])\n for i in range(n):\n swapped = False\n for j in range(0, n - i - 1):\n if [FIRST_ARG][j] > [FIRST_ARG][j + 1]:\n [FIRST_ARG][j], [FIRST_ARG][j + 1] = [FIRST_ARG][j + 1], [FIRST_ARG][j]\n swapped = True\n if not swapped: break\n return [FIRST_ARG]",
|
| 149 |
-
"recommended_name": "Quick Sort OR Merge Sort (O(n log n))",
|
| 150 |
-
"recommended_code": "# --- OPTION 1: QUICK SORT ---\nimport random\ndef [FUNC_NAME]_quicksort([ARGS]):\n if len([FIRST_ARG]) <= 1: return [FIRST_ARG]\n pivot = random.choice([FIRST_ARG])\n L = [x for x in [FIRST_ARG] if x < pivot]\n M = [x for x in [FIRST_ARG] if x == pivot]\n R = [x for x in [FIRST_ARG] if x > pivot]\n return [FUNC_NAME]_quicksort(L) + M + [FUNC_NAME]_quicksort(R)\n\n# --- OPTION 2: BUILT-IN SORT ---\ndef [FUNC_NAME]_timsort([ARGS]):\n return sorted([FIRST_ARG])"
|
| 151 |
-
},
|
| 152 |
-
"Insertion Sort": {
|
| 153 |
-
"space": "O(1)",
|
| 154 |
-
"explanation": "⚠️ WARNING: Insertion Sort is slow (O(n^2)) for large lists. It is okay for small inputs (<50 items), but consider Quick Sort for scalability.",
|
| 155 |
-
"improvements": ["Your logic is correct for small datasets, but fails to scale.", "For >50 items, pivot to a divide-and-conquer approach."],
|
| 156 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n for i in range(1, len([FIRST_ARG])):\n key = [FIRST_ARG][i]\n j = i - 1\n while j >= 0 and key < [FIRST_ARG][j]:\n [FIRST_ARG][j + 1] = [FIRST_ARG][j]\n j -= 1\n [FIRST_ARG][j + 1] = key\n return [FIRST_ARG]",
|
| 157 |
-
"recommended_name": "Quick Sort OR Merge Sort (O(n log n))",
|
| 158 |
-
"recommended_code": "# --- OPTION 1: QUICK SORT ---\ndef [FUNC_NAME]_quicksort([ARGS]):\n if len([FIRST_ARG]) <= 1: return [FIRST_ARG]\n pivot = [FIRST_ARG][len([FIRST_ARG]) // 2]\n return [FUNC_NAME]_quicksort([x for x in [FIRST_ARG] if x < pivot]) + \\\n [x for x in [FIRST_ARG] if x == pivot] + \\\n [FUNC_NAME]_quicksort([x for x in [FIRST_ARG] if x > pivot])"
|
| 159 |
-
},
|
| 160 |
-
"Hash Map Lookup": {
|
| 161 |
-
"space": "O(n)",
|
| 162 |
-
"explanation": "✅ GOOD: Uses a dictionary (Hash Map) for instant O(1) lookups instead of repeatedly searching through a list. This drops the time complexity from O(n^2) down to a highly efficient O(n).",
|
| 163 |
-
"improvements": ["You are correctly using a dictionary to map elements.", "This trades a small amount of memory O(n) for a massive speedup O(1) per lookup."],
|
| 164 |
-
"optimized_code": "def [FUNC_NAME]([ARGS], target):\n seen = {}\n for i, val in enumerate([FIRST_ARG]):\n needed = target - val\n if needed in seen:\n return [seen[needed], i]\n seen[val] = i\n return []"
|
| 165 |
-
},
|
| 166 |
-
"Selection Sort": {
|
| 167 |
-
"space": "O(1)",
|
| 168 |
-
"explanation": "⚠️ WARNING: Selection Sort is always O(n^2), even if the list is sorted. Switch to Insertion Sort (for small lists) or Merge Sort.",
|
| 169 |
-
"improvements": ["Avoid this algorithm entirely for production code.", "Replace with an algorithm that adapts to already-sorted data."],
|
| 170 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n for i in range(len([FIRST_ARG])):\n min_idx = i\n for j in range(i+1, len([FIRST_ARG])):\n if [FIRST_ARG][j] < [FIRST_ARG][min_idx]:\n min_idx = j\n [FIRST_ARG][i], [FIRST_ARG][min_idx] = [FIRST_ARG][min_idx], [FIRST_ARG][i]\n return [FIRST_ARG]",
|
| 171 |
-
"recommended_name": "Insertion Sort OR Merge Sort",
|
| 172 |
-
"recommended_code": "# --- OPTION 1: INSERTION SORT ---\ndef [FUNC_NAME]_insertion([ARGS]):\n for i in range(1, len([FIRST_ARG])):\n key = [FIRST_ARG][i]\n j = i - 1\n while j >= 0 and key < [FIRST_ARG][j]:\n [FIRST_ARG][j + 1] = [FIRST_ARG][j]\n j -= 1\n [FIRST_ARG][j + 1] = key\n return [FIRST_ARG]"
|
| 173 |
-
},
|
| 174 |
-
"Quick Sort": {
|
| 175 |
-
"space": "O(log n)",
|
| 176 |
-
"explanation": "✅ EXCELLENT: Quick Sort is a standard, efficient O(n log n) algorithm. Ensure you handle the worst-case pivot selection.",
|
| 177 |
-
"improvements": ["Ensure your pivot is chosen randomly instead of always picking the first or last element."],
|
| 178 |
-
"optimized_code": "import random\ndef [FUNC_NAME]([ARGS]):\n if len([FIRST_ARG]) <= 1: return [FIRST_ARG]\n pivot = random.choice([FIRST_ARG])\n left = [x for x in [FIRST_ARG] if x < pivot]\n middle = [x for x in [FIRST_ARG] if x == pivot]\n right = [x for x in [FIRST_ARG] if x > pivot]\n return [FUNC_NAME](left) + middle + [FUNC_NAME](right)"
|
| 179 |
-
},
|
| 180 |
-
"Merge Sort": {
|
| 181 |
-
"space": "O(n)",
|
| 182 |
-
"explanation": "✅ EXCELLENT: Merge Sort is stable and consistent O(n log n). Great for large datasets.",
|
| 183 |
-
"improvements": ["Your algorithm is optimal for time complexity.", "Be aware that Merge Sort uses O(n) extra memory."],
|
| 184 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n if len([FIRST_ARG]) > 1:\n mid = len([FIRST_ARG]) // 2\n L, R = [FIRST_ARG][:mid], [FIRST_ARG][mid:]\n [FUNC_NAME](L)\n [FUNC_NAME](R)\n i = j = k = 0\n while i < len(L) and j < len(R):\n if L[i] < R[j]:\n [FIRST_ARG][k] = L[i]\n i += 1\n else:\n [FIRST_ARG][k] = R[j]\n j += 1\n k += 1\n while i < len(L):\n [FIRST_ARG][k] = L[i]\n i, k = i + 1, k + 1\n while j < len(R):\n [FIRST_ARG][k] = R[j]\n j, k = j + 1, k + 1\n return [FIRST_ARG]"
|
| 185 |
-
},
|
| 186 |
-
"Heap Sort": {
|
| 187 |
-
"space": "O(1)",
|
| 188 |
-
"explanation": "✅ GOOD: Heap Sort is memory efficient (O(1) extra space) and fast (O(n log n)).",
|
| 189 |
-
"improvements": ["Use Python's built-in `heapq` library for C-level optimization."],
|
| 190 |
-
"optimized_code": "import heapq\ndef [FUNC_NAME]([ARGS]):\n heapq.heapify([FIRST_ARG])\n return [heapq.heappop([FIRST_ARG]) for _ in range(len([FIRST_ARG]))]"
|
| 191 |
-
},
|
| 192 |
-
"Counting Sort": {
|
| 193 |
-
"space": "O(n + k)",
|
| 194 |
-
"explanation": "✅ EFFICIENT: Very fast (O(n+k)) for integers with a small range. Not suitable for strings or large ranges.",
|
| 195 |
-
"improvements": ["Ensure your data strictly contains integers with a known maximum value."],
|
| 196 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n if not [FIRST_ARG]: return [FIRST_ARG]\n max_val = max([FIRST_ARG])\n count = [0] * (max_val + 1)\n for num in [FIRST_ARG]: count[num] += 1\n idx = 0\n for i in range(len(count)):\n while count[i] > 0:\n [FIRST_ARG][idx] = i\n idx += 1\n count[i] -= 1\n return [FIRST_ARG]"
|
| 197 |
-
},
|
| 198 |
-
|
| 199 |
-
# --- SEARCHING ---
|
| 200 |
-
"Linear Search": {
|
| 201 |
-
"space": "O(1)",
|
| 202 |
-
"explanation": "⚠️ INEFFICIENT: iterating through every item is O(n). If your data is sorted, switch to Binary Search (O(log n)) for a massive speedup.",
|
| 203 |
-
"improvements": ["Only checking items one by one requires O(n) time.", "If your data is sorted, use Binary Search."],
|
| 204 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n for i in range(len([FIRST_ARG])):\n if [FIRST_ARG][i] == target: return i # Target must be passed\n return -1",
|
| 205 |
-
"recommended_name": "Binary Search (O(log n))",
|
| 206 |
-
"recommended_code": "import bisect\ndef [FUNC_NAME]_binary([ARGS]):\n # Assuming [FIRST_ARG] is sorted\n idx = bisect.bisect_left([FIRST_ARG], target)\n if idx < len([FIRST_ARG]) and [FIRST_ARG][idx] == target:\n return idx\n return -1"
|
| 207 |
-
},
|
| 208 |
-
"Binary Search": {
|
| 209 |
-
"space": "O(1)",
|
| 210 |
-
"explanation": "✅ PERFECT: Binary Search is the gold standard (O(log n)) for sorted arrays.",
|
| 211 |
-
"improvements": ["Ensure your array is sorted first.", "You can manually write it with a while loop, or use Python's built in `bisect` library."],
|
| 212 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n # Manual implementation\n left, right = 0, len([FIRST_ARG]) - 1\n while left <= right:\n mid = (left + right) // 2\n if [FIRST_ARG][mid] == target: return mid\n elif [FIRST_ARG][mid] < target: left = mid + 1\n else: right = mid - 1\n return -1"
|
| 213 |
-
},
|
| 214 |
-
"Jump Search": {
|
| 215 |
-
"space": "O(1)",
|
| 216 |
-
"explanation": "✅ GOOD: Jump Search (O(√n)) is better than Linear Search, but Binary Search is still faster if random access is allowed.",
|
| 217 |
-
"improvements": ["If you are using standard lists, switch to Binary Search (O(log n))."],
|
| 218 |
-
"optimized_code": "import math\ndef [FUNC_NAME]([ARGS]):\n n = len([FIRST_ARG])\n step = int(math.sqrt(n))\n prev = 0\n while [FIRST_ARG][min(step, n)-1] < target:\n prev = step\n step += int(math.sqrt(n))\n if prev >= n: return -1\n while [FIRST_ARG][prev] < target:\n prev += 1\n if prev == min(step, n): return -1\n if [FIRST_ARG][prev] == target: return prev\n return -1",
|
| 219 |
-
"recommended_name": "Binary Search (O(log n))",
|
| 220 |
-
"recommended_code": "import bisect\ndef [FUNC_NAME]_binary([ARGS]):\n idx = bisect.bisect_left([FIRST_ARG], target)\n if idx < len([FIRST_ARG]) and [FIRST_ARG][idx] == target:\n return idx\n return -1"
|
| 221 |
-
},
|
| 222 |
-
|
| 223 |
-
# --- RECURSION, DP, & MATH ---
|
| 224 |
-
"Fibonacci Sequence": {
|
| 225 |
-
"space": "O(n)",
|
| 226 |
-
"explanation": "⚠️ RECURSION ALERT: Simple recursive Fibonacci is O(2^n) (Exponential). Refactor to use Dynamic Programming (Memoization) or an Iterative Loop to make it O(n).",
|
| 227 |
-
"improvements": ["Recursion causes stack overflow risks."],
|
| 228 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n if [FIRST_ARG] <= 0: return 0\n if [FIRST_ARG] == 1: return 1\n return [FUNC_NAME]([FIRST_ARG]-1) + [FUNC_NAME]([FIRST_ARG]-2)",
|
| 229 |
-
"recommended_name": "Iterative OR Memoized Fibonacci (O(n))",
|
| 230 |
-
"recommended_code": "# --- OPTION 1: ITERATIVE (O(1) Space) ---\ndef [FUNC_NAME]_iterative([ARGS]):\n if [FIRST_ARG] <= 0: return 0\n if [FIRST_ARG] == 1: return 1\n a, b = 0, 1\n for _ in range(2, [FIRST_ARG] + 1):\n a, b = b, a + b\n return b\n\n# --- OPTION 2: MEMOIZATION (Caching) ---\nfrom functools import lru_cache\n@lru_cache(maxsize=None)\ndef [FUNC_NAME]_memoized([ARGS]):\n if [FIRST_ARG] <= 1: return [FIRST_ARG]\n return [FUNC_NAME]_memoized([FIRST_ARG]-1) + [FUNC_NAME]_memoized([FIRST_ARG]-2)"
|
| 231 |
-
},
|
| 232 |
-
"Memoization": {
|
| 233 |
-
"space": "O(n)",
|
| 234 |
-
"explanation": "✅ EFFICIENT: You successfully applied Memoization (Top-Down DP) to prevent redundant calculations.",
|
| 235 |
-
"improvements": ["Caching results prevents the O(2^n) exponential blow-up of standard recursion."],
|
| 236 |
-
"optimized_code": "memo = {}\ndef [FUNC_NAME]([ARGS]):\n if [FIRST_ARG] in memo: return memo[[FIRST_ARG]]\n if [FIRST_ARG] <= 1: return [FIRST_ARG]\n memo[[FIRST_ARG]] = [FUNC_NAME]([FIRST_ARG]-1) + [FUNC_NAME]([FIRST_ARG]-2)\n return memo[[FIRST_ARG]]"
|
| 237 |
-
},
|
| 238 |
-
"Tabulation": {
|
| 239 |
-
"space": "O(n)",
|
| 240 |
-
"explanation": "✅ EFFICIENT: You successfully applied Tabulation (Bottom-Up DP) to prevent recursion stack overflow limits.",
|
| 241 |
-
"improvements": ["Iteratively building the table is memory safe and prevents RecursionError."],
|
| 242 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n if [FIRST_ARG] <= 0: return 0\n dp = [0] * ([FIRST_ARG] + 1)\n dp[1] = 1\n for i in range(2, [FIRST_ARG] + 1):\n dp[i] = dp[i-1] + dp[i-2]\n return dp[[FIRST_ARG]]"
|
| 243 |
-
},
|
| 244 |
-
"Factorial (Recursive)": {
|
| 245 |
-
"space": "O(n)",
|
| 246 |
-
"explanation": "⚠️ STACK RISK: Recursive Factorial works, but large inputs will cause a `RecursionError`. Use an Iterative Loop for safety.",
|
| 247 |
-
"improvements": ["Use a `for` loop to accumulate the result instead of recursion.", "Better yet, use Python's built in `math.factorial()`."],
|
| 248 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n if [FIRST_ARG] == 1 or [FIRST_ARG] == 0: return 1\n return [FIRST_ARG] * [FUNC_NAME]([FIRST_ARG] - 1)",
|
| 249 |
-
"recommended_name": "Iterative Factorial (O(n))",
|
| 250 |
-
"recommended_code": "import math\ndef [FUNC_NAME]_safe([ARGS]):\n # Built-in math functions run in C and avoid RecursionErrors\n return math.factorial([FIRST_ARG])"
|
| 251 |
-
},
|
| 252 |
-
"Factorial (Iterative)": {
|
| 253 |
-
"space": "O(1)",
|
| 254 |
-
"explanation": "✅ GOOD: Iterative Factorial is safe and efficient (O(n)).",
|
| 255 |
-
"improvements": ["Your logic is solid, but you can achieve even faster execution using the built-in math module."],
|
| 256 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n result = 1\n for i in range(2, [FIRST_ARG] + 1):\n result *= i\n return result"
|
| 257 |
-
},
|
| 258 |
-
"Prime Check": {
|
| 259 |
-
"space": "O(1)",
|
| 260 |
-
"explanation": "✅ EFFICIENT: This O(√n) approach is much faster than checking all numbers up to N.",
|
| 261 |
-
"improvements": ["Ensure your loop stops at the square root of n.", "Handle edge cases for 1, 2, and 3 explicitly."],
|
| 262 |
-
"optimized_code": "import math\ndef [FUNC_NAME]([ARGS]):\n if [FIRST_ARG] <= 1: return False\n if [FIRST_ARG] in (2, 3): return True\n if [FIRST_ARG] % 2 == 0 or [FIRST_ARG] % 3 == 0: return False\n for i in range(5, int(math.sqrt([FIRST_ARG])) + 1, 6):\n if [FIRST_ARG] % i == 0 or [FIRST_ARG] % (i + 2) == 0: return False\n return True"
|
| 263 |
-
},
|
| 264 |
-
"GCD (Euclidean)": {
|
| 265 |
-
"space": "O(1)",
|
| 266 |
-
"explanation": "✅ PERFECT: Euclidean algorithm is the most efficient way to find GCD.",
|
| 267 |
-
"improvements": ["Use Python's built-in `math.gcd` for cleaner and slightly faster code."],
|
| 268 |
-
"optimized_code": "def [FUNC_NAME](a, b):\n while b:\n a, b = b, a % b\n return abs(a)"
|
| 269 |
-
},
|
| 270 |
-
"Palindrome Check": {
|
| 271 |
-
"space": "O(1)",
|
| 272 |
-
"explanation": "✅ GOOD: O(n) is the optimal complexity for checking palindromes.",
|
| 273 |
-
"improvements": ["In Python, slicing is often faster than setting up a while loop with two pointers."],
|
| 274 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n return str([FIRST_ARG]) == str([FIRST_ARG])[::-1]"
|
| 275 |
-
},
|
| 276 |
-
"Armstrong Number": {
|
| 277 |
-
"space": "O(log n)",
|
| 278 |
-
"explanation": "✅ GOOD: Analyzing digits is O(log n), which is optimal.",
|
| 279 |
-
"improvements": ["Convert the number to a string to easily iterate over the digits."],
|
| 280 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n digits = str([FIRST_ARG])\n power = len(digits)\n return [FIRST_ARG] == sum(int(d)**power for d in digits)"
|
| 281 |
-
},
|
| 282 |
-
|
| 283 |
-
# --- GRAPHS, POINTERS, & DATA STRUCTURES ---
|
| 284 |
-
"Dijkstra's Algorithm": {
|
| 285 |
-
"space": "O(V)",
|
| 286 |
-
"explanation": "✅ INDUSTRY STANDARD: Best for finding shortest paths in weighted graphs.",
|
| 287 |
-
"improvements": ["Ensure you are using a Priority Queue (`heapq`) to achieve O(E log V) time complexity."],
|
| 288 |
-
"optimized_code": "import heapq\ndef [FUNC_NAME](graph, start):\n distances = {node: float('inf') for node in graph}\n distances[start] = 0\n pq = [(0, start)]\n while pq:\n curr_dist, curr_node = heapq.heappop(pq)\n if curr_dist > distances[curr_node]: continue\n for neighbor, weight in graph[curr_node].items():\n dist = curr_dist + weight\n if dist < distances[neighbor]:\n distances[neighbor] = dist\n heapq.heappush(pq, (dist, neighbor))\n return distances"
|
| 289 |
-
},
|
| 290 |
-
"Heap-Based Algorithm": {
|
| 291 |
-
"space": "O(N)",
|
| 292 |
-
"explanation": "✅ GOOD: Ideal for dynamically finding the top K elements (smallest/largest), scheduling tasks, or building priority queues without sorting the whole list.",
|
| 293 |
-
"improvements": ["Always use Python's built-in `heapq` module instead of manually sorting arrays with `.sort()`.", "Use `heapq.heapify()` to build your initial heap in O(N) time instead of pushing items one-by-one."],
|
| 294 |
-
"optimized_code": "import heapq\n\ndef [FUNC_NAME](data, k):\n # O(N) time to build the heap in-place\n heapq.heapify(data)\n # Extract the k smallest elements efficiently\n result = [heapq.heappop(data) for _ in range(k)]\n return result"
|
| 295 |
-
},
|
| 296 |
-
"Breadth-First Search": {
|
| 297 |
-
"space": "O(V)",
|
| 298 |
-
"explanation": "✅ GOOD: Perfect for shortest paths in unweighted graphs or level-order traversal.",
|
| 299 |
-
"improvements": ["Always use `collections.deque` for the queue instead of a standard list."],
|
| 300 |
-
"optimized_code": "from collections import deque\ndef [FUNC_NAME](graph, start):\n visited = set([start])\n queue = deque([start])\n result = []\n while queue:\n node = queue.popleft()\n result.append(node)\n for neighbor in graph[node]:\n if neighbor not in visited:\n visited.add(neighbor)\n queue.append(neighbor)\n return result"
|
| 301 |
-
},
|
| 302 |
-
"BFS (Graph)": {
|
| 303 |
-
"space": "O(V)",
|
| 304 |
-
"explanation": "✅ GOOD: Perfect for shortest paths in unweighted graphs or level-order traversal.",
|
| 305 |
-
"improvements": ["Always use `collections.deque` for the queue instead of a standard list."],
|
| 306 |
-
"optimized_code": "from collections import deque\ndef [FUNC_NAME](graph, start):\n visited = set([start])\n queue = deque([start])\n result = []\n while queue:\n node = queue.popleft()\n result.append(node)\n for neighbor in graph[node]:\n if neighbor not in visited:\n visited.add(neighbor)\n queue.append(neighbor)\n return result"
|
| 307 |
-
},
|
| 308 |
-
"Depth-First Search": {
|
| 309 |
-
"space": "O(V)",
|
| 310 |
-
"explanation": "✅ GOOD: Standard for pathfinding puzzles, topological sorting, and cycle detection.",
|
| 311 |
-
"improvements": ["If recursion depth is a concern, switch to an iterative DFS using a stack."],
|
| 312 |
-
"optimized_code": "def [FUNC_NAME](graph, start, visited=None):\n if visited is None: visited = set()\n visited.add(start)\n # Process node here\n for neighbor in graph[start]:\n if neighbor not in visited:\n [FUNC_NAME](graph, neighbor, visited)\n return visited"
|
| 313 |
-
},
|
| 314 |
-
"DFS (Graph)": {
|
| 315 |
-
"space": "O(V)",
|
| 316 |
-
"explanation": "✅ GOOD: Standard for pathfinding puzzles, topological sorting, and cycle detection.",
|
| 317 |
-
"improvements": ["If recursion depth is a concern, switch to an iterative DFS using a stack."],
|
| 318 |
-
"optimized_code": "def [FUNC_NAME](graph, start, visited=None):\n if visited is None: visited = set()\n visited.add(start)\n # Process node here\n for neighbor in graph[start]:\n if neighbor not in visited:\n [FUNC_NAME](graph, neighbor, visited)\n return visited"
|
| 319 |
-
},
|
| 320 |
-
"Sliding Window": {
|
| 321 |
-
"space": "O(1)",
|
| 322 |
-
"explanation": "✅ EFFICIENT: Sliding window prevents duplicate work when analyzing subarrays.",
|
| 323 |
-
"improvements": ["Maintains a running sum/condition without needing nested O(n^2) loops."],
|
| 324 |
-
"optimized_code": "def [FUNC_NAME](arr, k):\n current_sum = 0\n left = 0\n for right in range(len(arr)):\n current_sum += arr[right]\n if right - left + 1 > k:\n current_sum -= arr[left]\n left += 1\n return current_sum"
|
| 325 |
-
},
|
| 326 |
-
"Two-Pointer Technique": {
|
| 327 |
-
"space": "O(1)",
|
| 328 |
-
"explanation": "✅ EFFICIENT: Two pointers walking towards each other saves incredible amounts of memory.",
|
| 329 |
-
"improvements": ["Much faster than nested O(n^2) loops when dealing with sorted arrays."],
|
| 330 |
-
"optimized_code": "def [FUNC_NAME](arr, target):\n left, right = 0, len(arr) - 1\n while left < right:\n s = arr[left] + arr[right]\n if s == target: return True\n elif s < target: left += 1\n else: right -= 1\n return False"
|
| 331 |
-
},
|
| 332 |
-
"Binary Search Tree": {
|
| 333 |
-
"space": "O(n)",
|
| 334 |
-
"explanation": "ℹ️ INFO: Operations are O(log n) on average, but can degrade to O(n) if the tree is unbalanced. Consider an AVL Tree or Red-Black Tree for guaranteed performance.",
|
| 335 |
-
"improvements": ["Consider just using the built-in `dict` or `set` which are highly optimized Hash Tables in Python."],
|
| 336 |
-
"optimized_code": "class Node:\n def __init__(self, key):\n self.left, self.right, self.val = None, None, key\n\ndef [FUNC_NAME](root, key):\n if root is None or root.val == key: return root\n if root.val < key: return [FUNC_NAME](root.right, key)\n return [FUNC_NAME](root.left, key)"
|
| 337 |
-
},
|
| 338 |
-
"Stack Operations": {
|
| 339 |
-
"space": "O(n)",
|
| 340 |
-
"explanation": "✅ OPTIMAL: Push/Pop operations are O(1).",
|
| 341 |
-
"improvements": ["Standard Python lists are perfect for stacks. Just ensure you only use `.append()` and `.pop()`."],
|
| 342 |
-
"optimized_code": "def [FUNC_NAME]():\n stack = []\n stack.append('item') # Push O(1)\n item = stack.pop() # Pop O(1)\n return item"
|
| 343 |
-
},
|
| 344 |
-
"Queue (List)": {
|
| 345 |
-
"space": "O(n)",
|
| 346 |
-
"explanation": "⚠️ WARNING: Using `list.pop(0)` in Python is O(n). Use `collections.deque` for true O(1) queue operations.",
|
| 347 |
-
"improvements": ["Import 'deque' from the collections module.", "Use 'popleft()' instead of 'pop(0)' to achieve O(1) constant time."],
|
| 348 |
-
"optimized_code": "def [FUNC_NAME]([ARGS]):\n # Using list.pop(0) causes O(n) memory shifts\n queue = list([FIRST_ARG])\n queue.append('new_item')\n item = queue.pop(0) \n return item",
|
| 349 |
-
"recommended_name": "Collections.deque (True O(1) Queue)",
|
| 350 |
-
"recommended_code": "from collections import deque\ndef [FUNC_NAME]_optimized([ARGS]):\n queue = deque([FIRST_ARG])\n queue.append('new_item')\n # queue.popleft() is now O(1) instead of O(n)\n item = queue.popleft()\n return queue"
|
| 351 |
-
},
|
| 352 |
-
"Linked List (Singly)": {
|
| 353 |
-
"space": "O(n)",
|
| 354 |
-
"explanation": "ℹ️ INFO: Insertions are O(1) if you have the pointer, but searching is O(n).",
|
| 355 |
-
"improvements": ["Linked lists are rarely used in standard Python because standard lists are dynamic arrays."],
|
| 356 |
-
"optimized_code": "class Node:\n def __init__(self, data):\n self.data = data\n self.next = None\n\nclass LinkedList:\n def __init__(self):\n self.head = None\n def print_list(self):\n temp = self.head\n while temp:\n print(temp.data)\n temp = temp.next"
|
| 357 |
-
},
|
| 358 |
-
"Linked List (Doubly)": {
|
| 359 |
-
"space": "O(n)",
|
| 360 |
-
"explanation": "✅ FLEXIBLE: Doubly Linked Lists allow bidirectional traversal, at the cost of slightly more memory.",
|
| 361 |
-
"improvements": ["Python's built-in `collections.deque` is actually a Doubly Linked List under the hood! Use it for max performance."],
|
| 362 |
-
"optimized_code": "from collections import deque\n# deque is an optimized doubly linked list\ndef [FUNC_NAME]():\n dll = deque(['a', 'b', 'c'])\n dll.append('d') # Add to right\n dll.appendleft('z') # Add to left\n return dll"
|
| 363 |
-
}
|
| 364 |
-
}
|
| 365 |
-
|
| 366 |
-
# 4. Fallback Data
|
| 367 |
-
default_data = {
|
| 368 |
-
"space": "O(N)",
|
| 369 |
-
"explanation": f"CodeSense Engine Analysis: {ethan_summary}",
|
| 370 |
-
"improvements": ["Analysis pending for this algorithm."],
|
| 371 |
-
"optimized_code": "# Recognized Pattern. Specific optimization currently unavailable."
|
| 372 |
-
}
|
| 373 |
-
|
| 374 |
-
# Handle matching names (e.g. "Linear Search" vs "Linear Iterative" from different models)
|
| 375 |
-
if algo == "Linear Iterative" and "Linear Search" in complexity_map:
|
| 376 |
-
algo_key = "Linear Search"
|
| 377 |
-
elif algo == "Recursive (Exponential)" and "Factorial (Recursive)" in complexity_map:
|
| 378 |
-
algo_key = "Fibonacci Sequence" # General fallback for exponential recursion
|
| 379 |
-
else:
|
| 380 |
-
algo_key = algo
|
| 381 |
-
|
| 382 |
-
result_data = complexity_map.get(algo_key, default_data)
|
| 383 |
-
|
| 384 |
-
# --- YOUR MAGIC VARIABLE REPLACEMENT FOR BOTH CODES ---
|
| 385 |
-
# 1. Format Optimized Code
|
| 386 |
-
opt_code = result_data.get("optimized_code", "").replace("[FUNC_NAME]", analyzer.func_name).replace("[ARGS]", analyzer.args_string).replace("[FIRST_ARG]", analyzer.first_arg)
|
| 387 |
-
|
| 388 |
-
# 2. Format Recommended Code (if it exists)
|
| 389 |
-
rec_code = result_data.get("recommended_code", "")
|
| 390 |
-
if rec_code:
|
| 391 |
-
rec_code = rec_code.replace("[FUNC_NAME]", analyzer.func_name).replace("[ARGS]", analyzer.args_string).replace("[FIRST_ARG]", analyzer.first_arg)
|
| 392 |
-
rec_name = result_data.get("recommended_name", "")
|
| 393 |
-
|
| 394 |
-
# 5. Send EVERYTHING back to VS Code
|
| 395 |
-
return jsonify({
|
| 396 |
-
"algorithm": algo,
|
| 397 |
-
"confidence": f"{conf_percentage:.1f}%",
|
| 398 |
-
"dynamic_complexity": dynamic_comp,
|
| 399 |
-
"space_complexity": result_data.get("space", "O(N)"),
|
| 400 |
-
"explanation": result_data.get("explanation", ""),
|
| 401 |
-
"improvements": result_data.get("improvements", []),
|
| 402 |
-
"optimized_code": opt_code,
|
| 403 |
-
"recommended_name": rec_name,
|
| 404 |
-
"recommended_code": rec_code,
|
| 405 |
-
"safety_net_used": safety_net_triggered
|
| 406 |
-
})
|
| 407 |
-
|
| 408 |
-
except Exception as e:
|
| 409 |
-
import traceback
|
| 410 |
-
print(traceback.format_exc())
|
| 411 |
-
return jsonify({"error": str(e)}), 500
|
| 412 |
-
|
| 413 |
-
if __name__ == '__main__':
|
| 414 |
-
app.run(host='0.0.0.0', port=7860)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|