📄 Source: index.php
<?php
// index.php - VERSION FINALĂ (CU EVALUARE CORECTĂ 100%)
session_start();
// ========== FUNCȚIE DE EVALUARE MATEMATICĂ ==========
function evaluateExpression($expr) {
// Curățăm expresia
$expr = trim($expr);
if ($expr === '') return false;
// PASUL CHEIE: Înlocuim constantele, dar PROTEJĂM notația științifică
// 1. Protejăm temporar numerele în notație științifică (ex: 1.2e5, 3E-4, 17e3)
// Acestea vor fi înlocuite cu placeholder-uri
$scientificPlaceholders = [];
$expr = preg_replace_callback('/\b\d+(?:\.\d+)?[eE][+-]?\d+\b/', function($matches) use (&$scientificPlaceholders) {
$key = '###SCI_' . count($scientificPlaceholders) . '###';
$scientificPlaceholders[$key] = $matches[0];
return $key;
}, $expr);
// 2. Înlocuim 'e' doar când e o constantă separată (nu atașată de un număr)
// Cazuri: e, e+5, (e), e*10, 2*e, etc.
// Folosim regex care caută 'e' precedat și urmat de non-cifre/non-litere
$expr = preg_replace('/(?<![a-zA-Z0-9])e(?![a-zA-Z0-9])/i', M_E, $expr);
// 3. Înlocuim 'pi' și 'π' (aceștia nu au problema cu notația științifică)
$expr = preg_replace('/(?<![a-zA-Z0-9])pi(?![a-zA-Z0-9])/i', M_PI, $expr);
$expr = str_replace('π', M_PI, $expr);
// 4. Restaurăm placeholder-ele cu numerele în notație științifică originală
foreach ($scientificPlaceholders as $key => $value) {
$expr = str_replace($key, $value, $expr);
}
// Eliminăm spațiile
$expr = preg_replace('/\s+/', '', $expr);
// Validare caractere permise (acum 'e' poate apărea doar în notația științifică restaurată)
if (!preg_match('/^[0-9+\-*\/\(\)\.eE]+$/', $expr)) {
return false;
}
// Evaluare sigură
try {
$result = eval("return ($expr);");
if (!is_numeric($result)) return false;
return $result;
} catch (Throwable $e) {
return false;
}
}
// ========== RESTUL FUNCȚIILOR RĂMÂN LA FEL ==========
function getFibonacciUpToN($limit) {
if ($limit < 0) return [];
$fib = [];
$a = 0; $b = 1;
if ($limit >= 0) $fib[] = 0;
if ($limit >= 1) $fib[] = 1;
while (true) {
$next = $a + $b;
if ($next > $limit) break;
$fib[] = $next;
$a = $b;
$b = $next;
}
return $fib;
}
function getEvenNumbers($limit) {
$evens = [];
for ($i = 0; $i <= $limit; $i += 2) $evens[] = $i;
return $evens;
}
function getOddNumbers($limit) {
$odds = [];
for ($i = 1; $i <= $limit; $i += 2) $odds[] = $i;
return $odds;
}
function getPerfectSquares($limit) {
$squares = [];
for ($i = 1; $i * $i <= $limit; $i++) {
$squares[] = $i * $i;
}
return $squares;
}
function getPerfectCubes($limit) {
$cubes = [];
for ($i = 1; $i * $i * $i <= $limit; $i++) {
$cubes[] = $i * $i * $i;
}
return $cubes;
}
function getPowersOfTwo($limit) {
$powers = [];
$val = 1;
while ($val <= $limit) {
$powers[] = $val;
$val *= 2;
}
return $powers;
}
function getMultiplesOfThree($limit) {
$multiples = [];
for ($i = 3; $i <= $limit; $i += 3) $multiples[] = $i;
return $multiples;
}
function getPrimesUpTo($limit) {
if ($limit < 2) return [];
$sieve = array_fill(0, floor($limit) + 1, true);
$sieve[0] = $sieve[1] = false;
for ($i = 2; $i * $i <= $limit; $i++) {
if ($sieve[$i]) {
for ($j = $i * $i; $j <= $limit; $j += $i) {
$sieve[$j] = false;
}
}
}
$primes = [];
for ($i = 2; $i <= $limit; $i++) {
if ($sieve[$i]) $primes[] = $i;
}
return $primes;
}
function getArithmeticProgression($limit, $firstTerm = 1, $ratio = 4) {
$seq = [];
$current = $firstTerm;
while ($current <= $limit) {
$seq[] = $current;
$current += $ratio;
}
return $seq;
}
function getGeometricProgression($limit, $firstTerm = 1, $ratio = 2) {
$seq = [];
$current = $firstTerm;
while ($current <= $limit) {
$seq[] = $current;
$current *= $ratio;
}
return $seq;
}
function getLeonardoNumbers($limit) {
if ($limit < 0) return [];
$leo = [];
$a = 1; $b = 1;
if ($limit >= 1) $leo[] = 1;
if ($limit >= 1 && count($leo) < 2 && 1 <= $limit) $leo[] = 1;
while (true) {
$next = $a + $b + 1;
if ($next > $limit) break;
$leo[] = $next;
$a = $b;
$b = $next;
}
$unique = [];
$seen = [];
foreach ($leo as $val) {
if (!in_array($val, $seen)) {
$seen[] = $val;
$unique[] = $val;
}
}
return $unique;
}
function getTribonacciNumbers($limit) {
if ($limit < 0) return [];
$trib = [];
$a = 0; $b = 0; $c = 1;
if ($limit >= 0) $trib[] = 0;
if ($limit >= 0 && count($trib) == 1 && 0 <= $limit) $trib[] = 0;
if ($limit >= 1) $trib[] = 1;
while (true) {
$next = $a + $b + $c;
if ($next > $limit) break;
$trib[] = $next;
$a = $b;
$b = $c;
$c = $next;
}
return array_values(array_unique($trib));
}
function getFactorials($limit) {
$factorials = [];
$fact = 1;
$i = 0;
while ($fact <= $limit) {
$factorials[] = $fact;
$i++;
if ($i > 20) break;
$fact *= $i;
}
return $factorials;
}
function formatSequence($arr, $maxDisplay = 20) {
if (empty($arr)) return "∅ (niciun element)";
$displayArr = array_slice($arr, 0, $maxDisplay);
$str = implode(", ", $displayArr);
if (count($arr) > $maxDisplay) {
$str .= sprintf(", … (%d mai multe)", count($arr) - $maxDisplay);
}
return $str;
}
// Procesarea cererii
$error = "";
$sequences = null;
$submittedNumber = 50;
$rawInput = "50";
$evaluatedValue = 50;
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["number"])) {
$rawInput = trim($_POST["number"]);
$evaluated = evaluateExpression($rawInput);
if ($evaluated !== false && $evaluated > 0) {
$evaluatedValue = $evaluated;
$submittedNumber = max(1, (int)round($evaluated));
$N = $submittedNumber;
if ($N > 10000) {
$error = "Numărul este prea mare (maxim 10000). Te rog introdu o valoare mai mică.";
} else {
$sequences = [
'fibonacci' => getFibonacciUpToN($N),
'tribonacci' => getTribonacciNumbers($N),
'leonardo' => getLeonardoNumbers($N),
'even' => getEvenNumbers($N),
'odd' => getOddNumbers($N),
'squares' => getPerfectSquares($N),
'cubes' => getPerfectCubes($N),
'powersOfTwo' => getPowersOfTwo($N),
'multiplesOf3' => getMultiplesOfThree($N),
'primes' => getPrimesUpTo($N),
'arithProg' => getArithmeticProgression($N, 1, 4),
'geoProg' => getGeometricProgression($N, 1, 2),
'factorials' => getFactorials($N)
];
}
} else {
$error = "Expresie invalidă. Te rog introdu un număr sau o expresie validă (ex: 50, 12+4, 35/2, 5*10, e, pi, 3e5, 12e+2, 6pi/2+30).";
}
} else {
$N = 50;
$sequences = [
'fibonacci' => getFibonacciUpToN($N),
'tribonacci' => getTribonacciNumbers($N),
'leonardo' => getLeonardoNumbers($N),
'even' => getEvenNumbers($N),
'odd' => getOddNumbers($N),
'squares' => getPerfectSquares($N),
'cubes' => getPerfectCubes($N),
'powersOfTwo' => getPowersOfTwo($N),
'multiplesOf3' => getMultiplesOfThree($N),
'primes' => getPrimesUpTo($N),
'arithProg' => getArithmeticProgression($N, 1, 4),
'geoProg' => getGeometricProgression($N, 1, 2),
'factorials' => getFactorials($N)
];
}
?>
<!DOCTYPE html>
<html lang="ro">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Explorator de Șiruri Matematice</title>
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300;400;600;700;800&display=swap" rel="stylesheet">
<style>
.examples-panel {
background: var(--code-bg);
border-radius: 1rem;
padding: 0.75rem 1rem;
margin-top: 1rem;
font-size: 0.8rem;
}
.examples-panel h4 {
margin-bottom: 0.5rem;
font-size: 0.85rem;
}
.examples-grid {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.example-chip {
background: var(--bg-card);
border: 1px solid var(--border-color);
padding: 0.25rem 0.75rem;
border-radius: 2rem;
cursor: pointer;
transition: all 0.2s;
font-family: monospace;
font-size: 0.75rem;
}
.example-chip:hover {
background: var(--btn-bg);
color: white;
transform: scale(1.02);
}
.evaluated-badge {
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
color: white;
padding: 0.25rem 0.75rem;
border-radius: 2rem;
font-size: 0.7rem;
margin-left: 0.5rem;
}
.test-section {
margin-top: 1rem;
padding: 0.75rem;
background: rgba(59,130,246,0.1);
border-radius: 1rem;
font-size: 0.75rem;
}
</style>
</head>
<body>
<div class="theme-switcher">
<button class="theme-btn" data-theme="light">☀️</button>
<button class="theme-btn" data-theme="dark">🌙</button>
<button class="theme-btn" data-theme="ocean">🌊</button>
<button class="theme-btn" data-theme="sunset">🌅</button>
</div>
<div class="container">
<header class="header">
<h1>
<span class="icon">📐</span>
Explorator de Șiruri Matematice
</h1>
<p class="subhead">
✨ Evaluare matematică avansată + șiruri celebre
</p>
</header>
<div class="form-card">
<form method="POST" action="" id="mainForm">
<div class="input-group">
<div class="input-field">
<label for="number">
🧮 Expresie matematică (N)
<span class="tooltip">ℹ️ Acceptă: numere, constante (e, pi), operații (+, -, *, /), notație științifică (1.2e5, 17e3)</span>
</label>
<input type="text"
name="number"
id="number"
value="<?php echo htmlspecialchars($rawInput); ?>"
placeholder="Ex: 50, 12+4, 35/2, e, pi, 17e, 12e+2, 6pi/2+30"
autocomplete="off">
</div>
<button type="submit" class="btn-primary">
<span class="btn-icon">✨</span>
Generează șiruri
</button>
</div>
<?php if ($error): ?>
<div class="error-message">
⚠️ <?php echo htmlspecialchars($error); ?>
</div>
<?php endif; ?>
<div class="examples-panel">
<h4>📋 Click pe orice exemplu pentru a testa:</h4>
<div class="examples-grid">
<span class="example-chip" data-expr="50">50</span>
<span class="example-chip" data-expr="12+4">12+4</span>
<span class="example-chip" data-expr="35/2">35/2 = 17.5</span>
<span class="example-chip" data-expr="5*10">5*10</span>
<span class="example-chip" data-expr="e">e ≈ 2.718</span>
<span class="example-chip" data-expr="pi">π ≈ 3.141</span>
<span class="example-chip" data-expr="17e">17e ≈ 46.2</span>
<span class="example-chip" data-expr="12e+2">12e+2 = 1200</span>
<span class="example-chip" data-expr="6pi/2+30">6π/2+30 ≈ 39.42</span>
<span class="example-chip" data-expr="e*10+5">e·10+5 ≈ 32.18</span>
<span class="example-chip" data-expr="2e3">2e3 = 2000</span>
<span class="example-chip" data-expr="1.5e-1">1.5e-1 = 0.15</span>
</div>
</div>
</form>
<?php if ($submittedNumber && !$error): ?>
<div class="info-badge">
📊 Afișează șiruri cu elemente ≤ <strong><?php echo number_format($submittedNumber, 0, ',', '.'); ?></strong>
<?php if (abs($evaluatedValue - $submittedNumber) > 0.0001): ?>
<span class="evaluated-badge">evaluat: <?php echo round($evaluatedValue, 6); ?></span>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<div class="stats-bar">
<div class="stat-item">
<span class="stat-value"><?php echo count($sequences ?? []); ?></span>
<span class="stat-label">șiruri generate</span>
</div>
<div class="stat-item">
<span class="stat-value" id="totalElements">0</span>
<span class="stat-label">elemente totale</span>
</div>
<div class="stat-item">
<span class="stat-value">≤ <?php echo number_format($submittedNumber, 0, ',', '.'); ?></span>
<span class="stat-label">valoare maximă</span>
</div>
</div>
<div class="sequences-grid" id="sequencesGrid">
<?php if ($sequences):
$sequenceConfigs = [
'fibonacci' => ['title' => '🐚 Șirul lui Fibonacci', 'icon' => 'Fibonacci', 'desc' => 'Fₙ = Fₙ₋₁ + Fₙ₋₂', 'color' => 'gold'],
'tribonacci' => ['title' => '🔷 Șirul Tribonacci', 'icon' => 'Tribonacci', 'desc' => 'Tₙ = Tₙ₋₁ + Tₙ₋₂ + Tₙ₋₃', 'color' => 'blue'],
'leonardo' => ['title' => '🧠 Șirul lui Leonardo', 'icon' => 'Leonardo', 'desc' => 'Lₙ = Lₙ₋₁ + Lₙ₋₂ + 1', 'color' => 'purple'],
'even' => ['title' => '🟢 Numere pare', 'icon' => 'Par', 'desc' => '2k', 'color' => 'green'],
'odd' => ['title' => '🔵 Numere impare', 'icon' => 'Impar', 'desc' => '2k+1', 'color' => 'cyan'],
'squares' => ['title' => '⬛ Pătrate perfecte', 'icon' => 'n²', 'desc' => 'n²', 'color' => 'red'],
'cubes' => ['title' => '🧊 Cuburi perfecte', 'icon' => 'n³', 'desc' => 'n³', 'color' => 'orange'],
'powersOfTwo' => ['title' => '⚡ Puteri ale lui 2', 'icon' => '2ⁿ', 'desc' => '2ᵏ', 'color' => 'yellow'],
'multiplesOf3' => ['title' => '✖️ Multipli ai lui 3', 'icon' => '3k', 'desc' => '3·k', 'color' => 'teal'],
'primes' => ['title' => '🔷 Numere prime', 'icon' => 'Prime', 'desc' => 'Numere cu exact 2 divizori', 'color' => 'indigo'],
'arithProg' => ['title' => '📈 Progresie aritmetică', 'icon' => 'r=4', 'desc' => '1, 5, 9, 13...', 'color' => 'pink'],
'geoProg' => ['title' => '📊 Progresie geometrică', 'icon' => 'r=2', 'desc' => '1, 2, 4, 8...', 'color' => 'rose'],
'factorials' => ['title' => '! Factoriale', 'icon' => 'n!', 'desc' => '1, 1, 2, 6, 24...', 'color' => 'slate']
];
$totalElements = 0;
foreach ($sequenceConfigs as $key => $config):
$seq = $sequences[$key] ?? [];
$count = count($seq);
$totalElements += $count;
$formatted = formatSequence($seq);
$fullSequence = implode(", ", $seq);
?>
<div class="sequence-card" data-color="<?php echo $config['color']; ?>">
<div class="card-header">
<div class="card-title">
<?php echo $config['title']; ?>
<span class="card-badge"><?php echo $config['icon']; ?></span>
</div>
<div class="card-meta">
<span class="element-count">📊 <?php echo $count; ?> elemente</span>
</div>
</div>
<div class="card-desc"><?php echo $config['desc']; ?></div>
<div class="sequence-content">
<span class="sequence-label">Șir:</span>
<div class="sequence-values" data-full="<?php echo htmlspecialchars($fullSequence); ?>">
<?php echo htmlspecialchars($formatted); ?>
</div>
</div>
<?php if ($count > 20): ?>
<div class="card-footer">
<button class="expand-btn" onclick="toggleSequence(this)">📋 Afișează toate</button>
</div>
<?php endif; ?>
</div>
<?php
endforeach;
?>
<script>document.getElementById('totalElements').textContent = '<?php echo $totalElements; ?>';</script>
<?php else: ?>
<div class="empty-state">
<div class="empty-icon">🔢</div>
<h3>Niciun șir generat</h3>
<p>Introdu o expresie matematică în formularul de mai sus pentru a genera șirurile.</p>
</div>
<?php endif; ?>
</div>
<footer class="footer">
<p>⚡ Șirurile sunt generate până la valoarea N (elemente ≤ N, rotunjit la întreg)</p>
<p>📐 Constante: <code>e</code> = 2.71828..., <code>pi</code> / <code>π</code> = 3.14159...</p>
<p>🔢 Notație științifică: <code>17e</code> = 17×e, <code>12e+2</code> = 12×10² = 1200, <code>2e3</code> = 2000</p>
</footer>
</div>
<script>
// Teme
(function() {
const savedTheme = localStorage.getItem('math-sequence-theme');
if (savedTheme) document.documentElement.setAttribute('data-theme', savedTheme);
else document.documentElement.setAttribute('data-theme', 'light');
document.querySelectorAll('.theme-btn').forEach(btn => {
btn.addEventListener('click', function() {
const theme = this.getAttribute('data-theme');
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('math-sequence-theme', theme);
});
});
})();
// Expand/Collapse
window.toggleSequence = function(button) {
const card = button.closest('.sequence-card');
const valuesDiv = card.querySelector('.sequence-values');
const fullSequence = valuesDiv.getAttribute('data-full');
if (!fullSequence) return;
if (button.textContent.includes('Afișează toate')) {
if (!valuesDiv.getAttribute('data-short')) {
valuesDiv.setAttribute('data-short', valuesDiv.textContent);
}
valuesDiv.textContent = fullSequence;
button.textContent = '📖 Arată mai puțin';
} else {
const shortText = valuesDiv.getAttribute('data-short') ||
fullSequence.split(', ').slice(0, 20).join(', ') + ', …';
valuesDiv.textContent = shortText;
button.textContent = '📋 Afișează toate';
}
};
// Fade-in
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
observer.unobserve(entry.target);
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.sequence-card').forEach(card => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = 'all 0.5s ease';
observer.observe(card);
});
// Click pe exemple - setează valoarea în input
document.querySelectorAll('.example-chip').forEach(chip => {
chip.addEventListener('click', function() {
const expr = this.getAttribute('data-expr');
const input = document.getElementById('number');
if (input && expr) {
input.value = expr;
// Opțional: auto-submit
// document.getElementById('mainForm').submit();
}
});
});
// Salvare ultimul număr
function saveLastNumber() {
const lastNumber = document.getElementById('number')?.value;
if (lastNumber && lastNumber !== '') localStorage.setItem('last-number', lastNumber);
}
window.addEventListener('beforeunload', saveLastNumber);
</script>
</body>
</html>
← Back