joi, 5 februarie 2026

 Rezolvarea primelor de pe razele spiralei numerelor naturale

<html lang="ro">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Harta Numerică - Tabel Fractal Parascan-Margoș</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
    <style>
        body {
            background-color: #020617;
            color: #e2e8f0;
            overflow-y: auto;
            overflow-x: hidden;
            font-family: 'JetBrains Mono', monospace;
        }

        .main-wrapper {
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            padding: 20px;
        }

        .dot-map-container {
            flex-grow: 1;
            position: relative;
            background: #020617;
            border-radius: 24px;
            border: 1px solid #1e293b;
            overflow-x: auto;
            overflow-y: auto;
            max-height: 75vh;
            padding: 20px;
            scroll-behavior: smooth;
        }

        /* Layout-ul pentru coloane (raze) */
        .dot-layout {
            display: flex;
            gap: 40px;
            min-width: fit-content;
        }

        .dot-column {
            display: flex;
            flex-direction: column;
            gap: 2px;
            position: relative;
        }

        .ray-header {
            position: sticky;
            top: 0;
            background: #020617;
            padding: 10px 0;
            z-index: 50;
            border-bottom: 1px solid #1e293b;
            text-align: center;
        }

        /* Containerul pentru un rând (Număr + Scara Divizorilor) */
        .number-row {
            display: flex;
            align-items: center;
            height: 12px;
            position: relative;
            border-bottom: 1px solid rgba(30, 41, 59, 0.2);
        }

        /* Punctul central (Numărul de pe rază) */
        .main-node {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            flex-shrink: 0;
            z-index: 20;
            cursor: help;
        }

        /* Scara numerică a divizorilor */
        .divisor-scale {
            position: relative;
            height: 100%;
            /* Lățimea axei X este proporțională cu valoarea numărului sau fixă pentru aliniere */
            width: 300px;
            margin-left: 10px;
            background: rgba(15, 23, 42, 0.5);
        }

        .divisor-mark {
            position: absolute;
            width: 2px;
            height: 6px;
            top: 50%;
            transform: translateY(-50%);
            border-radius: 1px;
        }

        /* Culori conform logicii anterioare */
        .node-prime { background-color: #f59e0b; box-shadow: 0 0 8px rgba(245, 158, 11, 0.5); }
        .node-normal { background-color: #334155; }
        .node-cancelled { background-color: #ef4444; }

        .div-prime { background-color: #6366f1; width: 3px; height: 8px; }
        .div-composite { background-color: #1e293b; }

        .control-panel {
            background: rgba(15, 23, 42, 0.9);
            backdrop-filter: blur(12px);
            padding: 15px;
            border-radius: 20px;
            border: 1px solid #334155;
            margin-bottom: 20px;
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
            gap: 20px;
            align-items: center;
            position: sticky;
            top: 0;
            z-index: 100;
        }

        #export-loading {
            display: none;
            position: fixed;
            top: 0; left: 0; width: 100%; height: 100%;
            background: rgba(2, 6, 23, 0.95);
            z-index: 9999;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }

        .label-text {
            font-size: 8px;
            color: #64748b;
            text-transform: uppercase;
            letter-spacing: 0.1em;
        }
    </style>
</head>
<body>

    <div id="export-loading">
        <div class="animate-spin rounded-full h-16 w-16 border-t-4 border-amber-500 mb-4"></div>
        <p class="text-white font-black text-xs uppercase tracking-widest">Generare Tabel Fractal...</p>
    </div>

    <div class="main-wrapper">
        <header class="text-center mb-6">
            <h1 class="text-3xl font-black text-white tracking-tighter uppercase italic">
                Tabel Fractal <span class="text-amber-500">Parascan-Margoș</span>
            </h1>
            <p class="text-slate-500 text-[10px] mt-1 uppercase tracking-[0.3em]">Distribuția Divizorilor pe Scara Reală a Numerelor</p>
        </header>

        <div class="control-panel">
            <div class="flex flex-col gap-1">
                <div class="flex items-center gap-4 bg-slate-900 px-4 py-2 rounded-xl border border-slate-800">
                    <label class="text-[9px] font-bold text-slate-400 uppercase">Raze (1-50):</label>
                    <input type="range" id="ray-slider" min="1" max="50" value="6" oninput="updateUI()" class="h-1.5 bg-slate-700 rounded-lg appearance-none cursor-pointer w-40">
                    <span id="ray-val" class="text-amber-500 font-bold text-sm w-6">6</span>
                </div>
            </div>

            <div class="flex gap-2">
                <button onclick="renderGrid(100)" class="bg-slate-800 hover:bg-slate-700 text-white px-4 py-2 rounded-lg text-[10px] font-bold uppercase transition-all">Scurt (600)</button>
                <button onclick="renderGrid(1667)" class="bg-amber-600 hover:bg-amber-500 text-white px-5 py-2 rounded-lg text-[10px] font-black uppercase shadow-lg transition-all">Proiectează 10.000</button>
            </div>

            <div class="h-8 w-[1px] bg-slate-800 mx-2"></div>

            <button onclick="downloadJPG()" class="bg-indigo-700 hover:bg-indigo-600 text-white px-6 py-2 rounded-lg text-[10px] font-bold uppercase transition-all">Exportă JPG</button>
        </div>

        <div class="dot-map-container" id="scroll-container">
            <div id="fractal-layout" class="dot-layout"></div>
        </div>
    </div>

    <script>
        let currentRows = 100;

        function isPrime(n) {
            if (n <= 1) return false;
            if (n <= 3) return true;
            if (n % 2 === 0 || n % 3 === 0) return false;
            for (let i = 5; i * i <= n; i += 6) {
                if (n % i === 0 || n % (i + 2) === 0) return false;
            }
            return true;
        }

        function getDivisors(n) {
            const divs = [];
            if (n < 2) return divs;
            for (let i = 2; i <= Math.sqrt(n); i++) {
                if (n % i === 0) {
                    divs.push(i);
                    if (i*i !== n) divs.push(n/i);
                }
            }
            return divs.sort((a, b) => a - b);
        }

        function createRow(num) {
            const row = document.createElement('div');
            row.className = 'number-row';

            const prime = isPrime(num);
            const baseC = (num - 1) % 6;
            const isPrimeRay = (baseC === 0 || baseC === 4);
            const cancelled = isPrimeRay && !prime && num > 1;

            // Nodul principal
            const node = document.createElement('div');
            node.className = `main-node ${prime ? 'node-prime' : (cancelled ? 'node-cancelled' : 'node-normal')}`;
            node.title = `N: ${num}`;
            row.appendChild(node);

            // Scara Divizorilor (Tabel Fractal)
            const scale = document.createElement('div');
            scale.className = 'divisor-scale';

            const divisors = getDivisors(num);
            divisors.forEach(d => {
                const mark = document.createElement('div');
                const isDivPrime = isPrime(d);
                mark.className = `divisor-mark ${isDivPrime ? 'div-prime' : 'div-composite'}`;
               
                // Poziționare pe scara reală: (valoare divizor / valoare număr) * 100%
                // Pentru vizualizare fractală optimă, folosim o scară logaritmică sau fixă.
                // Aici folosim scara liniară raportată la un maxim local pentru a vedea densitatea.
                const position = (d / num) * 100;
                mark.style.left = `${position}%`;
                mark.title = `Divizor: ${d}`;
                scale.appendChild(mark);
            });

            row.appendChild(scale);
            return row;
        }

        function renderGrid(rows) {
            currentRows = rows;
            const colsCount = parseInt(document.getElementById('ray-slider').value);
            const layout = document.getElementById('fractal-layout');
            layout.innerHTML = '';

            const fragment = document.createDocumentFragment();

            for (let c = 0; c < colsCount; c++) {
                const col = document.createElement('div');
                col.className = 'dot-column';
               
                const header = document.createElement('div');
                header.className = 'ray-header';
                header.innerHTML = `<span class="label-text">Raza</span><br><span class="text-amber-500 font-bold">${c+1}</span>`;
                col.appendChild(header);

                for (let r = 0; r < rows; r++) {
                    const num = 1 + (r * colsCount) + c;
                    if (num > 10000) break;
                    col.appendChild(createRow(num));
                }
                fragment.appendChild(col);
            }
            layout.appendChild(fragment);
        }

        function updateUI() {
            const val = document.getElementById('ray-slider').value;
            document.getElementById('ray-val').innerText = val;
            renderGrid(currentRows);
        }

        async function downloadJPG() {
            const loading = document.getElementById('export-loading');
            const target = document.getElementById('fractal-layout');
            loading.style.display = 'flex';
           
            setTimeout(async () => {
                try {
                    const canvas = await html2canvas(target, {
                        backgroundColor: '#020617',
                        scale: 1,
                        logging: false,
                        useCORS: true
                    });
                   
                    const imgData = canvas.toDataURL('image/jpeg', 0.85);
                    const link = document.createElement('a');
                    link.href = imgData;
                    link.download = `Tabel_Fractal_Parascan_Margos_${new Date().getTime()}.jpg`;
                    document.body.appendChild(link);
                    link.click();
                    document.body.removeChild(link);
                } catch (e) {
                    console.error(e);
                    alert("Imaginea este prea mare pentru memoria browserului la 10.000 de puncte. Încercați o setare mai scurtă.");
                } finally {
                    loading.style.display = 'none';
                }
            }, 100);
        }

        window.onload = () => renderGrid(100);
    </script>
</body>
</html>



Niciun comentariu:

Trimiteți un comentariu