diff --git a/app/visualizer/stack/isfull/content.jsx b/app/visualizer/stack/isfull/content.jsx index b32ebaa..376ea98 100644 --- a/app/visualizer/stack/isfull/content.jsx +++ b/app/visualizer/stack/isfull/content.jsx @@ -239,6 +239,35 @@ const content = () => { + + {/* Mobile iframe at bottom */} +
+ {mounted && ( + + )} +
+ + Daily DSA Challenge by{" "} + + Hello World + + +
+
); }; diff --git a/app/visualizer/stack/polish/postfix/animation.jsx b/app/visualizer/stack/polish/postfix/animation.jsx index 1fc9b65..6c0fcce 100644 --- a/app/visualizer/stack/polish/postfix/animation.jsx +++ b/app/visualizer/stack/polish/postfix/animation.jsx @@ -1,16 +1,42 @@ -'use client'; -import React, { useState, useEffect } from 'react'; -import Footer from '@/app/components/footer'; -import ExploreOther from '@/app/components/ui/exploreOther'; -import Content from'@/app/visualizer/stack/polish/postfix/content'; -import CodeBlock from'@/app/visualizer/stack/polish/postfix/codeBlock'; -import GoBackButton from "@/app/components/ui/goback"; -import Quiz from '@/app/visualizer/stack/polish/postfix/quiz'; -import BackToTop from '@/app/components/ui/backtotop'; - +/* InfixToPostfixVisualizer.jsx – animated version */ +"use client"; +import React, { useState, useEffect, useRef } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import gsap from "gsap"; + +/* ---------- tiny reusable animated bits ---------- */ +const AnimatedStackItem = ({ char, isTop }) => ( + + {char} + {isTop &&
(Top)
} +
+); + +const AnimatedOutputToken = ({ char }) => ( + + {char} + +); + +/* ---------- main component ---------- */ const InfixToPostfixVisualizer = () => { - const [infix, setInfix] = useState('(A+B)*C'); - const [postfix, setPostfix] = useState(''); + /* ======= your existing state – nothing changed ======= */ + const [infix, setInfix] = useState("(A+B)*C"); + const [postfix, setPostfix] = useState(""); const [stack, setStack] = useState([]); const [output, setOutput] = useState([]); const [currentStep, setCurrentStep] = useState(0); @@ -18,451 +44,185 @@ const InfixToPostfixVisualizer = () => { 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 }; + /* ............ your existing logic ............ */ const reset = () => { - setStack([]); - setOutput([]); - setPostfix(''); - setCurrentStep(0); - setSteps([]); - setMessage('Enter an infix expression and click Convert'); - setOperation(null); - setIsPlaying(false); + setStack([]); setOutput([]); setPostfix(""); setCurrentStep(0); setSteps([]); + setMessage("Enter an infix expression and click Convert"); setOperation(null); setIsPlaying(false); }; const convertInfixToPostfix = () => { - if (!infix.trim()) { - setMessage('Please enter an infix expression'); - return; - } - - setIsProcessing(true); - reset(); - - const conversionSteps = []; - let tempStack = []; - let tempOutput = []; - - // Initial step - conversionSteps.push({ - stack: [], - output: [], - char: '', - action: 'Initialize', - description: 'Starting conversion process' - }); - + if (!infix.trim()) { setMessage("Please enter an infix expression"); return; } + setIsProcessing(true); reset(); + const conversionSteps = []; let tempStack = []; let tempOutput = []; + conversionSteps.push({ stack:[],output:[],char:"",action:"Initialize",description:"Starting conversion process" }); for (let i = 0; i < infix.length; i++) { const char = infix[i]; - - // If operand if (/[a-zA-Z0-9]/.test(char)) { tempOutput.push(char); - conversionSteps.push({ - stack: [...tempStack], - output: [...tempOutput], - char, - action: 'Add operand', - description: `Added operand "${char}" to output` - }); - } - // If '(' - else if (char === '(') { + conversionSteps.push({ stack:[...tempStack],output:[...tempOutput],char,action:"Add operand",description:`Added operand "${char}" to output` }); + } else if (char === "(") { tempStack.push(char); - conversionSteps.push({ - stack: [...tempStack], - output: [...tempOutput], - char, - action: 'Push to stack', - description: `Pushed "(" to stack` - }); - } - // If ')' - else if (char === ')') { - 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` - }); + conversionSteps.push({ stack:[...tempStack],output:[...tempOutput],char,action:"Push to stack",description:`Pushed "(" to stack` }); + } else if (char === ")") { + 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` }); } - tempStack.pop(); // Remove '(' - conversionSteps.push({ - stack: [...tempStack], - output: [...tempOutput], - char: '(', - action: 'Remove from stack', - description: 'Removed "(" from stack' - }); - } - // If operator - else { - while ( - tempStack.length && - tempStack[tempStack.length - 1] !== '(' && - precedence[char] <= precedence[tempStack[tempStack.length - 1]] - ) { - const popped = tempStack.pop(); - tempOutput.push(popped); - conversionSteps.push({ - stack: [...tempStack], - output: [...tempOutput], - char: popped, - action: 'Pop higher precedence', - description: `Popped higher precedence operator "${popped}"` - }); + tempStack.pop(); + conversionSteps.push({ stack:[...tempStack],output:[...tempOutput],char:"(",action:"Remove from stack",description:'Removed "(" from stack' }); + } else { + while (tempStack.length && tempStack[tempStack.length - 1] !== "(" && precedence[char] <= precedence[tempStack[tempStack.length - 1]]) { + const popped = tempStack.pop(); tempOutput.push(popped); + conversionSteps.push({ stack:[...tempStack],output:[...tempOutput],char:popped,action:"Pop higher precedence",description:`Popped higher precedence operator "${popped}"` }); } tempStack.push(char); - conversionSteps.push({ - stack: [...tempStack], - output: [...tempOutput], - char, - action: 'Push operator', - description: `Pushed operator "${char}" to stack` - }); + conversionSteps.push({ stack:[...tempStack],output:[...tempOutput],char,action:"Push operator",description:`Pushed operator "${char}" to stack` }); } } - - // Pop remaining operators - while (tempStack.length) { - const popped = tempStack.pop(); - tempOutput.push(popped); - conversionSteps.push({ - stack: [...tempStack], - output: [...tempOutput], - char: popped, - action: 'Pop remaining', - description: `Popped remaining operator "${popped}"` - }); - } - - setSteps(conversionSteps); - setPostfix(tempOutput.join(' ')); - setIsProcessing(false); - setIsPlaying(true); // Start automatic playback - }; - - const playNextStep = () => { - if (currentStep < steps.length - 1) { - setCurrentStep(prev => prev + 1); - } else { - setIsPlaying(false); - } - }; - - const playPrevStep = () => { - if (currentStep > 0) { - setCurrentStep(prev => prev - 1); + while (tempStack.length) { const popped = tempStack.pop(); tempOutput.push(popped); + conversionSteps.push({ stack:[...tempStack],output:[...tempOutput],char:popped,action:"Pop remaining",description:`Popped remaining operator "${popped}"` }); } + setSteps(conversionSteps); setPostfix(tempOutput.join(" ")); setIsProcessing(false); setIsPlaying(true); }; - const togglePlayPause = () => { - setIsPlaying(!isPlaying); - }; - - const jumpToStep = (stepIndex) => { - setCurrentStep(stepIndex); - if (stepIndex === steps.length - 1) { - setIsPlaying(false); - } - }; + const playNextStep = () => { if (currentStep < steps.length - 1) setCurrentStep(s => s + 1); else setIsPlaying(false); }; + const playPrevStep = () => { if (currentStep > 0) setCurrentStep(s => s - 1); }; + const togglePlayPause = () => setIsPlaying(p => !p); + const jumpToStep = (idx) => { setCurrentStep(idx); if (idx === 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); - }, [isPlaying, currentStep, steps.length, speed]); + useEffect(() => { 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 + /* ======= NEW: tiny GSAP flash on step 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); + if (statusRef.current) gsap.fromTo(statusRef.current, { scale: 0.95, opacity: 0.7 }, { scale: 1, opacity: 1, duration: 0.3 }); + }, [message]); - const timer = setTimeout(() => { - setIsAnimating(false); - }, 500); - - return () => clearTimeout(timer); - } - }, [currentStep, steps]); + 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]); + /* ---------- UI ---------- */ return ( -
-
- - { /* go back block here */} -
- +
+

Visualize the conversion from infix to postfix notation

+
+ {/* Input & Controls – same as before */} +
+
+ 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"/> + +
- { /* main logic here */} -

- Infix to Postfix -

-
- -

- Visualize the conversion from infix to postfix notation -

- -
- {/* 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 */} -
-
-
+ {steps.length > 0 && ( +
+
+ + +
- )} -
- - {/* Operation Status */} -
-

Conversion Status

- - {operation && ( -
- {operation} +
+ Speed: + +
Step {currentStep + 1} of {steps.length}
- )} - - {message && ( -
- {message} +
+
- )} +
+ )} +
- {postfix && currentStep === steps.length - 1 && ( -
-
Postfix Result:
-
{postfix}
-
- )} -
+ {/* Status panel with GSAP flash */} +
+

