+
+
-
-
- {children}
-
-
+
+ {children}
+
+
);
diff --git a/frontend/src/components/visualizations-new/index.ts b/frontend/src/components/visualizations-new/index.ts
index 7a61b43..25831ab 100644
--- a/frontend/src/components/visualizations-new/index.ts
+++ b/frontend/src/components/visualizations-new/index.ts
@@ -14,4 +14,5 @@ export { CalculationBubble } from "./primitives/calculation-bubble";
export { ArrayView } from "./data-structures/array-view";
// Algorithm visualizations
+export { PrefixSumVisualization } from "./algorithms/prefix-sum";
export { TwoPointersVisualization } from "./algorithms/two-pointers";
diff --git a/frontend/src/content/algorithms/binary-search.ts b/frontend/src/content/algorithms/binary-search.ts
new file mode 100644
index 0000000..e585fbe
--- /dev/null
+++ b/frontend/src/content/algorithms/binary-search.ts
@@ -0,0 +1,773 @@
+import type { AlgorithmDefinition } from '@/lib/visualizations/types';
+
+export const binarySearchAlgorithm: AlgorithmDefinition = {
+ id: 'binary-search',
+ title: 'Binary Search',
+ slug: 'binary-search',
+ pattern: {
+ name: 'Binary Search',
+ description:
+ 'Repeatedly divide the search space in half by comparing to the middle element.',
+ },
+ problemStatement:
+ 'Given a sorted array of integers, find the index of a target value. Return -1 if not found.',
+ intuition:
+ 'In a sorted array, we can eliminate half of the remaining elements with each comparison. Compare the target to the middle element: if smaller, search left half; if larger, search right half.',
+ code: {
+ language: 'python',
+ code: `def binary_search(nums: list[int], target: int) -> int:
+ left = 0
+ right = len(nums) - 1
+
+ while left <= right:
+ mid = (left + right) // 2
+
+ if nums[mid] == target:
+ return mid
+ elif nums[mid] < target:
+ left = mid + 1
+ else:
+ right = mid - 1
+
+ return -1`,
+ },
+ initialExample: {
+ input: { nums: [1, 3, 5, 7, 9, 11, 13], target: 9 },
+ expected: 4,
+ },
+ steps: [
+ // Phase 1: Problem (2 steps)
+ {
+ id: 'problem-1',
+ phase: 'problem',
+ explanation:
+ 'We have a sorted array [1, 3, 5, 7, 9, 11, 13] and need to find the index of target value 9.',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'target', name: 'target', value: 9 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'problem-2',
+ phase: 'problem',
+ explanation:
+ 'A linear search would check each element, giving O(n) time. Can we use the sorted property to do better?',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'comparing' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'target', name: 'target', value: 9 }],
+ calculations: [],
+ },
+ },
+
+ // Phase 2: Intuition (3 steps)
+ {
+ id: 'intuition-1',
+ phase: 'intuition',
+ explanation:
+ 'Key insight: If we check the middle element, we can eliminate half the array with one comparison.',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'highlighted' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'mid', name: 'mid', index: 3, color: 'mid' },
+ ],
+ variables: [{ id: 'target', name: 'target', value: 9 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'intuition-2',
+ phase: 'intuition',
+ explanation:
+ 'Middle element is 7. Since 9 > 7, the target must be in the right half. We can ignore the left half entirely!',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 7, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'target', name: 'target', value: 9 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'intuition-3',
+ phase: 'intuition',
+ explanation:
+ 'Repeat this process on the remaining half. Each step halves the search space, giving O(log n) time complexity.',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 7, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'highlighted' },
+ { value: 13, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'mid', name: 'mid', index: 5, color: 'mid' },
+ ],
+ variables: [{ id: 'target', name: 'target', value: 9 }],
+ calculations: [],
+ },
+ },
+
+ // Phase 3: Code walkthrough (5 steps)
+ {
+ id: 'code-1',
+ phase: 'code',
+ explanation:
+ 'Initialize two pointers: left at 0, right at the last index.',
+ codeLine: 2,
+ codeHighlightLines: [2, 3],
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'target', name: 'target', value: 9 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'code-2',
+ phase: 'code',
+ explanation:
+ 'Loop while the search space is valid (left <= right).',
+ codeLine: 5,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'target', name: 'target', value: 9 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'code-3',
+ phase: 'code',
+ explanation:
+ 'Calculate the middle index: mid = (left + right) // 2.',
+ codeLine: 6,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'target', name: 'target', value: 9 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'code-4',
+ phase: 'code',
+ explanation:
+ 'If nums[mid] equals target, we found it! Otherwise, narrow the search space.',
+ codeLine: 8,
+ codeHighlightLines: [8, 9, 10, 11, 12, 13],
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'target', name: 'target', value: 9 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'code-5',
+ phase: 'code',
+ explanation:
+ 'If target not found after search space is exhausted, return -1.',
+ codeLine: 15,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'target', name: 'target', value: 9 }],
+ calculations: [],
+ },
+ },
+
+ // Phase 4: Execution (~15 steps)
+ {
+ id: 'exec-1',
+ phase: 'execution',
+ explanation: 'Initialize left = 0, right = 6 (len(nums) - 1).',
+ codeLine: 2,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'highlighted' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 0, color: 'left', showValue: true },
+ { id: 'right', name: 'right', index: 6, color: 'right', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'left', name: 'left', value: 0 },
+ { id: 'right', name: 'right', value: 6 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-2',
+ phase: 'execution',
+ explanation: 'Check loop condition: left (0) <= right (6)? Yes, enter loop.',
+ codeLine: 5,
+ decision: {
+ question: 'Is left <= right?',
+ answer: '0 <= 6 = true',
+ action: 'Enter the while loop',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'highlighted' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 0, color: 'left', showValue: true },
+ { id: 'right', name: 'right', index: 6, color: 'right', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'left', name: 'left', value: 0 },
+ { id: 'right', name: 'right', value: 6 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-3',
+ phase: 'execution',
+ explanation: 'Calculate mid = (0 + 6) // 2 = 3. Middle element is 7.',
+ codeLine: 6,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'highlighted' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'comparing' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 0, color: 'left', showValue: true },
+ { id: 'mid', name: 'mid', index: 3, color: 'mid', showValue: true },
+ { id: 'right', name: 'right', index: 6, color: 'right', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'left', name: 'left', value: 0 },
+ { id: 'right', name: 'right', value: 6 },
+ { id: 'mid', name: 'mid', value: 3, derivation: '(0 + 6) // 2' },
+ ],
+ calculations: [
+ { id: 'calc-1', expression: '(0 + 6) // 2', result: '3', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-4',
+ phase: 'execution',
+ explanation: 'Compare: nums[3] = 7 vs target = 9. 7 < 9, so target is in right half.',
+ codeLine: 10,
+ decision: {
+ question: 'Is nums[mid] == target?',
+ answer: '7 != 9, and 7 < 9',
+ action: 'Search the right half (left = mid + 1)',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'highlighted' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 7, index: 3, state: 'comparing' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 0, color: 'left', showValue: true },
+ { id: 'mid', name: 'mid', index: 3, color: 'mid', showValue: true },
+ { id: 'right', name: 'right', index: 6, color: 'right', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'left', name: 'left', value: 0 },
+ { id: 'right', name: 'right', value: 6 },
+ { id: 'mid', name: 'mid', value: 3 },
+ ],
+ calculations: [
+ { id: 'calc-1', expression: '7 < 9', result: 'true', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-5',
+ phase: 'execution',
+ explanation: 'Update left = mid + 1 = 4. The left half is eliminated.',
+ codeLine: 11,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 7, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'highlighted' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 4, color: 'left', showValue: true },
+ { id: 'right', name: 'right', index: 6, color: 'right', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'left', name: 'left', value: 4, previousValue: 0 },
+ { id: 'right', name: 'right', value: 6 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-6',
+ phase: 'execution',
+ explanation: 'Check loop condition: left (4) <= right (6)? Yes, continue.',
+ codeLine: 5,
+ decision: {
+ question: 'Is left <= right?',
+ answer: '4 <= 6 = true',
+ action: 'Continue the while loop',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 7, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'highlighted' },
+ { value: 11, index: 5, state: 'normal' },
+ { value: 13, index: 6, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 4, color: 'left', showValue: true },
+ { id: 'right', name: 'right', index: 6, color: 'right', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'left', name: 'left', value: 4 },
+ { id: 'right', name: 'right', value: 6 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-7',
+ phase: 'execution',
+ explanation: 'Calculate mid = (4 + 6) // 2 = 5. Middle element is 11.',
+ codeLine: 6,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 7, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'highlighted' },
+ { value: 11, index: 5, state: 'comparing' },
+ { value: 13, index: 6, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 4, color: 'left', showValue: true },
+ { id: 'mid', name: 'mid', index: 5, color: 'mid', showValue: true },
+ { id: 'right', name: 'right', index: 6, color: 'right', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'left', name: 'left', value: 4 },
+ { id: 'right', name: 'right', value: 6 },
+ { id: 'mid', name: 'mid', value: 5, previousValue: 3, derivation: '(4 + 6) // 2' },
+ ],
+ calculations: [
+ { id: 'calc-2', expression: '(4 + 6) // 2', result: '5', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-8',
+ phase: 'execution',
+ explanation: 'Compare: nums[5] = 11 vs target = 9. 11 > 9, so target is in left half.',
+ codeLine: 12,
+ decision: {
+ question: 'Is nums[mid] == target?',
+ answer: '11 != 9, and 11 > 9',
+ action: 'Search the left half (right = mid - 1)',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 7, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'highlighted' },
+ { value: 11, index: 5, state: 'comparing' },
+ { value: 13, index: 6, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 4, color: 'left', showValue: true },
+ { id: 'mid', name: 'mid', index: 5, color: 'mid', showValue: true },
+ { id: 'right', name: 'right', index: 6, color: 'right', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'left', name: 'left', value: 4 },
+ { id: 'right', name: 'right', value: 6 },
+ { id: 'mid', name: 'mid', value: 5 },
+ ],
+ calculations: [
+ { id: 'calc-2', expression: '11 > 9', result: 'true', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-9',
+ phase: 'execution',
+ explanation: 'Update right = mid - 1 = 4. The right portion is eliminated.',
+ codeLine: 13,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 7, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'highlighted' },
+ { value: 11, index: 5, state: 'dimmed' },
+ { value: 13, index: 6, state: 'dimmed' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 4, color: 'left', showValue: true },
+ { id: 'right', name: 'right', index: 4, color: 'right', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'left', name: 'left', value: 4 },
+ { id: 'right', name: 'right', value: 4, previousValue: 6 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-10',
+ phase: 'execution',
+ explanation: 'Check loop condition: left (4) <= right (4)? Yes, continue.',
+ codeLine: 5,
+ decision: {
+ question: 'Is left <= right?',
+ answer: '4 <= 4 = true',
+ action: 'Continue the while loop',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 7, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'highlighted' },
+ { value: 11, index: 5, state: 'dimmed' },
+ { value: 13, index: 6, state: 'dimmed' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 4, color: 'left', showValue: true },
+ { id: 'right', name: 'right', index: 4, color: 'right', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'left', name: 'left', value: 4 },
+ { id: 'right', name: 'right', value: 4 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-11',
+ phase: 'execution',
+ explanation: 'Calculate mid = (4 + 4) // 2 = 4. Middle element is 9.',
+ codeLine: 6,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 7, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'comparing' },
+ { value: 11, index: 5, state: 'dimmed' },
+ { value: 13, index: 6, state: 'dimmed' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 4, color: 'left', showValue: true },
+ { id: 'mid', name: 'mid', index: 4, color: 'mid', showValue: true },
+ { id: 'right', name: 'right', index: 4, color: 'right', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'left', name: 'left', value: 4 },
+ { id: 'right', name: 'right', value: 4 },
+ { id: 'mid', name: 'mid', value: 4, previousValue: 5, derivation: '(4 + 4) // 2' },
+ ],
+ calculations: [
+ { id: 'calc-3', expression: '(4 + 4) // 2', result: '4', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-12',
+ phase: 'execution',
+ explanation: 'Compare: nums[4] = 9 vs target = 9. Found it!',
+ codeLine: 8,
+ decision: {
+ question: 'Is nums[mid] == target?',
+ answer: '9 == 9 = true',
+ action: 'Return mid = 4',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 7, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'success' },
+ { value: 11, index: 5, state: 'dimmed' },
+ { value: 13, index: 6, state: 'dimmed' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'mid', name: 'mid', index: 4, color: 'mid', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'mid', name: 'mid', value: 4 },
+ ],
+ calculations: [
+ { id: 'calc-3', expression: '9 == 9', result: 'true', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-13',
+ phase: 'execution',
+ explanation:
+ 'Return 4. Found target 9 at index 4 in just 3 comparisons! O(log n) time complexity.',
+ codeLine: 9,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 1, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 7, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'success' },
+ { value: 11, index: 5, state: 'dimmed' },
+ { value: 13, index: 6, state: 'dimmed' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'mid', name: 'mid', index: 4, color: 'mid', showValue: true },
+ ],
+ variables: [
+ { id: 'target', name: 'target', value: 9 },
+ { id: 'result', name: 'result', value: 4 },
+ ],
+ calculations: [],
+ },
+ },
+ ],
+};
diff --git a/frontend/src/content/algorithms/prefix-sum.ts b/frontend/src/content/algorithms/prefix-sum.ts
new file mode 100644
index 0000000..b594e56
--- /dev/null
+++ b/frontend/src/content/algorithms/prefix-sum.ts
@@ -0,0 +1,807 @@
+import type { AlgorithmDefinition } from '@/lib/visualizations/types';
+
+export const prefixSumAlgorithm: AlgorithmDefinition = {
+ id: 'prefix-sum',
+ title: 'Prefix Sum - Range Query',
+ slug: 'prefix-sum',
+ pattern: {
+ name: 'Prefix Sum',
+ description:
+ 'Precompute cumulative sums to answer range sum queries in O(1) time.',
+ },
+ problemStatement:
+ 'Given an array, answer multiple range sum queries efficiently. Each query asks for the sum of elements from index i to j.',
+ intuition:
+ 'Build a prefix sum array where prefix[k] = sum of all elements from 0 to k-1. Then any range sum from i to j is simply prefix[j+1] - prefix[i].',
+ code: {
+ language: 'python',
+ code: `def build_prefix(nums: list[int]) -> list[int]:
+ prefix = [0]
+ for num in nums:
+ prefix.append(prefix[-1] + num)
+ return prefix
+
+def range_sum(prefix: list[int], i: int, j: int) -> int:
+ return prefix[j + 1] - prefix[i]`,
+ },
+ initialExample: {
+ input: { nums: [3, 1, 4, 1, 5, 9], query: { i: 1, j: 4 } },
+ expected: 11,
+ },
+ steps: [
+ // Phase 1: Problem (2 steps)
+ {
+ id: 'problem-1',
+ phase: 'problem',
+ explanation:
+ 'We have an array [3, 1, 4, 1, 5, 9] and need to efficiently answer range sum queries like "sum from index 1 to 4".',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [],
+ calculations: [],
+ },
+ },
+ {
+ id: 'problem-2',
+ phase: 'problem',
+ explanation:
+ 'Naively summing each range takes O(n) per query. With many queries, this becomes expensive. Can we precompute something?',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 4, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 5, index: 4, state: 'highlighted' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'i', name: 'i', index: 1, color: 'left' },
+ { id: 'j', name: 'j', index: 4, color: 'right' },
+ ],
+ variables: [
+ { id: 'i', name: 'i', value: 1 },
+ { id: 'j', name: 'j', value: 4 },
+ ],
+ calculations: [],
+ },
+ },
+
+ // Phase 2: Intuition (3 steps)
+ {
+ id: 'intuition-1',
+ phase: 'intuition',
+ explanation:
+ 'Key insight: Build a prefix sum array where each element is the cumulative sum of all elements up to that point.',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 8, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 14, index: 5, state: 'normal' },
+ { value: 23, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [],
+ calculations: [],
+ },
+ },
+ {
+ id: 'intuition-2',
+ phase: 'intuition',
+ explanation:
+ 'prefix[k] represents the sum of elements from index 0 to k-1. The extra 0 at the start simplifies our formula.',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'highlighted' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 4, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 8, index: 3, state: 'highlighted' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 14, index: 5, state: 'normal' },
+ { value: 23, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [],
+ calculations: [
+ { id: 'calc-1', expression: '3 + 1 + 4', result: '8', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'intuition-3',
+ phase: 'intuition',
+ explanation:
+ 'Range sum from i to j = prefix[j+1] - prefix[i]. This is O(1) per query after O(n) preprocessing!',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 4, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 5, index: 4, state: 'highlighted' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'comparing' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 8, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 14, index: 5, state: 'comparing' },
+ { value: 23, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'i', name: 'i', index: 1, color: 'left' },
+ { id: 'j+1', name: 'j+1', index: 5, color: 'right' },
+ ],
+ variables: [
+ { id: 'i', name: 'i', value: 1 },
+ { id: 'j', name: 'j', value: 4 },
+ ],
+ calculations: [
+ { id: 'calc-1', expression: '14 - 3', result: '11', position: 'above' },
+ ],
+ },
+ },
+
+ // Phase 3: Code walkthrough (4 steps)
+ {
+ id: 'code-1',
+ phase: 'code',
+ explanation:
+ 'Start with prefix = [0]. This handles the edge case of summing from index 0.',
+ codeLine: 2,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [],
+ calculations: [],
+ },
+ },
+ {
+ id: 'code-2',
+ phase: 'code',
+ explanation:
+ 'For each element, append prefix[-1] + num. This builds the cumulative sum.',
+ codeLine: 3,
+ codeHighlightLines: [3, 4],
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [],
+ calculations: [],
+ },
+ },
+ {
+ id: 'code-3',
+ phase: 'code',
+ explanation:
+ 'The range_sum function computes prefix[j+1] - prefix[i] in O(1).',
+ codeLine: 8,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [],
+ calculations: [],
+ },
+ },
+ {
+ id: 'code-4',
+ phase: 'code',
+ explanation:
+ 'Why j+1? Because prefix[k] is the sum of elements 0 through k-1. So prefix[j+1] includes element j.',
+ codeLine: 8,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [],
+ calculations: [],
+ },
+ },
+
+ // Phase 4: Execution - Building prefix array (10 steps)
+ {
+ id: 'exec-1',
+ phase: 'execution',
+ explanation: 'Initialize prefix = [0].',
+ codeLine: 2,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-2',
+ phase: 'execution',
+ explanation: 'Process nums[0] = 3. Append prefix[-1] + 3 = 0 + 3 = 3.',
+ codeLine: 4,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'comparing' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'curr', name: 'num', index: 0, color: 'mid' },
+ ],
+ variables: [],
+ calculations: [
+ { id: 'calc-1', expression: '0 + 3', result: '3', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-3',
+ phase: 'execution',
+ explanation: 'Process nums[1] = 1. Append prefix[-1] + 1 = 3 + 1 = 4.',
+ codeLine: 4,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'comparing' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'curr', name: 'num', index: 1, color: 'mid' },
+ ],
+ variables: [],
+ calculations: [
+ { id: 'calc-2', expression: '3 + 1', result: '4', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-4',
+ phase: 'execution',
+ explanation: 'Process nums[2] = 4. Append prefix[-1] + 4 = 4 + 4 = 8.',
+ codeLine: 4,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'dimmed' },
+ { value: 4, index: 2, state: 'comparing' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 8, index: 3, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'curr', name: 'num', index: 2, color: 'mid' },
+ ],
+ variables: [],
+ calculations: [
+ { id: 'calc-3', expression: '4 + 4', result: '8', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-5',
+ phase: 'execution',
+ explanation: 'Process nums[3] = 1. Append prefix[-1] + 1 = 8 + 1 = 9.',
+ codeLine: 4,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'dimmed' },
+ { value: 4, index: 2, state: 'dimmed' },
+ { value: 1, index: 3, state: 'comparing' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 8, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'curr', name: 'num', index: 3, color: 'mid' },
+ ],
+ variables: [],
+ calculations: [
+ { id: 'calc-4', expression: '8 + 1', result: '9', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-6',
+ phase: 'execution',
+ explanation: 'Process nums[4] = 5. Append prefix[-1] + 5 = 9 + 5 = 14.',
+ codeLine: 4,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'dimmed' },
+ { value: 4, index: 2, state: 'dimmed' },
+ { value: 1, index: 3, state: 'dimmed' },
+ { value: 5, index: 4, state: 'comparing' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 8, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 14, index: 5, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'curr', name: 'num', index: 4, color: 'mid' },
+ ],
+ variables: [],
+ calculations: [
+ { id: 'calc-5', expression: '9 + 5', result: '14', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-7',
+ phase: 'execution',
+ explanation: 'Process nums[5] = 9. Append prefix[-1] + 9 = 14 + 9 = 23.',
+ codeLine: 4,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'dimmed' },
+ { value: 4, index: 2, state: 'dimmed' },
+ { value: 1, index: 3, state: 'dimmed' },
+ { value: 5, index: 4, state: 'dimmed' },
+ { value: 9, index: 5, state: 'comparing' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 8, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 14, index: 5, state: 'normal' },
+ { value: 23, index: 6, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'curr', name: 'num', index: 5, color: 'mid' },
+ ],
+ variables: [],
+ calculations: [
+ { id: 'calc-6', expression: '14 + 9', result: '23', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-8',
+ phase: 'execution',
+ explanation: 'Prefix array complete! Now we can answer range queries in O(1).',
+ codeLine: 5,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 5, index: 4, state: 'normal' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'success' },
+ { value: 3, index: 1, state: 'success' },
+ { value: 4, index: 2, state: 'success' },
+ { value: 8, index: 3, state: 'success' },
+ { value: 9, index: 4, state: 'success' },
+ { value: 14, index: 5, state: 'success' },
+ { value: 23, index: 6, state: 'success' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [],
+ calculations: [],
+ },
+ },
+ // Range query execution
+ {
+ id: 'exec-9',
+ phase: 'execution',
+ explanation: 'Query: sum from index 1 to 4. We need elements [1, 4, 1, 5].',
+ codeLine: 8,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 4, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 5, index: 4, state: 'highlighted' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'normal' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 8, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 14, index: 5, state: 'normal' },
+ { value: 23, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'i', name: 'i', index: 1, color: 'left' },
+ { id: 'j', name: 'j', index: 4, color: 'right' },
+ ],
+ variables: [
+ { id: 'i', name: 'i', value: 1 },
+ { id: 'j', name: 'j', value: 4 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-10',
+ phase: 'execution',
+ explanation: 'Use formula: prefix[j+1] - prefix[i] = prefix[5] - prefix[1].',
+ codeLine: 8,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 4, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 5, index: 4, state: 'highlighted' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'comparing' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 8, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 14, index: 5, state: 'comparing' },
+ { value: 23, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'prefix[i]', name: 'prefix[i]', index: 1, color: 'left' },
+ { id: 'prefix[j+1]', name: 'prefix[j+1]', index: 5, color: 'right' },
+ ],
+ variables: [
+ { id: 'i', name: 'i', value: 1 },
+ { id: 'j', name: 'j', value: 4 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-11',
+ phase: 'execution',
+ explanation: 'Calculate: prefix[5] - prefix[1] = 14 - 3 = 11.',
+ codeLine: 8,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'success' },
+ { value: 4, index: 2, state: 'success' },
+ { value: 1, index: 3, state: 'success' },
+ { value: 5, index: 4, state: 'success' },
+ { value: 9, index: 5, state: 'normal' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'normal' },
+ { value: 3, index: 1, state: 'comparing' },
+ { value: 4, index: 2, state: 'normal' },
+ { value: 8, index: 3, state: 'normal' },
+ { value: 9, index: 4, state: 'normal' },
+ { value: 14, index: 5, state: 'comparing' },
+ { value: 23, index: 6, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [
+ { id: 'i', name: 'i', value: 1 },
+ { id: 'j', name: 'j', value: 4 },
+ { id: 'result', name: 'result', value: 11, derivation: '14 - 3' },
+ ],
+ calculations: [
+ { id: 'calc-7', expression: '14 - 3', result: '11', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-12',
+ phase: 'execution',
+ explanation: 'Verify: 1 + 4 + 1 + 5 = 11. Correct! O(n) preprocessing enables O(1) queries.',
+ codeLine: 8,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ label: 'Original Array',
+ elements: [
+ { value: 3, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'success' },
+ { value: 4, index: 2, state: 'success' },
+ { value: 1, index: 3, state: 'success' },
+ { value: 5, index: 4, state: 'success' },
+ { value: 9, index: 5, state: 'dimmed' },
+ ],
+ },
+ {
+ id: 'prefix',
+ label: 'Prefix Sum Array',
+ elements: [
+ { value: 0, index: 0, state: 'dimmed' },
+ { value: 3, index: 1, state: 'success' },
+ { value: 4, index: 2, state: 'dimmed' },
+ { value: 8, index: 3, state: 'dimmed' },
+ { value: 9, index: 4, state: 'dimmed' },
+ { value: 14, index: 5, state: 'success' },
+ { value: 23, index: 6, state: 'dimmed' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [
+ { id: 'result', name: 'result', value: 11 },
+ ],
+ calculations: [
+ { id: 'calc-8', expression: '1 + 4 + 1 + 5', result: '11', position: 'above' },
+ ],
+ },
+ },
+ ],
+};
diff --git a/frontend/src/content/algorithms/sliding-window.ts b/frontend/src/content/algorithms/sliding-window.ts
new file mode 100644
index 0000000..6504fb4
--- /dev/null
+++ b/frontend/src/content/algorithms/sliding-window.ts
@@ -0,0 +1,732 @@
+import type { AlgorithmDefinition } from '@/lib/visualizations/types';
+
+export const slidingWindowAlgorithm: AlgorithmDefinition = {
+ id: 'max-sum-subarray',
+ title: 'Maximum Sum Subarray of Size K',
+ slug: 'max-sum-subarray',
+ pattern: {
+ name: 'Sliding Window',
+ description:
+ 'Maintain a window of elements that slides through the array, updating state incrementally.',
+ },
+ problemStatement:
+ 'Given an array of integers and a window size k, find the maximum sum of any contiguous subarray of size k.',
+ intuition:
+ 'Instead of recalculating the sum for each window from scratch (O(n*k)), we can slide the window by subtracting the element leaving and adding the element entering (O(n)).',
+ code: {
+ language: 'python',
+ code: `def max_sum_subarray(nums: list[int], k: int) -> int:
+ window_sum = sum(nums[:k])
+ max_sum = window_sum
+
+ for i in range(k, len(nums)):
+ window_sum += nums[i] - nums[i - k]
+ max_sum = max(max_sum, window_sum)
+
+ return max_sum`,
+ },
+ initialExample: {
+ input: { nums: [2, 1, 5, 1, 3, 2], k: 3 },
+ expected: 9,
+ },
+ steps: [
+ // Phase 1: Problem (2 steps)
+ {
+ id: 'problem-1',
+ phase: 'problem',
+ explanation:
+ 'We have an array [2, 1, 5, 1, 3, 2] and need to find the maximum sum of any 3 consecutive elements.',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'k', name: 'k', value: 3 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'problem-2',
+ phase: 'problem',
+ explanation:
+ 'A brute force approach would sum each window separately, giving O(n*k) time. Can we avoid redundant calculations?',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'highlighted' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 5, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'k', name: 'k', value: 3 }],
+ calculations: [],
+ },
+ },
+
+ // Phase 2: Intuition (3 steps)
+ {
+ id: 'intuition-1',
+ phase: 'intuition',
+ explanation:
+ 'Key insight: When sliding the window one position right, we only need to subtract the leaving element and add the entering element.',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'highlighted' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 5, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 0, color: 'left' },
+ { id: 'right', name: 'right', index: 2, color: 'right' },
+ ],
+ variables: [{ id: 'k', name: 'k', value: 3 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'intuition-2',
+ phase: 'intuition',
+ explanation:
+ 'Window slides: element at left exits (subtract), element after right enters (add). This gives O(1) per slide!',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 5, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 1, color: 'left' },
+ { id: 'right', name: 'right', index: 3, color: 'right' },
+ ],
+ variables: [{ id: 'k', name: 'k', value: 3 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'intuition-3',
+ phase: 'intuition',
+ explanation:
+ 'Track the maximum sum seen so far as the window slides through the entire array.',
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'max_sum', name: 'max_sum', value: '?' },
+ ],
+ calculations: [],
+ },
+ },
+
+ // Phase 3: Code walkthrough (4 steps)
+ {
+ id: 'code-1',
+ phase: 'code',
+ explanation:
+ 'First, calculate the sum of the initial window (first k elements).',
+ codeLine: 2,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'k', name: 'k', value: 3 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'code-2',
+ phase: 'code',
+ explanation:
+ 'Initialize max_sum with the initial window sum. This is our best answer so far.',
+ codeLine: 3,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'k', name: 'k', value: 3 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'code-3',
+ phase: 'code',
+ explanation:
+ 'Slide the window: add the new element nums[i], subtract the leaving element nums[i-k].',
+ codeLine: 6,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'k', name: 'k', value: 3 }],
+ calculations: [],
+ },
+ },
+ {
+ id: 'code-4',
+ phase: 'code',
+ explanation:
+ 'Update max_sum if the current window sum is larger.',
+ codeLine: 7,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'normal' },
+ { value: 1, index: 1, state: 'normal' },
+ { value: 5, index: 2, state: 'normal' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [{ id: 'k', name: 'k', value: 3 }],
+ calculations: [],
+ },
+ },
+
+ // Phase 4: Execution (~15 steps)
+ {
+ id: 'exec-1',
+ phase: 'execution',
+ explanation:
+ 'Calculate the initial window sum: nums[0] + nums[1] + nums[2] = 2 + 1 + 5 = 8.',
+ codeLine: 2,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'highlighted' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 5, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 0, color: 'left' },
+ { id: 'right', name: 'right', index: 2, color: 'right' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 8, derivation: '2 + 1 + 5' },
+ ],
+ calculations: [
+ { id: 'calc-1', expression: '2 + 1 + 5', result: '8', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-2',
+ phase: 'execution',
+ explanation: 'Initialize max_sum = window_sum = 8.',
+ codeLine: 3,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'highlighted' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 5, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 0, color: 'left' },
+ { id: 'right', name: 'right', index: 2, color: 'right' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 8 },
+ { id: 'max_sum', name: 'max_sum', value: 8 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-3',
+ phase: 'execution',
+ explanation: 'Start sliding: i = 3 (k). Loop condition: i < len(nums) = 6? Yes.',
+ codeLine: 5,
+ decision: {
+ question: 'Is i < len(nums)?',
+ answer: '3 < 6 = true',
+ action: 'Enter the for loop with i = 3',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'highlighted' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 5, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'comparing' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 0, color: 'left' },
+ { id: 'right', name: 'right', index: 2, color: 'right' },
+ { id: 'i', name: 'i', index: 3, color: 'mid' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 8 },
+ { id: 'max_sum', name: 'max_sum', value: 8 },
+ { id: 'i', name: 'i', value: 3 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-4',
+ phase: 'execution',
+ explanation: 'Slide window: add nums[3]=1, subtract nums[0]=2. New sum: 8 + 1 - 2 = 7.',
+ codeLine: 6,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 5, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 1, color: 'left' },
+ { id: 'right', name: 'right', index: 3, color: 'right' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 7, previousValue: 8, derivation: '8 + 1 - 2' },
+ { id: 'max_sum', name: 'max_sum', value: 8 },
+ { id: 'i', name: 'i', value: 3 },
+ ],
+ calculations: [
+ { id: 'calc-2', expression: '8 + 1 - 2', result: '7', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-5',
+ phase: 'execution',
+ explanation: 'Compare: window_sum (7) vs max_sum (8). 7 < 8, so max_sum stays 8.',
+ codeLine: 7,
+ decision: {
+ question: 'Is window_sum > max_sum?',
+ answer: '7 > 8 = false',
+ action: 'Keep max_sum = 8',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 5, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 1, color: 'left' },
+ { id: 'right', name: 'right', index: 3, color: 'right' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 7 },
+ { id: 'max_sum', name: 'max_sum', value: 8 },
+ { id: 'i', name: 'i', value: 3 },
+ ],
+ calculations: [
+ { id: 'calc-2', expression: '7 > 8', result: 'false', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-6',
+ phase: 'execution',
+ explanation: 'Next iteration: i = 4. Loop condition: 4 < 6? Yes.',
+ codeLine: 5,
+ decision: {
+ question: 'Is i < len(nums)?',
+ answer: '4 < 6 = true',
+ action: 'Continue for loop with i = 4',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'highlighted' },
+ { value: 5, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 3, index: 4, state: 'comparing' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 1, color: 'left' },
+ { id: 'right', name: 'right', index: 3, color: 'right' },
+ { id: 'i', name: 'i', index: 4, color: 'mid' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 7 },
+ { id: 'max_sum', name: 'max_sum', value: 8 },
+ { id: 'i', name: 'i', value: 4, previousValue: 3 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-7',
+ phase: 'execution',
+ explanation: 'Slide window: add nums[4]=3, subtract nums[1]=1. New sum: 7 + 3 - 1 = 9.',
+ codeLine: 6,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 3, index: 4, state: 'highlighted' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 2, color: 'left' },
+ { id: 'right', name: 'right', index: 4, color: 'right' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 9, previousValue: 7, derivation: '7 + 3 - 1' },
+ { id: 'max_sum', name: 'max_sum', value: 8 },
+ { id: 'i', name: 'i', value: 4 },
+ ],
+ calculations: [
+ { id: 'calc-3', expression: '7 + 3 - 1', result: '9', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-8',
+ phase: 'execution',
+ explanation: 'Compare: window_sum (9) > max_sum (8)! Update max_sum to 9.',
+ codeLine: 7,
+ decision: {
+ question: 'Is window_sum > max_sum?',
+ answer: '9 > 8 = true',
+ action: 'Update max_sum = 9',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'success' },
+ { value: 1, index: 3, state: 'success' },
+ { value: 3, index: 4, state: 'success' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 2, color: 'left' },
+ { id: 'right', name: 'right', index: 4, color: 'right' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 9 },
+ { id: 'max_sum', name: 'max_sum', value: 9, previousValue: 8 },
+ { id: 'i', name: 'i', value: 4 },
+ ],
+ calculations: [
+ { id: 'calc-3', expression: '9 > 8', result: 'true', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-9',
+ phase: 'execution',
+ explanation: 'Next iteration: i = 5. Loop condition: 5 < 6? Yes.',
+ codeLine: 5,
+ decision: {
+ question: 'Is i < len(nums)?',
+ answer: '5 < 6 = true',
+ action: 'Continue for loop with i = 5',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'highlighted' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 3, index: 4, state: 'highlighted' },
+ { value: 2, index: 5, state: 'comparing' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 2, color: 'left' },
+ { id: 'right', name: 'right', index: 4, color: 'right' },
+ { id: 'i', name: 'i', index: 5, color: 'mid' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 9 },
+ { id: 'max_sum', name: 'max_sum', value: 9 },
+ { id: 'i', name: 'i', value: 5, previousValue: 4 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-10',
+ phase: 'execution',
+ explanation: 'Slide window: add nums[5]=2, subtract nums[2]=5. New sum: 9 + 2 - 5 = 6.',
+ codeLine: 6,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 3, index: 4, state: 'highlighted' },
+ { value: 2, index: 5, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 3, color: 'left' },
+ { id: 'right', name: 'right', index: 5, color: 'right' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 6, previousValue: 9, derivation: '9 + 2 - 5' },
+ { id: 'max_sum', name: 'max_sum', value: 9 },
+ { id: 'i', name: 'i', value: 5 },
+ ],
+ calculations: [
+ { id: 'calc-4', expression: '9 + 2 - 5', result: '6', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-11',
+ phase: 'execution',
+ explanation: 'Compare: window_sum (6) vs max_sum (9). 6 < 9, so max_sum stays 9.',
+ codeLine: 7,
+ decision: {
+ question: 'Is window_sum > max_sum?',
+ answer: '6 > 9 = false',
+ action: 'Keep max_sum = 9',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 1, index: 3, state: 'highlighted' },
+ { value: 3, index: 4, state: 'highlighted' },
+ { value: 2, index: 5, state: 'highlighted' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 3, color: 'left' },
+ { id: 'right', name: 'right', index: 5, color: 'right' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 6 },
+ { id: 'max_sum', name: 'max_sum', value: 9 },
+ { id: 'i', name: 'i', value: 5 },
+ ],
+ calculations: [
+ { id: 'calc-4', expression: '6 > 9', result: 'false', position: 'above' },
+ ],
+ },
+ },
+ {
+ id: 'exec-12',
+ phase: 'execution',
+ explanation: 'Next iteration: i = 6. Loop condition: 6 < 6? No, exit loop.',
+ codeLine: 5,
+ decision: {
+ question: 'Is i < len(nums)?',
+ answer: '6 < 6 = false',
+ action: 'Exit the for loop',
+ },
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'dimmed' },
+ { value: 1, index: 3, state: 'normal' },
+ { value: 3, index: 4, state: 'normal' },
+ { value: 2, index: 5, state: 'normal' },
+ ],
+ },
+ ],
+ pointers: [],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'window_sum', name: 'window_sum', value: 6 },
+ { id: 'max_sum', name: 'max_sum', value: 9 },
+ { id: 'i', name: 'i', value: 6, previousValue: 5 },
+ ],
+ calculations: [],
+ },
+ },
+ {
+ id: 'exec-13',
+ phase: 'execution',
+ explanation:
+ 'Return max_sum = 9. The maximum sum window is [5, 1, 3] at indices 2-4. Achieved in O(n) time!',
+ codeLine: 9,
+ dataState: {
+ arrays: [
+ {
+ id: 'nums',
+ elements: [
+ { value: 2, index: 0, state: 'dimmed' },
+ { value: 1, index: 1, state: 'dimmed' },
+ { value: 5, index: 2, state: 'success' },
+ { value: 1, index: 3, state: 'success' },
+ { value: 3, index: 4, state: 'success' },
+ { value: 2, index: 5, state: 'dimmed' },
+ ],
+ },
+ ],
+ pointers: [
+ { id: 'left', name: 'left', index: 2, color: 'left' },
+ { id: 'right', name: 'right', index: 4, color: 'right' },
+ ],
+ variables: [
+ { id: 'k', name: 'k', value: 3 },
+ { id: 'result', name: 'result', value: 9 },
+ ],
+ calculations: [],
+ },
+ },
+ ],
+};
diff --git a/frontend/src/lib/visualizations/types.ts b/frontend/src/lib/visualizations/types.ts
index 2f36b08..a8eafec 100644
--- a/frontend/src/lib/visualizations/types.ts
+++ b/frontend/src/lib/visualizations/types.ts
@@ -9,17 +9,17 @@
/** Phases of algorithm explanation */
export type VisualizationPhase =
- | "problem"
- | "intuition"
- | "pattern"
- | "code"
- | "execution";
+ | 'problem'
+ | 'intuition'
+ | 'pattern'
+ | 'code'
+ | 'execution';
/** State of an individual array element */
export interface ArrayElementState {
value: number;
index: number;
- state: "normal" | "highlighted" | "dimmed" | "success" | "comparing";
+ state: 'normal' | 'highlighted' | 'dimmed' | 'success' | 'comparing';
}
/** Complete array state */
@@ -34,7 +34,7 @@ export interface PointerState {
id: string;
name: string;
index: number;
- color: "left" | "right" | "mid" | "default";
+ color: 'left' | 'right' | 'mid' | 'default';
showValue?: boolean;
}
@@ -59,13 +59,13 @@ export interface CalculationState {
id: string;
expression: string;
result: string;
- position: "above" | "below" | "inline";
+ position: 'above' | 'below' | 'inline';
anchorElementId?: string;
}
/** Animation descriptor for transitions */
export interface Animation {
- type: "move" | "highlight" | "fade" | "appear" | "disappear" | "calculate";
+ type: 'move' | 'highlight' | 'fade' | 'appear' | 'disappear' | 'calculate';
targetId: string;
duration?: number;
delay?: number;
@@ -93,7 +93,7 @@ export interface VisualizationStep {
/** Code definition for the algorithm */
export interface AlgorithmCode {
- language: "typescript" | "python" | "javascript";
+ language: 'typescript' | 'python' | 'javascript';
code: string;
}
diff --git a/frontend/src/lib/visualizations/use-visualization.ts b/frontend/src/lib/visualizations/use-visualization.ts
index 4965316..077d047 100644
--- a/frontend/src/lib/visualizations/use-visualization.ts
+++ b/frontend/src/lib/visualizations/use-visualization.ts
@@ -1,13 +1,13 @@
-"use client";
+'use client';
-import { useCallback, useEffect, useRef, useState } from "react";
+import { useCallback, useEffect, useRef, useState } from 'react';
import type {
AlgorithmDefinition,
PlaybackSpeed,
PlaybackState,
UseVisualizationReturn,
VisualizationControls,
-} from "./types";
+} from './types';
const SPEED_MULTIPLIERS: Record
= {
0.5: 2,
@@ -142,31 +142,31 @@ export function useVisualization(
}
switch (e.key) {
- case " ":
+ case ' ':
e.preventDefault();
togglePlay();
break;
- case "ArrowLeft":
+ case 'ArrowLeft':
e.preventDefault();
stepBackward();
break;
- case "ArrowRight":
+ case 'ArrowRight':
e.preventDefault();
stepForward();
break;
- case "Home":
+ case 'Home':
e.preventDefault();
goToFirst();
break;
- case "End":
+ case 'End':
e.preventDefault();
goToLast();
break;
}
};
- window.addEventListener("keydown", handleKeyDown);
- return () => window.removeEventListener("keydown", handleKeyDown);
+ window.addEventListener('keydown', handleKeyDown);
+ return () => window.removeEventListener('keydown', handleKeyDown);
}, [togglePlay, stepBackward, stepForward, goToFirst, goToLast]);
const currentStep = algorithm.steps[playback.currentStepIndex];