albmor commited on
Commit
0e6b902
·
verified ·
1 Parent(s): 2b939ad

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +1062 -18
index.html CHANGED
@@ -1,19 +1,1063 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>LLM Hill Climber - HuggingFace Spaces</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
9
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
10
+ <style>
11
+ * {
12
+ margin: 0;
13
+ padding: 0;
14
+ box-sizing: border-box;
15
+ }
16
+
17
+ body {
18
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
19
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
20
+ min-height: 100vh;
21
+ color: #333;
22
+ }
23
+
24
+ .header {
25
+ background: rgba(255, 255, 255, 0.1);
26
+ backdrop-filter: blur(10px);
27
+ padding: 20px;
28
+ text-align: center;
29
+ border-bottom: 1px solid rgba(255, 255, 255, 0.2);
30
+ }
31
+
32
+ .header h1 {
33
+ color: white;
34
+ font-size: 2.5em;
35
+ margin-bottom: 10px;
36
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
37
+ }
38
+
39
+ .header p {
40
+ color: rgba(255, 255, 255, 0.9);
41
+ font-size: 1.1em;
42
+ }
43
+
44
+ .spaces-info {
45
+ background: rgba(255, 255, 255, 0.95);
46
+ margin: 20px auto;
47
+ max-width: 1200px;
48
+ padding: 15px;
49
+ border-radius: 10px;
50
+ border-left: 4px solid #667eea;
51
+ }
52
+
53
+ .container {
54
+ max-width: 1400px;
55
+ margin: 0 auto;
56
+ padding: 20px;
57
+ display: grid;
58
+ grid-template-columns: 1fr 1fr;
59
+ gap: 20px;
60
+ min-height: calc(100vh - 200px);
61
+ }
62
+
63
+ .panel {
64
+ background: rgba(255, 255, 255, 0.95);
65
+ border-radius: 20px;
66
+ padding: 25px;
67
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
68
+ backdrop-filter: blur(10px);
69
+ }
70
+
71
+ .panel h2 {
72
+ color: #333;
73
+ margin-bottom: 20px;
74
+ font-size: 1.5em;
75
+ border-bottom: 3px solid #667eea;
76
+ padding-bottom: 10px;
77
+ }
78
+
79
+ .model-info {
80
+ background: #e8f5e8;
81
+ padding: 15px;
82
+ border-radius: 8px;
83
+ margin-bottom: 20px;
84
+ border-left: 4px solid #4caf50;
85
+ }
86
+
87
+ .problem-selector {
88
+ margin-bottom: 20px;
89
+ }
90
+
91
+ .problem-selector select {
92
+ width: 100%;
93
+ padding: 12px;
94
+ border: 2px solid #e0e0e0;
95
+ border-radius: 8px;
96
+ font-size: 16px;
97
+ background: white;
98
+ }
99
+
100
+ .problem-selector select:focus {
101
+ border-color: #667eea;
102
+ outline: none;
103
+ }
104
+
105
+ .problem-details {
106
+ background: #f8f9fa;
107
+ padding: 20px;
108
+ border-radius: 12px;
109
+ margin-bottom: 20px;
110
+ border-left: 4px solid #667eea;
111
+ }
112
+
113
+ .problem-details h3 {
114
+ color: #333;
115
+ margin-bottom: 10px;
116
+ }
117
+
118
+ .problem-details p {
119
+ line-height: 1.6;
120
+ margin-bottom: 15px;
121
+ }
122
+
123
+ .test-cases {
124
+ background: #2d3748;
125
+ color: #e2e8f0;
126
+ padding: 15px;
127
+ border-radius: 8px;
128
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
129
+ font-size: 14px;
130
+ overflow-x: auto;
131
+ white-space: pre-wrap;
132
+ }
133
+
134
+ .controls {
135
+ display: flex;
136
+ gap: 15px;
137
+ margin-bottom: 20px;
138
+ flex-wrap: wrap;
139
+ }
140
+
141
+ .btn {
142
+ padding: 12px 24px;
143
+ border: none;
144
+ border-radius: 8px;
145
+ cursor: pointer;
146
+ font-size: 16px;
147
+ font-weight: bold;
148
+ transition: all 0.3s ease;
149
+ text-transform: uppercase;
150
+ letter-spacing: 0.5px;
151
+ }
152
+
153
+ .btn-primary {
154
+ background: linear-gradient(45deg, #667eea, #764ba2);
155
+ color: white;
156
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
157
+ }
158
+
159
+ .btn-primary:hover:not(:disabled) {
160
+ transform: translateY(-2px);
161
+ box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
162
+ }
163
+
164
+ .btn-danger {
165
+ background: linear-gradient(45deg, #ff6b6b, #ee5a24);
166
+ color: white;
167
+ box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3);
168
+ }
169
+
170
+ .btn-danger:hover:not(:disabled) {
171
+ transform: translateY(-2px);
172
+ box-shadow: 0 8px 25px rgba(255, 107, 107, 0.4);
173
+ }
174
+
175
+ .btn:disabled {
176
+ opacity: 0.6;
177
+ cursor: not-allowed;
178
+ transform: none;
179
+ }
180
+
181
+ .settings {
182
+ display: grid;
183
+ grid-template-columns: 1fr 1fr;
184
+ gap: 15px;
185
+ margin-bottom: 20px;
186
+ }
187
+
188
+ .setting-group {
189
+ display: flex;
190
+ flex-direction: column;
191
+ }
192
+
193
+ .setting-group label {
194
+ font-weight: bold;
195
+ margin-bottom: 5px;
196
+ color: #555;
197
+ }
198
+
199
+ .setting-group input {
200
+ padding: 8px;
201
+ border: 2px solid #e0e0e0;
202
+ border-radius: 6px;
203
+ font-size: 14px;
204
+ }
205
+
206
+ .setting-group input:focus {
207
+ border-color: #667eea;
208
+ outline: none;
209
+ }
210
+
211
+ .progress-section {
212
+ margin-bottom: 20px;
213
+ }
214
+
215
+ .progress-bar {
216
+ width: 100%;
217
+ height: 20px;
218
+ background: #e0e0e0;
219
+ border-radius: 10px;
220
+ overflow: hidden;
221
+ margin-bottom: 10px;
222
+ }
223
+
224
+ .progress-fill {
225
+ height: 100%;
226
+ background: linear-gradient(45deg, #667eea, #764ba2);
227
+ width: 0%;
228
+ transition: width 0.3s ease;
229
+ }
230
+
231
+ .progress-text {
232
+ text-align: center;
233
+ font-weight: bold;
234
+ color: #555;
235
+ }
236
+
237
+ .evolution-log {
238
+ background: #2d3748;
239
+ color: #e2e8f0;
240
+ padding: 15px;
241
+ border-radius: 8px;
242
+ height: 250px;
243
+ overflow-y: auto;
244
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
245
+ font-size: 12px;
246
+ line-height: 1.4;
247
+ margin-bottom: 20px;
248
+ }
249
+
250
+ .current-solution {
251
+ background: #f8f9fa;
252
+ border: 2px solid #e0e0e0;
253
+ border-radius: 8px;
254
+ padding: 15px;
255
+ max-height: 300px;
256
+ overflow-y: auto;
257
+ }
258
+
259
+ .current-solution pre {
260
+ background: #2d3748;
261
+ color: #e2e8f0;
262
+ padding: 15px;
263
+ border-radius: 8px;
264
+ overflow-x: auto;
265
+ margin: 0;
266
+ }
267
+
268
+ .fitness-chart {
269
+ background: white;
270
+ padding: 15px;
271
+ border-radius: 8px;
272
+ border: 2px solid #e0e0e0;
273
+ margin-bottom: 20px;
274
+ }
275
+
276
+ .status {
277
+ padding: 15px;
278
+ border-radius: 8px;
279
+ margin-bottom: 20px;
280
+ font-weight: bold;
281
+ text-align: center;
282
+ }
283
+
284
+ .status-idle {
285
+ background: #e3f2fd;
286
+ color: #1976d2;
287
+ border: 2px solid #1976d2;
288
+ }
289
+
290
+ .status-running {
291
+ background: #fff3e0;
292
+ color: #f57c00;
293
+ border: 2px solid #f57c00;
294
+ }
295
+
296
+ .status-complete {
297
+ background: #e8f5e8;
298
+ color: #2e7d32;
299
+ border: 2px solid #2e7d32;
300
+ }
301
+
302
+ .status-error {
303
+ background: #ffebee;
304
+ color: #c62828;
305
+ border: 2px solid #c62828;
306
+ }
307
+
308
+ .spinner {
309
+ display: inline-block;
310
+ width: 20px;
311
+ height: 20px;
312
+ border: 2px solid #f3f3f3;
313
+ border-top: 2px solid #667eea;
314
+ border-radius: 50%;
315
+ animation: spin 1s linear infinite;
316
+ margin-right: 10px;
317
+ }
318
+
319
+ @keyframes spin {
320
+ 0% { transform: rotate(0deg); }
321
+ 100% { transform: rotate(360deg); }
322
+ }
323
+
324
+ .best-solution {
325
+ background: #e8f5e8;
326
+ border: 2px solid #4caf50;
327
+ border-radius: 8px;
328
+ padding: 20px;
329
+ margin-top: 20px;
330
+ }
331
+
332
+ .best-solution h3 {
333
+ color: #2e7d32;
334
+ margin-bottom: 15px;
335
+ }
336
+
337
+ .api-efficiency {
338
+ background: #fff3e0;
339
+ padding: 15px;
340
+ border-radius: 8px;
341
+ margin-bottom: 20px;
342
+ border-left: 4px solid #f57c00;
343
+ }
344
+
345
+ @media (max-width: 1200px) {
346
+ .container {
347
+ grid-template-columns: 1fr;
348
+ gap: 15px;
349
+ }
350
+ }
351
+
352
+ @media (max-width: 768px) {
353
+ .header h1 {
354
+ font-size: 2em;
355
+ }
356
+
357
+ .controls {
358
+ flex-direction: column;
359
+ }
360
+
361
+ .settings {
362
+ grid-template-columns: 1fr;
363
+ }
364
+ }
365
+ </style>
366
+ </head>
367
+ <body>
368
+ <div class="header">
369
+ <h1>🧬 LLM Hill Climber</h1>
370
+ <p>Efficient program evolution using StarCoder2-3B on HuggingFace Spaces</p>
371
+ </div>
372
+
373
+ <div class="spaces-info">
374
+ <h3>🚀 Optimized for HuggingFace Spaces</h3>
375
+ <p><strong>Model:</strong> bigcode/starcoder2-3b (specialized coding AI) • <strong>Strategy:</strong> Single mutation per generation (API efficient) • <strong>Hosting:</strong> Free on HF Spaces</p>
376
+ </div>
377
+
378
+ <div class="container">
379
+ <!-- Left Panel: Problem Setup & Controls -->
380
+ <div class="panel">
381
+ <h2>🎯 Problem Configuration</h2>
382
+
383
+ <div class="model-info">
384
+ <h4>🤖 AI Model: StarCoder2-3B</h4>
385
+ <p>Specialized coding model by BigCode. Excellent at JavaScript generation and code understanding.</p>
386
+ </div>
387
+
388
+ <div class="problem-selector">
389
+ <select id="problemSelect">
390
+ <option value="">Select a coding problem...</option>
391
+ <option value="palindrome">Palindrome Checker</option>
392
+ <option value="two_sum">Two Sum Problem</option>
393
+ <option value="fibonacci">Fibonacci Generator</option>
394
+ <option value="prime_check">Prime Number Checker</option>
395
+ <option value="reverse_string">String Reversal</option>
396
+ <option value="max_subarray">Maximum Subarray Sum</option>
397
+ <option value="binary_search">Binary Search</option>
398
+ <option value="anagram_check">Anagram Checker</option>
399
+ </select>
400
+ </div>
401
+
402
+ <div class="problem-details" id="problemDetails">
403
+ <h3>Select a problem to begin</h3>
404
+ <p>Choose a programming challenge for the AI to evolve solutions for.</p>
405
+ </div>
406
+
407
+ <div class="settings">
408
+ <div class="setting-group">
409
+ <label for="maxGenerations">Max Generations:</label>
410
+ <input type="number" id="maxGenerations" value="12" min="5" max="25">
411
+ </div>
412
+ <div class="setting-group">
413
+ <label for="temperature">Temperature:</label>
414
+ <input type="range" id="temperature" value="0.3" min="0.1" max="0.8" step="0.1">
415
+ </div>
416
+ <div class="setting-group">
417
+ <label for="maxTokens">Max Tokens:</label>
418
+ <input type="number" id="maxTokens" value="384" min="256" max="512" step="64">
419
+ </div>
420
+ <div class="setting-group">
421
+ <label for="retryDelay">Retry Delay (ms):</label>
422
+ <input type="number" id="retryDelay" value="2000" min="1000" max="5000" step="500">
423
+ </div>
424
+ </div>
425
+
426
+ <div class="api-efficiency">
427
+ <h4>⚡ API Efficiency</h4>
428
+ <p><strong>Single Mutation Strategy:</strong> One API call per generation for maximum efficiency. Estimated total: <span id="estimatedCalls">12</span> API calls.</p>
429
+ </div>
430
+
431
+ <div class="controls">
432
+ <button class="btn btn-primary" id="startBtn">🚀 Start Evolution</button>
433
+ <button class="btn btn-danger" id="stopBtn" disabled>⏹️ Stop</button>
434
+ </div>
435
+
436
+ <div class="status status-idle" id="status">
437
+ Ready to evolve JavaScript programs
438
+ </div>
439
+
440
+ <div class="progress-section">
441
+ <div class="progress-bar">
442
+ <div class="progress-fill" id="progressFill"></div>
443
+ </div>
444
+ <div class="progress-text" id="progressText">0 / 0 generations</div>
445
+ </div>
446
+
447
+ <h2>📊 Fitness Evolution</h2>
448
+ <div class="fitness-chart">
449
+ <canvas id="fitnessChart" width="400" height="200"></canvas>
450
+ </div>
451
+ </div>
452
+
453
+ <!-- Right Panel: Evolution Progress & Results -->
454
+ <div class="panel">
455
+ <h2>🔬 Evolution Progress</h2>
456
+
457
+ <div class="evolution-log" id="evolutionLog">
458
+ Ready to start evolution process...
459
+
460
+ 🧬 Hill Climber Algorithm:
461
+ • Generate initial solution with StarCoder2-3B
462
+ • Each generation: create one mutation
463
+ • Keep mutation if fitness improves
464
+ • Stop when perfect solution found or max generations reached
465
+ </div>
466
+
467
+ <h2>💻 Current Best Solution</h2>
468
+ <div class="current-solution" id="currentSolution">
469
+ <p style="text-align: center; color: #666; padding: 20px;">
470
+ No solution generated yet
471
+ </p>
472
+ </div>
473
+
474
+ <div class="best-solution" id="bestSolution" style="display: none;">
475
+ <h3>🏆 Final Best Solution</h3>
476
+ <div id="bestSolutionCode"></div>
477
+ <div id="bestSolutionStats"></div>
478
+ </div>
479
+ </div>
480
+ </div>
481
+
482
+ <script>
483
+ // StarCoder2-3B - Excellent coding model, Spaces-friendly
484
+ const MODEL_URL = 'https://api-inference.huggingface.co/models/bigcode/starcoder2-3b';
485
+
486
+ // Problem definitions optimized for StarCoder2
487
+ const PROBLEMS = {
488
+ palindrome: {
489
+ name: "Palindrome Checker",
490
+ description: "Write a JavaScript function that checks if a string is a palindrome (reads the same forwards and backwards). Ignore case and non-alphanumeric characters.",
491
+ functionName: "isPalindrome",
492
+ parameters: "s",
493
+ testCases: [
494
+ { input: ["racecar"], expected: true },
495
+ { input: ["A man a plan a canal Panama"], expected: true },
496
+ { input: ["race a car"], expected: false },
497
+ { input: [""], expected: true },
498
+ { input: ["Madam"], expected: true }
499
+ ]
500
+ },
501
+ two_sum: {
502
+ name: "Two Sum Problem",
503
+ description: "Given an array of integers and a target sum, return the indices of two numbers that add up to the target. Assume exactly one solution exists.",
504
+ functionName: "twoSum",
505
+ parameters: "nums, target",
506
+ testCases: [
507
+ { input: [[2, 7, 11, 15], 9], expected: [0, 1] },
508
+ { input: [[3, 2, 4], 6], expected: [1, 2] },
509
+ { input: [[3, 3], 6], expected: [0, 1] },
510
+ { input: [[1, 5, 3, 7], 8], expected: [1, 3] }
511
+ ]
512
+ },
513
+ fibonacci: {
514
+ name: "Fibonacci Generator",
515
+ description: "Generate the nth Fibonacci number efficiently. Handle edge cases for n=0 and n=1.",
516
+ functionName: "fibonacci",
517
+ parameters: "n",
518
+ testCases: [
519
+ { input: [0], expected: 0 },
520
+ { input: [1], expected: 1 },
521
+ { input: [2], expected: 1 },
522
+ { input: [10], expected: 55 },
523
+ { input: [15], expected: 610 }
524
+ ]
525
+ },
526
+ prime_check: {
527
+ name: "Prime Number Checker",
528
+ description: "Determine if a given positive integer is a prime number. A prime number is only divisible by 1 and itself.",
529
+ functionName: "isPrime",
530
+ parameters: "n",
531
+ testCases: [
532
+ { input: [2], expected: true },
533
+ { input: [3], expected: true },
534
+ { input: [4], expected: false },
535
+ { input: [17], expected: true },
536
+ { input: [25], expected: false },
537
+ { input: [1], expected: false }
538
+ ]
539
+ },
540
+ reverse_string: {
541
+ name: "String Reversal",
542
+ description: "Write a function that reverses a string. Handle empty strings appropriately.",
543
+ functionName: "reverseString",
544
+ parameters: "s",
545
+ testCases: [
546
+ { input: ["hello"], expected: "olleh" },
547
+ { input: ["world"], expected: "dlrow" },
548
+ { input: [""], expected: "" },
549
+ { input: ["a"], expected: "a" },
550
+ { input: ["JavaScript"], expected: "tpircSavaJ" }
551
+ ]
552
+ },
553
+ max_subarray: {
554
+ name: "Maximum Subarray Sum",
555
+ description: "Find the contiguous subarray with the largest sum and return the sum (Kadane's algorithm).",
556
+ functionName: "maxSubarraySum",
557
+ parameters: "nums",
558
+ testCases: [
559
+ { input: [[-2, 1, -3, 4, -1, 2, 1, -5, 4]], expected: 6 },
560
+ { input: [[1]], expected: 1 },
561
+ { input: [[5, 4, -1, 7, 8]], expected: 23 },
562
+ { input: [[-1]], expected: -1 }
563
+ ]
564
+ },
565
+ binary_search: {
566
+ name: "Binary Search",
567
+ description: "Implement binary search to find the index of a target value in a sorted array. Return -1 if not found.",
568
+ functionName: "binarySearch",
569
+ parameters: "arr, target",
570
+ testCases: [
571
+ { input: [[-1, 0, 3, 5, 9, 12], 9], expected: 4 },
572
+ { input: [[-1, 0, 3, 5, 9, 12], 2], expected: -1 },
573
+ { input: [[1, 2, 3, 4, 5], 1], expected: 0 },
574
+ { input: [[1, 2, 3, 4, 5], 5], expected: 4 }
575
+ ]
576
+ },
577
+ anagram_check: {
578
+ name: "Anagram Checker",
579
+ description: "Check if two strings are anagrams of each other. Ignore case and spaces.",
580
+ functionName: "areAnagrams",
581
+ parameters: "s1, s2",
582
+ testCases: [
583
+ { input: ["listen", "silent"], expected: true },
584
+ { input: ["evil", "vile"], expected: true },
585
+ { input: ["hello", "bello"], expected: false },
586
+ { input: ["A gentleman", "Elegant man"], expected: true }
587
+ ]
588
+ }
589
+ };
590
+
591
+ // Hill Climber state
592
+ let isRunning = false;
593
+ let currentGeneration = 0;
594
+ let maxGenerations = 12;
595
+ let currentProblem = null;
596
+ let currentSolution = null;
597
+ let bestSolution = null;
598
+ let bestFitness = -1;
599
+ let fitnessHistory = [];
600
+ let chart = null;
601
+ let apiCallCount = 0;
602
+
603
+ // DOM elements
604
+ const problemSelect = document.getElementById('problemSelect');
605
+ const problemDetails = document.getElementById('problemDetails');
606
+ const startBtn = document.getElementById('startBtn');
607
+ const stopBtn = document.getElementById('stopBtn');
608
+ const status = document.getElementById('status');
609
+ const progressFill = document.getElementById('progressFill');
610
+ const progressText = document.getElementById('progressText');
611
+ const evolutionLog = document.getElementById('evolutionLog');
612
+ const currentSolutionDiv = document.getElementById('currentSolution');
613
+ const bestSolutionDiv = document.getElementById('bestSolution');
614
+ const estimatedCalls = document.getElementById('estimatedCalls');
615
+
616
+ // Initialize
617
+ initializeChart();
618
+ setupEventListeners();
619
+
620
+ function initializeChart() {
621
+ const ctx = document.getElementById('fitnessChart').getContext('2d');
622
+ chart = new Chart(ctx, {
623
+ type: 'line',
624
+ data: {
625
+ labels: [],
626
+ datasets: [{
627
+ label: 'Fitness Score',
628
+ data: [],
629
+ borderColor: '#667eea',
630
+ backgroundColor: 'rgba(102, 126, 234, 0.1)',
631
+ tension: 0.4,
632
+ fill: true
633
+ }]
634
+ },
635
+ options: {
636
+ responsive: true,
637
+ scales: {
638
+ y: {
639
+ beginAtZero: true,
640
+ max: 1
641
+ }
642
+ },
643
+ plugins: {
644
+ legend: {
645
+ display: false
646
+ }
647
+ }
648
+ }
649
+ });
650
+ }
651
+
652
+ function setupEventListeners() {
653
+ problemSelect.addEventListener('change', handleProblemSelect);
654
+ startBtn.addEventListener('click', startEvolution);
655
+ stopBtn.addEventListener('click', stopEvolution);
656
+
657
+ // Update estimated API calls when generations change
658
+ document.getElementById('maxGenerations').addEventListener('input', (e) => {
659
+ estimatedCalls.textContent = e.target.value;
660
+ });
661
+ }
662
+
663
+ function handleProblemSelect() {
664
+ const selectedProblem = problemSelect.value;
665
+ if (selectedProblem) {
666
+ currentProblem = PROBLEMS[selectedProblem];
667
+ displayProblemDetails(currentProblem);
668
+ startBtn.disabled = false;
669
+ } else {
670
+ currentProblem = null;
671
+ problemDetails.innerHTML = `
672
+ <h3>Select a problem to begin</h3>
673
+ <p>Choose a programming challenge for the AI to evolve solutions for.</p>
674
+ `;
675
+ startBtn.disabled = true;
676
+ }
677
+ }
678
+
679
+ function displayProblemDetails(problem) {
680
+ const testCasesText = problem.testCases.map((tc, i) =>
681
+ `Test ${i + 1}: ${problem.functionName}(${tc.input.map(inp => JSON.stringify(inp)).join(', ')}) → ${JSON.stringify(tc.expected)}`
682
+ ).join('\n');
683
+
684
+ problemDetails.innerHTML = `
685
+ <h3>${problem.name}</h3>
686
+ <p><strong>Description:</strong> ${problem.description}</p>
687
+ <p><strong>Function signature:</strong> <code>function ${problem.functionName}(${problem.parameters}) { ... }</code></p>
688
+ <div class="test-cases">${testCasesText}</div>
689
+ `;
690
+ }
691
+
692
+ async function startEvolution() {
693
+ if (!currentProblem) {
694
+ alert('Please select a problem first');
695
+ return;
696
+ }
697
+
698
+ isRunning = true;
699
+ currentGeneration = 0;
700
+ maxGenerations = parseInt(document.getElementById('maxGenerations').value);
701
+ fitnessHistory = [];
702
+ bestSolution = null;
703
+ bestFitness = -1;
704
+ apiCallCount = 0;
705
+
706
+ updateUI();
707
+ updateStatus('running', 'Evolution in progress...');
708
+ log('🚀 Starting evolution with StarCoder2-3B...');
709
+ log(`Problem: ${currentProblem.name}`);
710
+ log(`Strategy: Single mutation per generation (API efficient)`);
711
+ log(`Max generations: ${maxGenerations}`);
712
+ log('');
713
+
714
+ try {
715
+ // Step 1: Generate initial solution
716
+ log('🔬 Generating initial solution...');
717
+ currentSolution = await generateInitialSolution();
718
+ apiCallCount++;
719
+
720
+ if (!currentSolution) {
721
+ throw new Error('Failed to generate initial solution');
722
+ }
723
+
724
+ log(`✅ Initial solution generated (API calls: ${apiCallCount})`);
725
+
726
+ // Evaluate initial solution
727
+ let currentFitness = evaluateSolution(currentSolution);
728
+ fitnessHistory.push(currentFitness);
729
+ bestSolution = currentSolution;
730
+ bestFitness = currentFitness;
731
+
732
+ log(`Initial fitness: ${currentFitness.toFixed(3)} (${Math.round(currentFitness * currentProblem.testCases.length)}/${currentProblem.testCases.length} tests)`);
733
+
734
+ updateProgress();
735
+ updateChart();
736
+ updateCurrentSolution();
737
+
738
+ // Step 2: Evolution loop
739
+ for (currentGeneration = 1; currentGeneration <= maxGenerations && isRunning; currentGeneration++) {
740
+ log(`\n📈 Generation ${currentGeneration}/${maxGenerations}`);
741
+
742
+ // Check if perfect solution found
743
+ if (currentFitness >= 1.0) {
744
+ log('🎉 Perfect solution found! Stopping evolution.');
745
+ break;
746
+ }
747
+
748
+ // Generate single mutation
749
+ log('🧬 Generating mutation...');
750
+ const mutatedSolution = await mutateSolution(currentSolution, currentFitness);
751
+ apiCallCount++;
752
+
753
+ if (!mutatedSolution) {
754
+ log('⚠️ Mutation failed, keeping current solution');
755
+ continue;
756
+ }
757
+
758
+ // Evaluate mutation
759
+ const mutatedFitness = evaluateSolution(mutatedSolution);
760
+ log(`Mutation fitness: ${mutatedFitness.toFixed(3)} (${Math.round(mutatedFitness * currentProblem.testCases.length)}/${currentProblem.testCases.length} tests)`);
761
+
762
+ // Hill Climber decision: accept if better or equal
763
+ if (mutatedFitness >= currentFitness) {
764
+ currentSolution = mutatedSolution;
765
+ currentFitness = mutatedFitness;
766
+ log('✅ Mutation accepted (fitness improved or maintained)');
767
+
768
+ // Update best solution
769
+ if (mutatedFitness > bestFitness) {
770
+ bestSolution = mutatedSolution;
771
+ bestFitness = mutatedFitness;
772
+ log('✨ New best solution found!');
773
+ }
774
+ } else {
775
+ log('❌ Mutation rejected (fitness decreased)');
776
+ }
777
+
778
+ fitnessHistory.push(Math.max(currentFitness, bestFitness));
779
+ log(`API calls used: ${apiCallCount}`);
780
+
781
+ updateProgress();
782
+ updateChart();
783
+ updateCurrentSolution();
784
+
785
+ // Add delay to be respectful to API
786
+ const delay = parseInt(document.getElementById('retryDelay').value);
787
+ await new Promise(resolve => setTimeout(resolve, delay));
788
+ }
789
+
790
+ // Evolution complete
791
+ if (isRunning) {
792
+ updateStatus('complete', `Evolution completed! Best fitness: ${bestFitness.toFixed(3)}`);
793
+ log(`\n🏁 Evolution completed!`);
794
+ log(`Best fitness: ${bestFitness.toFixed(3)}`);
795
+ log(`Total API calls: ${apiCallCount}`);
796
+ showBestSolution();
797
+ }
798
+
799
+ } catch (error) {
800
+ updateStatus('error', `Error: ${error.message}`);
801
+ log(`❌ Error: ${error.message}`);
802
+ console.error('Evolution error:', error);
803
+ } finally {
804
+ isRunning = false;
805
+ updateUI();
806
+ }
807
+ }
808
+
809
+ function stopEvolution() {
810
+ isRunning = false;
811
+ updateStatus('idle', 'Evolution stopped by user');
812
+ log('\n⏹️ Evolution stopped by user');
813
+ updateUI();
814
+ }
815
+
816
+ async function generateInitialSolution() {
817
+ const prompt = `Write a JavaScript function to solve this coding problem:
818
+
819
+ **Problem:** ${currentProblem.description}
820
+
821
+ **Function signature:** function ${currentProblem.functionName}(${currentProblem.parameters}) { }
822
+
823
+ **Test cases:**
824
+ ${currentProblem.testCases.map(tc =>
825
+ `${currentProblem.functionName}(${tc.input.map(inp => JSON.stringify(inp)).join(', ')}) should return ${JSON.stringify(tc.expected)}`
826
+ ).join('\n')}
827
+
828
+ Write only the complete JavaScript function with proper logic to pass all test cases:`;
829
+
830
+ return await callStarCoder(prompt);
831
+ }
832
+
833
+ async function mutateSolution(solution, currentFitness) {
834
+ const failingCases = [];
835
+ const passingCases = [];
836
+
837
+ for (const testCase of currentProblem.testCases) {
838
+ const result = executeTestCase(solution, testCase);
839
+ if (result.passed) {
840
+ passingCases.push(testCase);
841
+ } else {
842
+ failingCases.push({...testCase, actualOutput: result.actualOutput});
843
+ }
844
+ }
845
+
846
+ let prompt;
847
+ if (failingCases.length > 0) {
848
+ // Focus on fixing failing cases
849
+ prompt = `Fix this JavaScript function to pass all test cases:
850
+
851
+ **Current function:**
852
+ ${solution}
853
+
854
+ **Failing test cases:**
855
+ ${failingCases.map(fc =>
856
+ `${currentProblem.functionName}(${fc.input.map(inp => JSON.stringify(inp)).join(', ')}) returns ${JSON.stringify(fc.actualOutput)} but should return ${JSON.stringify(fc.expected)}`
857
+ ).join('\n')}
858
+
859
+ **Passing test cases:** ${passingCases.length}/${currentProblem.testCases.length}
860
+
861
+ Write the improved JavaScript function:`;
862
+ } else {
863
+ // Optimize already working solution
864
+ prompt = `Optimize this working JavaScript function for better performance or readability:
865
+
866
+ **Current function:**
867
+ ${solution}
868
+
869
+ **All test cases are passing**
870
+
871
+ Write an optimized version of the JavaScript function:`;
872
+ }
873
+
874
+ return await callStarCoder(prompt);
875
+ }
876
+
877
+ async function callStarCoder(prompt) {
878
+ const maxTokens = parseInt(document.getElementById('maxTokens').value);
879
+ const temperature = parseFloat(document.getElementById('temperature').value);
880
+
881
+ try {
882
+ const response = await fetch(MODEL_URL, {
883
+ method: 'POST',
884
+ headers: {
885
+ 'Content-Type': 'application/json',
886
+ },
887
+ body: JSON.stringify({
888
+ inputs: prompt,
889
+ parameters: {
890
+ max_new_tokens: maxTokens,
891
+ temperature: temperature,
892
+ top_p: 0.9,
893
+ do_sample: true,
894
+ return_full_text: false
895
+ }
896
+ })
897
+ });
898
+
899
+ if (!response.ok) {
900
+ if (response.status === 503) {
901
+ log('⚠️ Model loading, retrying in 10s...');
902
+ await new Promise(resolve => setTimeout(resolve, 10000));
903
+ return await callStarCoder(prompt);
904
+ }
905
+ throw new Error(`API request failed: ${response.status} ${response.statusText}`);
906
+ }
907
+
908
+ const data = await response.json();
909
+
910
+ if (data.error) {
911
+ throw new Error(data.error);
912
+ }
913
+
914
+ let generatedText = data[0]?.generated_text || '';
915
+
916
+ // Clean and extract JavaScript function
917
+ return extractJavaScriptFunction(generatedText);
918
+
919
+ } catch (error) {
920
+ log(`⚠️ API call failed: ${error.message}`);
921
+ throw error;
922
+ }
923
+ }
924
+
925
+ function extractJavaScriptFunction(text) {
926
+ // Clean the generated text
927
+ text = text.trim();
928
+
929
+ // Look for function definition
930
+ const functionMatch = text.match(/function\s+\w+[^{]*\{[^]*?\n}/);
931
+ if (functionMatch) {
932
+ return functionMatch[0];
933
+ }
934
+
935
+ // Look for arrow function
936
+ const arrowMatch = text.match(/const\s+\w+\s*=\s*\([^)]*\)\s*=>\s*\{[^]*?\n}/);
937
+ if (arrowMatch) {
938
+ return arrowMatch[0];
939
+ }
940
+
941
+ // If no clear function found, try to construct one
942
+ if (currentProblem) {
943
+ const lines = text.split('\n').filter(line => line.trim());
944
+ if (lines.length > 0) {
945
+ return `function ${currentProblem.functionName}(${currentProblem.parameters}) {\n ${lines.join('\n ')}\n}`;
946
+ }
947
+ }
948
+
949
+ return text;
950
+ }
951
+
952
+ function evaluateSolution(solution) {
953
+ let passedTests = 0;
954
+
955
+ for (const testCase of currentProblem.testCases) {
956
+ const result = executeTestCase(solution, testCase);
957
+ if (result.passed) {
958
+ passedTests++;
959
+ }
960
+ }
961
+
962
+ return passedTests / currentProblem.testCases.length;
963
+ }
964
+
965
+ function executeTestCase(solution, testCase) {
966
+ try {
967
+ const func = new Function(`
968
+ ${solution}
969
+ return ${currentProblem.functionName}(...arguments);
970
+ `);
971
+
972
+ const actualOutput = func(...testCase.input);
973
+ const passed = JSON.stringify(actualOutput) === JSON.stringify(testCase.expected);
974
+
975
+ return { passed, actualOutput };
976
+ } catch (error) {
977
+ return { passed: false, actualOutput: `Error: ${error.message}` };
978
+ }
979
+ }
980
+
981
+ function updateUI() {
982
+ startBtn.disabled = isRunning || !currentProblem;
983
+ stopBtn.disabled = !isRunning;
984
+ problemSelect.disabled = isRunning;
985
+ }
986
+
987
+ function updateStatus(type, message) {
988
+ status.className = `status status-${type}`;
989
+ if (type === 'running') {
990
+ status.innerHTML = `<span class="spinner"></span>${message}`;
991
+ } else {
992
+ status.textContent = message;
993
+ }
994
+ }
995
+
996
+ function updateProgress() {
997
+ const progress = (currentGeneration / maxGenerations) * 100;
998
+ progressFill.style.width = `${progress}%`;
999
+ progressText.textContent = `${currentGeneration} / ${maxGenerations} generations`;
1000
+ }
1001
+
1002
+ function updateChart() {
1003
+ chart.data.labels.push(currentGeneration === 0 ? 'Initial' : `Gen ${currentGeneration}`);
1004
+ chart.data.datasets[0].data.push(fitnessHistory[fitnessHistory.length - 1]);
1005
+ chart.update('none');
1006
+ }
1007
+
1008
+ function updateCurrentSolution() {
1009
+ if (bestSolution) {
1010
+ currentSolutionDiv.innerHTML = `
1011
+ <pre><code class="language-javascript">${escapeHtml(bestSolution)}</code></pre>
1012
+ `;
1013
+ hljs.highlightAll();
1014
+ }
1015
+ }
1016
+
1017
+ function showBestSolution() {
1018
+ if (bestSolution) {
1019
+ const passedTests = Math.round(bestFitness * currentProblem.testCases.length);
1020
+ const totalTests = currentProblem.testCases.length;
1021
+
1022
+ document.getElementById('bestSolutionCode').innerHTML = `
1023
+ <pre><code class="language-javascript">${escapeHtml(bestSolution)}</code></pre>
1024
+ `;
1025
+
1026
+ document.getElementById('bestSolutionStats').innerHTML = `
1027
+ <p><strong>Final Fitness:</strong> ${bestFitness.toFixed(3)}</p>
1028
+ <p><strong>Test Cases Passed:</strong> ${passedTests} / ${totalTests}</p>
1029
+ <p><strong>Generations Required:</strong> ${currentGeneration}</p>
1030
+ <p><strong>Total API Calls:</strong> ${apiCallCount}</p>
1031
+ <p><strong>Model Used:</strong> StarCoder2-3B</p>
1032
+ `;
1033
+
1034
+ bestSolutionDiv.style.display = 'block';
1035
+ hljs.highlightAll();
1036
+ }
1037
+ }
1038
+
1039
+ function log(message) {
1040
+ evolutionLog.innerHTML += message + '\n';
1041
+ evolutionLog.scrollTop = evolutionLog.scrollHeight;
1042
+ }
1043
+
1044
+ function escapeHtml(text) {
1045
+ const map = {
1046
+ '&': '&amp;',
1047
+ '<': '&lt;',
1048
+ '>': '&gt;',
1049
+ '"': '&quot;',
1050
+ "'": '&#039;'
1051
+ };
1052
+ return text.replace(/[&<>"']/g, function(m) { return map[m]; });
1053
+ }
1054
+
1055
+ // Initialize
1056
+ log('🧬 LLM Hill Climber ready!');
1057
+ log('🤖 Using StarCoder2-3B for code generation');
1058
+ log('⚡ Single mutation strategy for API efficiency');
1059
+ log('🚀 Select a problem to begin evolution');
1060
+ log('');
1061
+ </script>
1062
+ </body>
1063
  </html>