Conversion Status

+ {operation &&
{operation}
} + {message &&
{message}
} + {postfix && currentStep === steps.length - 1 && ( + +
Postfix Result:
{postfix}
+
+ )} +
- {/* Visualizations */} -
- {/* Stack Visualization */} -
-

Stack

-
-
- {stack.length > 0 ? '↑ Top' : ''} -
-
+ {/* Visualisations – now with motion */} +
+ {/* 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

-
- - - - - - - - - - - {steps.map((step, index) => ( - jumpToStep(index)} - > - - - - - - ))} - -
StepActionCharacterDescription
{index + 1}{step.action}{step.char || '-'}{step.description}
-
- )} +
- { /* quiz block here */} -

- Test Your Knowledge before moving forward! -

- - - - -
-
- -
-
+ {/* Step table – same as before, just with framer hover */} + {steps.length > 0 && ( + +

Conversion Steps

+
+ + + + + + + + + {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 }}> + + + + + + ))} + +
StepActionCharacterDescription
{idx + 1}{step.action}{step.char || "-"}{step.description}
+
+
+ )} +
+ ); }; diff --git a/app/visualizer/stack/polish/postfix/codeBlock.jsx b/app/visualizer/stack/polish/postfix/codeBlock.jsx index 057364f..b366978 100644 --- a/app/visualizer/stack/polish/postfix/codeBlock.jsx +++ b/app/visualizer/stack/polish/postfix/codeBlock.jsx @@ -206,10 +206,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/postfix/content.jsx b/app/visualizer/stack/polish/postfix/content.jsx index 73eefc6..93fb32e 100644 --- a/app/visualizer/stack/polish/postfix/content.jsx +++ b/app/visualizer/stack/polish/postfix/content.jsx @@ -1,4 +1,28 @@ -const InfixToPostfixContent = () => { +"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 = [ `Postfix notation (also called Reverse Polish Notation) is a way of writing expressions where the operator comes after the operands.`, `For example, the infix expression 3 + 4 becomes 3 4 + in postfix. It removes the need for parentheses by making operator precedence explicit through position.`, @@ -26,8 +50,37 @@ const InfixToPostfixContent = () => { ]; return ( -
-
+
+
+
+ {mounted && ( + + )} +
+
+ + Daily DSA Challenge by{" "} + + Hello World + + +
+
+
{/* What is Postfix Notation? */}

@@ -150,8 +203,37 @@ const InfixToPostfixContent = () => {

+ + {/* Mobile iframe at bottom */} +
+ {mounted && ( + + )} +
+ + Daily DSA Challenge by{" "} + + Hello World + + +
+
); }; - export default InfixToPostfixContent; \ No newline at end of file + export default content; \ No newline at end of file diff --git a/app/visualizer/stack/polish/postfix/page.jsx b/app/visualizer/stack/polish/postfix/page.jsx index 1f5dc0c..fc5b856 100644 --- a/app/visualizer/stack/polish/postfix/page.jsx +++ b/app/visualizer/stack/polish/postfix/page.jsx @@ -1,32 +1,117 @@ import Animation from "@/app/visualizer/stack/polish/postfix/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/postfix/content"; +import Quiz from "@/app/visualizer/stack/polish/postfix/quiz"; +import Code from "@/app/visualizer/stack/polish/postfix/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: 'Postfix Notation using Stack | Learn Postfix Evaluation in DSA with Code in JS, C, Python, Java', - description: 'Visualize how Postfix expressions are evaluated using a Stack through interactive animations and code examples in JavaScript, C, Python, and Java. Perfect for DSA beginners and technical interview preparation.', - keywords: [ - 'Postfix Notation', - 'Postfix Evaluation Stack', - 'Stack DSA', - 'Postfix Expression', - 'DSA Postfix', - 'Evaluate Postfix using Stack', - 'Learn Postfix Notation', - 'Postfix Evaluation in JavaScript', - 'Postfix Evaluation in C', - 'Postfix Evaluation in Python', - 'Postfix Evaluation in Java', - 'Stack Code Examples', - 'DSA Expression Evaluation', + title: + "Postfix Notation using Stack | Learn Postfix Evaluation in DSA with Code in JS, C, Python, Java", + description: + "Visualize how Postfix expressions are evaluated using a Stack through interactive animations and code examples in JavaScript, C, Python, and Java. Perfect for DSA beginners and technical interview preparation.", + keywords: [ + "Postfix Notation", + "Postfix Evaluation Stack", + "Stack DSA", + "Postfix Expression", + "DSA Postfix", + "Evaluate Postfix using Stack", + "Learn Postfix Notation", + "Postfix Evaluation in JavaScript", + "Postfix Evaluation in C", + "Postfix Evaluation in Python", + "Postfix Evaluation in Java", + "Stack Code Examples", + "DSA Expression Evaluation", + ], + robots: "index, follow", + openGraph: { + images: [ + { + url: "/og/stack/postfix.png", + width: 1200, + height: 630, + alt: "Stack infix to postfix", + }, ], - robots: "index, follow", - }; - -export default function Page (){ - return( - <> - - - - ); -}; \ No newline at end of file + }, +}; + +export default function Page() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Visualizer", href: "/visualizer" }, + { name: "Stack : Infix to postfix", href: "" }, + ]; + + return ( + <> +
+ +
+ +
+
+
+ +
+ +
+
+

+ Stack +

+
+

+ Infix to Postfix +

+ +
+
+ +
+ +
+ +
+ +
+

+ Test Your Knowledge before moving forward! +

+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+ + +