Claude 4 Sonnetのコーディング能力を試す 3
Claude 4 が話題を呼んでいる.今回はClaude 3.7との比較でランダムウォークのシミュレーションを行ってみた.
また今回は一つプロンプトに文言を追加した.こうすることで性能が上がるとのこと.
結果,以前よりもリッチなものが出てきた.
ランダムウォークのシミュレーションを行うコードを書いて.
Reactで動的に処理できるようにして.
エラーが出ないように自己点検して.
一切の遠慮は不要です!!最高品質を追い求めて.
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { Play, Pause, RotateCcw, Settings, TrendingUp } from 'lucide-react';
const RandomWalkSimulation = () => {
// 状態管理
const [isRunning, setIsRunning] = useState(false);
const [paths, setPaths] = useState([]);
const [currentPositions, setCurrentPositions] = useState([]);
const [stepCount, setStepCount] = useState(0);
const [statistics, setStatistics] = useState({ maxDistance: 0, avgDistance: 0 });
// パラメータ設定
const [numWalkers, setNumWalkers] = useState(5);
const [stepSize, setStepSize] = useState(2);
const [speed, setSpeed] = useState(100);
const [dimension, setDimension] = useState('2D');
const [maxSteps, setMaxSteps] = useState(1000);
const [showTrails, setShowTrails] = useState(true);
const animationRef = useRef();
const canvasRef = useRef();
// カラーパレット
const colors = [
'#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7',
'#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9'
];
// 初期化
const initializeWalkers = useCallback(() => {
const centerX = 400;
const centerY = 300;
const newPaths = Array.from({ length: numWalkers }, (_, i) => ({
id: i,
points: [{ x: centerX, y: centerY, z: dimension === '3D' ? 0 : undefined }],
color: colors[i % colors.length]
}));
const newPositions = Array.from({ length: numWalkers }, () => ({
x: centerX,
y: centerY,
z: dimension === '3D' ? 0 : undefined
}));
setPaths(newPaths);
setCurrentPositions(newPositions);
setStepCount(0);
setStatistics({ maxDistance: 0, avgDistance: 0 });
}, [numWalkers, dimension]);
// ランダムステップ生成
const generateRandomStep = () => {
if (dimension === '2D') {
const angle = Math.random() * 2 * Math.PI;
return {
dx: Math.cos(angle) * stepSize,
dy: Math.sin(angle) * stepSize
};
} else {
// 3D
const phi = Math.random() * 2 * Math.PI;
const theta = Math.random() * Math.PI;
return {
dx: Math.sin(theta) * Math.cos(phi) * stepSize,
dy: Math.sin(theta) * Math.sin(phi) * stepSize,
dz: Math.cos(theta) * stepSize
};
}
};
// 距離計算
const calculateDistance = (pos) => {
const centerX = 400, centerY = 300;
if (dimension === '2D') {
return Math.sqrt((pos.x - centerX) ** 2 + (pos.y - centerY) ** 2);
} else {
return Math.sqrt((pos.x - centerX) ** 2 + (pos.y - centerY) ** 2 + pos.z ** 2);
}
};
// シミュレーションステップ
const performStep = useCallback(() => {
if (stepCount >= maxSteps) {
setIsRunning(false);
return;
}
setPaths(prevPaths =>
prevPaths.map(path => {
const step = generateRandomStep();
const lastPoint = path.points[path.points.length - 1];
const newPoint = {
x: Math.max(50, Math.min(750, lastPoint.x + step.dx)),
y: Math.max(50, Math.min(550, lastPoint.y + step.dy)),
z: dimension === '3D' ? lastPoint.z + step.dz : undefined
};
const newPoints = showTrails
? [...path.points, newPoint]
: [newPoint];
return { ...path, points: newPoints };
})
);
setCurrentPositions(prevPositions =>
prevPositions.map(pos => {
const step = generateRandomStep();
return {
x: Math.max(50, Math.min(750, pos.x + step.dx)),
y: Math.max(50, Math.min(550, pos.y + step.dy)),
z: dimension === '3D' ? pos.z + step.dz : undefined
};
})
);
setStepCount(prev => prev + 1);
}, [stepCount, maxSteps, stepSize, dimension, showTrails]);
// 統計更新
useEffect(() => {
if (currentPositions.length > 0) {
const distances = currentPositions.map(calculateDistance);
const maxDist = Math.max(...distances);
const avgDist = distances.reduce((a, b) => a + b, 0) / distances.length;
setStatistics({
maxDistance: maxDist,
avgDistance: avgDist
});
}
}, [currentPositions, dimension]);
// アニメーションループ
useEffect(() => {
if (isRunning) {
animationRef.current = setInterval(performStep, speed);
} else {
clearInterval(animationRef.current);
}
return () => clearInterval(animationRef.current);
}, [isRunning, performStep, speed]);
// 初期化処理
useEffect(() => {
initializeWalkers();
}, [initializeWalkers]);
// 3D投影(簡易)
const project3DTo2D = (point) => {
if (dimension === '2D' || !point.z) return point;
const scale = 200 / (200 + point.z);
return {
x: point.x * scale + (1 - scale) * 400,
y: point.y * scale + (1 - scale) * 300
};
};
return (
<div className="w-full max-w-6xl mx-auto p-6 bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900 min-h-screen text-white">
{/* ヘッダー */}
<div className="text-center mb-8">
<h1 className="text-4xl font-bold bg-gradient-to-r from-blue-400 to-purple-400 bg-clip-text text-transparent mb-2">
ランダムウォーク シミュレーション
</h1>
<p className="text-slate-300">多次元ランダムウォークの動的可視化</p>
</div>
{/* コントロールパネル */}
<div className="bg-slate-800/50 backdrop-blur-sm rounded-lg p-6 mb-6 border border-slate-700">
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
<div>
<label className="block text-sm font-medium mb-2 text-slate-300">
<Settings className="inline w-4 h-4 mr-1" />
ウォーカー数
</label>
<input
type="range"
min="1"
max="20"
value={numWalkers}
onChange={(e) => setNumWalkers(parseInt(e.target.value))}
className="w-full accent-blue-500"
disabled={isRunning}
/>
<div className="text-center text-sm text-slate-400">{numWalkers}</div>
</div>
<div>
<label className="block text-sm font-medium mb-2 text-slate-300">
ステップサイズ
</label>
<input
type="range"
min="0.5"
max="10"
step="0.5"
value={stepSize}
onChange={(e) => setStepSize(parseFloat(e.target.value))}
className="w-full accent-green-500"
/>
<div className="text-center text-sm text-slate-400">{stepSize}</div>
</div>
<div>
<label className="block text-sm font-medium mb-2 text-slate-300">
速度 (ms)
</label>
<input
type="range"
min="10"
max="500"
value={speed}
onChange={(e) => setSpeed(parseInt(e.target.value))}
className="w-full accent-purple-500"
/>
<div className="text-center text-sm text-slate-400">{speed}</div>
</div>
<div>
<label className="block text-sm font-medium mb-2 text-slate-300">
最大ステップ数
</label>
<input
type="range"
min="100"
max="5000"
step="100"
value={maxSteps}
onChange={(e) => setMaxSteps(parseInt(e.target.value))}
className="w-full accent-orange-500"
/>
<div className="text-center text-sm text-slate-400">{maxSteps}</div>
</div>
</div>
<div className="flex flex-wrap gap-4 items-center">
<div className="flex gap-2">
<button
onClick={() => setIsRunning(!isRunning)}
className="flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded-lg transition-colors"
>
{isRunning ? <Pause className="w-4 h-4" /> : <Play className="w-4 h-4" />}
{isRunning ? '停止' : '開始'}
</button>
<button
onClick={initializeWalkers}
className="flex items-center gap-2 px-4 py-2 bg-slate-600 hover:bg-slate-700 rounded-lg transition-colors"
disabled={isRunning}
>
<RotateCcw className="w-4 h-4" />
リセット
</button>
</div>
<div className="flex gap-4">
<label className="flex items-center gap-2">
<input
type="radio"
name="dimension"
value="2D"
checked={dimension === '2D'}
onChange={(e) => setDimension(e.target.value)}
disabled={isRunning}
className="accent-blue-500"
/>
2D
</label>
<label className="flex items-center gap-2">
<input
type="radio"
name="dimension"
value="3D"
checked={dimension === '3D'}
onChange={(e) => setDimension(e.target.value)}
disabled={isRunning}
className="accent-blue-500"
/>
3D
</label>
</div>
<label className="flex items-center gap-2">
<input
type="checkbox"
checked={showTrails}
onChange={(e) => setShowTrails(e.target.checked)}
className="accent-green-500"
/>
軌跡表示
</label>
</div>
</div>
{/* 統計情報 */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<div className="bg-slate-800/50 backdrop-blur-sm rounded-lg p-4 border border-slate-700">
<div className="flex items-center gap-2 text-blue-400 mb-1">
<TrendingUp className="w-4 h-4" />
ステップ数
</div>
<div className="text-2xl font-bold">{stepCount.toLocaleString()}</div>
</div>
<div className="bg-slate-800/50 backdrop-blur-sm rounded-lg p-4 border border-slate-700">
<div className="text-green-400 mb-1">最大距離</div>
<div className="text-2xl font-bold">{statistics.maxDistance.toFixed(1)}</div>
</div>
<div className="bg-slate-800/50 backdrop-blur-sm rounded-lg p-4 border border-slate-700">
<div className="text-purple-400 mb-1">平均距離</div>
<div className="text-2xl font-bold">{statistics.avgDistance.toFixed(1)}</div>
</div>
</div>
{/* シミュレーション画面 */}
<div className="relative bg-slate-900/50 backdrop-blur-sm rounded-lg overflow-hidden border border-slate-700">
<svg
width="800"
height="600"
className="w-full h-auto"
viewBox="0 0 800 600"
>
{/* グリッド */}
<defs>
<pattern id="grid" width="50" height="50" patternUnits="userSpaceOnUse">
<path d="M 50 0 L 0 0 0 50" fill="none" stroke="#374151" strokeWidth="0.5" opacity="0.3"/>
</pattern>
<radialGradient id="centerGlow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stopColor="#3B82F6" stopOpacity="0.3"/>
<stop offset="100%" stopColor="#3B82F6" stopOpacity="0"/>
</radialGradient>
</defs>
<rect width="800" height="600" fill="url(#grid)"/>
<circle cx="400" cy="300" r="100" fill="url(#centerGlow)"/>
{/* 中心点 */}
<circle cx="400" cy="300" r="4" fill="#3B82F6" opacity="0.8"/>
<text x="410" y="305" fill="#3B82F6" fontSize="12" opacity="0.8">原点</text>
{/* パス描画 */}
{paths.map((path, index) => {
if (path.points.length < 2) return null;
const projectedPoints = path.points.map(project3DTo2D);
const pathData = projectedPoints.reduce((acc, point, i) => {
return i === 0 ? `M ${point.x} ${point.y}` : `${acc} L ${point.x} ${point.y}`;
}, '');
return (
<g key={path.id}>
{showTrails && (
<path
d={pathData}
stroke={path.color}
strokeWidth="1.5"
fill="none"
opacity="0.7"
style={{
filter: 'drop-shadow(0 0 2px rgba(255,255,255,0.1))'
}}
/>
)}
{/* 現在位置 */}
{projectedPoints.length > 0 && (
<circle
cx={projectedPoints[projectedPoints.length - 1].x}
cy={projectedPoints[projectedPoints.length - 1].y}
r="4"
fill={path.color}
stroke="white"
strokeWidth="1"
style={{
filter: 'drop-shadow(0 0 4px rgba(255,255,255,0.3))'
}}
/>
)}
</g>
);
})}
{/* 距離圏表示 */}
<circle cx="400" cy="300" r="50" fill="none" stroke="#64748B" strokeWidth="1" opacity="0.3" strokeDasharray="5,5"/>
<circle cx="400" cy="300" r="100" fill="none" stroke="#64748B" strokeWidth="1" opacity="0.3" strokeDasharray="5,5"/>
<circle cx="400" cy="300" r="150" fill="none" stroke="#64748B" strokeWidth="1" opacity="0.3" strokeDasharray="5,5"/>
</svg>
{/* 3D表示インジケーター */}
{dimension === '3D' && (
<div className="absolute top-4 right-4 bg-slate-800/80 backdrop-blur-sm rounded-lg p-2 text-sm">
3D モード (Z軸投影)
</div>
)}
</div>
{/* 説明 */}
<div className="mt-6 bg-slate-800/30 backdrop-blur-sm rounded-lg p-4 border border-slate-700">
<h3 className="font-semibold mb-2 text-slate-200">使い方</h3>
<ul className="text-sm text-slate-400 space-y-1">
<li>• スライダーでパラメータを調整し、開始ボタンでシミュレーション開始</li>
<li>• 2D/3Dモードを選択可能(3Dは簡易投影で表示)</li>
<li>• 軌跡表示のオン/オフで表示方法を変更</li>
<li>• 各ウォーカーは異なる色で表示され、統計情報をリアルタイム更新</li>
</ul>
</div>
</div>
);
};
export default RandomWalkSimulation;
