@@ -530,8 +530,7 @@ const sections = [
-
diff --git a/app/visualizer/stack/polish/postfix/animation.jsx b/app/visualizer/stack/polish/postfix/animation.jsx
index 6c0fcce..5878a81 100755
--- a/app/visualizer/stack/polish/postfix/animation.jsx
+++ b/app/visualizer/stack/polish/postfix/animation.jsx
@@ -1,4 +1,3 @@
-/* InfixToPostfixVisualizer.jsx – animated version */
"use client";
import React, { useState, useEffect, useRef } from "react";
import { motion, AnimatePresence } from "framer-motion";
diff --git a/app/visualizer/stack/polish/prefix/animation.jsx b/app/visualizer/stack/polish/prefix/animation.jsx
index 5c9c153..a97725b 100755
--- a/app/visualizer/stack/polish/prefix/animation.jsx
+++ b/app/visualizer/stack/polish/prefix/animation.jsx
@@ -1,14 +1,44 @@
-'use client';
-import React, { useState, useEffect } from 'react';
-import Footer from '@/app/components/footer';
-import ExploreOther from '@/app/components/ui/exploreOther';
-import CodeBlock from '@/app/visualizer/stack/polish/prefix/codeBlock';
-import Quiz from '@/app/visualizer/stack/polish/postfix/quiz';
-import BackToTop from '@/app/components/ui/backtotop';
-
+"use client";
+import React, { useState, useEffect, useRef } from "react";
+import { motion, AnimatePresence } from "framer-motion";
+import gsap from "gsap";
+
+/* ---------- tiny animated bits ---------- */
+const AnimatedStackItem = ({ char, isTop }) => (
+
+ {char}
+ {isTop && (Top)
}
+
+);
+
+const AnimatedOutputToken = ({ char }) => (
+
+ {char}
+
+);
+
+/* ---------- main component ---------- */
const InfixToPrefixVisualizer = () => {
- const [infix, setInfix] = useState('(A+B)*C');
- const [prefix, setPrefix] = useState('');
+ /* ======= state ======= */
+ const [infix, setInfix] = useState("(A+B)*C");
+ const [prefix, setPrefix] = useState("");
const [stack, setStack] = useState([]);
const [output, setOutput] = useState([]);
const [currentStep, setCurrentStep] = useState(0);
@@ -16,118 +46,101 @@ const InfixToPrefixVisualizer = () => {
const [isProcessing, setIsProcessing] = useState(false);
const [isAnimating, setIsAnimating] = useState(false);
const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState('Enter an infix expression and click Convert');
+ const [message, setMessage] = useState("Enter an infix expression and click Convert");
const [isPlaying, setIsPlaying] = useState(false);
- const [speed, setSpeed] = useState(1000); // Default speed: 1 second per step
+ const [speed, setSpeed] = useState(1000);
- const precedence = {
- '^': 4,
- '*': 3,
- '/': 3,
- '+': 2,
- '-': 2,
- };
+ const precedence = { "^": 4, "*": 3, "/": 3, "+": 2, "-": 2 };
+ /* ---------- helpers ---------- */
const reset = () => {
setStack([]);
setOutput([]);
- setPrefix('');
+ setPrefix("");
setCurrentStep(0);
setSteps([]);
- setMessage('Enter an infix expression and click Convert');
+ setMessage("Enter an infix expression and click Convert");
setOperation(null);
setIsPlaying(false);
};
const convertInfixToPrefix = () => {
if (!infix.trim()) {
- setMessage('Please enter an infix expression');
+ setMessage("Please enter an infix expression");
return;
}
-
setIsProcessing(true);
reset();
-
+
const conversionSteps = [];
let tempStack = [];
let tempOutput = [];
- // Step 1: Reverse the infix expression
- const reversedInfix = infix.split('').reverse().join('');
+ /* 1. reverse */
+ const reversed = infix.split("").reverse().join("");
conversionSteps.push({
stack: [],
output: [],
- char: '',
- action: 'Reverse infix',
- description: `Reversed infix expression: ${reversedInfix}`,
- infix: reversedInfix
+ char: "",
+ action: "Reverse infix",
+ description: `Reversed: ${reversed}`,
});
- // Step 2: Swap parentheses
- const modifiedInfix = reversedInfix.replace(/[()]/g, match => match === '(' ? ')' : '(');
+ /* 2. swap parentheses */
+ const swapped = reversed.replace(/[()]/g, (c) => (c === "(" ? ")" : "("));
conversionSteps.push({
stack: [],
output: [],
- char: '',
- action: 'Swap parentheses',
- description: `Swapped parentheses: ${modifiedInfix}`,
- infix: modifiedInfix
+ char: "",
+ action: "Swap parentheses",
+ description: `Swapped: ${swapped}`,
});
- // Step 3: Convert to postfix
- for (let i = 0; i < modifiedInfix.length; i++) {
- const char = modifiedInfix[i];
-
- // If operand
- if (/[a-zA-Z0-9]/.test(char)) {
- tempOutput.push(char);
+ /* 3. postfix on swapped */
+ for (const ch of swapped) {
+ if (/[a-zA-Z0-9]/.test(ch)) {
+ tempOutput.push(ch);
conversionSteps.push({
stack: [...tempStack],
output: [...tempOutput],
- char,
- action: 'Add operand',
- description: `Added operand "${char}" to output`
+ char: ch,
+ action: "Add operand",
+ description: `Added operand "${ch}"`,
});
- }
- // If '('
- else if (char === '(') {
- tempStack.push(char);
+ } else if (ch === "(") {
+ tempStack.push(ch);
conversionSteps.push({
stack: [...tempStack],
output: [...tempOutput],
- char,
- action: 'Push to stack',
- description: `Pushed "(" to stack`
+ char: ch,
+ action: "Push to stack",
+ description: `Pushed "("`,
});
- }
- // If ')'
- else if (char === ')') {
- while (tempStack.length && tempStack[tempStack.length - 1] !== '(') {
+ } else if (ch === ")") {
+ while (tempStack.length && tempStack[tempStack.length - 1] !== "(") {
const popped = tempStack.pop();
tempOutput.push(popped);
conversionSteps.push({
stack: [...tempStack],
output: [...tempOutput],
char: popped,
- action: 'Pop from stack',
- description: `Popped operator "${popped}" from stack`
+ action: "Pop from stack",
+ description: `Popped "${popped}"`,
});
}
- tempStack.pop(); // Remove '('
+ tempStack.pop(); // remove '('
conversionSteps.push({
stack: [...tempStack],
output: [...tempOutput],
- char: '(',
- action: 'Remove from stack',
- description: 'Removed "(" from stack'
+ char: "(",
+ action: "Remove from stack",
+ description: `Removed "("`,
});
- }
- // If operator
- else {
+ } else {
while (
- tempStack.length &&
- tempStack[tempStack.length - 1] !== '(' &&
- precedence[char] <= precedence[tempStack[tempStack.length - 1]]
+ tempStack.length &&
+ tempStack[tempStack.length - 1] !== "(" &&
+ precedence[ch] <= precedence[tempStack[tempStack.length - 1]]
) {
const popped = tempStack.pop();
tempOutput.push(popped);
@@ -135,22 +148,21 @@ const InfixToPrefixVisualizer = () => {
stack: [...tempStack],
output: [...tempOutput],
char: popped,
- action: 'Pop higher precedence',
- description: `Popped higher precedence operator "${popped}"`
+ action: "Pop higher precedence",
+ description: `Popped higher precedence "${popped}"`,
});
}
- tempStack.push(char);
+ tempStack.push(ch);
conversionSteps.push({
stack: [...tempStack],
output: [...tempOutput],
- char,
- action: 'Push operator',
- description: `Pushed operator "${char}" to stack`
+ char: ch,
+ action: "Push operator",
+ description: `Pushed "${ch}"`,
});
}
}
- // Pop remaining operators
while (tempStack.length) {
const popped = tempStack.pop();
tempOutput.push(popped);
@@ -158,317 +170,266 @@ const InfixToPrefixVisualizer = () => {
stack: [...tempStack],
output: [...tempOutput],
char: popped,
- action: 'Pop remaining',
- description: `Popped remaining operator "${popped}"`
+ action: "Pop remaining",
+ description: `Popped remaining "${popped}"`,
});
}
- // Step 4: Reverse the postfix to get prefix
- const prefixResult = tempOutput.reverse().join(' ');
+ /* 4. reverse to get prefix */
+ const prefixResult = tempOutput.reverse().join(" ");
conversionSteps.push({
stack: [],
- output: [...tempOutput.reverse()],
- char: '',
- action: 'Reverse postfix',
- description: `Reversed postfix to get prefix: ${prefixResult}`
+ output: [...tempOutput],
+ char: "",
+ action: "Reverse postfix",
+ description: `Reversed to get prefix: ${prefixResult}`,
});
setSteps(conversionSteps);
setPrefix(prefixResult);
setIsProcessing(false);
- setIsPlaying(true); // Start automatic playback
+ setIsPlaying(true);
};
+ /* ---------- playback ---------- */
const playNextStep = () => {
- if (currentStep < steps.length - 1) {
- setCurrentStep(prev => prev + 1);
- } else {
- setIsPlaying(false);
- }
+ if (currentStep < steps.length - 1) setCurrentStep((s) => s + 1);
+ else setIsPlaying(false);
};
-
const playPrevStep = () => {
- if (currentStep > 0) {
- setCurrentStep(prev => prev - 1);
- }
+ if (currentStep > 0) setCurrentStep((s) => s - 1);
};
-
- const togglePlayPause = () => {
- setIsPlaying(!isPlaying);
+ const togglePlayPause = () => setIsPlaying((p) => !p);
+ const jumpToStep = (idx) => {
+ setCurrentStep(idx);
+ if (idx === steps.length - 1) setIsPlaying(false);
};
- const jumpToStep = (stepIndex) => {
- setCurrentStep(stepIndex);
- if (stepIndex === steps.length - 1) {
- setIsPlaying(false);
- }
- };
-
- // Handle automatic playback
useEffect(() => {
- let timer;
- if (isPlaying && currentStep < steps.length - 1) {
- timer = setTimeout(() => {
- playNextStep();
- }, speed);
- } else if (currentStep >= steps.length - 1) {
- setIsPlaying(false);
- }
- return () => clearTimeout(timer);
+ let t;
+ if (isPlaying && currentStep < steps.length - 1) t = setTimeout(playNextStep, speed);
+ else if (currentStep >= steps.length - 1) setIsPlaying(false);
+ return () => clearTimeout(t);
}, [isPlaying, currentStep, steps.length, speed]);
- // Update visualization based on current step
+ /* ---------- GSAP flash on message change ---------- */
+ const statusRef = useRef();
useEffect(() => {
- if (steps.length > 0 && currentStep < steps.length) {
- setIsAnimating(true);
- const step = steps[currentStep];
- setStack(step.stack || []);
- setOutput(step.output || []);
- setOperation(step.action);
- setMessage(step.description);
-
- const timer = setTimeout(() => {
- setIsAnimating(false);
- }, 500);
+ if (statusRef.current)
+ gsap.fromTo(statusRef.current, { scale: 0.95, opacity: 0.7 }, { scale: 1, opacity: 1, duration: 0.3 });
+ }, [message]);
- return () => clearTimeout(timer);
+ useEffect(() => {
+ if (steps.length && currentStep < steps.length) {
+ setIsAnimating(true);
+ const s = steps[currentStep];
+ setStack(s.stack || []);
+ setOutput(s.output || []);
+ setOperation(s.action);
+ setMessage(s.description);
+ const t = setTimeout(() => setIsAnimating(false), 500);
+ return () => clearTimeout(t);
}
}, [currentStep, steps]);
+ /* ---------- render ---------- */
return (
-
-
-
- {/* Input and Controls */}
-
-
- setInfix(e.target.value)}
- className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
- placeholder="Enter infix expression (e.g., (A+B)*C)"
- />
-
-
-
-
- {/* Playback Controls */}
- {steps.length > 0 && (
-
-
-
-
-
-
-
-
-
Speed:
-
-
-
- Step {currentStep + 1} of {steps.length}
-
-
-
- {/* Progress bar */}
-
-
- )}
+
+
+ Visualize the conversion from infix to prefix notation
+
+
+ {/* Input & Controls */}
+
+
+ setInfix(e.target.value)}
+ placeholder="Enter infix expression (e.g., (A+B)*C)"
+ className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-neutral-900 dark:text-white"
+ />
+
+
- {/* Operation Status */}
-
-
Conversion Status
-
- {operation && (
-
- {operation}
+ {steps.length > 0 && (
+
+
+
+
+
- )}
-
- {message && (
-
- {message}
+
+
Speed:
+
+
+ Step {currentStep + 1} of {steps.length}
+
- )}
-
- {prefix && currentStep === steps.length - 1 && (
-
-
Prefix Result:
-
{prefix}
+
+
- )}
-
+
+ )}
+
- {/* Visualizations */}
-
- {/* Stack Visualization */}
-
-
Stack
-
-
- {stack.length > 0 ? '↑ Top' : ''}
-
-
+ {/* Status panel */}
+
+
Conversion Status
+ {operation && (
+
+ {operation}
+
+ )}
+ {message && (
+
+ {message}
+
+ )}
+ {prefix && currentStep === steps.length - 1 && (
+
+ Prefix Result:
+ {prefix}
+
+ )}
+
+
+ {/* Visualisations */}
+
+ {/* Stack */}
+
+
Stack
+
+
{stack.length > 0 ? "↑ Top" : ""}
+
+
{stack.length === 0 ? (
-
- Stack is empty
-
+ Stack is empty
) : (
- {stack.map((item, index) => (
-
- {item}
- {index === stack.length - 1 && (
-
- (Top)
-
- )}
-
+ {stack.map((item, i) => (
+
))}
)}
-
-
- {stack.length > 0 ? '↓ Bottom' : ''}
-
+
+
{stack.length > 0 ? "↓ Bottom" : ""}
+
- {/* Output Visualization */}
-
-
Output
-
-
+ {/* Output */}
+
+
Output
+
+
+
{output.length === 0 ? (
-
- Output will appear here
-
+ Output will appear here
) : (
- output.map((item, index) => (
-
- {item}
-
- ))
+ output.map((c, i) => )
)}
-
+
-
- {/* Step-by-step Table */}
- {steps.length > 0 && (
-
-
Conversion Steps
-
-
-
-
- | Step |
- Action |
- Character |
- Description |
-
-
-
- {steps.map((step, index) => (
- jumpToStep(index)}
- >
- | {index + 1} |
- {step.action} |
- {step.char || '-'} |
- {step.description} |
-
- ))}
-
-
-
-
- )}
- { /* quiz block here */}
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
+ {/* Step table */}
+ {steps.length > 0 && (
+
+ Conversion Steps
+
+
+
+
+ | Step |
+ Action |
+ Character |
+ Description |
+
+
+
+ {steps.map((step, idx) => (
+ jumpToStep(idx)}
+ className={`cursor-pointer ${
+ currentStep === idx ? "bg-blue-50 dark:bg-neutral-950" : "hover:bg-gray-50 dark:hover:bg-neutral-950"
+ }`}
+ whileHover={{ scale: 1.01 }}
+ whileTap={{ scale: 0.98 }}
+ >
+ {idx + 1} |
+ {step.action} |
+ {step.char || "-"} |
+ {step.description} |
+
+ ))}
+
+
+
+
+ )}
+
+
);
};
diff --git a/app/visualizer/stack/polish/prefix/codeBlock.jsx b/app/visualizer/stack/polish/prefix/codeBlock.jsx
index 6d099d9..0c03e46 100755
--- a/app/visualizer/stack/polish/prefix/codeBlock.jsx
+++ b/app/visualizer/stack/polish/prefix/codeBlock.jsx
@@ -213,10 +213,10 @@ int main() {
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
- className="bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden border border-gray-200 dark:border-gray-700 transition-colors duration-300"
+ className="bg-white dark:bg-neutral-950 rounded-xl shadow-lg overflow-hidden border border-gray-200 dark:border-gray-700 transition-colors duration-300"
>
{/* Header */}
-
+
diff --git a/app/visualizer/stack/polish/prefix/content.jsx b/app/visualizer/stack/polish/prefix/content.jsx
index 8fc1ace..2635aa1 100755
--- a/app/visualizer/stack/polish/prefix/content.jsx
+++ b/app/visualizer/stack/polish/prefix/content.jsx
@@ -1,4 +1,28 @@
-const InfixToPrefixContent = () => {
+"use client";
+import { useEffect, useState } from "react";
+
+const content = () => {
+ const [theme, setTheme] = useState("light");
+ const [mounted, setMounted] = useState(false);
+
+ useEffect(() => {
+ const updateTheme = () => {
+ const savedTheme = localStorage.getItem("theme") || "light";
+ setTheme(savedTheme);
+ };
+
+ updateTheme();
+ setMounted(true);
+
+ window.addEventListener("storage", updateTheme);
+ window.addEventListener("themeChange", updateTheme);
+
+ return () => {
+ window.removeEventListener("storage", updateTheme);
+ window.removeEventListener("themeChange", updateTheme);
+ };
+ }, []);
+
const paragraph = [
`Prefix notation (also called Polish Notation) is a way of writing expressions where the operator comes before the operands.`,
`For example, the infix expression 3 + 4 becomes + 3 4 in prefix. It removes the need for parentheses by using operator order directly.`,
@@ -20,8 +44,37 @@ const InfixToPrefixContent = () => {
];
return (
-
-
+
+
+
+ {mounted && (
+
+ )}
+
+
+
+
{/* What is Prefix Notation? */}
@@ -78,62 +131,62 @@ const InfixToPrefixContent = () => {
Operator Precedence Table
-
+
- |
+ |
Operator
|
-
+ |
Meaning
|
-
+ |
Precedence
|
- |
+ |
( )
|
-
+ |
Parentheses
|
-
+ |
Highest
|
- |
+ |
^ %
|
-
+ |
Exponentiation / Modulus
|
-
+ |
2
|
- |
+ |
* /
|
-
+ |
Multiplication / Division
|
-
+ |
3
|
- |
+ |
+ -
|
-
+ |
Addition / Subtraction
|
-
+ |
4 (Lowest)
|
@@ -145,8 +198,37 @@ const InfixToPrefixContent = () => {
+
+ {/* Mobile iframe at bottom */}
+
+ {mounted && (
+
+ )}
+
+
);
};
-export default InfixToPrefixContent;
\ No newline at end of file
+export default content;
\ No newline at end of file
diff --git a/app/visualizer/stack/polish/prefix/page.jsx b/app/visualizer/stack/polish/prefix/page.jsx
index 67d85d2..9b1d4d6 100755
--- a/app/visualizer/stack/polish/prefix/page.jsx
+++ b/app/visualizer/stack/polish/prefix/page.jsx
@@ -2,7 +2,14 @@ import Animation from "@/app/visualizer/stack/polish/prefix/animation";
import Navbar from "@/app/components/navbarinner";
import Breadcrumbs from "@/app/components/ui/Breadcrumbs";
import ArticleActions from "@/app/components/ui/ArticleActions";
-import Content from '@/app/visualizer/stack/polish/prefix/content';
+import Content from "@/app/visualizer/stack/polish/prefix/content";
+import Quiz from "@/app/visualizer/stack/polish/postfix/quiz";
+import Code from "@/app/visualizer/stack/polish/prefix/codeBlock";
+import ModuleCard from "@/app/components/ui/ModuleCard";
+import { MODULE_MAPS } from "@/lib/modulesMap";
+import Footer from "@/app/components/footer";
+import ExploreOther from "@/app/components/ui/exploreOther";
+import BackToTopButton from "@/app/components/ui/backtotop";
export const metadata = {
title:
@@ -31,7 +38,7 @@ export const metadata = {
url: "/og/stack/prefix.png",
width: 1200,
height: 630,
- alt: "Stack infix to postfix",
+ alt: "Stack infix to prefix",
},
],
},
@@ -74,7 +81,39 @@ export default function Page() {
+
+
+
+ Test Your Knowledge before moving forward!
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/lib/activity.js b/lib/activity.js
index c25c2eb..879442f 100755
--- a/lib/activity.js
+++ b/lib/activity.js
@@ -16,4 +16,4 @@ const trackActivity = async (userId, type = "site_visit") => {
}
};
-export default { trackActivity };
\ No newline at end of file
+export { trackActivity };
\ No newline at end of file
diff --git a/lib/modulesMap.js b/lib/modulesMap.js
index 5cfc5eb..b591d82 100755
--- a/lib/modulesMap.js
+++ b/lib/modulesMap.js
@@ -11,4 +11,5 @@ export const MODULE_MAPS = {
isEmpty : "05ecbddd-e3d4-4fa1-aa45-71accac97d79",
isFull : "54301ec9-0586-48f0-a6db-18a41adeb856",
postfix : "ca3daf8d-23f8-4ade-adfd-4bd0a88d3da2",
+ prefix : "a2971df4-5e48-4320-bc91-3de3242cac48",
}
\ No newline at end of file
diff --git a/public/og/stack/prefix.png b/public/og/stack/prefix.png
new file mode 100755
index 0000000..ac491fc
Binary files /dev/null and b/public/og/stack/prefix.png differ