86 lines
3.8 KiB
TypeScript
86 lines
3.8 KiB
TypeScript
import React, { useState } from 'react';
|
|
|
|
const RemainderTheoremWidget: React.FC = () => {
|
|
const [a, setA] = useState(2); // Dividing by (x - a)
|
|
|
|
// Polynomial P(x) = x^3 - 3x^2 - x + 3
|
|
const calculateP = (x: number) => Math.pow(x, 3) - 3 * Math.pow(x, 2) - x + 3;
|
|
|
|
const remainder = calculateP(a);
|
|
|
|
// Visualization
|
|
const width = 300;
|
|
const height = 200;
|
|
const rangeX = 4;
|
|
const rangeY = 10;
|
|
const scaleX = width / (rangeX * 2);
|
|
const scaleY = height / (rangeY * 2);
|
|
const centerX = width / 2;
|
|
const centerY = height / 2;
|
|
|
|
const toPx = (x: number, y: number) => ({
|
|
x: centerX + x * scaleX,
|
|
y: centerY - y * scaleY
|
|
});
|
|
|
|
const path = [];
|
|
for(let x = -rangeX; x <= rangeX; x+=0.1) {
|
|
const y = calculateP(x);
|
|
if(Math.abs(y) <= rangeY) {
|
|
path.push(toPx(x, y));
|
|
}
|
|
}
|
|
const pathD = `M ${path.map(p => `${p.x} ${p.y}`).join(' L ')}`;
|
|
const point = toPx(a, remainder);
|
|
|
|
return (
|
|
<div className="bg-white p-6 rounded-xl shadow-lg border border-slate-200">
|
|
<div className="flex flex-col md:flex-row gap-8 items-center">
|
|
<div className="flex-1 space-y-4">
|
|
<div className="p-4 bg-violet-50 rounded-xl border border-violet-100">
|
|
<p className="text-xs font-bold text-violet-400 uppercase mb-1">Polynomial</p>
|
|
<p className="font-mono font-bold text-lg text-slate-700">P(x) = x³ - 3x² - x + 3</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="text-xs font-bold text-slate-500 uppercase">Divisor (x - a)</label>
|
|
<div className="flex items-center gap-4 mt-1">
|
|
<span className="font-mono font-bold text-lg text-slate-700">x - </span>
|
|
<input
|
|
type="number" value={a} onChange={e => setA(parseFloat(e.target.value))}
|
|
className="w-16 p-2 border rounded text-center font-bold text-indigo-600"
|
|
/>
|
|
</div>
|
|
<input
|
|
type="range" min="-3" max="4" step="0.1" value={a}
|
|
onChange={e => setA(parseFloat(e.target.value))}
|
|
className="w-full mt-2 h-2 bg-slate-200 rounded-lg accent-indigo-600"
|
|
/>
|
|
</div>
|
|
|
|
<div className="p-4 bg-emerald-50 rounded-xl border border-emerald-100">
|
|
<p className="text-xs font-bold text-emerald-600 uppercase mb-1">Remainder Theorem Result</p>
|
|
<p className="text-sm text-slate-600 mb-2">Remainder of P(x) ÷ (x - {a}) is <strong>P({a})</strong></p>
|
|
<p className="font-mono font-bold text-2xl text-emerald-700">
|
|
R = {remainder.toFixed(2)}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex-none">
|
|
<div className="relative w-[300px] h-[200px] border border-slate-200 rounded-xl bg-white overflow-hidden">
|
|
<svg width="100%" height="100%" viewBox="0 0 300 200">
|
|
<line x1="0" y1={centerY} x2={width} y2={centerY} stroke="#e2e8f0" strokeWidth="2" />
|
|
<line x1={centerX} y1="0" x2={centerX} y2={height} stroke="#e2e8f0" strokeWidth="2" />
|
|
<path d={pathD} fill="none" stroke="#8b5cf6" strokeWidth="3" />
|
|
<circle cx={point.x} cy={point.y} r="6" fill="#10b981" stroke="white" strokeWidth="2" />
|
|
<text x={point.x + 10} y={point.y} className="text-xs font-bold fill-slate-500">({a}, {remainder.toFixed(1)})</text>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default RemainderTheoremWidget; |