Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width,initial-scale=1" />
- <title>Prime Decider</title>
- <style>
- :root{
- --bg:#071023;
- --panel:#0f1720;
- --muted:#9aa6b2;
- --accent-a:#14b8a6; /* teal renegade */
- --accent-b:#f97316; /* orange flame */
- --accent-c:#ff8bd8; /* pink */
- --glass: rgba(255,255,255,0.03);
- --glass-2: rgba(255,255,255,0.02);
- --hud: rgba(110,231,247,0.06);
- --danger:#ff6b6b;
- --success:#7ee787;
- font-family: Inter, ui-sans-serif, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial;
- }
- html,body{height:100%; background:linear-gradient(180deg,var(--bg), #02111a 80%); color:var(--muted); margin:0; -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;}
- /* Layout */
- .wrap{max-width:420px;margin:18px auto;padding:18px;display:block;}
- header{display:flex;align-items:center;gap:14px;padding:10px 12px;border-radius:10px;background:linear-gradient(90deg,var(--panel),rgba(255,255,255,0.01));box-shadow:0 6px 20px rgba(2,6,12,0.6);border:1px solid rgba(255,255,255,0.03);}
- h1{margin:0;font-size:1.15rem;color:var(--accent-a);letter-spacing:0.4px}
- .sub{font-size:0.85rem;color:var(--muted);opacity:0.9}
- /* Panel */
- .panel {background:linear-gradient(180deg,var(--panel),var(--glass));border-radius:10px;padding:14px;border:1px solid rgba(255,255,255,0.03);box-shadow:0 8px 30px rgba(2,6,12,0.6);}
- .big-value{font-weight:700;font-size:3.05rem;color:var(--accent-b);text-align:center;margin:6px 0 2px 0;letter-spacing:1px;}
- .small-sub{font-family:monospace;font-size:0.9rem;color:var(--muted);text-align:center;margin-bottom:8px}
- .hud-row{display:flex;gap:10px;align-items:center;justify-content:center;margin:8px 0}
- .stat{flex:1;background:var(--glass);padding:8px;border-radius:8px;border:1px solid rgba(255,255,255,0.02);text-align:center;}
- .stat .label{font-size:0.78rem;color:var(--muted);margin-bottom:6px}
- .stat .value{font-family:monospace;font-size:1.05rem;color:var(--accent-a);font-weight:600}
- /* Progress / waveform */
- .progress-wrap{background:linear-gradient(90deg, rgba(255,255,255,0.01), rgba(255,255,255,0.01));padding:10px;border-radius:8px;margin-top:10px;border:1px solid rgba(255,255,255,0.02);}
- #progress{width:100%;height:12px;background:linear-gradient(90deg,#072026,#0b2b36);border-radius:999px;overflow:hidden;border:1px solid rgba(0,0,0,0.6)}
- #progress > i{display:block;height:100%;width:0%;background:linear-gradient(90deg,var(--accent-b),var(--accent-a));transition:width 160ms linear}
- canvas.hud-canvas{width:100%;height:56px;background:linear-gradient(180deg,rgba(255,255,255,0.01),transparent);border-radius:6px;display:block}
- #equation{font-family:monospace; font-size:0.8rem; color:var(--accent-c); text-align:center; margin-top:4px; padding:2px; background:var(--glass); border-radius:4px; border:1px solid rgba(255,255,255,0.02); height:3em; overflow:hidden; display:flex; align-items:center; justify-content:center;}
- /* Controls */
- .controls{display:flex;gap:8px;flex-wrap:wrap;justify-content:center;margin-top:12px}
- .btn{background:transparent;border:1px solid rgba(255,255,255,0.04);padding:8px 12px;border-radius:8px;color:var(--muted);cursor:pointer;font-weight:600}
- .btn.primary{background:linear-gradient(90deg,var(--accent-a),var(--accent-c));color:#02121c;border:none;box-shadow:0 6px 18px rgba(110,231,247,0.06)}
- .btn.save{background:linear-gradient(90deg,#7ee787,#58a6ff);color:#02121c;border:none;box-shadow:0 6px 18px rgba(120,231,135,0.06)}
- .btn.load{background:linear-gradient(90deg,#8957e5,#da3633);color:#fff;border:none;box-shadow:0 6px 18px rgba(137,87,229,0.06)}
- .btn.ghost{background:transparent;border:1px dashed rgba(255,255,255,0.03)}
- /* Method list / controls */
- .method-list{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
- .method-pill{padding:6px 10px;border-radius:999px;border:1px solid rgba(255,255,255,0.03);background:linear-gradient(180deg,transparent,rgba(0,0,0,0.02));font-weight:600;font-size:0.85rem;color:var(--muted);cursor:pointer}
- .method-pill.active{border-color:rgba(110,231,247,0.18);box-shadow:0 6px 18px rgba(17,61,68,0.12);color:var(--accent-a)}
- /* Tile for methods */
- .tile{background:var(--glass-2);padding:12px;border-radius:10px;border:1px solid rgba(255,255,255,0.02);margin-top:12px}
- .tile h3{margin:0;color:var(--accent-c);font-size:0.95rem}
- .tile p{font-size:0.86rem;color:var(--muted);margin:8px 0 0 0}
- /* Terminal */
- .terminal-wrap{margin-top:18px;}
- .terminal-title{font-size:1rem;color:var(--accent-a);margin-bottom:8px;}
- #terminal{height:200px;overflow:auto;background:var(--panel);padding:10px;border-radius:8px;border:1px solid var(--glass);font-family:monospace;font-size:0.8rem;color:var(--success);line-height:1.2;}
- footer{text-align:center;color:var(--muted);margin-top:12px;font-size:0.86rem}
- /* small inputs */
- .row{display:flex;gap:8px;align-items:center}
- input[type="text"], select{background:transparent;border:1px solid rgba(255,255,255,0.03);padding:8px;border-radius:8px;color:var(--muted);min-width:0}
- input[type="file"]{display:none;}
- label.small{font-size:0.78rem;color:var(--muted);margin-right:6px}
- /* responsive */
- @media (max-width:980px){.wrap{padding:12px}}
- </style>
- </head>
- <body>
- <div class="wrap">
- <header>
- <div style="display:flex;flex-direction:column">
- <h1>Prime Decider</h1>
- <div class="sub">Infinite prime counting • 7 methods • Loading bar with error checking</div>
- </div>
- </header>
- <!-- HUD panel -->
- <section class="panel">
- <div class="small-sub">CURRENT PRIME</div>
- <div class="big-value" id="bigPrime">7</div>
- <div class="small-sub" id="primeSub">calculated by Trial Division</div>
- <div class="hud-row">
- <div class="stat">
- <div class="label">Primes Found</div>
- <div class="value" id="primesFound">4</div>
- </div>
- <div class="stat">
- <div class="label">Current N</div>
- <div class="value" id="currentN">21</div>
- </div>
- <div class="stat">
- <div class="label">Runtime</div>
- <div class="value" id="runtime">00:00:00</div>
- </div>
- </div>
- <div class="progress-wrap">
- <div id="progress"><i id="progressBar"></i></div>
- <canvas class="hud-canvas" id="wave" width="800" height="56"></canvas>
- <div style="display:flex;justify-content:space-between;margin-top:8px">
- <div style="font-family:monospace;color:var(--muted);font-size:0.85rem" id="calcMsg">Idle</div>
- <div style="font-family:monospace;color:var(--muted);font-size:0.85rem" id="speedLabel">Speed: 1x</div>
- </div>
- <div id="equation"></div>
- </div>
- <div class="controls">
- <button class="btn primary" id="toggleBtn">Start</button>
- <button class="btn" id="stepBtn" title="Advance one number">Step</button>
- <button class="btn save" id="saveBtn" title="Save primes to .txt">Save</button>
- <label for="loadFile" class="btn load" title="Load primes from .txt">Load</label>
- <input type="file" id="loadFile" accept=".txt">
- </div>
- <div style="margin-top:12px;display:flex;gap:8px;align-items:center;justify-content:center">
- <label class="small">Speed</label>
- <select id="speedSelect" style="min-width:88px">
- <option value="1">1x</option>
- <option value="2">2x</option>
- <option value="5">5x</option>
- <option value="10">10x</option>
- </select>
- <label class="small">Start N</label>
- <input type="text" id="startN" value="21" />
- </div>
- <div class="tile">
- <h3>Method Pipeline</h3>
- <p>Choose which prime tests rotate through. Click to enable/disable.</p>
- <div class="method-list" id="methodList">
- <!-- pills injected by JS -->
- </div>
- </div>
- </section>
- <div class="terminal-wrap">
- <div class="terminal-title">Output Terminal Window</div>
- <div id="terminal"></div>
- </div>
- <footer>Prime Decider • Infinite realm • Built for 20-40 years of runtime</footer>
- </div>
- <script>
- /* -----------------------------
- BigInt utilities
- ------------------------------*/
- function modPow(base, exp, mod) {
- let result = 1n;
- base = base % mod;
- while (exp > 0n) {
- if (exp & 1n) {
- result = (result * base) % mod;
- }
- base = (base * base) % mod;
- exp = exp >> 1n;
- }
- return result;
- }
- function bigSqrt(n) {
- if (n === 0n || n === 1n) return n;
- let low = 1n;
- let high = n / 2n + 1n;
- while (low < high) {
- let mid = low + (high - low + 1n) / 2n;
- if (mid * mid <= n) {
- low = mid;
- } else {
- high = mid - 1n;
- }
- }
- return low;
- }
- /* -----------------------------
- App state
- ------------------------------*/
- const state = {
- currentN: 21n,
- primes: [2n, 3n, 5n, 7n],
- running: false,
- progress: 0,
- phase: 'calc',
- speed: 1,
- methodIndex: 0,
- primaryMethod: null,
- verifyMethod: null,
- startTime: null,
- methods: [
- {id:'Trial Division', equation:'n % 2 ≠ 0 ∧ ∀ i=3 to √n step 2: n % i ≠ 0', fn:trialDivision, enabled:true},
- {id:'Sieve Optimized', equation:'∀ p in known primes p≤√n: n % p ≠ 0', fn:sieveOptimized, enabled:true},
- {id:'6k ± 1', equation:'n % 2=0 or %3=0? no; ∀ i=5 to √n step 6: n%i≠0 ∧ n%(i+2)≠0', fn:sixKOptimization, enabled:true},
- {id:'Fermat Test', equation:'a^{n-1} ≡ 1 mod n for a=2,3,5', fn:fermatsTest, enabled:true},
- {id:'Miller-Rabin', equation:'Strong pseudoprime to bases 2,3,5,7,11', fn:millerRabinTest, enabled:true},
- {id:'Wheel Factorization', equation:'Check 30k + {1,7,11,13,17,19,23,29} up to √n', fn:wheelFactorization, enabled:true},
- {id:'Solovay-Strassen', equation:'a^{(n-1)/2} ≡ (a/n) mod n for random a', fn:solovayStrassen, enabled:true}
- ]
- };
- /* -----------------------------
- DOM refs
- ------------------------------*/
- const bigPrime = document.getElementById('bigPrime');
- const primeSub = document.getElementById('primeSub');
- const primesFound = document.getElementById('primesFound');
- const currentNEl = document.getElementById('currentN');
- const runtimeEl = document.getElementById('runtime');
- const progressBar = document.getElementById('progressBar');
- const calcMsg = document.getElementById('calcMsg');
- const equationEl = document.getElementById('equation');
- const speedLabel = document.getElementById('speedLabel');
- const toggleBtn = document.getElementById('toggleBtn');
- const stepBtn = document.getElementById('stepBtn');
- const saveBtn = document.getElementById('saveBtn');
- const loadFile = document.getElementById('loadFile');
- const methodList = document.getElementById('methodList');
- const terminal = document.getElementById('terminal');
- document.getElementById('startN').addEventListener('change', e => {
- const vStr = e.target.value.trim() || '2';
- const v = BigInt(vStr);
- state.currentN = v % 2n === 0n ? v + 1n : v;
- updateUI();
- });
- document.getElementById('speedSelect').addEventListener('change', e => {
- state.speed = Number(e.target.value);
- speedLabel.textContent = `Speed: ${state.speed}x`;
- });
- function appendToTerminal(msg) {
- const div = document.createElement('div');
- div.textContent = msg;
- terminal.appendChild(div);
- terminal.scrollTop = terminal.scrollHeight;
- }
- loadFile.addEventListener('change', e => {
- const file = e.target.files[0];
- if (!file) return;
- const reader = new FileReader();
- reader.onload = ev => {
- try {
- const content = ev.target.result;
- const lines = content.split('\n').filter(line => line.trim());
- const loadedPrimes = [];
- lines.forEach(line => {
- const parts = line.split('\t');
- if (parts.length >= 2) {
- const primeStr = parts[1].trim();
- const prime = BigInt(primeStr);
- loadedPrimes.push(prime);
- }
- });
- if (loadedPrimes.length > 0) {
- state.primes = [...new Set([...state.primes, ...loadedPrimes])].sort((a,b) => (a > b ? 1 : -1)); // unique sorted
- state.currentN = state.primes.at(-1) + (state.primes.at(-1) % 2n === 0n ? 1n : 2n);
- terminal.innerHTML = '';
- state.primes.forEach(p => appendToTerminal(`PRIME: ${p.toString()}`));
- state.progress = 0;
- state.phase = 'calc';
- state.methodIndex = 0;
- state.startTime = new Date(); // reset runtime on load
- updateUI();
- appendToTerminal(`Loaded ${loadedPrimes.length} primes. Resuming from ${state.currentN.toString()}`);
- } else {
- appendToTerminal('No valid primes found in file.');
- }
- } catch (err) {
- appendToTerminal('Load error: ' + err.message);
- }
- };
- reader.readAsText(file);
- e.target.value = '';
- });
- saveBtn.onclick = () => {
- let content = '';
- state.primes.forEach((p, i) => {
- content += `${i}\t${p.toString()}\n`;
- });
- const blob = new Blob([content], {type: 'text/plain'});
- const url = URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = `prime-decider-primes-${Date.now()}.txt`;
- a.click();
- URL.revokeObjectURL(url);
- appendToTerminal('Primes saved to .txt file');
- };
- /* -----------------------------
- Canvas waveform
- ------------------------------*/
- const canvas = document.getElementById('wave');
- const ctx = canvas.getContext('2d');
- let wavePhase = 0;
- function drawWave(amp=12){
- const w = canvas.width;
- const h = canvas.height;
- ctx.clearRect(0,0,w,h);
- ctx.fillStyle = 'rgba(110,231,247,0.04)';
- ctx.beginPath();
- for(let x=0;x<w;x++){
- const v = Math.sin((x*0.03)+wavePhase) * Math.sin(wavePhase*0.1) * (amp/2) + (h/2);
- if(x===0) ctx.moveTo(x,v); else ctx.lineTo(x,v);
- }
- ctx.lineTo(w,h); ctx.lineTo(0,h); ctx.closePath(); ctx.fill();
- wavePhase += 0.14 * Math.max(0.5,state.progress/100);
- }
- /* -----------------------------
- UI helpers
- ------------------------------*/
- function updateRuntime() {
- if (!state.startTime) {
- runtimeEl.textContent = '00:00:00';
- return;
- }
- let elapsed = (Date.now() - state.startTime.getTime()) / 1000;
- let h = Math.floor(elapsed / 3600);
- let m = Math.floor((elapsed % 3600) / 60);
- let s = Math.floor(elapsed % 60);
- runtimeEl.textContent = `${h.toString().padStart(2,'0')}:${m.toString().padStart(2,'0')}:${s.toString().padStart(2,'0')}`;
- }
- function updateUI(){
- bigPrime.textContent = state.primes.length ? state.primes.at(-1).toString() : '-';
- primesFound.textContent = state.primes.length;
- currentNEl.textContent = state.currentN.toString();
- progressBar.style.width = `${state.progress}%`;
- let curMethod = state.phase === 'calc' ? state.primaryMethod : state.verifyMethod;
- let curId = curMethod ? curMethod.id : 'Idle';
- calcMsg.textContent = `${state.phase} • ${curId} • ${Math.round(state.progress)}%`;
- equationEl.textContent = curMethod ? curMethod.equation : '';
- primeSub.textContent = `last calculated by ${state.primaryMethod?.id || 'none'}`;
- // methods pills
- methodList.innerHTML = '';
- state.methods.forEach((m,i)=>{
- const p = document.createElement('div');
- p.className = 'method-pill' + (m.enabled? ' active':'');
- p.textContent = m.id;
- p.onclick = ()=>{ m.enabled = !m.enabled; updateUI(); }
- methodList.appendChild(p);
- });
- updateRuntime();
- }
- /* -----------------------------
- Controls
- ------------------------------*/
- toggleBtn.onclick = ()=>{
- if (!state.running) {
- state.running = true;
- if (!state.startTime) {
- state.startTime = new Date();
- }
- toggleBtn.textContent = 'Pause';
- toggleBtn.classList.add('primary');
- appendToTerminal('Started prime hunting');
- runLoop();
- } else {
- state.running = false;
- toggleBtn.textContent = 'Start';
- toggleBtn.classList.remove('primary');
- appendToTerminal('Paused prime hunting');
- }
- };
- stepBtn.onclick = ()=> {
- performOneCycle();
- };
- /* -----------------------------
- Run loop
- ------------------------------*/
- let loopHandle = null;
- function runLoop(){
- if(!state.running) return;
- const iterations = Math.max(1, state.speed);
- (function frame(){
- if(!state.running) return;
- for(let i=0;i<iterations;i++){
- performOneCycle();
- }
- drawWave();
- updateUI();
- loopHandle = requestAnimationFrame(frame);
- })();
- }
- /* performOneCycle */
- function performOneCycle(){
- if (state.phase === 'calc' && state.progress === 0) {
- const enabledMethods = state.methods.filter(m => m.enabled);
- if (enabledMethods.length === 0) {
- state.progress = 0;
- updateUI();
- return;
- }
- const idx = state.methodIndex % enabledMethods.length;
- state.primaryMethod = enabledMethods[idx];
- state.methodIndex++;
- state.verifyMethod = null;
- }
- let maxProg = state.phase === 'calc' ? 50 : 100;
- let delta = Math.max(8, 6 + Math.random()*8) * state.speed / 2;
- state.progress += delta;
- state.progress = Math.min(maxProg, state.progress);
- let phaseLimit = state.phase === 'calc' ? 50 : 100;
- if (state.progress >= phaseLimit) {
- if (state.phase === 'calc') {
- setTimeout(() => {
- const nStr = state.currentN.toString();
- const isP = state.primaryMethod.fn(state.currentN);
- if (!isP) {
- state.currentN = state.currentN % 2n === 0n ? state.currentN + 1n : state.currentN + 2n;
- state.progress = 0;
- state.phase = 'calc';
- const enabledMethods = state.methods.filter(m => m.enabled);
- if (enabledMethods.length > 0) {
- const idx = state.methodIndex % enabledMethods.length;
- state.primaryMethod = enabledMethods[idx];
- state.methodIndex++;
- }
- } else {
- let candidates = state.methods.filter(m => m.enabled && m !== state.primaryMethod);
- if (candidates.length === 0) candidates = [state.primaryMethod];
- const vIdx = Math.floor(Math.random() * candidates.length);
- state.verifyMethod = candidates[vIdx];
- state.phase = 'verify';
- state.progress = 50;
- }
- updateUI();
- }, 10);
- } else if (state.phase === 'verify') {
- setTimeout(() => {
- const nStr = state.currentN.toString();
- const isV = state.verifyMethod.fn(state.currentN);
- if (isV) {
- const lastPrime = state.primes.at(-1) || 0n;
- if (state.currentN > lastPrime && !state.primes.includes(state.currentN)) {
- state.primes.push(state.currentN);
- appendToTerminal(`PRIME FOUND: ${nStr}`);
- }
- }
- state.currentN = state.currentN % 2n === 0n ? state.currentN + 1n : state.currentN + 2n;
- state.progress = 0;
- state.phase = 'calc';
- const enabledMethods = state.methods.filter(m => m.enabled);
- if (enabledMethods.length > 0) {
- const idx = state.methodIndex % enabledMethods.length;
- state.primaryMethod = enabledMethods[idx];
- state.methodIndex++;
- }
- updateUI();
- }, 10);
- }
- }
- if(state.progress < (state.phase === 'calc' ? 50 : 100)){
- updateUI();
- }
- }
- /* -----------------------------
- Prime helpers
- ------------------------------*/
- function trialDivision(n) {
- n = BigInt(n);
- if (n < 2n) return false;
- if (n === 2n || n === 3n) return true;
- if (n % 2n === 0n || n % 3n === 0n) return false;
- let i = 5n;
- let lim = bigSqrt(n);
- while (i <= lim) {
- if (n % i === 0n || n % (i + 2n) === 0n) return false;
- i += 6n;
- }
- return true;
- }
- function sieveOptimized(n) {
- n = BigInt(n);
- if (n < 2n) return false;
- for (let p of state.primes) {
- if (p * p > n) break;
- if (n % p === 0n) return false;
- }
- return trialDivision(n);
- }
- function sixKOptimization(n) {
- return trialDivision(n);
- }
- function fermatsTest(n) {
- n = BigInt(n);
- if (n < 2n) return false;
- if (n <= 3n) return true;
- if (n % 2n === 0n) return false;
- const bases = [2n, 3n, 5n];
- for (let base of bases) {
- if (base >= n) break;
- if (modPow(base, n - 1n, n) !== 1n) return false;
- }
- return true;
- }
- function millerRabinTest(n) {
- n = BigInt(n);
- if (n < 2n) return false;
- if (n === 2n || n === 3n) return true;
- if (n % 2n === 0n) return false;
- const witnesses = [2n, 3n, 5n, 7n, 11n];
- let d = n - 1n;
- let s = 0n;
- while (d % 2n === 0n) {
- d /= 2n;
- s++;
- }
- for (let a of witnesses) {
- if (a >= n) break;
- let x = modPow(a, d, n);
- if (x === 1n || x === n - 1n) continue;
- let cont = false;
- for (let r = 1n; r < s; r++) {
- x = modPow(x, 2n, n);
- if (x === n - 1n) {
- cont = true;
- break;
- }
- }
- if (cont) continue;
- return false;
- }
- return true;
- }
- function wheelFactorization(n) {
- n = BigInt(n);
- if (n < 2n) return false;
- if (n <= 5n) return true;
- if (n % 2n === 0n || n % 3n === 0n || n % 5n === 0n) return false;
- const offsets = [1n,7n,11n,13n,17n,19n,23n,29n];
- let k = 0n;
- let lim = bigSqrt(n);
- while (true) {
- let d = 30n * k;
- let broke = true;
- for (let r of offsets) {
- let test = d + r;
- if (test > lim) break;
- if (n % test === 0n) return false;
- broke = false;
- }
- if (broke) break;
- k++;
- }
- return true;
- }
- function jacobiSymbol(a, n) {
- a = BigInt(a);
- n = BigInt(n);
- if (n <= 0n || n % 2n === 0n) return 0n;
- a = a % n;
- let result = 1n;
- while (a !== 0n) {
- while (a % 2n === 0n) {
- a /= 2n;
- let r = n % 8n;
- if (r === 3n || r === 5n) result = -result;
- }
- [a, n] = [n, a];
- if (a % 4n === 3n && n % 4n === 3n) result = -result;
- a %= n;
- }
- return n === 1n ? result : 0n;
- }
- function solovayStrassen(n) {
- n = BigInt(n);
- if (n < 2n) return false;
- if (n === 2n || n === 3n) return true;
- if (n % 2n === 0n) return false;
- const k = 5;
- for (let i = 0; i < k; i++) {
- let a = BigInt(2 + Math.floor(Math.random() * Number(n - 3n)));
- let legendre = jacobiSymbol(a, n);
- if (legendre === 0n) return false;
- let jacobi = legendre < 0n ? (n - 1n) : legendre;
- if (modPow(a, (n - 1n)/2n, n) !== jacobi) return false;
- }
- return true;
- }
- /* -----------------------------
- Misc UI and keyboard
- ------------------------------*/
- function tick(){
- drawWave();
- updateUI();
- requestAnimationFrame(tick);
- }
- tick();
- document.addEventListener('keydown', (e)=>{
- if(e.key==='p' || e.key==='P'){ toggleBtn.click(); }
- if(e.key==='s' || e.key==='S'){ stepBtn.click(); }
- });
- // Initialize terminal with initial primes
- state.primes.forEach(p => appendToTerminal(`PRIME: ${p.toString()}`));
- /* startup */
- updateUI();
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment