- {/* ══ LEFT — text ══ */}
-
- {/* headline */}
-
- The smartest way
-
- to learn DSA — visually.
-
-
- {/* animated topic pill */}
-
-
-
- {TOPICS[index].label}
-
-
-
- {/* CTAs */}
-
-
- Start Visualizing
-
-
-
-
-
-
- Read Blogs
-
-
-
-
- {/* ══ RIGHT — DSA visual card ══ */}
-
-
- {/* ── main card: code editor window ── */}
-
- {/* title bar */}
-
-
-
-
-
- binarySearch.js
-
-
-
- {/* code body */}
-
-
- function {" "}
- binarySearch
- (arr, target) {"{"}
-
-
- let {" "}
- left {" "}
- = {" "}
- 0
- , {" "}
- right {" "}
- = {" "}
- arr.length {" "}
- - {" "}
- 1
- ;
-
-
- while {" "}
- (left {" "}
- <= {" "}
- right) {"{"}
-
-
- const {" "}
- mid {" "}
- = {" "}
- Math.floor((left {" "}
- + {" "}
- right) {" "}
- / {" "}
- 2
- );
-
-
- if {" "}
- (arr[mid] {" "}
- === {" "}
- target) {" "}
- return {" "}
- mid
- ;
-
-
- else if {" "}
- (arr[mid] {" "}
- < {" "}
- target) left {" "}
- = {" "}
- mid {" "}
- + {" "}
- 1
- ;
-
-
- else {" "}
- right {" "}
- = {" "}
- mid {" "}
- - {" "}
- 1
- ;
-
-
- {"}"}
-
-
- return {" "}
- -1
- ;
-
-
- {"}"}
-
-
-
- {/* visualizer strip */}
-
-
-
- Visualization — step 2 of 4
-
- {/* array bars */}
-
- {[2, 5, 8, 12, 16, 23, 38, 45, 56, 72].map((v, i) => (
-
-
= 5
- ? "#3e4143" // right half — dimmed
- : "#6a6f73", // left half
- }}
- />
-
- {v}
-
-
- ))}
-
- {/* legend */}
-
-
- {" "}
- mid
-
-
- {" "}
- active
-
-
- {" "}
- eliminated
-
-
-
-
-
-
- {/* ── floating badge top-right ── */}
-
-
- O
-
- O(log n)
-
-
- {/* ── floating badge bottom-left ── */}
-
-
- ✓
-
- Found at index 5
-
-
- {/* glow */}
-
-
-
-
-
-
- );
-};
-
-export default HeroSection;
diff --git a/app/components/navbar.jsx b/app/components/navbar.jsx
deleted file mode 100644
index 4cb5ea563..000000000
--- a/app/components/navbar.jsx
+++ /dev/null
@@ -1,301 +0,0 @@
-"use client";
-import Link from "next/link";
-import { useState, useEffect, useRef } from "react";
-import { useRouter, usePathname } from "next/navigation";
-import { useUser } from "@/app/contexts/UserContext";
-import { supabase } from "@/lib/supabase";
-
-const NAV_LINKS = [];
-
-export default function Navbar() {
- const [menuOpen, setMenuOpen] = useState(false);
- const [userMenuOpen, setUserMenuOpen] = useState(false);
- const [scrolled, setScrolled] = useState(false);
- const [theme, setTheme] = useState("light");
- const pathname = usePathname();
- const router = useRouter();
- const { user, setUser } = useUser();
- const userRef = useRef(null);
-
- useEffect(() => {
- const savedTheme = localStorage.getItem("theme") || "light";
- setTheme(savedTheme);
- document.documentElement.classList.toggle("dark", savedTheme === "dark");
- }, []);
-
- const toggleTheme = () => {
- const newTheme = theme === "light" ? "dark" : "light";
- setTheme(newTheme);
- localStorage.setItem("theme", newTheme);
- document.documentElement.classList.toggle("dark", newTheme === "dark");
- };
-
- useEffect(() => {
- const handleScroll = () => setScrolled(window.scrollY > 4);
- window.addEventListener("scroll", handleScroll);
- return () => window.removeEventListener("scroll", handleScroll);
- }, []);
-
- useEffect(() => {
- const fn = (e) => {
- if (userRef.current && !userRef.current.contains(e.target))
- setUserMenuOpen(false);
- };
- document.addEventListener("mousedown", fn);
- return () => document.removeEventListener("mousedown", fn);
- }, []);
-
- const handleLogout = async () => {
- await supabase.auth.signOut();
- setUser(null);
- router.push("/");
- setMenuOpen(false);
- };
-
- const isActive = (href) => {
- if (href.startsWith("http")) return false;
- if (href.startsWith("/#")) return pathname === "/";
- return pathname === href || pathname.startsWith(href + "/");
- };
-
- return (
- <>
-
-
- {/* Logo */}
-
- Algo
Buddy
-
-
- {/* Desktop Nav Links */}
-
- {NAV_LINKS.map((l) => (
-
- {l.label}
-
- ))}
-
-
- {/* Right: auth + theme toggle */}
-
- {user ? (
-
-
setUserMenuOpen((o) => !o)}
- className="flex items-center gap-2 rounded-full px-3 py-1.5 border border-[#e5e7eb] dark:border-[#333] hover:border-[#a435f0] transition-colors"
- >
-
-
-
-
-
- {userMenuOpen && (
-
-
-
setUserMenuOpen(false)}
- className="flex items-center gap-2.5 px-4 py-3 text-[14px] font-medium text-[#1a1a1a] dark:text-[#f5f5f5] hover:bg-[#f9fafb] dark:hover:bg-[#222] transition-colors"
- >
-
-
-
- My Dashboard
-
-
{
- handleLogout();
- setUserMenuOpen(false);
- }}
- className="w-full flex items-center gap-2.5 px-4 py-3 text-[14px] font-medium text-[#dc2626] hover:bg-[#fef2f2] dark:hover:bg-[#2a1515] transition-colors border-t border-[#f3f4f6] dark:border-[#222]"
- >
-
-
-
- Log out
-
-
- )}
-
- ) : (
-
- Sign in
-
- )}
-
- {/* Dark mode toggle */}
-
- {theme === "light" ? (
-
-
-
- ) : (
-
-
-
- )}
-
-
-
- {/* Mobile Hamburger */}
-
setMenuOpen((o) => !o)}
- aria-label="Toggle menu"
- className="md:hidden w-10 h-10 flex items-center justify-center text-[#4b5563] dark:text-[#a3a3a3] rounded-lg hover:bg-[#f3f4f6] dark:hover:bg-[#222] transition-colors"
- >
- {menuOpen ? (
-
-
-
- ) : (
-
-
-
- )}
-
-
-
-
- {/* Mobile Drawer */}
- {menuOpen && (
-
-
- {NAV_LINKS.map((l) => (
- setMenuOpen(false)}
- className={`block px-6 py-3.5 text-[16px] font-medium transition-colors ${
- isActive(l.href)
- ? "text-[#a435f0] bg-[#faf5ff] dark:bg-[#1a0a2e]"
- : "text-[#374151] dark:text-[#a3a3a3] hover:bg-[#f9fafb] dark:hover:bg-[#1a1a1a] hover:text-[#1a1a1a] dark:hover:text-white"
- }`}
- >
- {l.label}
-
- ))}
-
-
- {user ? (
-
-
- {user.email}
-
-
setMenuOpen(false)}
- className="h-[44px] flex items-center justify-center text-[15px] font-semibold border border-[#d1d5db] dark:border-[#444] rounded-full text-[#1a1a1a] dark:text-white hover:border-[#a435f0] hover:text-[#a435f0] transition-all"
- >
- My Dashboard
-
-
- Log out
-
-
- ) : (
-
setMenuOpen(false)}
- className="h-[44px] flex items-center justify-center text-[15px] font-semibold text-[#1a1a1a] dark:text-white border border-[#d1d5db] dark:border-[#444] rounded-full hover:border-[#a435f0] hover:text-[#a435f0] transition-all"
- >
- Sign in
-
- )}
-
-
- )}
-
-
- >
- );
-}
diff --git a/app/components/navbarinner.jsx b/app/components/navbarinner.jsx
deleted file mode 100644
index 4cb5ea563..000000000
--- a/app/components/navbarinner.jsx
+++ /dev/null
@@ -1,301 +0,0 @@
-"use client";
-import Link from "next/link";
-import { useState, useEffect, useRef } from "react";
-import { useRouter, usePathname } from "next/navigation";
-import { useUser } from "@/app/contexts/UserContext";
-import { supabase } from "@/lib/supabase";
-
-const NAV_LINKS = [];
-
-export default function Navbar() {
- const [menuOpen, setMenuOpen] = useState(false);
- const [userMenuOpen, setUserMenuOpen] = useState(false);
- const [scrolled, setScrolled] = useState(false);
- const [theme, setTheme] = useState("light");
- const pathname = usePathname();
- const router = useRouter();
- const { user, setUser } = useUser();
- const userRef = useRef(null);
-
- useEffect(() => {
- const savedTheme = localStorage.getItem("theme") || "light";
- setTheme(savedTheme);
- document.documentElement.classList.toggle("dark", savedTheme === "dark");
- }, []);
-
- const toggleTheme = () => {
- const newTheme = theme === "light" ? "dark" : "light";
- setTheme(newTheme);
- localStorage.setItem("theme", newTheme);
- document.documentElement.classList.toggle("dark", newTheme === "dark");
- };
-
- useEffect(() => {
- const handleScroll = () => setScrolled(window.scrollY > 4);
- window.addEventListener("scroll", handleScroll);
- return () => window.removeEventListener("scroll", handleScroll);
- }, []);
-
- useEffect(() => {
- const fn = (e) => {
- if (userRef.current && !userRef.current.contains(e.target))
- setUserMenuOpen(false);
- };
- document.addEventListener("mousedown", fn);
- return () => document.removeEventListener("mousedown", fn);
- }, []);
-
- const handleLogout = async () => {
- await supabase.auth.signOut();
- setUser(null);
- router.push("/");
- setMenuOpen(false);
- };
-
- const isActive = (href) => {
- if (href.startsWith("http")) return false;
- if (href.startsWith("/#")) return pathname === "/";
- return pathname === href || pathname.startsWith(href + "/");
- };
-
- return (
- <>
-
-
- {/* Logo */}
-
- Algo
Buddy
-
-
- {/* Desktop Nav Links */}
-
- {NAV_LINKS.map((l) => (
-
- {l.label}
-
- ))}
-
-
- {/* Right: auth + theme toggle */}
-
- {user ? (
-
-
setUserMenuOpen((o) => !o)}
- className="flex items-center gap-2 rounded-full px-3 py-1.5 border border-[#e5e7eb] dark:border-[#333] hover:border-[#a435f0] transition-colors"
- >
-
-
-
-
-
- {userMenuOpen && (
-
-
-
setUserMenuOpen(false)}
- className="flex items-center gap-2.5 px-4 py-3 text-[14px] font-medium text-[#1a1a1a] dark:text-[#f5f5f5] hover:bg-[#f9fafb] dark:hover:bg-[#222] transition-colors"
- >
-
-
-
- My Dashboard
-
-
{
- handleLogout();
- setUserMenuOpen(false);
- }}
- className="w-full flex items-center gap-2.5 px-4 py-3 text-[14px] font-medium text-[#dc2626] hover:bg-[#fef2f2] dark:hover:bg-[#2a1515] transition-colors border-t border-[#f3f4f6] dark:border-[#222]"
- >
-
-
-
- Log out
-
-
- )}
-
- ) : (
-
- Sign in
-
- )}
-
- {/* Dark mode toggle */}
-
- {theme === "light" ? (
-
-
-
- ) : (
-
-
-
- )}
-
-
-
- {/* Mobile Hamburger */}
-
setMenuOpen((o) => !o)}
- aria-label="Toggle menu"
- className="md:hidden w-10 h-10 flex items-center justify-center text-[#4b5563] dark:text-[#a3a3a3] rounded-lg hover:bg-[#f3f4f6] dark:hover:bg-[#222] transition-colors"
- >
- {menuOpen ? (
-
-
-
- ) : (
-
-
-
- )}
-
-
-
-
- {/* Mobile Drawer */}
- {menuOpen && (
-
-
- {NAV_LINKS.map((l) => (
- setMenuOpen(false)}
- className={`block px-6 py-3.5 text-[16px] font-medium transition-colors ${
- isActive(l.href)
- ? "text-[#a435f0] bg-[#faf5ff] dark:bg-[#1a0a2e]"
- : "text-[#374151] dark:text-[#a3a3a3] hover:bg-[#f9fafb] dark:hover:bg-[#1a1a1a] hover:text-[#1a1a1a] dark:hover:text-white"
- }`}
- >
- {l.label}
-
- ))}
-
-
- {user ? (
-
-
- {user.email}
-
-
setMenuOpen(false)}
- className="h-[44px] flex items-center justify-center text-[15px] font-semibold border border-[#d1d5db] dark:border-[#444] rounded-full text-[#1a1a1a] dark:text-white hover:border-[#a435f0] hover:text-[#a435f0] transition-all"
- >
- My Dashboard
-
-
- Log out
-
-
- ) : (
-
setMenuOpen(false)}
- className="h-[44px] flex items-center justify-center text-[15px] font-semibold text-[#1a1a1a] dark:text-white border border-[#d1d5db] dark:border-[#444] rounded-full hover:border-[#a435f0] hover:text-[#a435f0] transition-all"
- >
- Sign in
-
- )}
-
-
- )}
-
-
- >
- );
-}
diff --git a/app/components/termsOfServicesModal.jsx b/app/components/termsOfServicesModal.jsx
deleted file mode 100755
index 98b1bb4af..000000000
--- a/app/components/termsOfServicesModal.jsx
+++ /dev/null
@@ -1,167 +0,0 @@
-import React, { useEffect } from "react";
-import { FiX } from "react-icons/fi";
-
-const termsSections = [
- {
- id: "1",
- title: "Acceptance of Terms",
- data: "By accessing and using this website, you accept and agree to be bound by the terms and provision of this agreement.",
- },
- {
- id: "2",
- title: "Use License",
- points: [
- "Permission is granted to temporarily use the materials on this website for personal, non-commercial transitory viewing only",
- "This is the grant of a license, not a transfer of title",
- "You may not modify or copy the materials, use them for any commercial purpose, or remove any copyright or proprietary notations",
- ],
- },
- {
- id: "3",
- title: "User Responsibilities",
- points: [
- "Provide accurate and complete information when required",
- "Maintain the confidentiality of your account credentials",
- "Notify us immediately of any unauthorized use of your account",
- "Use the service in compliance with all applicable laws and regulations",
- ],
- },
- {
- id: "4",
- title: "Intellectual Property",
- data: "All content, features, and functionality on this website, including but not limited to text, graphics, logos, and software, are the exclusive property of the company and are protected by international copyright, trademark, and other intellectual property laws.",
- },
- {
- id: "5",
- title: "Limitation of Liability",
- data: "In no event shall the company, nor its directors, employees, partners, agents, suppliers, or affiliates, be liable for any indirect, incidental, special, consequential or punitive damages, including without limitation, loss of profits, data, use, goodwill, or other intangible losses.",
- },
- {
- id: "6",
- title: "Governing Law",
- data: "These Terms shall be governed and construed in accordance with the laws of the applicable jurisdiction, without regard to its conflict of law provisions.",
- },
- {
- id: "7",
- title: "Changes to Terms",
- data: "We reserve the right, at our sole discretion, to modify or replace these Terms at any time. By continuing to access or use our service after those revisions become effective, you agree to be bound by the revised terms.",
- },
- {
- id: "8",
- title: "Contact Information",
- data: "If you have any questions about these Terms, please contact us at",
- contact: "hello@algobuddy.in",
- },
-];
-
-const TermsOfServiceModal = ({ isOpen, onClose }) => {
- // Prevent body scroll when modal is open
- useEffect(() => {
- if (isOpen) {
- document.body.style.overflow = "hidden";
- } else {
- document.body.style.overflow = "auto";
- }
- return () => {
- document.body.style.overflow = "auto";
- };
- }, [isOpen]);
-
- if (!isOpen) return null;
-
- return (
-
- {/* Backdrop with fade-in animation */}
-
-
- {/* Modal container with slide-up animation */}
-
- {/* Header with close button */}
-
-
- Terms of Service
-
-
-
-
-
-
- {/* Scrollable content */}
-
-
- Please read these terms and conditions carefully before using our
- website and services. Your access to and use of the service is
- conditioned on your acceptance of and compliance with these terms.
-
-
- {/* Terms sections */}
-
-
- {termsSections.map((item, index) => (
-
-
-
-
- {item.id}
-
-
- {item.title}
-
-
- {item.points && (
-
- {item.points.map((subitem, subindex) => (
-
-
- {subitem}
-
-
- ))}
-
- )}
-
- {item.data}
-
- {item.contact && (
-
- {item.contact}
-
- )}
-
-
- ))}
-
-
-
-
-
- Last updated: May 17, 2025
-
-
-
-
- {/* Footer with close button */}
-
-
- I Agree
-
-
-
-
- );
-};
-
-export default TermsOfServiceModal;
diff --git a/app/components/ui/ArticleActions.jsx b/app/components/ui/ArticleActions.jsx
deleted file mode 100755
index ac5ff61ef..000000000
--- a/app/components/ui/ArticleActions.jsx
+++ /dev/null
@@ -1,55 +0,0 @@
-"use client";
-import { useState } from "react";
-import { Copy, Share2, Check } from "lucide-react";
-
-export default function ArticleActions() {
- const [copied, setCopied] = useState(false);
-
- const handleCopy = async () => {
- try {
- await navigator.clipboard.writeText(window.location.href);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy: ", err);
- }
- };
-
- const handleShare = async () => {
- if (navigator.share) {
- try {
- await navigator.share({
- title: document.title,
- url: window.location.href,
- });
- } catch (err) {
- console.error("Share failed: ", err);
- }
- } else {
- handleCopy();
- }
- };
-
- return (
-
-
- {copied ? (
-
- ) : (
-
- )}
- {copied ? "Copied!" : "Copy Link"}
-
-
-
- Share
-
-
- );
-}
\ No newline at end of file
diff --git a/app/components/ui/Breadcrumbs.jsx b/app/components/ui/Breadcrumbs.jsx
deleted file mode 100755
index fa7a8baf7..000000000
--- a/app/components/ui/Breadcrumbs.jsx
+++ /dev/null
@@ -1,23 +0,0 @@
-"use client";
-import { ChevronRight } from "lucide-react";
-import Link from "next/link";
-
-export default function Breadcrumbs({ paths }) {
- return (
-
- {paths.map((path, index) => (
-
-
- {path.name}
-
- {index !== paths.length - 1 && (
-
- )}
-
- ))}
-
- );
-}
\ No newline at end of file
diff --git a/app/components/ui/ClientLayoutWrapper.jsx b/app/components/ui/ClientLayoutWrapper.jsx
deleted file mode 100755
index 9cc346876..000000000
--- a/app/components/ui/ClientLayoutWrapper.jsx
+++ /dev/null
@@ -1,11 +0,0 @@
-"use client";
-import { Toaster } from "react-hot-toast";
-
-export default function ClientLayoutWrapper({ children }) {
- return (
- <>
-
- {children}
- >
- );
-}
\ No newline at end of file
diff --git a/app/components/ui/ModuleCard.jsx b/app/components/ui/ModuleCard.jsx
deleted file mode 100755
index de9e3a17a..000000000
--- a/app/components/ui/ModuleCard.jsx
+++ /dev/null
@@ -1,119 +0,0 @@
-"use client";
-import { useState } from "react";
-import { supabase } from "@/lib/supabase";
-import { useUser } from "@/app/contexts/UserContext";
-import { toast } from "react-hot-toast";
-import { TriangleAlert } from "lucide-react";
-import { useEffect } from "react";
-
-
-export default function ModuleCard({ moduleId, description, initialDone }) {
- const { user } = useUser();
- const [isDone, setIsDone] = useState(initialDone);
-
- useEffect(() => {
- const fetchUserProgress = async () => {
- if (!user) return;
-
- const { data, error } = await supabase
- .from("user_progress")
- .select("is_done")
- .eq("user_id", user.id)
- .eq("module_id", moduleId)
- .single();
-
- if (error) {
- console.error("Error fetching user progress:", error);
- return;
- }
-
- setIsDone(data?.is_done ?? false);
- };
-
- fetchUserProgress();
-}, [user, moduleId]);
-
- async function toggleCompletion() {
- if (!user) {
- toast.custom((t) => (
-
-
-
-
- You are in guest mode. Login or signup to track your progress.
-
-
-
- {
- window.location.href = "/login";
- toast.dismiss(t.id);
- }}
- className="px-4 py-2 rounded-full font-medium bg-gradient-to-r from-blue-500 to-blue-600 text-white hover:from-blue-600 hover:to-blue-700 transition duration-300 shadow-md flex items-center gap-2"
- >
- Login/Signup
-
- toast.dismiss(t.id)}
- className="px-4 py-2 rounded-full font-medium bg-neutral-100 hover:bg-neutral-200 dark:hover:bg-neutral-900 dark:bg-neutral-800 border border-blue-500 dark:text-white text-black transition duration-300 shadow-lg flex items-center"
- >
- Continue as Guest
-
-
-
- ));
- return;
- }
-
- try {
- const { error } = await supabase
- .from("user_progress")
- .upsert(
- {
- user_id: user.id,
- module_id: moduleId,
- is_done: !isDone,
- updated_at: new Date(),
- },
- { onConflict: ["user_id", "module_id"] }
- );
-
- if (error) {
- console.error("Error updating progress:", error.message, error.details);
- toast.error(`Failed to update progress: ${error.message}`);
- return;
- }
-
- setIsDone(!isDone);
- toast.success(isDone ? "Module marked as incomplete." : "Module marked as completed!");
- } catch (err) {
- console.error("Unexpected error during progress update:", err);
- toast.error("Unexpected error. Please try again.");
- }
- }
-
- return (
-
-
-
-
- Done With the Learning
-
-
{description}
-
-
-
-
- );
-}
\ No newline at end of file
diff --git a/app/components/ui/PushPop.jsx b/app/components/ui/PushPop.jsx
deleted file mode 100755
index 2ef0a98b6..000000000
--- a/app/components/ui/PushPop.jsx
+++ /dev/null
@@ -1,109 +0,0 @@
-'use client';
-
-import { useState } from 'react';
-
-const PushPop = ({ stack, setStack, isAnimating, setIsAnimating, setMessage, setOperation }) => {
- const [inputValue, setInputValue] = useState('');
-
- // Push operation
- const push = () => {
- if (!inputValue.trim()) {
- setMessage('Please enter a value');
- return;
- }
-
- setIsAnimating(true);
- setOperation(`Pushing "${inputValue}"...`);
-
- setTimeout(() => {
- setStack(prev => [inputValue, ...prev]);
- setOperation(null);
- setMessage(`"${inputValue}" pushed to stack`);
- setInputValue('');
- setIsAnimating(false);
- }, 1000);
- };
-
- // Pop operation
- const pop = () => {
- if (stack.length === 0) {
- setMessage('Stack is empty!');
- return;
- }
-
- setIsAnimating(true);
- const poppedValue = stack[0];
- setOperation(`Popping "${poppedValue}"...`);
-
- setTimeout(() => {
- setStack(prev => prev.slice(1));
- setOperation(null);
- setMessage(`"${poppedValue}" popped from stack`);
- setIsAnimating(false);
- }, 1000);
- };
-
- // Peek operation
- const peek = () => {
- if (stack.length === 0) {
- setMessage('Stack is empty!');
- return;
- }
-
- setIsAnimating(true);
- setOperation(`Peeking at "${stack[0]}"`);
-
- setTimeout(() => {
- setOperation(null);
- setMessage(`Top element is "${stack[0]}"`);
- setIsAnimating(false);
- }, 1000);
- };
-
- return (
-
-
- setInputValue(e.target.value)}
- placeholder="Enter value"
- className="flex-1 p-2 border rounded dark:bg-neutral-900 focus:ring-2 focus:ring-blue-500"
- disabled={isAnimating}
- />
-
- Push
-
-
-
-
- Pop
-
-
- Peek
-
- setStack([])}
- className="bg-red-500 text-white px-4 py-2 rounded col-span-2 sm:col-span-1"
- disabled={isAnimating}
- >
- Reset
-
-
-
- );
-};
-
-export default PushPop;
\ No newline at end of file
diff --git a/app/components/ui/SearchBar.jsx b/app/components/ui/SearchBar.jsx
deleted file mode 100755
index 7c92a5101..000000000
--- a/app/components/ui/SearchBar.jsx
+++ /dev/null
@@ -1,74 +0,0 @@
-'use client';
-import { useState, useEffect } from 'react';
-
-const SearchBar = ({ sections, onSearchResults }) => {
- const [searchQuery, setSearchQuery] = useState('');
-
- const handleSearch = (e) => {
- const query = e.target.value.toLowerCase();
- setSearchQuery(query);
-
- if (!query) {
- onSearchResults(sections);
- return;
- }
-
- const filtered = sections.map(section => {
- const sectionTitleMatch = section.title.toLowerCase().includes(query);
-
- const subsectionMatches = section.subsections?.map(subsection => {
- const subsectionTitleMatch = subsection.title.toLowerCase().includes(query);
- const itemMatches = subsection.items.filter(item =>
- item.name.toLowerCase().includes(query)
- );
- return {
- ...subsection,
- items: subsectionTitleMatch ? subsection.items : itemMatches,
- isHighlighted: subsectionTitleMatch || itemMatches.length > 0
- };
- }).filter(subsection => subsection.items.length > 0);
-
- const itemMatches = section.items?.filter(item =>
- item.name.toLowerCase().includes(query)
- );
-
- return {
- ...section,
- subsections: section.subsections ? subsectionMatches : undefined,
- items: section.subsections ? undefined : (itemMatches?.length > 0 ? itemMatches : undefined),
- isHighlighted: sectionTitleMatch ||
- (subsectionMatches?.length > 0) ||
- (itemMatches?.length > 0)
- };
- }).filter(section =>
- section.isHighlighted ||
- section.subsections?.length > 0 ||
- section.items?.length > 0
- );
-
- onSearchResults(filtered);
- };
-
- return (
-
- );
-};
-
-export default SearchBar;
\ No newline at end of file
diff --git a/app/components/ui/TutorialOverlay.jsx b/app/components/ui/TutorialOverlay.jsx
deleted file mode 100755
index c1080d76e..000000000
--- a/app/components/ui/TutorialOverlay.jsx
+++ /dev/null
@@ -1,110 +0,0 @@
-"use client";
-
-import { useEffect, useState, useRef } from "react";
-import gsap from "gsap";
-
-export default function TutorialOverlay() {
- const [showOverlay, setShowOverlay] = useState(false);
- const [step, setStep] = useState(0);
- const overlayRef = useRef();
-
- useEffect(() => {
- const seenTutorial = localStorage.getItem("tutorialSeen");
-
- if (!seenTutorial) {
- setShowOverlay(true);
- gsap.fromTo(
- overlayRef.current,
- { opacity: 0 },
- { opacity: 1, duration: 0.5, ease: "power2.out" },
- );
- }
- }, []);
-
- const nextStep = () => {
- if (step < 2) {
- setStep(step + 1);
- } else {
- gsap.to(overlayRef.current, {
- opacity: 0,
- duration: 0.5,
- ease: "power2.in",
- onComplete: () => {
- localStorage.setItem("tutorialSeen", "true");
- setShowOverlay(false);
- },
- });
- }
- };
-
- const closeOverlay = () => {
- gsap.to(overlayRef.current, {
- opacity: 0,
- duration: 0.5,
- ease: "power2.in",
- onComplete: () => {
- localStorage.setItem("tutorialSeen", "true");
- setShowOverlay(false);
- },
- });
- };
-
- if (!showOverlay) return null;
-
- return (
-
-
-
- ×
-
- {(step === 1 || step === 2) && (
-
- )}
-
- {step === 0 && "Welcome to AlgoBuddy!"}
- {step === 1 && "Choose a Data Structure"}
- {step === 2 && "Learn More About Each Structure"}
-
-
- {step === 0 &&
- "Here’s a quick guide to help you get started with visualizing data structures."}
- {step === 1 &&
- "This is the algorithm page where you can choose a data structure and explore related algorithms."}
- {step === 2 &&
- "Click the 'i' button on each data structure card to learn more about it before visualizing."}
-
- {step > 0 && (
-
- Step {step}/2
-
- )}
-
-
- {step < 2 ? "Next" : "Finish"}
-
-
- Skip
-
-
-
-
- );
-}
diff --git a/app/components/ui/backtotop.jsx b/app/components/ui/backtotop.jsx
deleted file mode 100755
index 2f8b52cad..000000000
--- a/app/components/ui/backtotop.jsx
+++ /dev/null
@@ -1,68 +0,0 @@
-"use client";
-import { useEffect, useState } from 'react';
-
-const BackToTop = () => {
- const [visible, setVisible] = useState(false);
-
- useEffect(() => {
- const handleScroll = () => {
- setVisible(window.scrollY > 300);
- };
-
- window.addEventListener('scroll', handleScroll);
- return () => window.removeEventListener('scroll', handleScroll);
- }, []);
-
- const scrollToTop = () => {
- window.scrollTo({
- top: 0,
- behavior: 'smooth'
- });
- };
-
- return (
-
- {/* Tooltip */}
-
- Back to top
-
-
- {/* Arrow icon */}
-
-
-
-
- );
-};
-
-export default BackToTop;
\ No newline at end of file
diff --git a/app/components/ui/customArrayInput.jsx b/app/components/ui/customArrayInput.jsx
deleted file mode 100755
index 6d7c748bc..000000000
--- a/app/components/ui/customArrayInput.jsx
+++ /dev/null
@@ -1,68 +0,0 @@
-"use client";
-import { useState } from "react";
-
-const CustomArrayInput = ({
- onUseCustomArray = (numbers) => console.log("Received:", numbers),
- disabled = false,
- className = ""
-}) => {
- const [inputValue, setInputValue] = useState("");
- const [error, setError] = useState("");
-
- const handleSubmit = () => {
- setError("");
-
- if (!inputValue.trim()) {
- setError("Please enter numbers separated by commas");
- return;
- }
-
- try {
- const numbers = inputValue
- .split(",")
- .map(item => {
- const num = Number(item.trim());
- if (isNaN(num)) throw new Error(`"${item}" is not a valid number`);
- return num;
- });
-
- if (numbers.length === 0) {
- setError("No valid numbers found");
- return;
- }
-
- onUseCustomArray(numbers);
- setInputValue("");
- } catch (err) {
- setError(err.message);
- }
- };
-
- return (
-
-
-
-
setInputValue(e.target.value)}
- placeholder="Example: 5, 3, 8, 1, 2"
- className="w-full p-2 border rounded dark:bg-gray-700"
- disabled={disabled}
- onKeyDown={(e) => e.key === "Enter" && handleSubmit()}
- />
- {error &&
{error}
}
-
-
- Use Array
-
-
-
- );
-};
-
-export default CustomArrayInput;
\ No newline at end of file
diff --git a/app/components/ui/exploreOther.jsx b/app/components/ui/exploreOther.jsx
deleted file mode 100755
index 771bcc773..000000000
--- a/app/components/ui/exploreOther.jsx
+++ /dev/null
@@ -1,83 +0,0 @@
-"use client";
-import { motion } from 'framer-motion';
-import { FiArrowRight, FiExternalLink } from 'react-icons/fi';
-
-const ExploreOther = ({
- title,
- links,
- columns = "4",
- icon =
,
- showExternalIcon = true
-}) => {
- // Responsive grid columns mapping
- const gridColumns = {
- "1": "sm:grid-cols-1",
- "2": "sm:grid-cols-2",
- "3": "sm:grid-cols-2 lg:grid-cols-3",
- "4": "sm:grid-cols-2 lg:grid-cols-4",
- "5": "sm:grid-cols-2 lg:grid-cols-5",
- }[columns] || "sm:grid-cols-2 lg:grid-cols-4";
-
- // Check if links should open in new tab
- const isExternal = (url) => url.startsWith('http') || url.startsWith('www');
-
- return (
-
-
-
-
-
- {title}
-
-
-
-
- {links.map((link, index) => (
-
- {/* Animated hover effect */}
-
-
-
- {/* Custom icon or default */}
-
- {link.icon || icon}
-
-
-
-
- {link.text}
-
- {link.description && (
-
- {link.description}
-
- )}
-
-
- {/* External link indicator */}
- {showExternalIcon && isExternal(link.url) && (
-
- )}
-
-
- ))}
-
-
-
- );
-};
-
-export default ExploreOther;
\ No newline at end of file
diff --git a/app/components/ui/goButton.jsx b/app/components/ui/goButton.jsx
deleted file mode 100755
index 9fadeea5d..000000000
--- a/app/components/ui/goButton.jsx
+++ /dev/null
@@ -1,17 +0,0 @@
-'use client';
-import React from 'react';
-
-const GoButton = ({ onGo, isAnimating }) => {
- return (
-
- Go
-
- );
-};
-
-export default GoButton;
\ No newline at end of file
diff --git a/app/components/ui/navigationLink.jsx b/app/components/ui/navigationLink.jsx
deleted file mode 100755
index 13a684042..000000000
--- a/app/components/ui/navigationLink.jsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react';
-
-const NavigationLink = ({ href, text, className = '' }) => {
- return (
-
- );
-};
-
-export default NavigationLink;
\ No newline at end of file
diff --git a/app/components/ui/productHunt.jsx b/app/components/ui/productHunt.jsx
deleted file mode 100755
index 89f400a0f..000000000
--- a/app/components/ui/productHunt.jsx
+++ /dev/null
@@ -1,23 +0,0 @@
-"use client";
-import React from "react";
-
-const ProductHuntBadge = () => {
- return (
-
-
-
- );
-};
-
-export default ProductHuntBadge;
\ No newline at end of file
diff --git a/app/components/ui/randomArray.jsx b/app/components/ui/randomArray.jsx
deleted file mode 100755
index 186120c50..000000000
--- a/app/components/ui/randomArray.jsx
+++ /dev/null
@@ -1,23 +0,0 @@
-"use client";
-
-const ArrayGenerator = ({ onGenerate }) => {
- const generateRandomArray = (size = 10, min = 5, max = 100) => {
- return Array.from({ length: size }, () => Math.floor(Math.random() * (max - min + 1)) + min);
- };
-
- const handleGenerate = () => {
- const newArray = generateRandomArray();
- onGenerate(newArray);
- };
-
- return (
-
- Generate Random Array
-
- );
-};
-
-export default ArrayGenerator;
\ No newline at end of file
diff --git a/app/components/ui/resetButton.jsx b/app/components/ui/resetButton.jsx
deleted file mode 100755
index 2be44fc98..000000000
--- a/app/components/ui/resetButton.jsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import React from 'react';
-
-const ResetButton = ({ onReset, isAnimating }) => {
- return (
-
- Reset
-
- );
-};
-
-export default ResetButton;
\ No newline at end of file
diff --git a/app/contexts/AuthContext.js b/app/contexts/AuthContext.js
deleted file mode 100755
index 4afee4914..000000000
--- a/app/contexts/AuthContext.js
+++ /dev/null
@@ -1,80 +0,0 @@
-'use client';
-import { createContext, useContext, useEffect, useState } from 'react';
-import axios from 'axios';
-
-const AuthContext = createContext();
-
-const API = process.env.NEXT_PUBLIC_API_URL;
-
-export const AuthProvider = ({ children }) => {
- const [user, setUser] = useState(null);
-
- const signup = async (email, password, name) => {
- try {
- const res = await axios.post(`${API}/auth/signup`, {
- email,
- password,
- name,
- });
-
- if (res.data.success) {
- setUser(res.data.user);
- return { success: true };
- }
-
- return { success: false, message: res.data.message };
- } catch (error) {
- return { success: false, message: error.response?.data?.message || 'Signup failed' };
- }
- };
-
- const login = async (email, password) => {
- try {
- const res = await axios.post(`${API}/auth/login`, {
- email,
- password,
- });
-
- if (res.data.success) {
- setUser(res.data.user);
- localStorage.setItem('token', res.data.token);
- return { success: true };
- }
-
- return { success: false, message: res.data.message };
- } catch (error) {
- return { success: false, message: error.response?.data?.message || 'Login failed' };
- }
- };
-
- const logout = () => {
- setUser(null);
- localStorage.removeItem('token');
- };
-
- useEffect(() => {
- const fetchUser = async () => {
- const token = localStorage.getItem('token');
- if (token) {
- try {
- const res = await axios.get(`${API}/auth/me`, {
- headers: { Authorization: `Bearer ${token}` },
- });
- if (res.data.user) setUser(res.data.user);
- } catch {
- localStorage.removeItem('token');
- }
- }
- };
-
- fetchUser();
- }, []);
-
- return (
-
- {children}
-
- );
-};
-
-export const useUser = () => useContext(AuthContext);
\ No newline at end of file
diff --git a/app/contexts/UserContext.jsx b/app/contexts/UserContext.jsx
deleted file mode 100755
index 34a91eca1..000000000
--- a/app/contexts/UserContext.jsx
+++ /dev/null
@@ -1,39 +0,0 @@
-"use client";
-import { createContext, useContext, useEffect, useState } from "react";
-import { createClient } from "@supabase/supabase-js";
-
-const UserContext = createContext();
-
-const supabaseClient = createClient(
- process.env.NEXT_PUBLIC_SUPABASE_URL || "https://placeholder.supabase.co",
- process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || "placeholder-key",
-);
-
-export const UserProvider = ({ children }) => {
- const [user, setUser] = useState(null);
- const supabase = supabaseClient;
-
- useEffect(() => {
- const getSessionAndUser = async () => {
- const { data: sessionData } = await supabase.auth.getSession();
- if (!sessionData.session) {
- return;
- }
-
- const {
- data: { user },
- } = await supabase.auth.getUser();
- setUser(user);
- };
-
- getSessionAndUser();
- }, []);
-
- return (
-
- {children}
-
- );
-};
-
-export const useUser = () => useContext(UserContext);
diff --git a/app/dashboard/page.jsx b/app/dashboard/page.jsx
deleted file mode 100755
index 99e698925..000000000
--- a/app/dashboard/page.jsx
+++ /dev/null
@@ -1,149 +0,0 @@
-"use client";
-import Navbar from "@/app/components/navbar";
-import { useEffect, useState } from "react";
-import { useRouter } from "next/navigation";
-import { supabase } from "@/lib/supabase";
-import { useUser } from "@/app/contexts/UserContext";
-import Link from "next/link";
-import ActivityDashboard from "@/app/components/dashboard/ActivityDashboard";
-import Footer from "@/app/components/footer";
-import { trackActivity } from "@/lib/activity";
-
-export default function Dashboard() {
- const router = useRouter();
- const { user } = useUser();
- const [modules, setModules] = useState([]);
- const [progress, setProgress] = useState({});
- const [showAllCompleted, setShowAllCompleted] = useState(false);
-
- useEffect(() => {
- if (!user) {
- router.push("/login");
- } else {
- fetchModules();
- trackActivity(user.id, "site_visit");
- }
- }, [user]);
-
- async function fetchModules() {
- const { data: modulesData, error: modulesError } = await supabase
- .from("modules")
- .select("*");
-
- if (modulesError) {
- console.error(modulesError);
- return;
- }
-
- const { data: progressData, error: progressError } = await supabase
- .from("user_progress")
- .select("*")
- .eq("user_id", user.id);
-
- if (progressError) {
- console.error(progressError);
- return;
- }
-
- const progressMap = {};
- progressData.forEach((item) => {
- progressMap[item.module_id] = {
- is_done: item.is_done,
- updated_at: item.updated_at
- };
- });
-
- setModules(modulesData);
- setProgress(progressMap);
- }
-
- return (
-
-
-
-
-
- {user && (
-
-
-
- Welcome, {user.user_metadata?.name || user.email.split("@")[0]}
-
-
-
- )}
-
- {user && (
-
- )}
-
-
- Modules Completed
- {(() => {
- const completedModules = modules.filter((mod) => progress[mod.id]?.is_done);
- if (completedModules.length > 0) {
- const modulesToShow = showAllCompleted ? completedModules : completedModules.slice(0, 3);
- return (
- <>
-
- {modulesToShow.map((mod) => (
-
-
-
-
{mod.title}
-
{mod.description}
-
-
-
-
Conquered : {new Date(progress[mod.id].updated_at).toLocaleDateString()}
-
-
-
- ))}
-
- {completedModules.length > 3 && (
-
- setShowAllCompleted(!showAllCompleted)}
- className="px-4 py-2 rounded-lg font-medium bg-gradient-to-br from-blue-600 to-blue-500 text-white hover:bg-blue-700 shadow-lg transition duration-300"
- >
- {showAllCompleted ? "Show Less" : "Load More"}
-
-
- )}
- >
- );
- } else {
- return (
-
-
- You haven't completed any modules yet.
-
-
- Start Learning
-
-
- );
- }
- })()}
-
-
-
-
-
-
-
- );
-}
\ No newline at end of file
diff --git a/app/globals.css b/app/globals.css
deleted file mode 100755
index be8c2fb60..000000000
--- a/app/globals.css
+++ /dev/null
@@ -1,173 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Source+Sans+3:ital,wght@0,300;0,400;0,600;0,700;1,400&family=Source+Serif+4:wght@400;600;700&display=swap');
-
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-/* ── Udemy Design System ── */
-:root {
- --udemy-purple: #a435f0;
- --udemy-purple-dark: #7d2be0;
- --udemy-purple-light: #c27cf7;
- --udemy-yellow: #f4c430;
- --udemy-bg: #ffffff;
- --udemy-surface: #f7f9fa;
- --udemy-border: #d1d7dc;
- --udemy-text: #1c1d1f;
- --udemy-muted: #6a6f73;
- --udemy-dark-bg: #1c1d1f;
- --udemy-dark-surface: #2d2f31;
- --udemy-dark-border: #3e4143;
- --udemy-dark-text: #f7f9fa;
- --udemy-dark-muted: #9e9e9e;
-}
-
-body {
- font-family: 'Source Sans 3', 'Source Sans Pro', ui-sans-serif, system-ui, sans-serif;
- color: var(--udemy-text);
- background: var(--udemy-bg);
-}
-
-h1, h2, h3, h4 {
- font-family: 'Source Serif 4', 'Source Serif Pro', Georgia, serif;
- font-weight: 700;
-}
-
-.dark body {
- color: var(--udemy-dark-text);
- background: var(--udemy-dark-bg);
-}
-
-html {
- scroll-behavior: smooth;
-}
-
-@keyframes float {
-
- 0%,
- 100% {
- transform: translateY(0);
- }
-
- 50% {
- transform: translateY(-10px);
- }
-}
-
-.animate-float {
- animation: float 4s ease-in-out infinite;
-}
-
-.animation-delay-1000 {
- animation-delay: 1s;
-}
-
-.animation-delay-2000 {
- animation-delay: 2s;
-}
-
-@keyframes float-slow {
-
- 0%,
- 100% {
- transform: translateY(0) translateX(0);
- }
-
- 50% {
- transform: translateY(-20px) translateX(10px);
- }
-}
-
-@keyframes float-slower {
-
- 0%,
- 100% {
- transform: translateY(0) translateX(0);
- }
-
- 50% {
- transform: translateY(20px) translateX(-10px);
- }
-}
-
-.animate-float-slow {
- animation: float-slow 8s ease-in-out infinite;
-}
-
-.animate-float-slower {
- animation: float-slower 10s ease-in-out infinite;
-}
-
-@keyframes draw-loop {
- 0% {
- stroke-dashoffset: 100;
- }
- 50% {
- stroke-dashoffset: 0;
- }
- 100% {
- stroke-dashoffset: 100;
- }
-}
-
-.animate-draw .path {
- stroke-dasharray: 100;
- stroke-dashoffset: 100;
- animation: draw-loop 2s ease-in-out infinite;
-}
-
-/* 404 Animation styles */
-@keyframes bounce-pin-1 {
- 0%, 100% { transform: translateY(0); }
- 50% { transform: translateY(-5px); }
-}
-.animate-bounce-pin-1 { animation: bounce-pin-1 2s ease-in-out infinite; }
-
-@keyframes bounce-pin-2 {
- 0%, 100% { transform: translateY(0); }
- 50% { transform: translateY(-8px); }
-}
-.animate-bounce-pin-2 { animation: bounce-pin-2 2.5s ease-in-out infinite; }
-
-@keyframes spark {
- 0%, 100% { opacity: 0; }
- 50% { opacity: 1; }
-}
-.animate-spark-1 { animation: spark 3s ease-in-out infinite; }
-.animate-spark-2 { animation: spark 3.5s ease-in-out infinite; }
-
-@keyframes swing {
- 0%, 100% { transform: translateX(-50%) rotate(-5deg); }
- 50% { transform: translateX(-50%) rotate(5deg); }
-}
-.animate-swing { animation: swing 4s ease-in-out infinite; }
-
-@keyframes pulse {
- 0%, 100% { opacity: 0; transform: translateX(-50%) scale(1); }
- 50% { opacity: 1; transform: translateX(-50%) scale(1.2); }
-}
-.animate-pulse { animation: pulse 3s ease-in-out infinite; }
-
-/* Page load animation */
-.page-loaded .page-loaded\:opacity-100 { opacity: 1; }
-.page-loaded .page-loaded\:translate-y-0 { transform: translateY(0); }
-
-@keyframes bot-vibe {
- 0%, 100% {
- transform: translateY(-1px) rotate(-1deg);
- }
- 50% {
- transform: translateY(1px) rotate(1deg);
- }
-}
-
-.glow-btn .glow-border {
- animation: shimmer-glow 2s ease-in-out infinite;
- background: linear-gradient(45deg, #3b82f6, #60a5fa);
- opacity: 0.4;
- filter: blur(10px);
-}
-
-.bot-wiggle {
- animation: bot-vibe 1s infinite;
-}
\ No newline at end of file
diff --git a/app/layout.jsx b/app/layout.jsx
deleted file mode 100755
index 81202a495..000000000
--- a/app/layout.jsx
+++ /dev/null
@@ -1,101 +0,0 @@
-import "./globals.css";
-import Script from "next/script";
-import { SpeedInsights } from "@vercel/speed-insights/next";
-import { AuthProvider } from "@/app/contexts/AuthContext";
-import { UserProvider } from "@/app/contexts/UserContext";
-import ClientLayoutWrapper from "@/app/components/ui/ClientLayoutWrapper";
-
-const GA_ID = process.env.NEXT_PUBLIC_GA_ID;
-
-export const metadata = {
- metadataBase: new URL("https://algobuddy.in"),
- title: "AlgoBuddy | Visualize & Learn DSA the Smart Way",
- description:
- "Master Data Structures and Algorithms with interactive visualizations. Perfect for students, beginners, and interview prep. Visualize Stack, Queue, Tree, Graph, Sorting & more.",
- keywords: [
- "AlgoBuddy",
- "DSA Visualizer",
- "Data Structures and Algorithms",
- "Visual DSA Tool",
- "Learn DSA Online",
- "DSA for Beginners",
- "DSA Practice",
- "Stack Visualizer",
- "Queue Visualizer",
- "Graph Visualizer",
- "Sorting Algorithms",
- ],
- authors: [{ name: "Sohan Rout" }],
- creator: "Sohan Rout",
- publisher: "AlgoBuddy",
- robots: "index, follow",
- icons: {
- icon: "/favicon.svg",
- },
- openGraph: {
- title: "AlgoBuddy | Visualize & Learn DSA the Smart Way",
- description:
- "Interactive platform to visualize and learn DSA concepts easily. Great for students and interview preparation.",
- url: "https://algobuddy.in/",
- siteName: "AlgoBuddy",
- images: [
- {
- url: "/og.png",
- width: 1200,
- height: 630,
- alt: "AlgoBuddy Preview Image",
- },
- ],
- locale: "en_US",
- type: "website",
- },
- twitter: {
- card: "summary_large_image",
- title: "AlgoBuddy | Learn DSA the Smart Way",
- description:
- "Visualize algorithms like Stack, Queue, Graphs, and Sorting in real-time. Learn DSA interactively.",
- images: ["/og.png"],
- },
-};
-
-export default async function RootLayout({ children }) {
- const session = null; // auth is handled client-side via AuthContext
-
- return (
-
-
-
-
-
-
- {/* Google Analytics Script */}
- {GA_ID && (
- <>
-
-
- >
- )}
-
-
-
-
- {children}
-
-
-
-
-
- );
-}
diff --git a/app/login/page.jsx b/app/login/page.jsx
deleted file mode 100755
index 6db4d9ad7..000000000
--- a/app/login/page.jsx
+++ /dev/null
@@ -1,280 +0,0 @@
-"use client";
-import { useState, useEffect } from "react";
-import { supabase } from "../../lib/supabase";
-import { useRouter } from "next/navigation";
-import {
- FiMail,
- FiLock,
- FiUser,
- FiLogIn,
- FiUserPlus,
- FiSun,
- FiMoon,
-} from "react-icons/fi";
-import { motion } from "framer-motion";
-import Link from "next/link";
-import dynamic from "next/dynamic";
-
-const Turnstile = dynamic(
- () => import("@marsidev/react-turnstile").then((mod) => mod.Turnstile),
- { ssr: false },
-);
-
-export default function LoginPage() {
- const [email, setEmail] = useState("");
- const [password, setPassword] = useState("");
- const [name, setName] = useState("");
- const [isLogin, setIsLogin] = useState(true);
- const [loading, setLoading] = useState(false);
- const [error, setError] = useState("");
- const [theme, setTheme] = useState("light");
- const [captchaToken, setCaptchaToken] = useState(null);
- const router = useRouter();
-
- useEffect(() => {
- const savedTheme = localStorage.getItem("theme") || "light";
- setTheme(savedTheme);
- document.documentElement.classList.toggle("dark", savedTheme === "dark");
- }, []);
-
- const toggleTheme = () => {
- const newTheme = theme === "light" ? "dark" : "light";
- setTheme(newTheme);
- localStorage.setItem("theme", newTheme);
- document.documentElement.classList.toggle("dark", newTheme === "dark");
- };
-
- const handleAuth = async () => {
- setLoading(true);
- setError("");
-
- try {
- if (!captchaToken) throw new Error("Please complete captcha");
-
- if (isLogin) {
- // Verify captcha first via API route
- const verifyRes = await fetch("/api/auth", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- email,
- password,
- captchaToken,
- action: "login",
- }),
- });
- const verifyData = await verifyRes.json();
- if (!verifyData.success)
- throw new Error(verifyData.message || "Captcha verification failed");
-
- // After captcha verified, login using frontend anon key
- const { error } = await supabase.auth.signInWithPassword({
- email,
- password,
- });
- if (error) throw error;
-
- router.push("/dashboard");
- } else {
- // Signup flow remains the same
- const res = await fetch("/api/auth", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- email,
- password,
- captchaToken,
- action: "signup",
- name,
- }),
- });
- const data = await res.json();
- if (!data.success) throw new Error(data.message || "Signup failed");
- alert(data.message);
- setIsLogin(true);
- }
- } catch (err) {
- setError(err.message || "Something went wrong");
- } finally {
- setLoading(false);
- }
- };
-
- const handleGoogleSignIn = async () => {
- const { error } = await supabase.auth.signInWithOAuth({
- provider: "google",
- });
- if (error) console.error("Google sign-in error:", error.message);
- };
-
- return (
-
-
- {/* Header */}
-
-
-
- {isLogin ? "Welcome Back" : "Create Account"}
-
-
- {isLogin
- ? "Sign in to access your dashboard"
- : "Join us to get started"}
-
-
-
-
-
- {/* Google OAuth */}
-
-
- Continue with Google
-
-
-
-
-
-
- {error && (
-
- {error}
-
- )}
-
- {/* Form */}
-
-
-
-
-
-
setEmail(e.target.value)}
- />
-
-
-
-
-
-
-
setPassword(e.target.value)}
- />
-
-
- {!isLogin && (
-
-
-
-
-
setName(e.target.value)}
- />
-
- )}
-
- {/* Turnstile for both login and signup */}
-
- setCaptchaToken(token)}
- />
-
-
-
- {loading ? (
- "Processing..."
- ) : isLogin ? (
- <>
- Continue
- >
- ) : (
- <>
- Continue
- >
- )}
-
-
-
- {/* Switch forms */}
-
- {isLogin ? (
-
- Don't have an account?{" "}
- setIsLogin(false)}
- className="text-udemy-purple dark:text-udemy-purple-light hover:underline font-semibold"
- >
- Sign up
-
-
- ) : (
-
- Already have an account?{" "}
- setIsLogin(true)}
- className="text-udemy-purple dark:text-udemy-purple-light hover:underline font-semibold"
- >
- Sign in
-
-
- )}
-
-
-
- By continuing, you agree to our{" "}
-
- Terms of Service
- {" "}
- and{" "}
-
- Privacy Policy
-
-
-
-
-
- );
-}
diff --git a/app/not-found.jsx b/app/not-found.jsx
deleted file mode 100755
index ed1b31c3c..000000000
--- a/app/not-found.jsx
+++ /dev/null
@@ -1,94 +0,0 @@
-"use client";
-import { useEffect } from 'react';
-import { useRouter } from 'next/navigation';
-import { FiArrowLeft, FiHome, FiZap } from 'react-icons/fi';
-
-const NotFoundPage = () => {
- const router = useRouter();
-
- useEffect(() => {
- if (typeof window !== 'undefined' && window.gtag) {
- window.gtag('event', 'page_view', {
- page_title: '404 Not Found',
- page_path: window.location.pathname,
- });
- }
- }, []);
-
- useEffect(() => {
- document.body.classList.add('page-loaded');
- }, []);
-
- return (
-
- {/* Animated background elements */}
-
-
-
- {/* Broken plug animation */}
-
- {/* Plug base */}
-
-
- {/* Plug pins - broken animation */}
-
-
- {/* Red cross icon */}
-
-
-
-
-
- {/* Content */}
-
-
- Connection Lost
-
-
- The page you're trying to reach seems to be unplugged or doesn't exist.
-
-
-
- {/* Action buttons */}
-
-
router.back()}
- className="flex items-center justify-center gap-2 px-6 py-3 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 rounded-lg font-medium transition-all duration-300 hover:-translate-y-0.5 hover:shadow-md"
- >
-
- Go Back
-
-
-
- Return Home
-
-
-
- {/* Footer note */}
-
- Still stuck? Contact support
-
-
-
- );
-};
-
-export default NotFoundPage;
\ No newline at end of file
diff --git a/app/page.jsx b/app/page.jsx
deleted file mode 100755
index b5fecba6d..000000000
--- a/app/page.jsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import Navbar from "@/app/components/navbar";
-import Hero from "@/app/components/hero";
-import ConceptsSection from "@/app/components/ConceptsSection";
-import PersonalizedSection from "@/app/components/PersonalizedSection";
-import Footer from "@/app/components/footer";
-import BottomAd from "./components/ads/bottom";
-
-export const metadata = {
- title: "AlgoBuddy | Visualize & Learn DSA the Smart Way",
- description:
- "Master Data Structures and Algorithms with interactive visualizations. Perfect for students, beginners, and interview prep. Visualize Stack, Queue, Tree, Graph, Sorting & more.",
- keywords: [
- "DSA Visualizer",
- "Algorithm Visualizer",
- "Learn DSA",
- "Practice DSA Problems",
- "DSA Quizzes",
- "Interactive DSA",
- "Sorting Algorithms",
- "Searching Algorithms",
- "Stack",
- "Queue",
- "Tree",
- "Linked List",
- "Heap Sort",
- "Tree Traversal",
- "Linear Search",
- "Bubble Sort",
- "Singly Linked List",
- "Doubly Linked List",
- "Circular Linked List",
- "Data Structures for Beginners",
- "DSA Practice Platform",
- "Quiz for DSA",
- "Algorithm Quiz",
- "Interactive Algorithm Quiz",
- "Learn DSA with Quizzes",
- ],
- robots: "index, follow",
-};
-
-export default function Home() {
- return (
- <>
-
- >
- );
-}
diff --git a/app/visualizer/VisualizerClient.jsx b/app/visualizer/VisualizerClient.jsx
deleted file mode 100755
index 07733ae09..000000000
--- a/app/visualizer/VisualizerClient.jsx
+++ /dev/null
@@ -1,737 +0,0 @@
-"use client";
-import { useState, useMemo } from "react";
-import Link from "next/link";
-import { motion, AnimatePresence } from "framer-motion";
-import { FiArrowLeft, FiSearch, FiChevronRight } from "react-icons/fi";
-
-/* ─── colour + icon theme per DS ─── */
-const DS_THEME = {
- Array: {
- color: "#a435f0",
- bg: "#faf5ff",
- darkBg: "#160d22",
- border: "#e9d5ff",
- label: "7 algorithms",
- bars: [65, 30, 80, 45, 55, 20, 70],
- icon: (c) => (
-
-
-
- ),
- },
- Stack: {
- color: "#2563eb",
- bg: "#eff6ff",
- darkBg: "#0d1627",
- border: "#bfdbfe",
- label: "8 algorithms",
- stack: ["push(42)", "push(17)", "peek → 17"],
- icon: (c) => (
-
-
-
- ),
- },
- Queue: {
- color: "#059669",
- bg: "#f0fdf4",
- darkBg: "#0d1f14",
- border: "#d1fae5",
- label: "10 algorithms",
- icon: (c) => (
-
-
-
- ),
- },
- "Linked List": {
- color: "#d97706",
- bg: "#fffbeb",
- darkBg: "#1a1506",
- border: "#fde68a",
- label: "10 algorithms",
- icon: (c) => (
-
-
-
- ),
- },
- Tree: {
- color: "#7c3aed",
- bg: "#faf5ff",
- darkBg: "#160d22",
- border: "#e9d5ff",
- label: "20 algorithms",
- icon: (c) => (
-
-
-
- ),
- },
- Graph: {
- color: "#dc2626",
- bg: "#fef2f2",
- darkBg: "#1f0d0d",
- border: "#fecaca",
- label: "8 algorithms",
- icon: (c) => (
-
-
-
- ),
- },
-};
-const getTheme = (t) =>
- DS_THEME[t] || {
- icon: (c) => (
-
-
-
- ),
- color: "#6b7280",
- bg: "#f9fafb",
- darkBg: "#111",
- border: "#e5e7eb",
- label: "",
- };
-
-/* ═══════════════════════════════════════
- Mini Visuals for cards
- ═══════════════════════════════════════ */
-function ArrayMiniViz({ color }) {
- const bars = [65, 30, 80, 45, 55, 20, 70];
- const highlight = 2;
- return (
-
- {bars.map((h, i) => (
-
- ))}
-
- );
-}
-
-function StackMiniViz({ color }) {
- const items = ["8", "17", "42"];
- return (
-
- {items.map((v, i) => (
-
- {v}
-
- ))}
-
- );
-}
-
-function QueueMiniViz({ color }) {
- const items = ["A", "B", "C", "D"];
- return (
-
- {items.map((v, i) => (
-
- {v}
-
- ))}
-
- →
-
-
- );
-}
-
-function LinkedListMiniViz({ color }) {
- const nodes = [7, 3, 9, 1];
- return (
-
- {nodes.map((v, i) => (
-
-
- {v}
-
- {i < nodes.length - 1 && (
-
-
-
-
-
-
-
-
- )}
-
- ))}
-
- );
-}
-
-function TreeMiniViz({ color }) {
- return (
-
- {/* edges */}
-
-
-
-
- {/* nodes */}
-
-
-
-
-
- {/* labels */}
-
- 8
-
-
- 3
-
-
- 10
-
-
- );
-}
-
-function GraphMiniViz({ color }) {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-const MINI_VIZ = {
- Array: ArrayMiniViz,
- Stack: StackMiniViz,
- Queue: QueueMiniViz,
- "Linked List": LinkedListMiniViz,
- Tree: TreeMiniViz,
- Graph: GraphMiniViz,
-};
-
-/* ═══════════════════════════════════════
- DS Card — homepage-style window card
- ═══════════════════════════════════════ */
-function DSCard({ section, theme, onClick, delay }) {
- const MiniViz = MINI_VIZ[section.title];
- const count = section.subsections
- ? section.subsections.reduce((a, s) => a + s.items.length, 0)
- : 0;
-
- return (
-
-
- {/* title bar — like homepage code cards */}
-
-
-
-
-
- {section.title.toLowerCase().replace(/\s/g, "")}.js
-
-
-
- {/* card body */}
-
- {/* icon + title */}
-
-
- {theme.icon(theme.color)}
-
-
-
- {section.title}
-
-
- {count} algorithm{count !== 1 ? "s" : ""} to explore
-
-
-
-
- {/* description */}
-
- {section.desc}
-
-
- {/* mini visualization */}
- {MiniViz && (
-
-
-
- )}
-
- {/* CTA pill — like homepage buttons */}
-
- Explore {section.title}
-
-
-
-
-
- );
-}
-
-/* ═══════════════════════════════════════
- Module View — drill-down page
- ═══════════════════════════════════════ */
-function ModuleView({ section, theme, onBack }) {
- const count = section.subsections
- ? section.subsections.reduce((a, s) => a + s.items.length, 0)
- : 0;
-
- return (
-
- {/* hero banner for this DS */}
-
-
- Back to all topics
-
-
-
-
- {theme.icon(theme.color)}
-
-
-
- {section.title}
-
-
- {count} algorithm{count !== 1 ? "s" : ""} · {section.desc}
-
-
-
-
-
- {/* subsections */}
-
- {section.subsections?.map((sub, si) => (
-
-
- {sub.title}
-
-
- {sub.items.map((item, ii) => (
-
-
-
- {ii + 1}
-
-
- {item.name}
-
-
-
-
- ))}
-
-
- ))}
-
-
- );
-}
-
-/* ═══════════════════════════════════════
- Main Client Component
- ═══════════════════════════════════════ */
-export default function VisualizerClient({ initialSections }) {
- const [activeSection, setActiveSection] = useState(null);
- const [search, setSearch] = useState("");
-
- /* ── filter sections ── */
- const filtered = useMemo(() => {
- if (!search.trim()) return initialSections;
- const q = search.toLowerCase();
- return initialSections
- .map((sec) => {
- const titleHit = sec.title.toLowerCase().includes(q);
- const subs = sec.subsections
- ?.map((sub) => {
- const subHit = sub.title.toLowerCase().includes(q);
- const items = sub.items.filter((i) =>
- i.name.toLowerCase().includes(q),
- );
- return { ...sub, items: subHit ? sub.items : items };
- })
- .filter((sub) => sub.items.length > 0);
- return {
- ...sec,
- subsections: subs,
- _hit: titleHit || (subs && subs.length > 0),
- };
- })
- .filter((s) => s._hit);
- }, [search, initialSections]);
-
- /* ── flat results for search ── */
- const flatResults = useMemo(() => {
- if (!search.trim()) return [];
- const q = search.toLowerCase();
- const r = [];
- initialSections.forEach((sec) =>
- sec.subsections?.forEach((sub) =>
- sub.items.forEach((item) => {
- if (item.name.toLowerCase().includes(q))
- r.push({ ...item, ds: sec.title });
- }),
- ),
- );
- return r;
- }, [search, initialSections]);
-
- return (
-
- {/* ═══════ CONTENT AREA ═══════ */}
-
-
- {/* page heading + search */}
-
-
- Algorithm Visualizer
-
-
- Pick any data structure, tap an algorithm, and watch it run step
- by step. Learning DSA has never been this fun.
-
-
-
-
- {/* ─── SEARCH RESULTS ─── */}
- {search.trim() ? (
-
- {flatResults.length > 0 ? (
-
-
- {flatResults.length} result
- {flatResults.length !== 1 ? "s" : ""}
-
-
- {flatResults.map((item, i) => {
- const t = getTheme(item.ds);
- return (
-
-
- {t.icon(t.color)}
-
-
-
- {item.name}
-
-
- {item.ds}
-
-
-
-
- );
- })}
-
-
- ) : (
-
-
🔍
-
- No results found
-
-
- Try a different search term
-
-
- )}
-
- ) : /* ─── MODULE DRILL-DOWN ─── */
- activeSection ? (
- setActiveSection(null)}
- />
- ) : (
- /* ─── MAIN GRID ─── */
-
-
- {filtered.map((section, i) => (
- setActiveSection(section)}
- delay={i * 0.07}
- />
- ))}
-
-
- {filtered.length === 0 && (
-
-
🔍
-
- No topics found
-
-
- Try a different search term
-
-
- )}
-
- )}
-
-
-
-
- );
-}
diff --git a/app/visualizer/linkedList/operations/comparison/animation.jsx b/app/visualizer/linkedList/operations/comparison/animation.jsx
deleted file mode 100755
index c6e9bc376..000000000
--- a/app/visualizer/linkedList/operations/comparison/animation.jsx
+++ /dev/null
@@ -1,302 +0,0 @@
-"use client";
-import React, { useState, useRef, useEffect } from 'react';
-import { gsap } from 'gsap';
-import Footer from '@/app/components/footer';
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Content from "@/app/visualizer/linkedList/operations/comparison/content";
-import Quiz from '@/app/visualizer/linkedList/operations/comparison/quiz';
-import CodeBlock from "@/app/visualizer/linkedList/operations/comparison/codeBlock";
-import BackToTop from '@/app/components/ui/backtotop';
-import GoBackButton from "@/app/components/ui/goback";
-
-const LinkedListComparison = () => {
- const [list1, setList1] = useState([]);
- const [list2, setList2] = useState([]);
- const [isAnimating, setIsAnimating] = useState(false);
- const [currentPointers, setCurrentPointers] = useState({ list1: 0, list2: 0 });
- const [comparisonResult, setComparisonResult] = useState(null);
- const list1Refs = useRef([]);
- const list2Refs = useRef([]);
- const containerRef = useRef(null);
- const animationTimeline = useRef(gsap.timeline());
-
- // Generate random linked list with realistic values
- const generateRandomList = (setList) => {
- const size = Math.floor(Math.random() * 3) + 3; // 3-5 nodes
- const values = Array.from({ length: size }, (_, i) => {
- const base = Math.floor(Math.random() * 20) + 1;
- return base + i * 5; // Ensure some order but not perfectly sorted
- }).sort((a, b) => a - b); // Sort the values
-
- const newList = values.map((value, index) => ({
- value,
- id: Date.now() + index + Math.random(),
- next: index < size - 1 ? `0x${(1000 + index).toString(16).padStart(4, '0')}` : 'NULL'
- }));
-
- setList(newList);
- };
-
- // Reset handler
- const handleReset = () => {
- gsap.killTweensOf("*");
- animationTimeline.current.clear();
- setList1([]);
- setList2([]);
- setIsAnimating(false);
- setCurrentPointers({ list1: 0, list2: 0 });
- setComparisonResult(null);
- list1Refs.current = [];
- list2Refs.current = [];
- };
-
- // Animate the comparison process step-by-step
- const animateComparison = async () => {
- if (isAnimating || list1.length === 0 || list2.length === 0) return;
-
- setIsAnimating(true);
- animationTimeline.current.clear();
- setCurrentPointers({ list1: 0, list2: 0 });
- setComparisonResult(null);
-
- const maxLength = Math.max(list1.length, list2.length);
- let areSame = true;
-
- for (let i = 0; i < maxLength; i++) {
- setCurrentPointers({ list1: i, list2: i });
-
- const node1 = list1[i];
- const node2 = list2[i];
-
- const highlightNodes = [list1Refs.current[i], list2Refs.current[i]].filter(Boolean);
-
- animationTimeline.current.to(highlightNodes, {
- scale: 1.3,
- duration: 0.4,
- ease: 'power1.inOut'
- });
-
- await new Promise(resolve => setTimeout(resolve, 600));
-
- if (!node1 || !node2 || node1.value !== node2.value) {
- areSame = false;
- setComparisonResult({
- match: false,
- index: i,
- value1: node1?.value,
- value2: node2?.value,
- });
- break;
- }
-
- animationTimeline.current.to(highlightNodes, {
- scale: 1,
- duration: 0.3
- });
- }
-
- if (areSame) {
- setComparisonResult({ match: true });
- }
-
- animationTimeline.current.call(() => {
- setIsAnimating(false);
- });
- };
-
- // Update refs when lists change
- useEffect(() => {
- list1Refs.current = list1Refs.current.slice(0, list1.length);
- list2Refs.current = list2Refs.current.slice(0, list2.length);
- }, [list1, list2]);
-
- return (
-
-
-
-
-
-
-
- Linked List Comparison
-
-
-
-
- Visualize comparison of two linked lists node by node
-
-
- {/* Controls - Responsive */}
-
-
-
-
- generateRandomList(setList1)}
- disabled={isAnimating}
- className="bg-emerald-600 hover:bg-emerald-700 text-white px-4 py-2 sm:px-6 sm:py-3 rounded-lg disabled:bg-gray-400 w-full"
- >
- Generate List 1
-
- generateRandomList(setList2)}
- disabled={isAnimating}
- className="bg-emerald-600 hover:bg-emerald-700 text-white px-4 py-2 sm:px-6 sm:py-3 rounded-lg disabled:bg-gray-400 w-full"
- >
- Generate List 2
-
-
-
-
- {isAnimating ? "Comparing..." : "Compare Lists"}
-
-
- Reset All
-
-
-
-
-
-
- {/* Legend - Responsive */}
-
-
- {comparisonResult && (
-
- {comparisonResult.match ? (
-
✅ Both linked lists are the same.
- ) : (
-
- Lists differ at node {comparisonResult.index + 1} : List 1 has {comparisonResult.value1 ?? 'NULL'} and List 2 has {comparisonResult.value2 ?? 'NULL'}
-
- )}
-
- )}
-
- {/* Visualization Area */}
-
- {/* List 1 */}
-
-
List 1 {currentPointers.list1 < list1.length && `(Current: ${currentPointers.list1 + 1})`}
-
- {list1.length === 0 ? (
-
- Generate List 1 to begin
-
- ) : (
-
- {list1.map((node, index) => (
-
- (list1Refs.current[index] = el)}
- className={`node flex flex-col items-center justify-center bg-emerald-600 text-white text-lg w-20 h-16 rounded-md shadow-md transition-all ${
- index === currentPointers.list1 && isAnimating ? 'ring-4 ring-emerald-300 scale-110' : ''
- }`}
- >
- {node.value}
-
{node.next}
-
- {index < list1.length - 1 && (
-
-
-
- )}
-
- ))}
-
- )}
-
-
-
- {/* List 2 */}
-
-
List 2 {currentPointers.list2 < list2.length && `(Current: ${currentPointers.list2 + 1})`}
-
- {list2.length === 0 ? (
-
- Generate List 2 to continue
-
- ) : (
-
- {list2.map((node, index) => (
-
- (list2Refs.current[index] = el)}
- className={`node flex flex-col items-center justify-center bg-emerald-600 text-white text-lg w-20 h-16 rounded-md shadow-md transition-all ${
- index === currentPointers.list2 && isAnimating ? 'ring-4 ring-emerald-300 scale-110' : ''
- }`}
- >
- {node.value}
-
{node.next}
-
- {index < list2.length - 1 && (
-
-
-
- )}
-
- ))}
-
- )}
-
-
-
-
-
- Test Your Knowledge Before Moving Forward!
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default LinkedListComparison;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/comparison/codeBlock.jsx b/app/visualizer/linkedList/operations/comparison/codeBlock.jsx
deleted file mode 100755
index fbd10bba5..000000000
--- a/app/visualizer/linkedList/operations/comparison/codeBlock.jsx
+++ /dev/null
@@ -1,159 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-import CodeExamples from "@/app/visualizer/linkedList/operations/comparison/data/codeExamples.json";
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
-const codeExamples = CodeExamples;
-
- return (
-
setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Linked List Comparison Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/comparison/data/codeExamples.json b/app/visualizer/linkedList/operations/comparison/data/codeExamples.json
deleted file mode 100755
index f968730bb..000000000
--- a/app/visualizer/linkedList/operations/comparison/data/codeExamples.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "javascript": "class Node {\n constructor(data) {\n this.data = data;\n this.next = null;\n }\n}\n\nfunction compareLists(l1, l2) {\n while (l1 && l2) {\n if (l1.data !== l2.data) return false;\n l1 = l1.next;\n l2 = l2.next;\n }\n return l1 === null && l2 === null;\n}",
- "python": "class Node:\n def __init__(self, data):\n self.data = data\n self.next = None\n\ndef compare_lists(l1, l2):\n while l1 and l2:\n if l1.data != l2.data:\n return False\n l1 = l1.next\n l2 = l2.next\n return l1 is None and l2 is None",
- "java": "class Node {\n int data;\n Node next;\n Node(int data) {\n this.data = data;\n this.next = null;\n }\n}\n\npublic class CompareLists {\n public static boolean compare(Node l1, Node l2) {\n while (l1 != null && l2 != null) {\n if (l1.data != l2.data) return false;\n l1 = l1.next;\n l2 = l2.next;\n }\n return l1 == null && l2 == null;\n }\n}",
- "c": "#include
\n#include \n#include \n\ntypedef struct Node {\n int data;\n struct Node* next;\n} Node;\n\nbool compareLists(Node* l1, Node* l2) {\n while (l1 && l2) {\n if (l1->data != l2->data) return false;\n l1 = l1->next;\n l2 = l2->next;\n }\n return l1 == NULL && l2 == NULL;\n}",
- "cpp": "#include \nusing namespace std;\n\nclass Node {\npublic:\n int data;\n Node* next;\n Node(int d) : data(d), next(nullptr) {}\n};\n\nbool compareLists(Node* l1, Node* l2) {\n while (l1 && l2) {\n if (l1->data != l2->data) return false;\n l1 = l1->next;\n l2 = l2->next;\n }\n return l1 == nullptr && l2 == nullptr;\n}"
-}
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/comparison/data/questions.json b/app/visualizer/linkedList/operations/comparison/data/questions.json
deleted file mode 100755
index 07a432903..000000000
--- a/app/visualizer/linkedList/operations/comparison/data/questions.json
+++ /dev/null
@@ -1,112 +0,0 @@
-[
- {
- "question": "What is the primary goal when comparing two linked lists?",
- "options": [
- "To merge them into one list",
- "To determine if they are structurally and value-wise identical",
- "To reverse both lists",
- "To delete duplicate nodes"
- ],
- "correctAnswer": 1,
- "explanation": "The comparison aims to check whether the two linked lists have the same sequence of values in the same order."
- },
- {
- "question": "What condition indicates that two linked lists are not equal?",
- "options": [
- "Both have the same head node",
- "One list is longer than the other",
- "Both lists have the same length",
- "Both are empty"
- ],
- "correctAnswer": 1,
- "explanation": "If one list ends before the other, they differ in length and are not equal."
- },
- {
- "question": "What approach is commonly used to compare two linked lists?",
- "options": [
- "Recursive traversal",
- "Simultaneous traversal using two pointers",
- "Storing values in a hash map",
- "Binary search"
- ],
- "correctAnswer": 1,
- "explanation": "The most common method is using two pointers to traverse both lists node by node and compare their values."
- },
- {
- "question": "What should be checked at each step during linked list comparison?",
- "options": [
- "If node values are equal",
- "If both nodes are at the tail",
- "If the next pointers match",
- "If memory addresses are the same"
- ],
- "correctAnswer": 0,
- "explanation": "At each step, the values of corresponding nodes should be compared to determine equality."
- },
- {
- "question": "What does it mean if both pointers reach null at the same time during comparison?",
- "options": [
- "The lists are not equal",
- "An error occurred",
- "Both lists are equal",
- "One list is circular"
- ],
- "correctAnswer": 2,
- "explanation": "If both lists end simultaneously without any mismatches, they are equal."
- },
- {
- "question": "What is the time complexity of comparing two linked lists with n nodes each?",
- "options": [
- "O(n^2)",
- "O(log n)",
- "O(n)",
- "O(1)"
- ],
- "correctAnswer": 2,
- "explanation": "Each node is visited once during comparison, resulting in linear time complexity O(n)."
- },
- {
- "question": "Which case is a valid edge case in linked list comparison?",
- "options": [
- "One list is empty",
- "Both lists contain the same object references",
- "Both lists are infinite",
- "Both lists are sorted"
- ],
- "correctAnswer": 0,
- "explanation": "An important edge case is when one list is empty and the other is not."
- },
- {
- "question": "How should object nodes with same values but different references be treated in comparison?",
- "options": [
- "As equal if their values match",
- "As unequal always",
- "Only compare memory addresses",
- "Skip such nodes"
- ],
- "correctAnswer": 0,
- "explanation": "Linked list comparison typically checks for value equality, not memory address equality."
- },
- {
- "question": "Why is it important to compare both length and values when comparing two linked lists?",
- "options": [
- "Length indicates memory usage",
- "Lists must be sorted first",
- "To ensure complete equality",
- "To avoid stack overflow"
- ],
- "correctAnswer": 2,
- "explanation": "Even if values match in part, differing lengths imply inequality. Full comparison ensures both length and value match."
- },
- {
- "question": "What will the comparison function return if the lists differ at any node?",
- "options": [
- "True",
- "Null",
- "False",
- "0"
- ],
- "correctAnswer": 2,
- "explanation": "The comparison function returns false as soon as a mismatch is detected."
- }
-]
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/comparison/page.jsx b/app/visualizer/linkedList/operations/comparison/page.jsx
deleted file mode 100755
index 1ee53e477..000000000
--- a/app/visualizer/linkedList/operations/comparison/page.jsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import Animation from "@/app/visualizer/linkedList/operations/comparison/animation";
-import Navbar from "@/app/components/navbarinner";
-
-export const metadata = {
- title: 'Linked List Comparison Algorithm | Interactive Visualization & Step-by-Step Guide',
- description:
- 'Learn how comparison works in Linked Lists with interactive animations, detailed explanations, and hands-on practice. Visualize each step of the comparison process and master linked list algorithms efficiently.',
- keywords: [
- 'Linked List Comparison',
- 'Comparison Animation Linked List',
- 'Visualize Comparison in Linked List',
- 'Linked List Algorithm',
- 'DSA Linked List Comparison',
- 'Linked List Comparison Visualization',
- 'Interactive Linked List',
- 'Comparison Step-by-Step',
- 'Linked List Learning',
- 'Data Structures Animation',
- 'DSA Practice Linked List',
- 'Comparison Code Example',
- 'Linked List Tutorial',
- 'Comparison using C',
- 'Comparison using Java',
- 'Comparison using Javascript',
- 'Comparison using Python',
- 'Comparison using linked list',
- ],
- robots: 'index, follow',
-};
-
-export default function Page() {
- return (
- <>
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/comparison/quiz.jsx b/app/visualizer/linkedList/operations/comparison/quiz.jsx
deleted file mode 100755
index c37e51aeb..000000000
--- a/app/visualizer/linkedList/operations/comparison/quiz.jsx
+++ /dev/null
@@ -1,398 +0,0 @@
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import Questions from "@/app/visualizer/linkedList/operations/comparison/data/questions.json"
-
-const Quiz = () => {
-const questions = Questions;
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Comparing Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default Quiz;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/deletion/animation.jsx b/app/visualizer/linkedList/operations/deletion/animation.jsx
deleted file mode 100755
index 8bf47ab54..000000000
--- a/app/visualizer/linkedList/operations/deletion/animation.jsx
+++ /dev/null
@@ -1,257 +0,0 @@
-"use client";
-import React, { useState, useRef, useEffect } from 'react';
-import { gsap } from 'gsap';
-import Footer from '@/app/components/footer';
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Content from "@/app/visualizer/linkedList/operations/deletion/content";
-import Quiz from '@/app/visualizer/linkedList/operations/deletion/quiz';
-import CodeBlock from "@/app/visualizer/linkedList/operations/deletion/codeBlock";
-import BackToTop from '@/app/components/ui/backtotop';
-import GoBackButton from "@/app/components/ui/goback";
-
-const LinkedListVisualizer = () => {
- const [inputValue, setInputValue] = useState('');
- const [list, setList] = useState([]);
- const [isAnimating, setIsAnimating] = useState(false);
- const nodeRefs = useRef([]);
- const containerRef = useRef(null);
-
- // Generate a random hex address for demonstration
- const generateAddress = () => {
- return '0x' + Math.floor(Math.random() * 0x10000).toString(16).toUpperCase().padStart(4, '0');
- };
-
- const addNode = () => {
- if (!inputValue || isAnimating) return;
- setIsAnimating(true);
-
- const newNode = {
- value: inputValue,
- id: Date.now(),
- address: generateAddress(),
- next: 'NULL' // Initialize as NULL by default
- };
-
- // Create temporary node for animation
- const tempNode = document.createElement('div');
- tempNode.className = 'node flex border border-gray-300 absolute';
- tempNode.innerHTML = `
- ${inputValue}
- NULL
- `;
- containerRef.current.appendChild(tempNode);
-
- // Position at the top center
- gsap.set(tempNode, {
- x: window.innerWidth / 2 - 100,
- y: -100,
- opacity: 0,
- });
-
- // Calculate final position
- const finalX = 50 + (list.length * 220);
-
- // Animation sequence
- gsap.to(tempNode, {
- opacity: 1,
- y: 50,
- duration: 0.5,
- onComplete: () => {
- gsap.to(tempNode, {
- x: finalX,
- duration: 1,
- onComplete: () => {
- // Update the previous node's next pointer to point to this new node
- if (list.length > 0) {
- const updatedList = [...list];
- updatedList[updatedList.length - 1].next = newNode.address;
- setList([...updatedList, newNode]);
- } else {
- setList([newNode]);
- }
- setIsAnimating(false);
- tempNode.remove();
- }
- });
- }
- });
- };
-
- const deleteNode = () => {
- if (list.length === 0 || isAnimating) return;
- setIsAnimating(true);
-
- const nodeToDelete = nodeRefs.current[list.length - 1];
-
- // Animation for deletion
- gsap.to(nodeToDelete, {
- opacity: 0,
- y: -50,
- duration: 0.5,
- onComplete: () => {
- if (list.length > 1) {
- const updatedList = [...list];
- updatedList.pop(); // Remove last node
- updatedList[updatedList.length - 1].next = 'NULL'; // Update new last node's next pointer
- setList(updatedList);
- } else {
- setList([]); // Empty the list if only one node
- }
- setIsAnimating(false);
- }
- });
- };
-
- const resetList = () => {
- if (isAnimating) return;
-
- // Animate all nodes out
- gsap.to(nodeRefs.current, {
- opacity: 0,
- y: -50,
- duration: 0.5,
- stagger: 0.1,
- onComplete: () => {
- setList([]);
- }
- });
- };
-
- // Update node refs when list changes
- useEffect(() => {
- if (list.length > 0 && nodeRefs.current.length === list.length) {
- gsap.from(nodeRefs.current, {
- opacity: 0,
- y: 20,
- duration: 0.5,
- stagger: 0.1,
- });
- }
- }, [list]);
-
- return (
-
-
-
-
-
-
-
- Linked List Deletion
-
-
-
-
- Visualize Linked List Deletion Operation
-
-
- {/* Input Form */}
-
-
-
- setInputValue(e.target.value)}
- className="flex-1 p-3 border bg-white dark:bg-gray-700 rounded-lg"
- placeholder="Enter value"
- disabled={isAnimating}
- />
-
- {isAnimating ? 'Adding...' : 'Add Node'}
-
-
-
-
- {isAnimating ? 'Deleting...' : 'Delete Last Node'}
-
-
- Reset
-
-
-
-
-
- {/* Legend - Responsive */}
-
-
- {/* Visualization Area */}
-
-
- {list.length === 0 ? (
-
- No nodes added yet
-
- ) : (
-
- {list.map((node, index) => (
-
-
(nodeRefs.current[index] = el)}
- className="node flex"
- >
-
- {node.value}
-
-
- {node.next}
-
-
- {index < list.length - 1 && (
-
→
- )}
-
- ))}
-
- )}
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default LinkedListVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/deletion/codeBlock.jsx b/app/visualizer/linkedList/operations/deletion/codeBlock.jsx
deleted file mode 100755
index 9b0b88b04..000000000
--- a/app/visualizer/linkedList/operations/deletion/codeBlock.jsx
+++ /dev/null
@@ -1,159 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-import CodeExamples from "@/app/visualizer/linkedList/operations/deletion/data/codeExamples.json";
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
-const codeExamples = CodeExamples;
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Linked List Deletion Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/deletion/content.jsx b/app/visualizer/linkedList/operations/deletion/content.jsx
deleted file mode 100755
index 0f7ece6f1..000000000
--- a/app/visualizer/linkedList/operations/deletion/content.jsx
+++ /dev/null
@@ -1,405 +0,0 @@
-const content = () => {
- const overview = [
- `Linked List deletion involves removing nodes from the linked data structure at various positions. Unlike arrays, linked lists allow efficient deletion at any point without requiring shifting of remaining elements.`,
- `Deletion is a fundamental operation that enables dynamic modification of the list. The efficiency varies based on deletion position, from O(1) for head to O(n) for arbitrary positions or tail (without tail pointer).`,
- `Proper deletion requires careful pointer manipulation to maintain list integrity and avoid memory leaks (in languages without garbage collection).`,
- ];
-
- const deletionTypes = [
- {
- name: "Deletion at Head",
- complexity: "O(1)",
- description: "Removes the first node, making the next node the new head",
- code: `function deleteHead() {
- if (!head) return; // Empty list
-
- const temp = head;
- head = head.next;
-
- // In languages without GC:
- // temp.next = null; // Isolate node
- // free(temp); // Free memory
-
- // Special case: If list becomes empty
- if (!head) tail = null;
-}`
- },
- {
- name: "Deletion at Tail",
- complexity: "O(n) without tail pointer, O(1) with doubly linked list",
- description: "Removes the last node, requiring traversal to find new tail",
- code: `function deleteTail() {
- if (!head) return; // Empty list
-
- // Single node case
- if (!head.next) {
- head = null;
- tail = null;
- return;
- }
-
- // Traverse to find node before tail
- let current = head;
- while (current.next && current.next.next) {
- current = current.next;
- }
-
- // Now current is the new tail
- current.next = null;
- tail = current;
-}`
- },
- {
- name: "Deletion by Value",
- complexity: "O(n)",
- description: "Finds and removes first node containing matching value",
- code: `function deleteValue(value) {
- if (!head) return; // Empty list
-
- // Special case: head contains value
- if (head.data === value) {
- deleteHead();
- return;
- }
-
- let current = head;
- while (current.next && current.next.data !== value) {
- current = current.next;
- }
-
- if (current.next) {
- const toDelete = current.next;
- current.next = toDelete.next;
-
- // Update tail if deleting last node
- if (!current.next) tail = current;
-
- // In languages without GC:
- // toDelete.next = null;
- // free(toDelete);
- }
-}`
- },
- {
- name: "Deletion at Position",
- complexity: "O(n)",
- description: "Removes node at specific index (0-based)",
- code: `function deleteAt(position) {
- if (!head || position < 0) return;
-
- if (position === 0) {
- deleteHead();
- return;
- }
-
- let current = head;
- for (let i = 0; current && i < position-1; i++) {
- current = current.next;
- }
-
- if (!current || !current.next) return; // Out of bounds
-
- const toDelete = current.next;
- current.next = toDelete.next;
-
- // Update tail if deleting last node
- if (!current.next) tail = current;
-
- // Memory cleanup in non-GC languages
- // toDelete.next = null;
- // free(toDelete);
-}`
- },
- ];
-
- const headDeletionSteps = [
- { step: "Check if list is empty (head is null)" },
- { step: "Store reference to current head node" },
- { step: "Update head pointer to head.next" },
- { step: "Handle memory cleanup (if needed)" },
- { step: "Special case: If list becomes empty, update tail pointer" },
- ];
-
- const tailDeletionSteps = [
- { step: "Check for empty list" },
- { step: "Handle single node case separately" },
- { step: "Traverse to find node before tail (penultimate node)" },
- { step: "Set penultimate node's next to null" },
- { step: "Update tail pointer to penultimate node" },
- ];
-
- const middleDeletionSteps = [
- { step: "Traverse to find node before target node" },
- { step: "Update previous node's next pointer to skip target" },
- { step: "Handle special case when deleting last node" },
- { step: "Perform memory cleanup (if needed)" },
- ];
-
- const visualization = [
- { operation: "Initial State", state: "head → [A] → [B] → [C] → [D] → null" },
- { operation: "deleteHead()", state: "head → [B] → [C] → [D] → null" },
- { operation: "deleteTail()", state: "head → [B] → [C] → null" },
- { operation: "deleteValue('C')", state: "head → [B] → null" },
- { operation: "deleteAt(0)", state: "head → null" },
- ];
-
- const edgeCases = [
- "Empty list (head = null)",
- "Single node list (head = tail)",
- "Deleting head node",
- "Deleting tail node",
- "Deleting non-existent value",
- "Deleting at invalid position (negative or out of bounds)",
- "Memory management in non-GC languages",
- ];
-
- const bestPractices = [
- "Always check for empty list before deletion",
- "Maintain proper head/tail pointers after deletion",
- "Handle single node case separately",
- "In non-GC languages, properly free deleted node memory",
- "Consider using dummy nodes to simplify edge cases",
- "Document position/indexing scheme (0-based vs 1-based)",
- "Validate position bounds before deletion attempts",
- ];
-
- const comparisonTable = [
- {
- feature: "Time Complexity",
- array: "O(n) (requires shifting)",
- linkedList: "O(1) head, O(n) arbitrary/tail"
- },
- {
- feature: "Space Complexity",
- array: "O(1)",
- linkedList: "O(1)"
- },
- {
- feature: "Memory Usage",
- array: "Fixed size unless resized",
- linkedList: "Dynamic, no unused capacity"
- },
- {
- feature: "Implementation",
- array: "Simple indexing",
- linkedList: "Pointer manipulation"
- },
- {
- feature: "Best For",
- array: "Frequent random access",
- linkedList: "Frequent deletions at head"
- },
- ];
-
- return (
-
-
- {/* Overview Section */}
-
-
-
- Deletion
-
-
- {overview.map((para, index) => (
-
- {para}
-
- ))}
-
-
- Key Consideration: Proper deletion requires maintaining list connectivity and handling memory appropriately to prevent leaks (in manual memory management environments).
-
-
-
-
-
- {/* Deletion Types */}
-
- Deletion Types
-
- {deletionTypes.map((type, index) => (
-
-
{type.name}
-
-
-
Complexity: {type.complexity}
-
{type.description}
-
-
-
-
- ))}
-
-
-
- {/* Deletion Processes */}
-
- Deletion Processes
-
- {/* Head Deletion */}
-
-
Head Deletion
-
- {headDeletionSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
- {/* Tail Deletion */}
-
-
Tail Deletion
-
- {tailDeletionSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
- {/* Middle Deletion */}
-
-
Middle Deletion
-
- {middleDeletionSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
-
-
- {/* Visualization */}
-
- Operation Visualization
-
-
-
-
- Operation
- List State
-
-
-
- {visualization.map((item, index) => (
-
- {item.operation}
- {item.state}
-
- ))}
-
-
-
-
-
- {/* Edge Cases */}
-
- Edge Cases to Consider
-
- {edgeCases.map((caseItem, index) => (
-
- ))}
-
-
-
- {/* Best Practices */}
-
- Best Practices
-
- {bestPractices.map((practice, index) => (
-
- ))}
-
-
-
- {/* Comparison with Arrays */}
-
- Comparison with Array Deletion
-
-
-
-
- Feature
- Array
- Linked List
-
-
-
- {comparisonTable.map((row, index) => (
-
- {row.feature}
- {row.array}
- {row.linkedList}
-
- ))}
-
-
-
-
-
- When to Choose: Prefer linked lists when you need frequent deletions, especially at the head. Use arrays when you need index-based access and memory efficiency for small, fixed-size collections.
-
-
-
-
- {/* Final Notes */}
-
- Implementation Notes
-
-
-
- Memory Management: In languages without garbage collection, ensure proper memory deallocation when deleting nodes
-
-
- Error Handling: Implement robust checks for edge cases to prevent null pointer exceptions
-
-
- Testing: Thoroughly test all deletion scenarios including empty list, single-node list, head/tail deletions
-
-
- Optimizations: For frequent tail deletions, consider using a doubly linked list for O(1) performance
-
-
- Documentation: Clearly document whether your deletion methods return the deleted value or just remove it
-
-
-
-
-
-
- );
-};
-
-export default content;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/deletion/data/codeExamples.json b/app/visualizer/linkedList/operations/deletion/data/codeExamples.json
deleted file mode 100755
index 45a5dd128..000000000
--- a/app/visualizer/linkedList/operations/deletion/data/codeExamples.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "javascript": "class SinglyLinkedList {\n // 1. Delete first node\n deleteFirst() {\n if (!this.head) return null;\n \n const deletedNode = this.head;\n this.head = this.head.next;\n this.size--;\n return deletedNode.data;\n }\n\n // 2. Delete last node\n deleteLast() {\n if (!this.head) return null;\n \n if (!this.head.next) {\n const data = this.head.data;\n this.head = null;\n this.size--;\n return data;\n }\n \n let current = this.head;\n while (current.next.next) {\n current = current.next;\n }\n \n const data = current.next.data;\n current.next = null;\n this.size--;\n return data;\n }\n\n // 3. Delete at specific index\n deleteAt(index) {\n if (index < 0 || index >= this.size) return null;\n if (index === 0) return this.deleteFirst();\n \n let current = this.head;\n for (let i = 0; i < index - 1; i++) {\n current = current.next;\n }\n \n const deletedNode = current.next;\n current.next = deletedNode.next;\n this.size--;\n return deletedNode.data;\n }\n\n // 4. Delete by value (first occurrence)\n deleteValue(value) {\n if (!this.head) return null;\n \n if (this.head.data === value) {\n return this.deleteFirst();\n }\n \n let current = this.head;\n while (current.next && current.next.data !== value) {\n current = current.next;\n }\n \n if (!current.next) return null;\n \n const deletedNode = current.next;\n current.next = deletedNode.next;\n this.size--;\n return deletedNode.data;\n }\n}",
- "python": "class SinglyLinkedList:\n # 1. Delete first node\n def delete_first(self):\n if not self.head:\n return None\n \n deleted_node = self.head\n self.head = self.head.next\n self.size -= 1\n return deleted_node.data\n \n # 2. Delete last node\n def delete_last(self):\n if not self.head:\n return None\n \n if not self.head.next:\n data = self.head.data\n self.head = None\n self.size -= 1\n return data\n \n current = self.head\n while current.next.next:\n current = current.next\n \n data = current.next.data\n current.next = None\n self.size -= 1\n return data\n \n # 3. Delete at specific index\n def delete_at(self, index):\n if index < 0 or index >= self.size:\n return None\n if index == 0:\n return self.delete_first()\n \n current = self.head\n for _ in range(index - 1):\n current = current.next\n \n deleted_node = current.next\n current.next = deleted_node.next\n self.size -= 1\n return deleted_node.data\n \n # 4. Delete by value (first occurrence)\n def delete_value(self, value):\n if not self.head:\n return None\n \n if self.head.data == value:\n return self.delete_first()\n \n current = self.head\n while current.next and current.next.data != value:\n current = current.next\n \n if not current.next:\n return None\n \n deleted_node = current.next\n current.next = deleted_node.next\n self.size -= 1\n return deleted_node.data",
- "java": "public class SinglyLinkedList {\n // 1. Delete first node\n public Integer deleteFirst() {\n if (head == null) return null;\n \n int data = head.data;\n head = head.next;\n size--;\n return data;\n }\n \n // 2. Delete last node\n public Integer deleteLast() {\n if (head == null) return null;\n \n if (head.next == null) {\n int data = head.data;\n head = null;\n size--;\n return data;\n }\n \n Node current = head;\n while (current.next.next != null) {\n current = current.next;\n }\n \n int data = current.next.data;\n current.next = null;\n size--;\n return data;\n }\n \n // 3. Delete at specific index\n public Integer deleteAt(int index) {\n if (index < 0 || index >= size) return null;\n if (index == 0) return deleteFirst();\n \n Node current = head;\n for (int i = 0; i < index - 1; i++) {\n current = current.next;\n }\n \n int data = current.next.data;\n current.next = current.next.next;\n size--;\n return data;\n }\n \n // 4. Delete by value (first occurrence)\n public Integer deleteValue(int value) {\n if (head == null) return null;\n \n if (head.data == value) {\n return deleteFirst();\n }\n \n Node current = head;\n while (current.next != null && current.next.data != value) {\n current = current.next;\n }\n \n if (current.next == null) return null;\n \n int data = current.next.data;\n current.next = current.next.next;\n size--;\n return data;\n }\n \n // Usage Example\n public static void main(String[] args) {\n SinglyLinkedList sll = new SinglyLinkedList();\n // Example of the insertion for insertion refer insertion article\n sll.insertLast(100);\n sll.insertLast(200);\n sll.insertLast(300);\n sll.insertLast(400);\n \n System.out.println(sll.deleteFirst()); // 100\n System.out.println(sll.deleteLast()); // 400\n System.out.println(sll.deleteAt(1)); // 300\n System.out.println(sll.deleteValue(200)); // 200\n }\n}",
- "c": "int deleteFirst(SinglyLinkedList* list) {\n if (list->head == NULL) return -1;\n \n Node* temp = list->head;\n int data = temp->data;\n list->head = list->head->next;\n free(temp);\n list->size--;\n return data;\n}\n\n// 2. Delete last node\nint deleteLast(SinglyLinkedList* list) {\n if (list->head == NULL) return -1;\n \n if (list->head->next == NULL) {\n int data = list->head->data;\n free(list->head);\n list->head = NULL;\n list->size--;\n return data;\n }\n \n Node* current = list->head;\n while (current->next->next != NULL) {\n current = current->next;\n }\n \n int data = current->next->data;\n free(current->next);\n current->next = NULL;\n list->size--;\n return data;\n}\n\n// 3. Delete at specific index\nint deleteAt(SinglyLinkedList* list, int index) {\n if (index < 0 || index >= list->size) return -1;\n if (index == 0) return deleteFirst(list);\n \n Node* current = list->head;\n for (int i = 0; i < index - 1; i++) {\n current = current->next;\n }\n \n Node* temp = current->next;\n int data = temp->data;\n current->next = temp->next;\n free(temp);\n list->size--;\n return data;\n}\n\n// 4. Delete by value (first occurrence)\nint deleteValue(SinglyLinkedList* list, int value) {\n if (list->head == NULL) return -1;\n \n if (list->head->data == value) {\n return deleteFirst(list);\n }\n \n Node* current = list->head;\n while (current->next != NULL && current->next->data != value) {\n current = current->next;\n }\n \n if (current->next == NULL) return -1;\n \n Node* temp = current->next;\n int data = temp->data;\n current->next = temp->next;\n free(temp);\n list->size--;\n return data;\n}",
- "cpp": "public:\n // 1. Delete first node\n int deleteFirst() {\n if (!head) throw std::out_of_range(\"List is empty\");\n \n Node* temp = head;\n int data = temp->data;\n head = head->next;\n delete temp;\n size--;\n return data;\n }\n \n // 2. Delete last node\n int deleteLast() {\n if (!head) throw std::out_of_range(\"List is empty\");\n \n if (!head->next) {\n int data = head->data;\n delete head;\n head = nullptr;\n size--;\n return data;\n }\n \n Node* current = head;\n while (current->next->next) {\n current = current->next;\n }\n \n int data = current->next->data;\n delete current->next;\n current->next = nullptr;\n size--;\n return data;\n }\n \n // 3. Delete at specific index\n int deleteAt(int index) {\n if (index < 0 || index >= size) throw std::out_of_range(\"Index out of range\");\n if (index == 0) return deleteFirst();\n \n Node* current = head;\n for (int i = 0; i < index - 1; i++) {\n current = current->next;\n }\n \n Node* temp = current->next;\n int data = temp->data;\n current->next = temp->next;\n delete temp;\n size--;\n return data;\n }\n \n // 4. Delete by value (first occurrence)\n int deleteValue(int value) {\n if (!head) throw std::out_of_range(\"List is empty\");\n \n if (head->data == value) {\n return deleteFirst();\n }\n \n Node* current = head;\n while (current->next && current->next->data != value) {\n current = current->next;\n }\n \n if (!current->next) throw std::out_of_range(\"Value not found\");\n \n Node* temp = current->next;\n int data = temp->data;\n current->next = temp->next;\n delete temp;\n size--;\n return data;\n }\n};"
-}
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/deletion/data/questions.json b/app/visualizer/linkedList/operations/deletion/data/questions.json
deleted file mode 100755
index e54b97895..000000000
--- a/app/visualizer/linkedList/operations/deletion/data/questions.json
+++ /dev/null
@@ -1,156 +0,0 @@
-[
- {
- "question": "What is the time complexity of deleting the head node in a linked list?",
- "options": [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n²)"
- ],
- "correctAnswer": 0,
- "explanation": "Head deletion is O(1) as it only requires updating the head pointer."
- },
- {
- "question": "What special case must be handled when deleting the last node in a linked list?",
- "options": [
- "Update both head and tail pointers to null",
- "Only update the head pointer",
- "Create a circular reference",
- "No special handling needed"
- ],
- "correctAnswer": 0,
- "explanation": "When deleting the last node, both head and tail pointers must be set to null as the list becomes empty."
- },
- {
- "question": "What is the time complexity of deleting a node by value in the worst case?",
- "options": [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n log n)"
- ],
- "correctAnswer": 1,
- "explanation": "Deleting by value is O(n) in the worst case as it may require traversing the entire list."
- },
- {
- "question": "Which pointer modifications are needed when deleting a middle node?",
- "options": [
- "Update the previous node's next to skip the deleted node",
- "Set the deleted node's next to null",
- "Update the head pointer",
- "Both A and B"
- ],
- "correctAnswer": 3,
- "explanation": "Middle deletion requires: (1) bypassing the deleted node in the list, and (2) cleaning up the deleted node's pointers."
- },
- {
- "question": "What is the main advantage of linked list deletion over array deletion?",
- "options": [
- "No need to shift remaining elements",
- "Better cache locality",
- "Lower memory usage overall",
- "Built-in sorting after deletion"
- ],
- "correctAnswer": 0,
- "explanation": "Linked lists don't require shifting elements during deletion, unlike arrays."
- },
- {
- "question": "What critical step is needed when deleting nodes in languages without garbage collection?",
- "options": [
- "Manually free the deleted node's memory",
- "Update all other nodes' data",
- "Create a new tail pointer",
- "Nothing special is needed"
- ],
- "correctAnswer": 0,
- "explanation": "In non-GC languages, you must manually free the memory of deleted nodes to prevent leaks."
- },
- {
- "question": "When deleting at position in a linked list, what case requires O(1) time?",
- "options": [
- "Position 0 (head)",
- "Middle positions",
- "Last position without tail pointer",
- "All positions"
- ],
- "correctAnswer": 0,
- "explanation": "Only head deletion (position 0) is O(1); others may require traversal."
- },
- {
- "question": "What happens if you forget to update the tail pointer when deleting the last node?",
- "options": [
- "The tail pointer becomes dangling",
- "Automatic garbage collection fixes it",
- "No issues occur",
- "The list becomes circular"
- ],
- "correctAnswer": 0,
- "explanation": "The tail pointer would point to deallocated memory, creating a dangerous dangling pointer."
- },
- {
- "question": "Which deletion scenario requires traversing approximately half the list on average?",
- "options": [
- "Head deletion",
- "Tail deletion with tail pointer",
- "Random middle position deletion",
- "Deleting by value at head"
- ],
- "correctAnswer": 2,
- "explanation": "Random middle deletions average n/2 traversal operations (O(n))."
- },
- {
- "question": "What should be your first step in any deletion operation?",
- "options": [
- "Check if the list is empty",
- "Update the head pointer",
- "Free all memory",
- "Traverse the entire list"
- ],
- "correctAnswer": 0,
- "explanation": "Always first check for empty list to avoid null pointer exceptions."
- },
- {
- "question": "Why is tail deletion O(n) in a singly linked list without a tail pointer?",
- "options": [
- "Need to traverse to find the new tail",
- "Requires sorting after deletion",
- "Must update all node values",
- "Memory allocation is slow"
- ],
- "correctAnswer": 0,
- "explanation": "Without a tail pointer, you must traverse from head to find the penultimate node to update."
- },
- {
- "question": "What is the space complexity of deletion operations in a linked list?",
- "options": [
- "O(1)",
- "O(n)",
- "O(log n)",
- "Depends on the position"
- ],
- "correctAnswer": 0,
- "explanation": "Deletion uses constant space regardless of list size, only needing a few temporary pointers."
- },
- {
- "question": "When deleting by value, what happens if the value appears multiple times?",
- "options": [
- "Only the first occurrence is deleted",
- "All occurrences are deleted",
- "Random occurrence is deleted",
- "Implementation determines behavior"
- ],
- "correctAnswer": 3,
- "explanation": "The behavior depends on implementation - some delete first match, some delete all."
- },
- {
- "question": "What optimization allows O(1) tail deletion?",
- "options": [
- "Maintaining a tail pointer in doubly linked list",
- "Using a circular list",
- "Keeping a size counter",
- "Storing all node addresses in an array"
- ],
- "correctAnswer": 0,
- "explanation": "A doubly linked list with tail pointer enables O(1) tail deletion via the previous pointers."
- }
-]
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/deletion/page.jsx b/app/visualizer/linkedList/operations/deletion/page.jsx
deleted file mode 100755
index 27bcfcf99..000000000
--- a/app/visualizer/linkedList/operations/deletion/page.jsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import Animation from "@/app/visualizer/linkedList/operations/deletion/animation";
-import Navbar from "@/app/components/navbarinner";
-
-export const metadata = {
- title: 'Linked List Deletion Algorithm | Interactive Visualization & Step-by-Step Guide',
- description:
- 'Learn how deletion works in Linked Lists with interactive animations, detailed explanations, and hands-on practice. Visualize each step of the deletion process and master linked list algorithms efficiently.',
- keywords: [
- 'Linked List Deletion',
- 'Deletion Animation Linked List',
- 'Visualize Deletion in Linked List',
- 'Linked List Algorithm',
- 'DSA Linked List Deletion',
- 'Linked List Deletion Visualization',
- 'Interactive Linked List',
- 'Deletion Step-by-Step',
- 'Linked List Learning',
- 'Data Structures Animation',
- 'DSA Practice Linked List',
- 'Deletion Code Example',
- 'Linked List Tutorial',
- 'Deletion using C',
- 'Deletion using Java',
- 'Deletion using Javascript',
- 'Deletion using Python',
- 'Deletion using linked list',
- ],
- robots: 'index, follow',
-};
-
-export default function Page() {
- return (
- <>
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/deletion/quiz.jsx b/app/visualizer/linkedList/operations/deletion/quiz.jsx
deleted file mode 100755
index 560356c25..000000000
--- a/app/visualizer/linkedList/operations/deletion/quiz.jsx
+++ /dev/null
@@ -1,399 +0,0 @@
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import Questions from "@/app/visualizer/linkedList/operations/deletion/data/questions.json";
-
-const Quiz = () => {
-const questions = Questions;
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Deletion Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default Quiz;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/insertion/animation.jsx b/app/visualizer/linkedList/operations/insertion/animation.jsx
deleted file mode 100755
index d30d2b086..000000000
--- a/app/visualizer/linkedList/operations/insertion/animation.jsx
+++ /dev/null
@@ -1,251 +0,0 @@
-"use client";
-import React, { useState, useRef, useEffect } from 'react';
-import { gsap } from 'gsap';
-import Footer from '@/app/components/footer';
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Content from "@/app/visualizer/linkedList/operations/insertion/content";
-import Quiz from '@/app/visualizer/linkedList/operations/insertion/quiz';
-import CodeBlock from "@/app/visualizer/linkedList/operations/insertion/codeBlock";
-import BackToTop from '@/app/components/ui/backtotop';
-import GoBackButton from "@/app/components/ui/goback";
-
-const LinkedListVisualizer = () => {
- const [inputValue, setInputValue] = useState('');
- const [list, setList] = useState([]);
- const [isAnimating, setIsAnimating] = useState(false);
- const nodeRefs = useRef([]);
- const containerRef = useRef(null);
- const animationTimeline = useRef(gsap.timeline());
-
- // Generate a random hex address for demonstration
- const generateAddress = () => {
- return '0x' + Math.floor(Math.random() * 0x10000).toString(16).toUpperCase().padStart(4, '0');
- };
-
- const addNode = () => {
- if (!inputValue || isAnimating) return;
- setIsAnimating(true);
-
- const newNode = {
- value: inputValue,
- id: Date.now(),
- address: generateAddress(),
- next: 'NULL'
- };
-
- const tempNode = document.createElement('div');
- tempNode.className = 'node flex border border-gray-300 absolute';
- tempNode.innerHTML = `
- ${inputValue}
- NULL
- `;
- containerRef.current.appendChild(tempNode);
-
- // Center the temporary node
- gsap.set(tempNode, {
- x: '50%',
- xPercent: -50,
- y: -100,
- opacity: 0,
- });
-
- // Calculate final position
- const finalX = list.length * 220;
-
- // Clear previous animations and create new sequence
- animationTimeline.current.clear();
- animationTimeline.current
- .to(tempNode, {
- opacity: 1,
- y: 50,
- duration: 0.5
- })
- .to(tempNode, {
- x: finalX,
- xPercent: 0,
- duration: 1,
- onComplete: () => {
- if (list.length > 0) {
- const updatedList = [...list];
- updatedList[updatedList.length - 1].next = newNode.address;
- setList([...updatedList, newNode]);
- } else {
- setList([newNode]);
- }
- setIsAnimating(false);
- tempNode.remove();
- }
- });
- };
-
- // Reset handler
- const handleReset = () => {
- // Kill all GSAP animations
- gsap.killTweensOf("*");
- animationTimeline.current.clear();
-
- // Clear all nodes from DOM
- if (containerRef.current) {
- const tempNodes = containerRef.current.querySelectorAll(".node");
- tempNodes.forEach((node) => node.remove());
- }
-
- // Reset state
- setInputValue("");
- setList([]);
- nodeRefs.current = [];
- setIsAnimating(false);
- };
-
- // Update node refs when list changes
- useEffect(() => {
- // Reset nodeRefs to match the current list length
- nodeRefs.current = nodeRefs.current.slice(0, list.length);
-
- if (list.length > 0 && nodeRefs.current.length === list.length) {
- gsap.from(nodeRefs.current, {
- opacity: 0,
- y: 20,
- duration: 0.5,
- stagger: 0.1,
- });
- }
- }, [list]);
-
- return (
-
-
-
-
-
-
-
- Linked List Insertion
-
-
-
-
- Visualize Linked List Insertion
-
-
- {/* Input Form - Responsive */}
-
-
-
-
setInputValue(e.target.value)}
- className="flex-1 p-3 border border-gray-400 bg-white dark:bg-gray-800 rounded-lg"
- placeholder="Enter value"
- disabled={isAnimating}
- />
- {/* Buttons for desktop */}
-
-
- {isAnimating ? "Adding..." : "Add Node"}
-
-
- Reset
-
-
-
- {/* Buttons for mobile */}
-
-
- {isAnimating ? "Adding..." : "Add Node"}
-
-
- Reset
-
-
-
-
-
- {/* Legend - Responsive */}
-
-
- {/* Visualization Area - Responsive */}
-
-
- {list.length === 0 ? (
-
- No nodes added yet
-
- ) : (
-
- {list.map((node, index) => (
-
-
(nodeRefs.current[index] = el)}
- className="node flex"
- >
-
- {node.value}
-
-
- {node.next}
-
-
- {index < list.length - 1 && (
-
→
- )}
-
- ))}
-
- )}
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default LinkedListVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/insertion/codeBlock.jsx b/app/visualizer/linkedList/operations/insertion/codeBlock.jsx
deleted file mode 100755
index 6773c578b..000000000
--- a/app/visualizer/linkedList/operations/insertion/codeBlock.jsx
+++ /dev/null
@@ -1,159 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-import CodeExamples from "@/app/visualizer/linkedList/operations/insertion/data/codeExamples.json";
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
-const codeExamples = CodeExamples;
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Linked List Insertion Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/insertion/content.jsx b/app/visualizer/linkedList/operations/insertion/content.jsx
deleted file mode 100755
index fea2e1c4d..000000000
--- a/app/visualizer/linkedList/operations/insertion/content.jsx
+++ /dev/null
@@ -1,352 +0,0 @@
-const content = () => {
- const overview = [
- `Linked List insertion involves adding new nodes to the linked data structure at various positions. Unlike arrays, linked lists allow efficient insertion at any point without reallocation or shifting of existing elements.`,
- `Insertion is a fundamental operation that enables dynamic growth of the list. The efficiency varies based on insertion position, from O(1) for head/tail (with tail pointer) to O(n) for arbitrary positions.`,
- `Mastering insertion techniques is crucial for building more complex data structures and algorithms that utilize linked lists as their foundation.`,
- ];
-
- const insertionTypes = [
- {
- name: "Insertion at Head",
- complexity: "O(1)",
- description: "Adds new node at the beginning, making it the new head",
- code: `function insertHead(data) {
- const newNode = new Node(data);
- newNode.next = head;
- head = newNode;
-}`
- },
- {
- name: "Insertion at Tail",
- complexity: "O(1) with tail pointer, O(n) without",
- description: "Appends new node at the end of the list",
- code: `function insertTail(data) {
- const newNode = new Node(data);
- if (!head) {
- head = newNode;
- tail = newNode;
- } else {
- tail.next = newNode;
- tail = newNode;
- }
-}`
- },
- {
- name: "Insertion at Position",
- complexity: "O(n)",
- description: "Inserts node at specific index (0-based)",
- code: `function insertAt(data, position) {
- if (position === 0) return insertHead(data);
-
- let current = head;
- for (let i = 0; i < position-1 && current; i++) {
- current = current.next;
- }
-
- if (!current) return; // Position out of bounds
-
- const newNode = new Node(data);
- newNode.next = current.next;
- current.next = newNode;
-
- if (!newNode.next) tail = newNode;
-}`
- },
- {
- name: "Insertion After Node",
- complexity: "O(1)",
- description: "Inserts new node after a given reference node",
- code: `function insertAfter(refNode, data) {
- const newNode = new Node(data);
- newNode.next = refNode.next;
- refNode.next = newNode;
-
- if (refNode === tail) tail = newNode;
-}`
- },
- ];
-
- const headInsertionSteps = [
- { step: "Create a new node with the given data" },
- { step: "Set the new node's next pointer to current head" },
- { step: "Update the head pointer to point to the new node" },
- { step: "Special case: If list was empty, update tail pointer too" },
- ];
-
- const tailInsertionSteps = [
- { step: "Create a new node with the given data" },
- { step: "If list is empty, set both head and tail to new node" },
- { step: "Otherwise, set current tail's next pointer to new node" },
- { step: "Update tail pointer to the new node" },
- ];
-
- const middleInsertionSteps = [
- { step: "Traverse the list to find the insertion position" },
- { step: "Create a new node with the given data" },
- { step: "Set new node's next to the next node of current position" },
- { step: "Set current node's next pointer to the new node" },
- { step: "Special case: If inserting at end, update tail pointer" },
- ];
-
- const visualization = [
- { operation: "Initial State", state: "head → [A] → [B] → [C] → null" },
- { operation: "insertHead(X)", state: "head → [X] → [A] → [B] → [C] → null" },
- { operation: "insertTail(Y)", state: "head → [X] → [A] → [B] → [C] → [Y] → null" },
- { operation: "insertAt(Z, 2)", state: "head → [X] → [A] → [Z] → [B] → [C] → [Y] → null" },
- ];
-
- const edgeCases = [
- "Empty list (head = null)",
- "Insertion at position 0 (becomes new head)",
- "Insertion at position = list length (becomes new tail)",
- "Insertion at position > list length (should handle gracefully)",
- "Insertion after tail node (should update tail pointer)",
- "Insertion with invalid node references",
- ];
-
- const bestPractices = [
- "Always check for empty list condition",
- "Maintain tail pointer for O(1) tail insertion",
- "Validate position bounds before insertion",
- "Update tail pointer when inserting at end",
- "Consider using dummy nodes to simplify edge cases",
- "Document whether position is 0-based or 1-based",
- ];
-
- const comparisonTable = [
- {
- feature: "Time Complexity",
- array: "O(n) (requires shifting)",
- linkedList: "O(1) head/tail, O(n) arbitrary"
- },
- {
- feature: "Space Complexity",
- array: "O(1) (amortized)",
- linkedList: "O(1) per insertion"
- },
- {
- feature: "Memory Usage",
- array: "May need reallocation",
- linkedList: "No reallocation needed"
- },
- {
- feature: "Implementation",
- array: "Simple indexing",
- linkedList: "Pointer manipulation"
- },
- {
- feature: "Best For",
- array: "Frequent random access",
- linkedList: "Frequent insertions/deletions"
- },
- ];
-
- return (
-
-
- {/* Overview Section */}
-
-
-
- Insertion
-
-
- {overview.map((para, index) => (
-
- {para}
-
- ))}
-
-
- Key Insight: Linked list insertion doesn't require shifting elements like arrays, but does require careful pointer manipulation to maintain list integrity.
-
-
-
-
-
- {/* Insertion Types */}
-
- Insertion Types
-
- {insertionTypes.map((type, index) => (
-
-
{type.name}
-
-
-
Complexity: {type.complexity}
-
{type.description}
-
-
-
-
- ))}
-
-
-
- {/* Insertion Processes */}
-
- Insertion Processes
-
- {/* Head Insertion */}
-
-
Head Insertion
-
- {headInsertionSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
- {/* Tail Insertion */}
-
-
Tail Insertion
-
- {tailInsertionSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
- {/* Middle Insertion */}
-
-
Middle Insertion
-
- {middleInsertionSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
-
-
- {/* Visualization */}
-
- Operation Visualization
-
-
-
-
- Operation
- List State
-
-
-
- {visualization.map((item, index) => (
-
- {item.operation}
- {item.state}
-
- ))}
-
-
-
-
-
- {/* Edge Cases */}
-
- Edge Cases to Consider
-
- {edgeCases.map((caseItem, index) => (
-
- ))}
-
-
-
- {/* Best Practices */}
-
- Best Practices
-
- {bestPractices.map((practice, index) => (
-
- ))}
-
-
-
- {/* Comparison with Arrays */}
-
- Comparison with Array Insertion
-
-
-
-
- Feature
- Array
- Linked List
-
-
-
- {comparisonTable.map((row, index) => (
-
- {row.feature}
- {row.array}
- {row.linkedList}
-
- ))}
-
-
-
-
-
- When to Choose: Prefer linked lists when you need frequent insertions at arbitrary positions and don't require random access. Use arrays when you need index-based access and memory efficiency for small, fixed-size collections.
-
-
-
-
- {/* Final Notes */}
-
- Implementation Notes
-
-
-
- Memory Management: Remember to properly allocate memory for new nodes in languages that require manual memory management
-
-
- Error Handling: Always validate input parameters and handle edge cases gracefully
-
-
- Testing: Thoroughly test all insertion scenarios including empty list, single-node list, head/tail insertions
-
-
- Optimizations: Consider maintaining both head and tail pointers for O(1) insertions at both ends
-
-
-
-
-
-
- );
-};
-
-export default content;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/insertion/data/codeExamples.json b/app/visualizer/linkedList/operations/insertion/data/codeExamples.json
deleted file mode 100755
index ae27d94a1..000000000
--- a/app/visualizer/linkedList/operations/insertion/data/codeExamples.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "javascript": "class Node {\n constructor(data) {\n this.data = data;\n this.next = null;\n }\n}\n\nclass SinglyLinkedList {\n constructor() {\n this.head = null;\n this.size = 0;\n }\n\n // 1. Insert at beginning\n insertFirst(data) {\n const newNode = new Node(data);\n newNode.next = this.head;\n this.head = newNode;\n this.size++;\n }\n\n // 2. Insert at end\n insertLast(data) {\n const newNode = new Node(data);\n \n if (!this.head) {\n this.head = newNode;\n } else {\n let current = this.head;\n while (current.next) {\n current = current.next;\n }\n current.next = newNode;\n }\n this.size++;\n }\n\n // 3. Insert at specific index\n insertAt(data, index) {\n if (index < 0 || index > this.size) {\n console.log(\"Invalid index\");\n return;\n }\n \n if (index === 0) {\n this.insertFirst(data);\n return;\n }\n \n const newNode = new Node(data);\n let current = this.head;\n let count = 0;\n \n while (count < index - 1) {\n current = current.next;\n count++;\n }\n \n newNode.next = current.next;\n current.next = newNode;\n this.size++;\n }\n\n printList() {\n let current = this.head;\n let result = \"\";\n while (current) {\n result += current.data + \" -> \";\n current = current.next;\n }\n result += \"null\";\n console.log(result);\n }\n}\n\nconst sll = new SinglyLinkedList();\nsll.insertFirst(100);\nsll.insertFirst(200);\nsll.insertLast(300);\nsll.insertAt(500, 1);\nsll.printList();",
- "python": "class Node:\n def __init__(self, data):\n self.data = data\n self.next = None\n\nclass SinglyLinkedList:\n def __init__(self):\n self.head = None\n self.size = 0\n \n # 1. Insert at beginning\n def insert_first(self, data):\n new_node = Node(data)\n new_node.next = self.head\n self.head = new_node\n self.size += 1\n \n # 2. Insert at end\n def insert_last(self, data):\n new_node = Node(data)\n \n if not self.head:\n self.head = new_node\n else:\n current = self.head\n while current.next:\n current = current.next\n current.next = new_node\n self.size += 1\n \n # 3. Insert at specific index\n def insert_at(self, data, index):\n if index < 0 or index > self.size:\n print(\"Invalid index\")\n return\n \n if index == 0:\n self.insert_first(data)\n return\n \n new_node = Node(data)\n current = self.head\n count = 0\n \n # Traverse to the node before the insertion point\n while count < index - 1:\n current = current.next\n count += 1\n \n new_node.next = current.next\n current.next = new_node\n self.size += 1\n \n # Print the list\n def print_list(self):\n current = self.head\n result = []\n while current:\n result.append(str(current.data))\n current = current.next\n print(\" -> \".join(result) + \" -> None\")\n\n# Usage Example\nsll = SinglyLinkedList()\nsll.insert_first(100) # List: 100 -> None\nsll.insert_first(200) # List: 200 -> 100 -> None\nsll.insert_last(300) # List: 200 -> 100 -> 300 -> None\nsll.insert_at(500, 1) # List: 200 -> 500 -> 100 -> 300 -> None\nsll.print_list()",
- "java": "public class SinglyLinkedList {\n private class Node {\n int data;\n Node next;\n \n Node(int data) {\n this.data = data;\n this.next = null;\n }\n }\n \n private Node head;\n private int size;\n \n public SinglyLinkedList() {\n head = null;\n size = 0;\n }\n \n // 1. Insert at beginning\n public void insertFirst(int data) {\n Node newNode = new Node(data);\n newNode.next = head;\n head = newNode;\n size++;\n }\n \n // 2. Insert at end\n public void insertLast(int data) {\n Node newNode = new Node(data);\n \n if (head == null) {\n head = newNode;\n } else {\n Node current = head;\n while (current.next != null) {\n current = current.next;\n }\n current.next = newNode;\n }\n size++;\n }\n \n // 3. Insert at specific index\n public void insertAt(int data, int index) {\n if (index < 0 || index > size) {\n System.out.println(\"Invalid index\");\n return;\n }\n \n if (index == 0) {\n insertFirst(data);\n return;\n }\n \n Node newNode = new Node(data);\n Node current = head;\n int count = 0;\n \n // Traverse to the node before the insertion point\n while (count < index - 1) {\n current = current.next;\n count++;\n }\n \n newNode.next = current.next;\n current.next = newNode;\n size++;\n }\n \n // Print the list\n public void printList() {\n Node current = head;\n while (current != null) {\n System.out.print(current.data + \" -> \");\n current = current.next;\n }\n System.out.println(\"null\");\n }\n \n // Usage Example\n public static void main(String[] args) {\n SinglyLinkedList sll = new SinglyLinkedList();\n sll.insertFirst(100); // List: 100 -> null\n sll.insertFirst(200); // List: 200 -> 100 -> null\n sll.insertLast(300); // List: 200 -> 100 -> 300 -> null\n sll.insertAt(500, 1); // List: 200 -> 500 -> 100 -> 300 -> null\n sll.printList();\n }\n}",
- "c": "#include \n#include \n\ntypedef struct Node {\n int data;\n struct Node* next;\n} Node;\n\ntypedef struct {\n Node* head;\n int size;\n} SinglyLinkedList;\n\nvoid initList(SinglyLinkedList* list) {\n list->head = NULL;\n list->size = 0;\n}\n\n// 1. Insert at beginning\nvoid insertFirst(SinglyLinkedList* list, int data) {\n Node* newNode = (Node*)malloc(sizeof(Node));\n newNode->data = data;\n newNode->next = list->head;\n list->head = newNode;\n list->size++;\n}\n\n// 2. Insert at end\nvoid insertLast(SinglyLinkedList* list, int data) {\n Node* newNode = (Node*)malloc(sizeof(Node));\n newNode->data = data;\n newNode->next = NULL;\n \n if (list->head == NULL) {\n list->head = newNode;\n } else {\n Node* current = list->head;\n while (current->next != NULL) {\n current = current->next;\n }\n current->next = newNode;\n }\n list->size++;\n}\n\n// 3. Insert at specific index\nvoid insertAt(SinglyLinkedList* list, int data, int index) {\n if (index < 0 || index > list->size) {\n printf(\"Invalid index\\n\");\n return;\n }\n \n if (index == 0) {\n insertFirst(list, data);\n return;\n }\n \n Node* newNode = (Node*)malloc(sizeof(Node));\n newNode->data = data;\n \n Node* current = list->head;\n int count = 0;\n \n // Traverse to the node before the insertion point\n while (count < index - 1) {\n current = current->next;\n count++;\n }\n \n newNode->next = current->next;\n current->next = newNode;\n list->size++;\n}\n\n// Print the list\nvoid printList(SinglyLinkedList* list) {\n Node* current = list->head;\n while (current != NULL) {\n printf(\"%d -> \", current->data);\n current = current->next;\n }\n printf(\"NULL\\n\");\n}\n\n// Usage Example\nint main() {\n SinglyLinkedList list;\n initList(&list);\n \n insertFirst(&list, 100); // List: 100 -> NULL\n insertFirst(&list, 200); // List: 200 -> 100 -> NULL\n insertLast(&list, 300); // List: 200 -> 100 -> 300 -> NULL\n insertAt(&list, 500, 1); // List: 200 -> 500 -> 100 -> 300 -> NULL\n printList(&list);\n \n return 0;\n}",
- "cpp": "#include \nusing namespace std;\n\nclass Node {\npublic:\n int data;\n Node* next;\n \n Node(int data) : data(data), next(nullptr) {}\n};\n\nclass SinglyLinkedList {\nprivate:\n Node* head;\n int size;\n \npublic:\n SinglyLinkedList() : head(nullptr), size(0) {}\n \n // 1. Insert at beginning\n void insertFirst(int data) {\n Node* newNode = new Node(data);\n newNode->next = head;\n head = newNode;\n size++;\n }\n \n // 2. Insert at end\n void insertLast(int data) {\n Node* newNode = new Node(data);\n \n if (head == nullptr) {\n head = newNode;\n } else {\n Node* current = head;\n while (current->next != nullptr) {\n current = current->next;\n }\n current->next = newNode;\n }\n size++;\n }\n \n // 3. Insert at specific index\n void insertAt(int data, int index) {\n if (index < 0 || index > size) {\n cout << \"Invalid index\" << endl;\n return;\n }\n \n if (index == 0) {\n insertFirst(data);\n return;\n }\n \n Node* newNode = new Node(data);\n Node* current = head;\n int count = 0;\n \n // Traverse to the node before the insertion point\n while (count < index - 1) {\n current = current->next;\n count++;\n }\n \n newNode->next = current->next;\n current->next = newNode;\n size++;\n }\n \n // Print the list\n void printList() {\n Node* current = head;\n while (current != nullptr) {\n cout << current->data << \" -> \";\n current = current->next;\n }\n cout << \"NULL\" << endl;\n }\n};\n\n// Usage Example\nint main() {\n SinglyLinkedList sll;\n sll.insertFirst(100); // List: 100 -> NULL\n sll.insertFirst(200); // List: 200 -> 100 -> NULL\n sll.insertLast(300); // List: 200 -> 100 -> 300 -> NULL\n sll.insertAt(500, 1); // List: 200 -> 500 -> 100 -> 300 -> NULL\n sll.printList();\n \n return 0;\n}"
-}
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/insertion/data/questions.json b/app/visualizer/linkedList/operations/insertion/data/questions.json
deleted file mode 100755
index 4ae9b98fa..000000000
--- a/app/visualizer/linkedList/operations/insertion/data/questions.json
+++ /dev/null
@@ -1,134 +0,0 @@
-[
- {
- "question": "What is the time complexity of inserting a node at the head of a linked list?",
- "options": [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n²)"
- ],
- "correctAnswer": 0,
- "explanation": "Head insertion is O(1) as it only requires updating the head pointer and the new node's next pointer."
- },
- {
- "question": "Which pointer modifications are needed for inserting a new node at the head?",
- "options": [
- "New node's next points to current head, then update head",
- "Traverse to end first",
- "Update tail pointer only",
- "Modify all existing nodes' pointers"
- ],
- "correctAnswer": 0,
- "explanation": "Head insertion requires: (1) new node's next = current head, (2) head = new node."
- },
- {
- "question": "What is the time complexity of inserting at the tail without a tail pointer?",
- "options": [
- "O(1)",
- "O(n)",
- "O(log n)",
- "Depends on list size"
- ],
- "correctAnswer": 1,
- "explanation": "Without a tail pointer, you must traverse the entire list (O(n)) to reach the end before inserting."
- },
- {
- "question": "When inserting at position in a linked list, what is the worst-case time complexity?",
- "options": [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n log n)"
- ],
- "correctAnswer": 1,
- "explanation": "Position insertion is O(n) in the worst case when inserting near the end of the list."
- },
- {
- "question": "What special case must be handled when inserting into an empty linked list?",
- "options": [
- "Update both head and tail pointers",
- "Only update head pointer",
- "Create a circular reference",
- "No special handling needed"
- ],
- "correctAnswer": 0,
- "explanation": "For an empty list, both head and tail pointers should point to the new node."
- },
- {
- "question": "What is the correct sequence for inserting a node after a given reference node?",
- "options": [
- "newNode.next = refNode.next; refNode.next = newNode",
- "refNode.next = newNode; newNode.next = refNode.next",
- "Only set refNode.next = newNode",
- "Traverse the entire list first"
- ],
- "correctAnswer": 0,
- "explanation": "First set newNode's next to refNode's next, then update refNode's next to point to newNode."
- },
- {
- "question": "Which of these is NOT an advantage of linked list insertion over array insertion?",
- "options": [
- "No need to shift existing elements",
- "Dynamic size growth",
- "Better cache locality",
- "No reallocation needed"
- ],
- "correctAnswer": 2,
- "explanation": "Linked lists generally have worse cache locality than arrays due to non-contiguous memory allocation."
- },
- {
- "question": "What should you do when inserting at a position that's greater than the list length?",
- "options": [
- "Insert at head",
- "Insert at tail",
- "Throw an error or handle gracefully",
- "Create multiple empty nodes"
- ],
- "correctAnswer": 2,
- "explanation": "The implementation should either throw an error or handle the out-of-bounds case gracefully."
- },
- {
- "question": "Why is maintaining a tail pointer beneficial for linked list insertion?",
- "options": [
- "Enables O(1) tail insertion",
- "Allows random access to elements",
- "Reduces memory usage",
- "Simplifies middle insertions"
- ],
- "correctAnswer": 0,
- "explanation": "A tail pointer allows O(1) insertion at the tail by eliminating the need for traversal."
- },
- {
- "question": "What happens if you incorrectly order pointer assignments during insertion?",
- "options": [
- "Memory leak",
- "Lost nodes or broken list",
- "Compiler error",
- "Automatic garbage collection"
- ],
- "correctAnswer": 1,
- "explanation": "Incorrect pointer assignment order can lead to lost nodes or a broken list structure."
- },
- {
- "question": "Which insertion scenario requires traversing approximately half the list on average?",
- "options": [
- "Head insertion",
- "Tail insertion with tail pointer",
- "Middle insertion at random position",
- "Insertion after given node reference"
- ],
- "correctAnswer": 2,
- "explanation": "Random middle insertions require traversal that averages n/2 operations (O(n))."
- },
- {
- "question": "What is the space complexity for a single insertion operation in a linked list?",
- "options": [
- "O(1)",
- "O(n)",
- "O(log n)",
- "Depends on position"
- ],
- "correctAnswer": 0,
- "explanation": "Each insertion only requires space for one new node, regardless of list size (O(1))."
- }
-]
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/insertion/page.jsx b/app/visualizer/linkedList/operations/insertion/page.jsx
deleted file mode 100755
index 9c9354d46..000000000
--- a/app/visualizer/linkedList/operations/insertion/page.jsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import Animation from "@/app/visualizer/linkedList/operations/insertion/animation";
-import Navbar from "@/app/components/navbarinner";
-
-export const metadata = {
- title: 'Linked List Insertion Algorithm | Interactive Visualization & Step-by-Step Guide',
- description:
- 'Learn how insertion works in Linked Lists with interactive animations, detailed explanations, and hands-on practice. Visualize each step of the insertion process and master linked list algorithms efficiently.',
- keywords: [
- 'Linked List Insertion',
- 'Insertion Animation Linked List',
- 'Visualize Insertion in Linked List',
- 'Linked List Algorithm',
- 'DSA Linked List Insertion',
- 'Linked List Insertion Visualization',
- 'Interactive Linked List',
- 'Insertion Step-by-Step',
- 'Linked List Learning',
- 'Data Structures Animation',
- 'DSA Practice Linked List',
- 'Insertion Code Example',
- 'Linked List Tutorial',
- 'Insertion using C',
- 'Insertion using Java',
- 'Insertion using Javascript',
- 'Insertion using Python',
- 'Insertion using linked list',
- ],
- robots: 'index, follow',
-};
-export default function Page() {
- return (
- <>
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/insertion/quiz.jsx b/app/visualizer/linkedList/operations/insertion/quiz.jsx
deleted file mode 100755
index 1979a41a4..000000000
--- a/app/visualizer/linkedList/operations/insertion/quiz.jsx
+++ /dev/null
@@ -1,399 +0,0 @@
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import Questions from "@/app/visualizer/linkedList/operations/insertion/data/questions.json";
-
-const Quiz = () => {
-const questions = Questions;
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Insertion Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default Quiz;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/merge/._codeBlock.jsx b/app/visualizer/linkedList/operations/merge/._codeBlock.jsx
deleted file mode 100755
index c6b0cdc6b..000000000
Binary files a/app/visualizer/linkedList/operations/merge/._codeBlock.jsx and /dev/null differ
diff --git a/app/visualizer/linkedList/operations/merge/animation.jsx b/app/visualizer/linkedList/operations/merge/animation.jsx
deleted file mode 100755
index 24fda7917..000000000
--- a/app/visualizer/linkedList/operations/merge/animation.jsx
+++ /dev/null
@@ -1,415 +0,0 @@
-"use client";
-import React, { useState, useRef, useEffect } from 'react';
-import { gsap } from 'gsap';
-import Footer from '@/app/components/footer';
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Content from "@/app/visualizer/linkedList/operations/merge/content";
-import Quiz from '@/app/visualizer/linkedList/operations/merge/quiz';
-import CodeBlock from "@/app/visualizer/linkedList/operations/merge/codeBlock";
-import BackToTop from '@/app/components/ui/backtotop';
-import GoBackButton from "@/app/components/ui/goback";
-
-const LinkedListMerge = () => {
- const [list1, setList1] = useState([]);
- const [list2, setList2] = useState([]);
- const [mergedList, setMergedList] = useState([]);
- const [isAnimating, setIsAnimating] = useState(false);
- const [currentPointers, setCurrentPointers] = useState({ list1: 0, list2: 0 });
- const list1Refs = useRef([]);
- const list2Refs = useRef([]);
- const mergedRefs = useRef([]);
- const arrowRefs = useRef([]);
- const containerRef = useRef(null);
- const animationTimeline = useRef(gsap.timeline());
-
- // Generate random linked list with realistic values
- const generateRandomList = (setList) => {
- const size = Math.floor(Math.random() * 3) + 3; // 3-5 nodes
- const values = Array.from({ length: size }, (_, i) => {
- const base = Math.floor(Math.random() * 20) + 1;
- return base + i * 5; // Ensure some order but not perfectly sorted
- }).sort((a, b) => a - b); // Sort the values
-
- const newList = values.map((value, index) => ({
- value,
- id: Date.now() + index + Math.random(),
- next: index < size - 1 ? `0x${(1000 + index).toString(16).padStart(4, '0')}` : 'NULL'
- }));
-
- setList(newList);
- };
-
- // Reset handler
- const handleReset = () => {
- gsap.killTweensOf("*");
- animationTimeline.current.clear();
- setList1([]);
- setList2([]);
- setMergedList([]);
- setIsAnimating(false);
- setCurrentPointers({ list1: 0, list2: 0 });
- list1Refs.current = [];
- list2Refs.current = [];
- mergedRefs.current = [];
- arrowRefs.current = [];
- };
-
- // Animate the merge process step-by-step
- const animateMerge = async () => {
- if (isAnimating || list1.length === 0 || list2.length === 0) return;
-
- setIsAnimating(true);
- animationTimeline.current.clear();
-
- // Create sorted copies
- const sortedList1 = [...list1].sort((a, b) => a.value - b.value);
- const sortedList2 = [...list2].sort((a, b) => a.value - b.value);
-
- let i = 0, j = 0;
- const result = [];
-
- // Initial state
- gsap.set([...list1Refs.current, ...list2Refs.current], {
- opacity: 1,
- scale: 1,
- backgroundColor: i => i < sortedList1.length ? '#10b981' : '#10b981'
- });
-
- gsap.set(arrowRefs.current, { opacity: 0.7 });
- setMergedList([]);
- setCurrentPointers({ list1: 0, list2: 0 });
-
- const mergeStep = async () => {
- if (i >= sortedList1.length && j >= sortedList2.length) {
- setIsAnimating(false);
- return;
- }
-
- // Highlight current pointers
- animationTimeline.current.to([
- i < sortedList1.length ? list1Refs.current[i] : null,
- j < sortedList2.length ? list2Refs.current[j] : null
- ].filter(Boolean), {
- scale: 1.3,
- duration: 0.3,
- ease: 'power1.inOut'
- }, '<');
-
- await new Promise(resolve => {
- animationTimeline.current.call(() => {
- setCurrentPointers({ list1: i, list2: j });
- resolve();
- }, null, '+=0.3');
- });
-
- let nextNode;
- if (j >= sortedList2.length || (i < sortedList1.length && sortedList1[i].value <= sortedList2[j].value)) {
- // Take from list1
- nextNode = { ...sortedList1[i], source: 'list1' };
- i++;
- } else {
- // Take from list2
- nextNode = { ...sortedList2[j], source: 'list2' };
- j++;
- }
-
- // Animate the selected node moving to merged list
- const tempNode = document.createElement('div');
- tempNode.className = `node flex items-center justify-center absolute w-20 h-16 rounded-md shadow-md text-white font-bold ${
- nextNode.source === 'list1' ? 'bg-emerald-600' : 'bg-emerald-600'
- }`;
- tempNode.textContent = nextNode.value;
- containerRef.current.appendChild(tempNode);
-
- // Get positions
- const fromRect = nextNode.source === 'list1'
- ? list1Refs.current[i-1]?.getBoundingClientRect()
- : list2Refs.current[j-1]?.getBoundingClientRect();
- const toPos = mergedList.length * 80 + 40; // Calculate new position
-
- gsap.set(tempNode, {
- x: fromRect?.left - containerRef.current.getBoundingClientRect().left || 0,
- y: fromRect?.top - containerRef.current.getBoundingClientRect().top || 0,
- opacity: 0,
- scale: 0.5
- });
-
- // Improved animation: pop, move, color transition
- animationTimeline.current.to(tempNode, {
- opacity: 1,
- scale: 1.1,
- duration: 0.4,
- ease: 'power2.out'
- }, '<');
-
- animationTimeline.current.to(tempNode, {
- x: toPos,
- y: 20,
- scale: 1,
- backgroundColor: '#2563eb', // transition to merged blue color
- duration: 0.8,
- ease: 'power3.inOut'
- });
-
- animationTimeline.current.call(() => {
- result.push(nextNode);
- setMergedList([...result]);
- tempNode.remove();
- }, null, `+=0.2`);
-
- // Update pointers
- await new Promise(resolve => {
- animationTimeline.current.call(() => {
- setCurrentPointers({ list1: i, list2: j });
- resolve();
- }, null, '+=0.1');
- });
-
- // Recursively call next step
- await new Promise(resolve => {
- animationTimeline.current.call(() => {
- mergeStep().then(resolve);
- }, null, '+=0.3');
- });
- };
-
- await mergeStep();
- };
-
- // Update refs when lists change
- useEffect(() => {
- list1Refs.current = list1Refs.current.slice(0, list1.length);
- list2Refs.current = list2Refs.current.slice(0, list2.length);
- mergedRefs.current = mergedRefs.current.slice(0, mergedList.length);
- arrowRefs.current = arrowRefs.current.slice(0, Math.max(0, mergedList.length - 1));
- }, [list1, list2, mergedList]);
-
- return (
-
-
-
-
-
-
-
- Linked List Merge
-
-
-
-
- Visualize merging two sorted linked lists
-
-
- {/* Controls - Responsive */}
-
-
-
-
- generateRandomList(setList1)}
- disabled={isAnimating}
- className="bg-emerald-600 hover:bg-emerald-700 text-white px-4 py-2 sm:px-6 sm:py-3 rounded-lg disabled:bg-gray-400 w-full"
- >
- Generate List 1
-
- generateRandomList(setList2)}
- disabled={isAnimating}
- className="bg-emerald-600 hover:bg-emerald-700 text-white px-4 py-2 sm:px-6 sm:py-3 rounded-lg disabled:bg-gray-400 w-full"
- >
- Generate List 2
-
-
-
-
- {isAnimating ? "Merging..." : "Merge Lists"}
-
-
- Reset All
-
-
-
-
-
-
- {/* Legend - Responsive */}
-
-
- {/* Visualization Area */}
-
- {/* List 1 */}
-
-
List 1 {currentPointers.list1 < list1.length && `(Current: ${currentPointers.list1 + 1})`}
-
- {list1.length === 0 ? (
-
- Generate List 1 to begin
-
- ) : (
-
- {list1.map((node, index) => (
-
- (list1Refs.current[index] = el)}
- className={`node flex flex-col items-center justify-center bg-emerald-600 text-white text-lg w-20 h-16 rounded-md shadow-md transition-all ${
- index === currentPointers.list1 && isAnimating ? 'ring-4 ring-emerald-300 scale-110' : ''
- }`}
- >
- {node.value}
-
{node.next}
-
- {index < list1.length - 1 && (
-
-
-
- )}
-
- ))}
-
- )}
-
-
-
- {/* List 2 */}
-
-
List 2 {currentPointers.list2 < list2.length && `(Current: ${currentPointers.list2 + 1})`}
-
- {list2.length === 0 ? (
-
- Generate List 2 to continue
-
- ) : (
-
- {list2.map((node, index) => (
-
- (list2Refs.current[index] = el)}
- className={`node flex flex-col items-center justify-center bg-emerald-600 text-white text-lg w-20 h-16 rounded-md shadow-md transition-all ${
- index === currentPointers.list2 && isAnimating ? 'ring-4 ring-emerald-300 scale-110' : ''
- }`}
- >
- {node.value}
-
{node.next}
-
- {index < list2.length - 1 && (
-
-
-
- )}
-
- ))}
-
- )}
-
-
-
- {/* Merged List */}
-
-
Merged List
-
- {mergedList.length === 0 ? (
-
- {list1.length > 0 && list2.length > 0 ? (
- "Click 'Merge Lists' to visualize"
- ) : (
- "Generate both lists and merge them"
- )}
-
- ) : (
-
- {mergedList.map((node, index) => (
-
- (mergedRefs.current[index] = el)}
- className={`node flex flex-col items-center justify-center bg-blue-600 text-white text-lg w-20 h-16 rounded-md shadow-md ${
- index === mergedList.length - 1 && isAnimating ? 'animate-pulse' : ''
- }`}
- >
- {node.value}
- {/* No address shown for merged list */}
-
- {index < mergedList.length - 1 && (
- (arrowRefs.current[index] = el)}
- className="w-8 h-8 opacity-70 text-gray-600 dark:text-gray-300"
- viewBox="0 0 24 24"
- fill="none"
- stroke="currentColor"
- strokeWidth="2"
- >
-
-
- )}
-
- ))}
-
- )}
-
-
-
-
-
- Test Your Knowledge Before Moving Forward!
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default LinkedListMerge;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/merge/codeBlock.jsx b/app/visualizer/linkedList/operations/merge/codeBlock.jsx
deleted file mode 100755
index bd6a31592..000000000
--- a/app/visualizer/linkedList/operations/merge/codeBlock.jsx
+++ /dev/null
@@ -1,159 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-import CodeExamples from "@/app/visualizer/linkedList/operations/merge/data/codeExamples.json";
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
-const codeExamples = CodeExamples;
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Linked List Merging Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/merge/data/codeExamples.json b/app/visualizer/linkedList/operations/merge/data/codeExamples.json
deleted file mode 100755
index e02e6929c..000000000
--- a/app/visualizer/linkedList/operations/merge/data/codeExamples.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "javascript": "class Node {\n constructor(data) {\n this.data = data;\n this.next = null;\n }\n}\n\nfunction mergeLists(l1, l2) {\n const dummy = new Node(0);\n let current = dummy;\n\n while (l1 && l2) {\n if (l1.data < l2.data) {\n current.next = l1;\n l1 = l1.next;\n } else {\n current.next = l2;\n l2 = l2.next;\n }\n current = current.next;\n }\n\n current.next = l1 || l2;\n return dummy.next;\n}",
- "python": "class Node:\n def __init__(self, data):\n self.data = data\n self.next = None\n\ndef merge_lists(l1, l2):\n dummy = Node(0)\n current = dummy\n\n while l1 and l2:\n if l1.data < l2.data:\n current.next = l1\n l1 = l1.next\n else:\n current.next = l2\n l2 = l2.next\n current = current.next\n\n current.next = l1 or l2\n return dummy.next",
- "java": "class Node {\n int data;\n Node next;\n Node(int data) {\n this.data = data;\n this.next = null;\n }\n}\n\npublic class MergeLists {\n public static Node merge(Node l1, Node l2) {\n Node dummy = new Node(0);\n Node current = dummy;\n\n while (l1 != null && l2 != null) {\n if (l1.data < l2.data) {\n current.next = l1;\n l1 = l1.next;\n } else {\n current.next = l2;\n l2 = l2.next;\n }\n current = current.next;\n }\n\n current.next = (l1 != null) ? l1 : l2;\n return dummy.next;\n }\n}",
- "c": "#include \n#include \n\ntypedef struct Node {\n int data;\n struct Node* next;\n} Node;\n\nNode* mergeLists(Node* l1, Node* l2) {\n Node dummy;\n Node* current = &dummy;\n dummy.next = NULL;\n\n while (l1 && l2) {\n if (l1->data < l2->data) {\n current->next = l1;\n l1 = l1->next;\n } else {\n current->next = l2;\n l2 = l2->next;\n }\n current = current->next;\n }\n\n current->next = l1 ? l1 : l2;\n return dummy.next;\n}",
- "cpp": "#include \nusing namespace std;\n\nclass Node {\npublic:\n int data;\n Node* next;\n Node(int d) : data(d), next(nullptr) {}\n};\n\nNode* mergeLists(Node* l1, Node* l2) {\n Node dummy(0);\n Node* current = &dummy;\n\n while (l1 && l2) {\n if (l1->data < l2->data) {\n current->next = l1;\n l1 = l1->next;\n } else {\n current->next = l2;\n l2 = l2->next;\n }\n current = current->next;\n }\n\n current->next = l1 ? l1 : l2;\n return dummy.next;\n}"
-}
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/merge/data/questions.json b/app/visualizer/linkedList/operations/merge/data/questions.json
deleted file mode 100755
index 626278e8e..000000000
--- a/app/visualizer/linkedList/operations/merge/data/questions.json
+++ /dev/null
@@ -1,112 +0,0 @@
-[
- {
- "question": "What is the primary purpose of using a dummy node when merging two linked lists?",
- "options": [
- "To simplify pointer management and avoid edge cases",
- "To increase performance",
- "To store the tail node",
- "To sort the input lists"
- ],
- "correctAnswer": 0,
- "explanation": "A dummy node acts as a placeholder to simplify the logic and avoid handling head assignment edge cases separately."
- },
- {
- "question": "Which approach is commonly used to merge two sorted linked lists?",
- "options": [
- "Two-pointer technique",
- "Recursive backtracking",
- "Binary search",
- "Breadth-first traversal"
- ],
- "correctAnswer": 0,
- "explanation": "The two-pointer technique is used to traverse both lists and compare current nodes to build the merged list."
- },
- {
- "question": "What is the time complexity of merging two sorted linked lists with a total of n nodes?",
- "options": [
- "O(log n)",
- "O(n)",
- "O(n log n)",
- "O(n²)"
- ],
- "correctAnswer": 1,
- "explanation": "Each node is visited once during the merge, leading to O(n) time complexity."
- },
- {
- "question": "What happens when one of the two input lists is empty during merging?",
- "options": [
- "The result is empty",
- "Only dummy node is returned",
- "The non-empty list is directly attached to the merged list",
- "The algorithm throws an error"
- ],
- "correctAnswer": 2,
- "explanation": "If one list is empty, the other list is appended as-is to the end of the merged list."
- },
- {
- "question": "Which of these is NOT necessary before merging two linked lists?",
- "options": [
- "Sorting both input lists",
- "Creating a dummy node",
- "Tracking the current node in merged list",
- "Comparing node values from both lists"
- ],
- "correctAnswer": 0,
- "explanation": "Sorting is not required if the input lists are already sorted."
- },
- {
- "question": "When merging lists, how do you decide which node to attach next?",
- "options": [
- "Attach the node with greater value",
- "Alternate nodes from each list",
- "Attach the node with smaller value",
- "Attach the last node from each list first"
- ],
- "correctAnswer": 2,
- "explanation": "The smaller value node is chosen to maintain sorted order."
- },
- {
- "question": "What pointer is updated after attaching a node to the merged list?",
- "options": [
- "Tail of second list",
- "Current pointer of merged list",
- "Dummy pointer",
- "Original head pointer"
- ],
- "correctAnswer": 1,
- "explanation": "After attaching a node, the current pointer in the merged list is updated to point to the newly added node."
- },
- {
- "question": "What is the space complexity of merging two linked lists iteratively?",
- "options": [
- "O(n)",
- "O(1)",
- "O(log n)",
- "O(n²)"
- ],
- "correctAnswer": 1,
- "explanation": "Iterative merging does not require extra space beyond a few pointers (O(1) auxiliary space)."
- },
- {
- "question": "What advantage does recursion offer in list merging?",
- "options": [
- "Faster execution",
- "Less memory usage",
- "Simplified code",
- "Always better performance"
- ],
- "correctAnswer": 2,
- "explanation": "Recursion simplifies the logic but can use more stack space."
- },
- {
- "question": "What kind of input lists produce a sorted merged output?",
- "options": [
- "Unsorted lists",
- "Randomly linked nodes",
- "Already sorted lists",
- "Lists with circular references"
- ],
- "correctAnswer": 2,
- "explanation": "Merging produces a sorted result only when both input lists are sorted."
- }
-]
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/merge/page.jsx b/app/visualizer/linkedList/operations/merge/page.jsx
deleted file mode 100755
index 18dfc2e91..000000000
--- a/app/visualizer/linkedList/operations/merge/page.jsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import Animation from "@/app/visualizer/linkedList/operations/merge/animation";
-import Navbar from "@/app/components/navbarinner";
-
-export const metadata = {
- title: 'Linked List Merge Algorithm | Interactive Visualization & Step-by-Step Guide',
- description:
- 'Learn how merging works in Linked Lists with interactive animations, detailed explanations, and hands-on practice. Visualize each step of the merge process and master linked list algorithms efficiently.',
- keywords: [
- 'Linked List Merge',
- 'Merge Animation Linked List',
- 'Visualize Merge in Linked List',
- 'Linked List Algorithm',
- 'DSA Linked List Merge',
- 'Linked List Merge Visualization',
- 'Interactive Linked List',
- 'Merge Step-by-Step',
- 'Linked List Learning',
- 'Data Structures Animation',
- 'DSA Practice Linked List',
- 'Merge Code Example',
- 'Linked List Tutorial',
- 'Merge using C',
- 'Merge using Java',
- 'Merge using Javascript',
- 'Merge using Python',
- 'Merge using linked list',
- ],
- robots: 'index, follow',
-};
-
-export default function Page() {
- return (
- <>
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/merge/quiz.jsx b/app/visualizer/linkedList/operations/merge/quiz.jsx
deleted file mode 100755
index 48ff71347..000000000
--- a/app/visualizer/linkedList/operations/merge/quiz.jsx
+++ /dev/null
@@ -1,398 +0,0 @@
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import Questions from "@/app/visualizer/linkedList/operations/merge/data/questions.json"
-
-const Quiz = () => {
-const questions = Questions;
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Merging Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default Quiz;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/reverse/animation.jsx b/app/visualizer/linkedList/operations/reverse/animation.jsx
deleted file mode 100755
index d690ca532..000000000
--- a/app/visualizer/linkedList/operations/reverse/animation.jsx
+++ /dev/null
@@ -1,380 +0,0 @@
-"use client";
-import React, { useState, useRef, useEffect } from 'react';
-import { gsap } from 'gsap';
-import Footer from '@/app/components/footer';
-import ExploreOther from '@/app/components/ui/exploreOther';
-import BackToTop from '@/app/components/ui/backtotop';
-import GoBackButton from "@/app/components/ui/goback";
-import Content from "@/app/visualizer/linkedList/operations/reverse/content";
-import Quiz from "@/app/visualizer/linkedList/operations/reverse/quiz";
-import CodeBlock from "@/app/visualizer/linkedList/operations/reverse/codeBlock";
-
-const LinkedListReverse = () => {
- const [list, setList] = useState([]);
- const [isAnimating, setIsAnimating] = useState(false);
- const [currentPointer, setCurrentPointer] = useState(-1);
- const [prevPointer, setPrevPointer] = useState(-1);
- const [nextPointer, setNextPointer] = useState(-1);
- const listRefs = useRef([]);
- const containerRef = useRef(null);
- const animationTimeline = useRef(gsap.timeline());
-
- // Generate random linked list with realistic values
- const generateRandomList = () => {
- const size = Math.floor(Math.random() * 3) + 3; // 3-5 nodes
- const values = Array.from({ length: size }, (_, i) => {
- const base = Math.floor(Math.random() * 20) + 1;
- return base + i * 5;
- });
- const newList = values.map((value, index) => ({
- value,
- id: Date.now() + index + Math.random(),
- next: index < size - 1 ? `0x${(1000 + index).toString(16).padStart(4, '0')}` : 'NULL'
- }));
- setList(newList);
- setCurrentPointer(-1);
- setPrevPointer(-1);
- setNextPointer(-1);
- };
-
- // Reset handler
- const handleReset = () => {
- gsap.killTweensOf("*");
- animationTimeline.current.clear();
- setList([]);
- setIsAnimating(false);
- setCurrentPointer(-1);
- setPrevPointer(-1);
- setNextPointer(-1);
- listRefs.current = [];
- };
-
- // Animate the reverse process step-by-step with pointer logic and visual next updates
- const animateReverse = async () => {
- if (isAnimating || list.length === 0) return;
- setIsAnimating(true);
- animationTimeline.current.clear();
-
- // Copy list so we can mutate next pointers
- let nodes = list.map(node => ({ ...node }));
- let prevIndex = -1;
- let currentIndex = 0;
- let nextIndex = nodes[currentIndex] && nodes[currentIndex].next === 'NULL' ? -1 : currentIndex + 1;
-
- // Helper to update next pointer string after rewiring
- const updateNextField = (index, nextIdx) => {
- if (nextIdx === -1) {
- nodes[index].next = 'NULL';
- } else {
- nodes[index].next = `0x${(1000 + nextIdx).toString(16).padStart(4, '0')}`;
- }
- };
-
- // Initial highlight setup: reset all nodes to base color
- gsap.set(listRefs.current, {
- backgroundColor: '#10b981',
- scale: 1,
- opacity: 1,
- clearProps: 'all'
- });
-
- // Animate function to highlight nodes with different colors
- const highlightNodes = (prevI, currI, nextI) => {
- listRefs.current.forEach((el, idx) => {
- if (!el) return;
- if (idx === currI) {
- gsap.to(el, { backgroundColor: '#2563eb', scale: 1.1, duration: 0.3 }); // current - blue
- } else if (idx === prevI) {
- gsap.to(el, { backgroundColor: '#f59e0b', scale: 1.05, duration: 0.3 }); // prev - amber
- } else if (idx === nextI) {
- gsap.to(el, { backgroundColor: '#6b7280', scale: 1, duration: 0.3 }); // next - gray
- } else {
- gsap.to(el, { backgroundColor: '#10b981', scale: 1, duration: 0.3 }); // normal - green
- }
- });
- };
-
- // Create pointer arrows or labels overlays
- // We'll create divs for prev, current, next pointers positioned above nodes
- const pointerContainer = document.createElement('div');
- pointerContainer.style.position = 'relative';
- pointerContainer.style.width = '100%';
- pointerContainer.style.height = '0px';
- pointerContainer.style.marginBottom = '8px';
- containerRef.current.prepend(pointerContainer);
-
- const createPointerLabel = (color, text) => {
- const label = document.createElement('div');
- label.textContent = text;
- label.style.position = 'absolute';
- label.style.top = '0px';
- label.style.padding = '2px 6px';
- label.style.borderRadius = '4px';
- label.style.color = 'white';
- label.style.fontSize = '12px';
- label.style.fontWeight = 'bold';
- label.style.backgroundColor = color;
- label.style.pointerEvents = 'none';
- label.style.whiteSpace = 'nowrap';
- label.style.transition = 'left 0.5s ease';
- pointerContainer.appendChild(label);
- return label;
- };
-
- const prevLabel = createPointerLabel('#f59e0b', 'Prev');
- const currentLabel = createPointerLabel('#2563eb', 'Current');
- const nextLabel = createPointerLabel('#6b7280', 'Next');
-
- // Helper to position pointer labels above the nodes
- const positionPointers = (prevI, currI, nextI) => {
- const containerRect = containerRef.current.getBoundingClientRect();
- const offsetTop = -30; // above nodes
-
- const setLabelPos = (label, idx) => {
- if (idx === -1) {
- label.style.opacity = '0';
- return;
- }
- const nodeEl = listRefs.current[idx];
- if (!nodeEl) {
- label.style.opacity = '0';
- return;
- }
- const rect = nodeEl.getBoundingClientRect();
- const left = rect.left - containerRect.left + rect.width / 2 - label.offsetWidth / 2;
- label.style.left = `${left}px`;
- label.style.top = `${offsetTop}px`;
- label.style.opacity = '1';
- };
-
- setLabelPos(prevLabel, prevI);
- setLabelPos(currentLabel, currI);
- setLabelPos(nextLabel, nextI);
- };
-
- // Initial pointer positions
- setCurrentPointer(currentIndex);
- setPrevPointer(prevIndex);
- setNextPointer(nextIndex);
- highlightNodes(prevIndex, currentIndex, nextIndex);
- positionPointers(prevIndex, currentIndex, nextIndex);
-
- // Animate the reversal step by step
- while (currentIndex !== -1) {
- setCurrentPointer(currentIndex);
- setPrevPointer(prevIndex);
- setNextPointer(nextIndex);
- highlightNodes(prevIndex, currentIndex, nextIndex);
- positionPointers(prevIndex, currentIndex, nextIndex);
-
- // Wait a bit for user to see pointers
- await new Promise(r => setTimeout(r, 800));
-
- // Show rewiring: change current node's next pointer to prev
- animationTimeline.current.clear();
-
- // Animate the 'next' field text change
- const currentNodeEl = listRefs.current[currentIndex];
- if (currentNodeEl) {
- const nextFieldEl = currentNodeEl.querySelector('.text-xs');
- if (nextFieldEl) {
- // Animate fade out, change text, fade in
- await new Promise(resolve => {
- gsap.to(nextFieldEl, {
- opacity: 0,
- duration: 0.3,
- onComplete: () => {
- updateNextField(currentIndex, prevIndex);
- setList([...nodes]);
- resolve();
- }
- });
- });
- await new Promise(resolve => {
- gsap.to(nextFieldEl, {
- opacity: 1,
- duration: 0.3,
- onComplete: resolve
- });
- });
- }
- }
-
- // Small pause after rewiring
- await new Promise(r => setTimeout(r, 500));
-
- // Move pointers forward for next iteration
- const tempNext = nextIndex;
- prevIndex = currentIndex;
- currentIndex = nextIndex;
- nextIndex = currentIndex !== -1 && nodes[currentIndex].next !== 'NULL' ? currentIndex + 1 : -1;
- }
-
- // Final highlight: all nodes green, pointers hidden
- highlightNodes(-1, -1, -1);
- setCurrentPointer(-1);
- setPrevPointer(-1);
- setNextPointer(-1);
- positionPointers(-1, -1, -1);
-
- // Remove pointer labels after animation finished
- await new Promise(r => setTimeout(r, 500));
- if (pointerContainer.parentNode) {
- pointerContainer.parentNode.removeChild(pointerContainer);
- }
-
- setIsAnimating(false);
- };
-
- // Update refs when list changes
- useEffect(() => {
- listRefs.current = listRefs.current.slice(0, list.length);
- }, [list]);
-
- return (
-
-
-
-
-
-
-
- Linked List Reverse
-
-
-
-
-
- Visualize reversing a linked list step by step
-
-
- {/* Controls - Responsive */}
-
-
-
-
-
- Generate List
-
-
-
-
- {isAnimating ? "Reversing..." : "Reverse List"}
-
-
- Reset All
-
-
-
-
-
-
- {/* Legend - Responsive */}
-
-
- {/* Visualization Area */}
-
- {/* List */}
-
-
- List {currentPointer >= 0 && `(Current: ${currentPointer + 1})`}
-
-
- {list.length === 0 ? (
-
- Generate List to begin
-
- ) : (
-
- {list.map((node, index) => (
-
- (listRefs.current[index] = el)}
- className={`node flex flex-col items-center justify-center text-white text-lg w-20 h-16 rounded-md shadow-md transition-all ${
- index === currentPointer
- ? 'bg-blue-600 ring-4 ring-blue-300 scale-110'
- : index === prevPointer
- ? 'bg-amber-500 ring-4 ring-amber-300 scale-105'
- : index === nextPointer
- ? 'bg-gray-600 ring-2 ring-gray-400'
- : 'bg-emerald-600'
- }`}
- >
- {node.value}
-
{node.next}
-
- {index < list.length - 1 && (
-
-
-
- )}
-
- ))}
-
- )}
-
-
-
-
-
- Test Your Knowledge Before Moving Forward!
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default LinkedListReverse;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/reverse/codeBlock.jsx b/app/visualizer/linkedList/operations/reverse/codeBlock.jsx
deleted file mode 100755
index 3e60a925e..000000000
--- a/app/visualizer/linkedList/operations/reverse/codeBlock.jsx
+++ /dev/null
@@ -1,159 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-import CodeExamples from "@/app/visualizer/linkedList/operations/reverse/data/codeExamples.json";
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const codeExamples = CodeExamples
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Linked List Reversal Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/reverse/data/codeExamples.json b/app/visualizer/linkedList/operations/reverse/data/codeExamples.json
deleted file mode 100755
index a3180d10c..000000000
--- a/app/visualizer/linkedList/operations/reverse/data/codeExamples.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "javascript": "class Node {\n constructor(data) {\n this.data = data;\n this.next = null;\n }\n}\n\nfunction reverseList(head) {\n let prev = null;\n let current = head;\n\n while (current) {\n let next = current.next;\n current.next = prev;\n prev = current;\n current = next;\n }\n\n return prev;\n}",
- "python": "class Node:\n def __init__(self, data):\n self.data = data\n self.next = None\n\ndef reverse_list(head):\n prev = None\n current = head\n\n while current:\n next_node = current.next\n current.next = prev\n prev = current\n current = next_node\n\n return prev",
- "java": "class Node {\n int data;\n Node next;\n Node(int data) {\n this.data = data;\n this.next = null;\n }\n}\n\npublic class ReverseList {\n public static Node reverse(Node head) {\n Node prev = null;\n Node current = head;\n\n while (current != null) {\n Node next = current.next;\n current.next = prev;\n prev = current;\n current = next;\n }\n\n return prev;\n }\n}",
- "c": "#include \n#include \n\ntypedef struct Node {\n int data;\n struct Node* next;\n} Node;\n\nNode* reverseList(Node* head) {\n Node* prev = NULL;\n Node* current = head;\n\n while (current) {\n Node* next = current->next;\n current->next = prev;\n prev = current;\n current = next;\n }\n\n return prev;\n}",
- "cpp": "#include \nusing namespace std;\n\nclass Node {\npublic:\n int data;\n Node* next;\n Node(int d) : data(d), next(nullptr) {}\n};\n\nNode* reverseList(Node* head) {\n Node* prev = nullptr;\n Node* current = head;\n\n while (current) {\n Node* next = current->next;\n current->next = prev;\n prev = current;\n current = next;\n }\n\n return prev;\n}"
-}
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/reverse/data/questions.json b/app/visualizer/linkedList/operations/reverse/data/questions.json
deleted file mode 100755
index 447da74a7..000000000
--- a/app/visualizer/linkedList/operations/reverse/data/questions.json
+++ /dev/null
@@ -1,112 +0,0 @@
-[
- {
- "question": "What is the primary purpose of reversing a linked list?",
- "options": [
- "To traverse the list in reverse order",
- "To sort the list",
- "To delete all nodes",
- "To merge two lists"
- ],
- "correctAnswer": 0,
- "explanation": "Reversing a linked list allows you to traverse the list from tail to head, which is not directly possible in a singly linked list."
- },
- {
- "question": "Which pointers are typically used during the reversal process?",
- "options": [
- "Current, Previous, Next",
- "Head, Tail, Middle",
- "Left, Right, Mid",
- "Start, End, Temp"
- ],
- "correctAnswer": 0,
- "explanation": "The reversal process commonly uses three pointers: current (the node being processed), previous (the node before current), and next (the node after current)."
- },
- {
- "question": "What is the time complexity of reversing a singly linked list iteratively?",
- "options": [
- "O(1)",
- "O(log n)",
- "O(n)",
- "O(n^2)"
- ],
- "correctAnswer": 2,
- "explanation": "Each node is visited once, so the time complexity is O(n)."
- },
- {
- "question": "What happens to the original head after a successful reversal?",
- "options": [
- "It becomes the new tail",
- "It is deleted",
- "It remains the head",
- "It points to itself"
- ],
- "correctAnswer": 0,
- "explanation": "After reversal, the original head node becomes the new tail of the linked list."
- },
- {
- "question": "What is the space complexity of the iterative reversal approach?",
- "options": [
- "O(n)",
- "O(1)",
- "O(log n)",
- "O(n^2)"
- ],
- "correctAnswer": 1,
- "explanation": "Iterative reversal only uses a few pointers, so it has O(1) auxiliary space complexity."
- },
- {
- "question": "What is the final value of the `.next` field of the new tail node after reversal?",
- "options": [
- "Points to the old head",
- "Points to itself",
- "Is null",
- "Points to the new head"
- ],
- "correctAnswer": 2,
- "explanation": "The new tail node's `.next` should be set to null, indicating the end of the list."
- },
- {
- "question": "What happens if you reverse an empty linked list?",
- "options": [
- "It throws an error",
- "The result is still an empty list",
- "It becomes a circular list",
- "It creates a new node"
- ],
- "correctAnswer": 1,
- "explanation": "Reversing an empty linked list results in an empty list (null head)."
- },
- {
- "question": "How can you visually confirm that the list has been reversed?",
- "options": [
- "By checking if the order of nodes is flipped",
- "By checking if the length has changed",
- "By checking memory addresses",
- "By checking if all values are zero"
- ],
- "correctAnswer": 0,
- "explanation": "The order of nodes should be the exact reverse of the original list."
- },
- {
- "question": "What should be done before changing the `.next` pointer of a node?",
- "options": [
- "Save the next node in a temporary variable",
- "Delete the node",
- "Set the node's value to zero",
- "Move the head pointer"
- ],
- "correctAnswer": 0,
- "explanation": "Always save the next node in a temporary variable before changing `.next`, or you may lose access to the rest of the list."
- },
- {
- "question": "Which approach is safer in terms of memory usage for large lists?",
- "options": [
- "Recursive reversal",
- "Iterative reversal",
- "Merging",
- "Sorting"
- ],
- "correctAnswer": 1,
- "explanation": "Iterative reversal is safer for large lists because it uses constant space, whereas recursion can cause stack overflow."
- }
-]
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/reverse/page.jsx b/app/visualizer/linkedList/operations/reverse/page.jsx
deleted file mode 100755
index 9be76f911..000000000
--- a/app/visualizer/linkedList/operations/reverse/page.jsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import Animation from "@/app/visualizer/linkedList/operations/reverse/animation";
-import Navbar from "@/app/components/navbarinner";
-
-export const metadata = {
- title: 'Linked List Reverse Algorithm | Interactive Visualization & Step-by-Step Guide',
- description:
- 'Explore how reversing a linked list works with interactive animations, clear explanations, and hands-on practice. Visualize each step of the reverse process and master linked list algorithms efficiently.',
- keywords: [
- 'Linked List Reverse',
- 'Reverse Animation Linked List',
- 'Visualize Reverse in Linked List',
- 'Linked List Algorithm',
- 'DSA Linked List Reverse',
- 'Linked List Reverse Visualization',
- 'Interactive Linked List',
- 'Reverse Step-by-Step',
- 'Linked List Learning',
- 'Data Structures Animation',
- 'DSA Practice Linked List',
- 'Reverse Code Example',
- 'Linked List Tutorial',
- 'Reverse using C',
- 'Reverse using Java',
- 'Reverse using Javascript',
- 'Reverse using Python',
- 'Reverse linked list',
- ],
- robots: 'index, follow',
-};
-
-export default function Page() {
- return (
- <>
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/reverse/quiz.jsx b/app/visualizer/linkedList/operations/reverse/quiz.jsx
deleted file mode 100755
index 35ebd0a89..000000000
--- a/app/visualizer/linkedList/operations/reverse/quiz.jsx
+++ /dev/null
@@ -1,398 +0,0 @@
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import Questions from "@/app/visualizer/linkedList/operations/reverse/data/questions.json";
-
-const Quiz = () => {
-const questions = Questions
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Reverse Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default Quiz;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/traversal/animation.jsx b/app/visualizer/linkedList/operations/traversal/animation.jsx
deleted file mode 100755
index b45cf7a03..000000000
--- a/app/visualizer/linkedList/operations/traversal/animation.jsx
+++ /dev/null
@@ -1,306 +0,0 @@
-"use client";
-import React, { useState, useRef, useEffect } from 'react';
-import { gsap } from 'gsap';
-import Footer from '@/app/components/footer';
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Content from "@/app/visualizer/linkedList/operations/traversal/content";
-import Quiz from '@/app/visualizer/linkedList/operations/traversal/quiz';
-import CodeBlock from "@/app/visualizer/linkedList/operations/traversal/codeBlock";
-import BackToTop from '@/app/components/ui/backtotop';
-import GoBackButton from "@/app/components/ui/goback";
-
-const LinkedListTraversal = () => {
- const [list, setList] = useState([]);
- const [isAnimating, setIsAnimating] = useState(false);
- const nodeRefs = useRef([]);
- const arrowRefs = useRef([]);
- const addressRefs = useRef([]);
- const containerRef = useRef(null);
- const animationTimeline = useRef(gsap.timeline());
-
- // Generate random linked list with cute emoji values
- const generateRandomList = () => {
- if (isAnimating) return;
- handleReset();
-
- const emojis = ['🐶', '🐱', '🐭', '🐹', '🐰', '🦊', '🐻', '🐼'];
- const size = Math.min(Math.floor(Math.random() * 3) + 3, emojis.length); //nodes
- const shuffledEmojis = [...emojis].sort(() => 0.5 - Math.random());
-
- const newList = shuffledEmojis.slice(0, size).map((emoji, index) => ({
- value: emoji,
- id: Date.now() + index,
- address: `0x${Math.floor(Math.random() * 0x10000).toString(16).padStart(4, '0')}`,
- next: index < size - 1 ? `0x${Math.floor(Math.random() * 0x10000).toString(16).padStart(4, '0')}` : 'NULL'
- }));
-
- setList(newList);
- };
-
- // Animate traversal with cute bouncy effect
- const animateTraversal = () => {
- if (isAnimating || list.length === 0) return;
- setIsAnimating(true);
-
- // Reset all nodes to default state
- gsap.set(nodeRefs.current, {
- backgroundColor: '#3b82f6',
- scale: 1,
- y: 0
- });
-
- gsap.set(arrowRefs.current, {
- opacity: 0.6,
- scale: 1
- });
-
- gsap.set(addressRefs.current, {
- color: '#6b7280'
- });
-
- animationTimeline.current.clear();
-
- list.forEach((node, index) => {
- // Bounce-in effect for node
- animationTimeline.current.to(nodeRefs.current[index], {
- duration: 0.5,
- backgroundColor: '#10b981',
- scale: 1.2,
- y: -20,
- ease: 'elastic.out(1, 0.5)'
- }, `+=${index * 0.3}`);
-
- // Highlight address
- animationTimeline.current.to(addressRefs.current[index], {
- duration: 0.3,
- color: '#3b82f6',
- fontWeight: 'bold',
- ease: 'power1.inOut'
- }, `-=${0.4}`);
-
- // Highlight arrow if not last node
- if (index < list.length - 1) {
- animationTimeline.current.to(arrowRefs.current[index], {
- duration: 0.3,
- opacity: 1,
- scale: 1.3,
- ease: 'power1.inOut'
- }, `-=${0.3}`);
- }
-
- // Return to normal state
- animationTimeline.current.to(nodeRefs.current[index], {
- duration: 0.5,
- backgroundColor: '#3b82f6',
- scale: 1,
- y: 0,
- ease: 'back.out(1)'
- }, `+=${0.2}`);
-
- if (index < list.length - 1) {
- animationTimeline.current.to(arrowRefs.current[index], {
- duration: 0.3,
- opacity: 0.6,
- scale: 1,
- ease: 'power1.inOut'
- }, `+=${0.1}`);
- }
-
- animationTimeline.current.to(addressRefs.current[index], {
- duration: 0.3,
- color: '#6b7280',
- fontWeight: 'normal',
- ease: 'power1.inOut'
- }, `+=${0.1}`);
- });
-
- animationTimeline.current.eventCallback('onComplete', () => {
- setIsAnimating(false);
- });
- };
-
- // Reset handler
- const handleReset = () => {
- gsap.killTweensOf("*");
- animationTimeline.current.clear();
- setList([]);
- setIsAnimating(false);
- nodeRefs.current = [];
- arrowRefs.current = [];
- addressRefs.current = [];
- };
-
- // Update refs when list changes
- useEffect(() => {
- nodeRefs.current = nodeRefs.current.slice(0, list.length);
- arrowRefs.current = arrowRefs.current.slice(0, Math.max(0, list.length - 1));
- addressRefs.current = addressRefs.current.slice(0, list.length);
- }, [list]);
-
- return (
-
-
-
-
-
-
-
- Linked List Traversal
-
-
-
-
- Visualize how we traverse through each node in a linked list
-
-
- {/* Controls - Responsive */}
-
-
-
- {/* Buttons for desktop */}
-
-
- Generate List
-
-
- {isAnimating ? "Traversing..." : "Animate Traversal"}
-
-
- Reset
-
-
-
- {/* Buttons for mobile */}
-
-
- 🎲 Generate List
-
-
- ✨ {isAnimating ? "Traversing..." : "Animate Traversal"}
-
-
- 🔄 Reset
-
-
-
-
-
-
- {/* Legend - Responsive */}
-
-
- {/* Visualization Area */}
-
-
- {list.length === 0 ? (
-
- Click "Generate List" to create a linked list 🌈
-
- ) : (
-
- {list.map((node, index) => (
-
-
-
addressRefs.current[index] = el}>
- {node.address}
-
-
(nodeRefs.current[index] = el)}
- className="node flex flex-col items-center justify-center bg-blue-500 text-white text-3xl w-16 h-16 rounded-full shadow-md cursor-pointer hover:shadow-lg transition-all"
- onClick={animateTraversal}
- >
- {node.value}
-
-
- Next: {node.next}
-
-
- {index < list.length - 1 && (
- (arrowRefs.current[index] = el)}
- className="w-8 h-8 my-4 opacity-60 text-gray-600 dark:text-gray-300"
- viewBox="0 0 24 24"
- fill="none"
- stroke="currentColor"
- strokeWidth="2"
- strokeLinecap="round"
- strokeLinejoin="round"
- >
-
-
- )}
-
- ))}
-
- )}
-
-
-
-
- Test Your Knowledge Before Moving Forward!
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default LinkedListTraversal;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/traversal/codeBlock.jsx b/app/visualizer/linkedList/operations/traversal/codeBlock.jsx
deleted file mode 100755
index 2c401ea0a..000000000
--- a/app/visualizer/linkedList/operations/traversal/codeBlock.jsx
+++ /dev/null
@@ -1,159 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-import CodeExamples from "@/app/visualizer/linkedList/operations/traversal/data/codeExamples.json"
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
-const codeExamples = CodeExamples;
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Linked List Insertion Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/traversal/content.jsx b/app/visualizer/linkedList/operations/traversal/content.jsx
deleted file mode 100755
index 68838314d..000000000
--- a/app/visualizer/linkedList/operations/traversal/content.jsx
+++ /dev/null
@@ -1,261 +0,0 @@
-const content = () => {
- const overview = [
- `Linked List traversal involves visiting each node in the list exactly once, starting from the head and moving through the next pointers until the end is reached.`,
- `Traversal is essential for operations like searching, displaying, or processing each element of the list. It ensures that all elements are accessed in sequence.`,
- `Understanding traversal is a foundational step for more advanced linked list algorithms, including deletion, reversal, and cycle detection.`,
- ];
-
- const traversalTypes = [
- {
- name: "Iterative Traversal",
- complexity: "O(n)",
- description: "Uses a loop to traverse from head to end of list",
- code: `function traverseIterative() {
- let current = head;
- while (current) {
- console.log(current.data);
- current = current.next;
- }
-}`
- },
- {
- name: "Recursive Traversal",
- complexity: "O(n) and O(n) space (due to recursion stack)",
- description: "Uses recursion to print each node from head to end",
- code: `function traverseRecursive(node) {
- if (!node) return;
- console.log(node.data);
- traverseRecursive(node.next);
-}`
- }
- ];
-
- const traversalSteps = [
- { step: "Start from the head node" },
- { step: "Access the data of the current node" },
- { step: "Move to the next node using the next pointer" },
- { step: "Repeat until the current node becomes null" }
- ];
-
- const visualization = [
- { operation: "Initial State", state: "head → [A] → [B] → [C] → null" },
- { operation: "Traverse", state: "Visited: A → B → C" }
- ];
-
- const edgeCases = [
- "Empty list (head = null)",
- "Single-node list (head → [A] → null)",
- "List with cycles (can cause infinite traversal if not handled)",
- "Recursive traversal stack overflow for large lists"
- ];
-
- const bestPractices = [
- "Always check if the list is empty before traversal",
- "Avoid infinite loops by checking for cycles",
- "Use iteration for large lists to prevent stack overflow",
- "Keep traversal read-only unless modifying the list is necessary",
- "Separate logic for display and manipulation for better modularity"
- ];
-
- const comparisonTable = [
- {
- feature: "Time Complexity",
- array: "O(n)",
- linkedList: "O(n)"
- },
- {
- feature: "Access Method",
- array: "Direct via index",
- linkedList: "Sequential via next pointer"
- },
- {
- feature: "Recursion Friendly",
- array: "Not typically used recursively",
- linkedList: "Supports recursive traversal"
- },
- {
- feature: "Loop Detection Required",
- array: "Not needed",
- linkedList: "May be necessary in some cases"
- }
- ];
-
- return (
-
-
- {/* Overview Section */}
-
-
-
- Traversal
-
-
- {overview.map((para, index) => (
-
- {para}
-
- ))}
-
-
- Key Insight: Traversal is the basis for all linked list operations—ensure you visit every node, and beware of cycles that can cause infinite loops.
-
-
-
-
-
- {/* Traversal Types */}
-
- Traversal Types
-
- {traversalTypes.map((type, index) => (
-
-
{type.name}
-
-
-
Complexity: {type.complexity}
-
{type.description}
-
-
-
-
- ))}
-
-
-
- {/* Traversal Process */}
-
- Traversal Process
-
-
- {traversalSteps.map((step, index) => (
- {step.step}
- ))}
-
-
-
-
- {/* Visualization */}
-
- Operation Visualization
-
-
-
-
- Operation
- List State
-
-
-
- {visualization.map((item, index) => (
-
- {item.operation}
- {item.state}
-
- ))}
-
-
-
-
-
- {/* Edge Cases */}
-
- Edge Cases to Consider
-
- {edgeCases.map((caseItem, index) => (
-
- ))}
-
-
-
- {/* Best Practices */}
-
- Best Practices
-
- {bestPractices.map((practice, index) => (
-
- ))}
-
-
-
- {/* Comparison with Arrays */}
-
- Comparison with Array Traversal
-
-
-
-
- Feature
- Array
- Linked List
-
-
-
- {comparisonTable.map((row, index) => (
-
- {row.feature}
- {row.array}
- {row.linkedList}
-
- ))}
-
-
-
-
-
- When to Choose: Use arrays for indexed, direct access and linked lists for flexible sequential access and recursive algorithms.
-
-
-
-
- {/* Final Notes */}
-
- Implementation Notes
-
-
-
- Cycle Detection: Be cautious of loops in the list during traversal, consider Floyd’s algorithm for detection
-
-
- Logging: Use console or UI to log visited nodes during visualization
-
-
- Testing: Test traversal on empty, single-node, and multi-node lists
-
-
- Efficiency: For large lists, prefer iteration to avoid stack issues with recursion
-
-
-
-
-
-
- );
-};
-
-export default content;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/traversal/data/codeExamples.json b/app/visualizer/linkedList/operations/traversal/data/codeExamples.json
deleted file mode 100755
index d9544feea..000000000
--- a/app/visualizer/linkedList/operations/traversal/data/codeExamples.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "javascript": "class Node {\n constructor(data) {\n this.data = data;\n this.next = null;\n }\n}\n\nfunction traverse(head) {\n let current = head;\n while (current) {\n console.log(current.data);\n current = current.next;\n }\n}\n\nlet head = new Node(1);\nhead.next = new Node(2);\nhead.next.next = new Node(3);\ntraverse(head);",
- "python": "class Node:\n def __init__(self, data):\n self.data = data\n self.next = None\n\ndef traverse(head):\n current = head\n while current:\n print(current.data)\n current = current.next\n\nhead = Node(1)\nhead.next = Node(2)\nhead.next.next = Node(3)\ntraverse(head)",
- "java": "class Node {\n int data;\n Node next;\n Node(int data) {\n this.data = data;\n this.next = null;\n }\n}\n\npublic class Main {\n public static void traverse(Node head) {\n Node current = head;\n while (current != null) {\n System.out.println(current.data);\n current = current.next;\n }\n }\n\n public static void main(String[] args) {\n Node head = new Node(1);\n head.next = new Node(2);\n head.next.next = new Node(3);\n traverse(head);\n }\n}",
- "c": "#include \n#include \n\nstruct Node {\n int data;\n struct Node* next;\n};\n\nvoid traverse(struct Node* head) {\n struct Node* current = head;\n while (current != NULL) {\n printf(\"%d\\n\", current->data);\n current = current->next;\n }\n}\n\nint main() {\n struct node * head = (struct node *)malloc(sizeof(struct node));\n struct node * second = (struct node *)malloc(sizeof(struct node));\n struct node * third = (struct node *)malloc(sizeof(struct node));\n\n head->data = 1;\n head->next = second;\n second->data = 2;\n second->next = third;\n third->data = 3;\n third->next = NULL;\n\n traverse(head);\n\n return 0;\n}",
- "cpp": "#include \nusing namespace std;\n\nclass Node {\npublic:\n int data;\n Node* next;\n Node(int data) : data(data), next(nullptr) {}\n};\n\nvoid traverse(Node* head) {\n Node* current = head;\n while (current != nullptr) {\n cout << current->data << endl;\n current = current->next;\n }\n}\n\nint main() {\n Node* head = new Node(1);\n head->next = new Node(2);\n head->next->next = new Node(3);\n traverse(head);\n\n // Free memory\n Node* temp;\n while (head != nullptr) {\n temp = head;\n head = head->next;\n delete temp;\n }\n\n return 0;\n}"
-}
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/traversal/data/questions.json b/app/visualizer/linkedList/operations/traversal/data/questions.json
deleted file mode 100755
index 9ad58cccf..000000000
--- a/app/visualizer/linkedList/operations/traversal/data/questions.json
+++ /dev/null
@@ -1,112 +0,0 @@
-[
- {
- "question": "What is the main purpose of linked list traversal?",
- "options": [
- "To modify the structure of the list",
- "To search, display or process each node",
- "To reverse the list",
- "To insert nodes efficiently"
- ],
- "correctAnswer": 1,
- "explanation": "Traversal allows visiting each node for operations like searching, displaying, or processing."
- },
- {
- "question": "What is the time complexity of traversing a singly linked list with 'n' nodes?",
- "options": [
- "O(1)",
- "O(log n)",
- "O(n)",
- "O(n log n)"
- ],
- "correctAnswer": 2,
- "explanation": "Each of the n nodes is visited once, so the time complexity is O(n)."
- },
- {
- "question": "What happens if a linked list has a cycle and you traverse it without detection?",
- "options": [
- "Traversal ends normally",
- "Compiler throws an error",
- "Traversal goes into infinite loop",
- "Nodes are skipped"
- ],
- "correctAnswer": 2,
- "explanation": "A cycle in the list causes infinite traversal unless cycle detection is implemented."
- },
- {
- "question": "Which traversal method uses the call stack and can risk stack overflow?",
- "options": [
- "Iterative traversal",
- "Recursive traversal",
- "Tail traversal",
- "Breadth-first traversal"
- ],
- "correctAnswer": 1,
- "explanation": "Recursive traversal uses the call stack and may overflow for large lists."
- },
- {
- "question": "Which pointer is used to move through a singly linked list during traversal?",
- "options": [
- "prev",
- "head",
- "tail",
- "current"
- ],
- "correctAnswer": 3,
- "explanation": "A 'current' pointer is typically used to walk through the nodes starting from head."
- },
- {
- "question": "When does a traversal loop stop in a properly structured singly linked list?",
- "options": [
- "When current equals head",
- "When current becomes null",
- "When current reaches tail",
- "After n iterations"
- ],
- "correctAnswer": 1,
- "explanation": "Traversal ends when the current pointer reaches null."
- },
- {
- "question": "Which of the following is NOT an edge case in traversal?",
- "options": [
- "Empty list",
- "List with a cycle",
- "List with one node",
- "Head insertion"
- ],
- "correctAnswer": 3,
- "explanation": "Head insertion is not a traversal case; it's an insertion case."
- },
- {
- "question": "Why is it recommended to use iteration over recursion for large lists?",
- "options": [
- "Recursion is slower",
- "Iteration uses less memory",
- "Recursion doesn’t work with linked lists",
- "Iteration is more readable"
- ],
- "correctAnswer": 1,
- "explanation": "Iteration avoids the overhead of recursive call stacks and prevents stack overflow."
- },
- {
- "question": "What is a key insight for safe traversal?",
- "options": [
- "Skip null checks to save time",
- "Pre-allocate nodes for speed",
- "Ensure there are no cycles",
- "Avoid using a current pointer"
- ],
- "correctAnswer": 2,
- "explanation": "Cycle detection (like Floyd’s algorithm) is important to avoid infinite loops."
- },
- {
- "question": "How many times is each node visited during traversal?",
- "options": [
- "Only first and last nodes",
- "Only once",
- "Depends on data",
- "Until tail is updated"
- ],
- "correctAnswer": 1,
- "explanation": "Each node is visited once in a standard traversal operation."
- }
-]
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/traversal/page.jsx b/app/visualizer/linkedList/operations/traversal/page.jsx
deleted file mode 100755
index ea52d723a..000000000
--- a/app/visualizer/linkedList/operations/traversal/page.jsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import Animation from "@/app/visualizer/linkedList/operations/traversal/animation";
-import Navbar from "@/app/components/navbarinner";
-
-export const metadata = {
- title: 'Linked List Traversal Algorithm | Interactive Visualization & Step-by-Step Guide',
- description:
- 'Explore how traversal works in Linked Lists with interactive animations, clear explanations, and hands-on practice. Visualize each step of the traversal process and master linked list algorithms efficiently.',
- keywords: [
- 'Linked List Traversal',
- 'Traversal Animation Linked List',
- 'Visualize Traversal in Linked List',
- 'Linked List Algorithm',
- 'DSA Linked List Traversal',
- 'Linked List Traversal Visualization',
- 'Interactive Linked List',
- 'Traversal Step-by-Step',
- 'Linked List Learning',
- 'Data Structures Animation',
- 'DSA Practice Linked List',
- 'Traversal Code Example',
- 'Linked List Tutorial',
- 'Traversal using C',
- 'Traversal using Java',
- 'Traversal using Javascript',
- 'Traversal using Python',
- 'Traversal using linked list',
- ],
- robots: 'index, follow',
-};
-export default function Page() {
- return (
- <>
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/app/visualizer/linkedList/operations/traversal/quiz.jsx b/app/visualizer/linkedList/operations/traversal/quiz.jsx
deleted file mode 100755
index 8508dcd68..000000000
--- a/app/visualizer/linkedList/operations/traversal/quiz.jsx
+++ /dev/null
@@ -1,399 +0,0 @@
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import Questions from "@/app/visualizer/linkedList/operations/traversal/data/questions.json";
-
-const Quiz = () => {
-const questions = Questions;
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Traversal Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default Quiz;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/circular/animation.jsx b/app/visualizer/linkedList/types/circular/animation.jsx
deleted file mode 100755
index da8d8caaa..000000000
--- a/app/visualizer/linkedList/types/circular/animation.jsx
+++ /dev/null
@@ -1,283 +0,0 @@
-'use client';
-import React, { useState, useRef, useEffect } from 'react';
-import { gsap } from 'gsap';
-import Footer from '@/app/components/footer';
-import ResetButton from '@/app/components/ui/resetButton';
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Content from "@/app/visualizer/linkedList/types/circular/content";
-import Quiz from '@/app/visualizer/linkedList/types/circular/quiz';
-import CodeBlock from "@/app/visualizer/linkedList/types/circular/codeBlock";
-import BackToTop from '@/app/components/ui/backtotop';
-import GoBackButton from "@/app/components/ui/goback";
-
-const CircularLinkedListVisualizer = () => {
- const [inputValue, setInputValue] = useState('');
- const [list, setList] = useState([]);
- const [isAnimating, setIsAnimating] = useState(false);
- const nodeIdCounter = useRef(1);
- const containerRef = useRef(null);
-
- // Generate random memory addresses
- const generateMemoryAddress = () => {
- return '0x' + Math.floor(Math.random() * 0xFFFF).toString(16).padStart(4, '0');
- };
-
- const addNode = () => {
- if (!inputValue || isAnimating) return;
- setIsAnimating(true);
-
- const newNode = {
- value: inputValue,
- id: nodeIdCounter.current++,
- address: generateMemoryAddress(),
- };
-
- setList(prev => {
- if (prev.length === 0) {
- newNode.next = newNode.address;
- return [newNode];
- } else {
- const updatedList = [...prev];
- newNode.next = updatedList[0].address;
- updatedList[updatedList.length - 1].next = newNode.address;
- return [...updatedList, newNode];
- }
- });
-
- setInputValue('');
- setIsAnimating(false);
- };
-
- const animateNodeAddition = (nodeId) => {
- const newNodeElement = document.querySelector(`[data-node-id="${nodeId}"]`);
- const arrows = document.querySelectorAll('.connection-arrow');
-
- if (!newNodeElement) return;
-
- // Node entry animation
- gsap.from(newNodeElement, {
- opacity: 0,
- scale: 0.5,
- duration: 0.5,
- ease: 'back.out(1.7)'
- });
-
- // Arrow animations
- gsap.from(arrows, {
- opacity: 0,
- duration: 0.3,
- stagger: 0.1
- });
- };
-
- const resetList = () => {
- // Animate nodes out
- const nodes = document.querySelectorAll('[data-node-id]');
- gsap.to(nodes, {
- opacity: 0,
- scale: 0.5,
- duration: 0.3,
- stagger: 0.05,
- onComplete: () => {
- setList([]);
- nodeIdCounter.current = 1;
- }
- });
- };
-
- useEffect(() => {
- if (list.length > 0) {
- animateNodeAddition(list[list.length - 1].id);
- }
- }, [list]);
-
- return (
-
-
- {/* go back block here */}
-
-
-
-
- {/* main logic here */}
-
- Circular Linked List
-
-
-
-
- Visualize Circular Linked List Operations
-
-
- {/* Input Form */}
-
-
-
- Node Value
-
- setInputValue(e.target.value)}
- className="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
- placeholder="Enter value"
- disabled={isAnimating}
- onKeyDown={(e) => e.key === 'Enter' && addNode()}
- />
-
-
-
- Add Node
-
-
-
-
-
- {/* Visualization Area */}
-
- {list.length === 0 ? (
-
-
-
Empty List
-
Add nodes to visualize the circular linked list
-
- ) : (
-
- {/* Circular arrangement of nodes */}
-
- {list.map((node, index) => {
- const angle = (index * (360 / list.length)) * (Math.PI / 180);
- const radius = Math.min(200, 150 + list.length * 15);
- const centerX = 0;
- const centerY = 0;
- const nodeX = centerX + radius * Math.cos(angle);
- const nodeY = centerY + radius * Math.sin(angle);
-
- return (
-
-
-
-
- {node.address}
-
-
- {index === 0 ? 'HEAD' : `Node ${index}`}
-
-
-
-
-
-
Next
-
- {node.next === node.address ? 'self' : node.next}
-
-
-
-
-
- );
- })}
-
- {/* Arrow connections */}
- {list.length > 0 && (
-
- {list.map((node, index) => {
- const nextIndex = (index + 1) % list.length;
- const angle1 = (index * (360 / list.length)) * (Math.PI / 180);
- const angle2 = (nextIndex * (360 / list.length)) * (Math.PI / 180);
- const radius = Math.min(200, 150 + list.length * 15);
- const startX = 50 + (radius * Math.cos(angle1)) / 5;
- const startY = 50 + (radius * Math.sin(angle1)) / 5;
- const endX = 50 + (radius * Math.cos(angle2)) / 5;
- const endY = 50 + (radius * Math.sin(angle2)) / 5;
-
- // Calculate control points for curved arrows
- const controlX = 50;
- const controlY = 50;
-
- return (
-
- {/* Curved path */}
-
-
- {/* Arrowhead */}
-
-
-
-
- {/* Arrow line with arrowhead */}
-
-
- );
- })}
-
- )}
-
-
- )}
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default CircularLinkedListVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/circular/codeBlock.jsx b/app/visualizer/linkedList/types/circular/codeBlock.jsx
deleted file mode 100755
index 5ebcab2ee..000000000
--- a/app/visualizer/linkedList/types/circular/codeBlock.jsx
+++ /dev/null
@@ -1,1152 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
-const codeExamples = {
- javascript: `// Circular Linked List Implementation in JavaScript
-class Node {
- constructor(data) {
- this.data = data;
- this.next = null;
- }
-}
-
-class CircularLinkedList {
- constructor() {
- this.head = null;
- this.tail = null;
- this.size = 0;
- }
-
- // Insert at beginning
- insertFirst(data) {
- const newNode = new Node(data);
- if (!this.head) {
- this.head = newNode;
- this.tail = newNode;
- newNode.next = this.head; // Point to itself
- } else {
- newNode.next = this.head;
- this.head = newNode;
- this.tail.next = this.head; // Update tail's next to new head
- }
- this.size++;
- }
-
- // Insert at end
- insertLast(data) {
- const newNode = new Node(data);
- if (!this.head) {
- this.head = newNode;
- this.tail = newNode;
- newNode.next = this.head;
- } else {
- this.tail.next = newNode;
- newNode.next = this.head;
- this.tail = newNode;
- }
- this.size++;
- }
-
- // Insert at index
- insertAt(data, index) {
- if (index < 0 || index > this.size) return;
- if (index === 0) return this.insertFirst(data);
- if (index === this.size) return this.insertLast(data);
-
- const newNode = new Node(data);
- let current = this.head;
- let count = 0;
-
- while (count < index - 1) {
- current = current.next;
- count++;
- }
-
- newNode.next = current.next;
- current.next = newNode;
- this.size++;
- }
-
- // Remove from beginning
- removeFirst() {
- if (!this.head) return null;
- const removedNode = this.head;
- if (this.size === 1) {
- this.head = null;
- this.tail = null;
- } else {
- this.head = this.head.next;
- this.tail.next = this.head; // Update tail's next to new head
- }
- this.size--;
- return removedNode.data;
- }
-
- // Remove from end
- removeLast() {
- if (!this.head) return null;
- const removedNode = this.tail;
- if (this.size === 1) {
- this.head = null;
- this.tail = null;
- } else {
- let current = this.head;
- while (current.next !== this.tail) {
- current = current.next;
- }
- current.next = this.head; // Point new tail to head
- this.tail = current;
- }
- this.size--;
- return removedNode.data;
- }
-
- // Remove at index
- removeAt(index) {
- if (index < 0 || index >= this.size) return null;
- if (index === 0) return this.removeFirst();
- if (index === this.size - 1) return this.removeLast();
-
- let current = this.head;
- let count = 0;
- while (count < index - 1) {
- current = current.next;
- count++;
- }
- const removedNode = current.next;
- current.next = removedNode.next;
- this.size--;
- return removedNode.data;
- }
-
- // Get at index
- getAt(index) {
- if (index < 0 || index >= this.size) return null;
- let current = this.head;
- let count = 0;
- while (count < index) {
- current = current.next;
- count++;
- }
- return current.data;
- }
-
- // Clear list
- clear() {
- this.head = null;
- this.tail = null;
- this.size = 0;
- }
-
- // Print list
- print() {
- if (!this.head) {
- console.log("List is empty");
- return;
- }
- let current = this.head;
- let result = "";
- do {
- result += current.data + " -> ";
- current = current.next;
- } while (current !== this.head);
- result += "(head)";
- console.log(result);
- }
-
- // Check if list is circular
- isCircular() {
- if (!this.head) return true;
- let slow = this.head;
- let fast = this.head.next;
- while (fast && fast.next) {
- if (slow === fast) return true;
- slow = slow.next;
- fast = fast.next.next;
- }
- return false;
- }
-}
-
-// Usage Example
-const cll = new CircularLinkedList();
-cll.insertFirst(100);
-cll.insertFirst(200);
-cll.insertLast(300);
-cll.insertAt(500, 1);
-cll.print(); // 200 -> 500 -> 100 -> 300 -> (head)
-cll.removeAt(2);
-console.log(cll.getAt(1)); // 500
-console.log("Is circular:", cll.isCircular()); // true`,
-
- python: `# Circular Linked List Implementation in Python
-class Node:
- def __init__(self, data):
- self.data = data
- self.next = None
-
-class CircularLinkedList:
- def __init__(self):
- self.head = None
- self.tail = None
- self.size = 0
-
- # Insert at beginning
- def insert_first(self, data):
- new_node = Node(data)
- if not self.head:
- self.head = new_node
- self.tail = new_node
- new_node.next = self.head # Point to itself
- else:
- new_node.next = self.head
- self.head = new_node
- self.tail.next = self.head # Update tail's next to new head
- self.size += 1
-
- # Insert at end
- def insert_last(self, data):
- new_node = Node(data)
- if not self.head:
- self.head = new_node
- self.tail = new_node
- new_node.next = self.head
- else:
- self.tail.next = new_node
- new_node.next = self.head
- self.tail = new_node
- self.size += 1
-
- # Insert at index
- def insert_at(self, data, index):
- if index < 0 or index > self.size:
- return
- if index == 0:
- return self.insert_first(data)
- if index == self.size:
- return self.insert_last(data)
-
- new_node = Node(data)
- current = self.head
- count = 0
-
- while count < index - 1:
- current = current.next
- count += 1
-
- new_node.next = current.next
- current.next = new_node
- self.size += 1
-
- # Remove from beginning
- def remove_first(self):
- if not self.head:
- return None
- removed_node = self.head
- if self.size == 1:
- self.head = None
- self.tail = None
- else:
- self.head = self.head.next
- self.tail.next = self.head # Update tail's next to new head
- self.size -= 1
- return removed_node.data
-
- # Remove from end
- def remove_last(self):
- if not self.head:
- return None
- removed_node = self.tail
- if self.size == 1:
- self.head = None
- self.tail = None
- else:
- current = self.head
- while current.next != self.tail:
- current = current.next
- current.next = self.head # Point new tail to head
- self.tail = current
- self.size -= 1
- return removed_node.data
-
- # Remove at index
- def remove_at(self, index):
- if index < 0 or index >= self.size:
- return None
- if index == 0:
- return self.remove_first()
- if index == self.size - 1:
- return self.remove_last()
-
- current = self.head
- count = 0
- while count < index - 1:
- current = current.next
- count += 1
-
- removed_node = current.next
- current.next = removed_node.next
- self.size -= 1
- return removed_node.data
-
- # Get at index
- def get_at(self, index):
- if index < 0 or index >= self.size:
- return None
- current = self.head
- count = 0
- while count < index:
- current = current.next
- count += 1
- return current.data
-
- # Clear list
- def clear(self):
- self.head = None
- self.tail = None
- self.size = 0
-
- # Print list
- def print_list(self):
- if not self.head:
- print("List is empty")
- return
- current = self.head
- result = []
- while True:
- result.append(str(current.data))
- current = current.next
- if current == self.head:
- break
- print(" -> ".join(result) + " -> (head)")
-
- # Check if list is circular
- def is_circular(self):
- if not self.head:
- return True
- slow = self.head
- fast = self.head.next
- while fast and fast.next:
- if slow == fast:
- return True
- slow = slow.next
- fast = fast.next.next
- return False
-
-# Usage Example
-cll = CircularLinkedList()
-cll.insert_first(100)
-cll.insert_first(200)
-cll.insert_last(300)
-cll.insert_at(500, 1)
-cll.print_list() # 200 -> 500 -> 100 -> 300 -> (head)
-cll.remove_at(2)
-print(cll.get_at(1)) # 500
-print("Is circular:", cll.is_circular()) # True`,
-
- java: `// Circular Linked List Implementation in Java
-public class CircularLinkedList {
- private class Node {
- int data;
- Node next;
-
- Node(int data) {
- this.data = data;
- this.next = null;
- }
- }
-
- private Node head;
- private Node tail;
- private int size;
-
- public CircularLinkedList() {
- head = null;
- tail = null;
- size = 0;
- }
-
- // Insert at beginning
- public void insertFirst(int data) {
- Node newNode = new Node(data);
- if (head == null) {
- head = newNode;
- tail = newNode;
- newNode.next = head; // Point to itself
- } else {
- newNode.next = head;
- head = newNode;
- tail.next = head; // Update tail's next to new head
- }
- size++;
- }
-
- // Insert at end
- public void insertLast(int data) {
- Node newNode = new Node(data);
- if (head == null) {
- head = newNode;
- tail = newNode;
- newNode.next = head;
- } else {
- tail.next = newNode;
- newNode.next = head;
- tail = newNode;
- }
- size++;
- }
-
- // Insert at index
- public void insertAt(int data, int index) {
- if (index < 0 || index > size) return;
- if (index == 0) {
- insertFirst(data);
- return;
- }
- if (index == size) {
- insertLast(data);
- return;
- }
-
- Node newNode = new Node(data);
- Node current = head;
- for (int i = 0; i < index - 1; i++) {
- current = current.next;
- }
-
- newNode.next = current.next;
- current.next = newNode;
- size++;
- }
-
- // Remove from beginning
- public Integer removeFirst() {
- if (head == null) return null;
- int removedData = head.data;
- if (size == 1) {
- head = null;
- tail = null;
- } else {
- head = head.next;
- tail.next = head; // Update tail's next to new head
- }
- size--;
- return removedData;
- }
-
- // Remove from end
- public Integer removeLast() {
- if (head == null) return null;
- int removedData = tail.data;
- if (size == 1) {
- head = null;
- tail = null;
- } else {
- Node current = head;
- while (current.next != tail) {
- current = current.next;
- }
- current.next = head; // Point new tail to head
- tail = current;
- }
- size--;
- return removedData;
- }
-
- // Remove at index
- public Integer removeAt(int index) {
- if (index < 0 || index >= size) return null;
- if (index == 0) return removeFirst();
- if (index == size - 1) return removeLast();
-
- Node current = head;
- for (int i = 0; i < index - 1; i++) {
- current = current.next;
- }
-
- int removedData = current.next.data;
- current.next = current.next.next;
- size--;
- return removedData;
- }
-
- // Get at index
- public Integer getAt(int index) {
- if (index < 0 || index >= size) return null;
- Node current = head;
- for (int i = 0; i < index; i++) {
- current = current.next;
- }
- return current.data;
- }
-
- // Clear list
- public void clear() {
- head = null;
- tail = null;
- size = 0;
- }
-
- // Print list
- public void printList() {
- if (head == null) {
- System.out.println("List is empty");
- return;
- }
- Node current = head;
- do {
- System.out.print(current.data + " -> ");
- current = current.next;
- } while (current != head);
- System.out.println("(head)");
- }
-
- // Check if list is circular
- public boolean isCircular() {
- if (head == null) return true;
- Node slow = head;
- Node fast = head.next;
- while (fast != null && fast.next != null) {
- if (slow == fast) return true;
- slow = slow.next;
- fast = fast.next.next;
- }
- return false;
- }
-
- // Usage Example
- public static void main(String[] args) {
- CircularLinkedList cll = new CircularLinkedList();
- cll.insertFirst(100);
- cll.insertFirst(200);
- cll.insertLast(300);
- cll.insertAt(500, 1);
- cll.printList(); // 200 -> 500 -> 100 -> 300 -> (head)
- cll.removeAt(2);
- System.out.println(cll.getAt(1)); // 500
- System.out.println("Is circular: " + cll.isCircular()); // true
- }
-}`,
-
- c: `// Circular Linked List Implementation in C
-#include
-#include
-
-typedef struct Node {
- int data;
- struct Node* next;
-} Node;
-
-typedef struct {
- Node* head;
- Node* tail;
- int size;
-} CircularLinkedList;
-
-void initList(CircularLinkedList* list) {
- list->head = NULL;
- list->tail = NULL;
- list->size = 0;
-}
-
-// Insert at beginning
-void insertFirst(CircularLinkedList* list, int data) {
- Node* newNode = (Node*)malloc(sizeof(Node));
- newNode->data = data;
-
- if (list->head == NULL) {
- list->head = newNode;
- list->tail = newNode;
- newNode->next = list->head; // Point to itself
- } else {
- newNode->next = list->head;
- list->head = newNode;
- list->tail->next = list->head; // Update tail's next to new head
- }
- list->size++;
-}
-
-// Insert at end
-void insertLast(CircularLinkedList* list, int data) {
- Node* newNode = (Node*)malloc(sizeof(Node));
- newNode->data = data;
-
- if (list->head == NULL) {
- list->head = newNode;
- list->tail = newNode;
- newNode->next = list->head;
- } else {
- list->tail->next = newNode;
- newNode->next = list->head;
- list->tail = newNode;
- }
- list->size++;
-}
-
-// Insert at index
-void insertAt(CircularLinkedList* list, int data, int index) {
- if (index < 0 || index > list->size) return;
- if (index == 0) {
- insertFirst(list, data);
- return;
- }
- if (index == list->size) {
- insertLast(list, data);
- return;
- }
-
- Node* newNode = (Node*)malloc(sizeof(Node));
- newNode->data = data;
-
- Node* current = list->head;
- for (int i = 0; i < index - 1; i++) {
- current = current->next;
- }
-
- newNode->next = current->next;
- current->next = newNode;
- list->size++;
-}
-
-// Remove from beginning
-int removeFirst(CircularLinkedList* list, int* success) {
- if (list->head == NULL) {
- *success = 0;
- return -1;
- }
-
- int data = list->head->data;
- Node* temp = list->head;
-
- if (list->size == 1) {
- list->head = NULL;
- list->tail = NULL;
- } else {
- list->head = list->head->next;
- list->tail->next = list->head; // Update tail's next to new head
- }
-
- free(temp);
- list->size--;
- *success = 1;
- return data;
-}
-
-// Remove from end
-int removeLast(CircularLinkedList* list, int* success) {
- if (list->head == NULL) {
- *success = 0;
- return -1;
- }
-
- int data = list->tail->data;
- Node* temp = list->tail;
-
- if (list->size == 1) {
- list->head = NULL;
- list->tail = NULL;
- } else {
- Node* current = list->head;
- while (current->next != list->tail) {
- current = current->next;
- }
- current->next = list->head; // Point new tail to head
- list->tail = current;
- }
-
- free(temp);
- list->size--;
- *success = 1;
- return data;
-}
-
-// Remove at index
-int removeAt(CircularLinkedList* list, int index, int* success) {
- if (index < 0 || index >= list->size) {
- *success = 0;
- return -1;
- }
- if (index == 0) return removeFirst(list, success);
- if (index == list->size - 1) return removeLast(list, success);
-
- Node* current = list->head;
- for (int i = 0; i < index - 1; i++) {
- current = current->next;
- }
-
- Node* temp = current->next;
- int data = temp->data;
- current->next = temp->next;
- free(temp);
- list->size--;
- *success = 1;
- return data;
-}
-
-// Get at index
-int getAt(CircularLinkedList* list, int index, int* success) {
- if (index < 0 || index >= list->size) {
- *success = 0;
- return -1;
- }
-
- Node* current = list->head;
- for (int i = 0; i < index; i++) {
- current = current->next;
- }
-
- *success = 1;
- return current->data;
-}
-
-// Clear list
-void clear(CircularLinkedList* list) {
- if (list->head == NULL) return;
-
- Node* current = list->head;
- Node* temp;
-
- do {
- temp = current;
- current = current->next;
- free(temp);
- } while (current != list->head);
-
- list->head = NULL;
- list->tail = NULL;
- list->size = 0;
-}
-
-// Print list
-void printList(CircularLinkedList* list) {
- if (list->head == NULL) {
- printf("List is empty\\n");
- return;
- }
-
- Node* current = list->head;
- do {
- printf("%d -> ", current->data);
- current = current->next;
- } while (current != list->head);
- printf("(head)\\n");
-}
-
-// Check if list is circular
-int isCircular(CircularLinkedList* list) {
- if (list->head == NULL) return 1;
-
- Node* slow = list->head;
- Node* fast = list->head->next;
-
- while (fast != NULL && fast->next != NULL) {
- if (slow == fast) return 1;
- slow = slow->next;
- fast = fast->next->next;
- }
- return 0;
-}
-
-// Usage Example
-int main() {
- CircularLinkedList list;
- initList(&list);
-
- insertFirst(&list, 100);
- insertFirst(&list, 200);
- insertLast(&list, 300);
- insertAt(&list, 500, 1);
- printList(&list); // 200 -> 500 -> 100 -> 300 -> (head)
-
- int success;
- removeAt(&list, 2, &success);
- int value = getAt(&list, 1, &success);
- if (success) {
- printf("%d\\n", value); // 500
- }
-
- printf("Is circular: %d\\n", isCircular(&list)); // 1
-
- clear(&list);
- return 0;
-}`,
-
- cpp: `// Circular Linked List Implementation in C++
-#include
-using namespace std;
-
-class Node {
-public:
- int data;
- Node* next;
-
- Node(int data) : data(data), next(nullptr) {}
-};
-
-class CircularLinkedList {
-private:
- Node* head;
- Node* tail;
- int size;
-
-public:
- CircularLinkedList() : head(nullptr), tail(nullptr), size(0) {}
-
- ~CircularLinkedList() {
- clear();
- }
-
- // Insert at beginning
- void insertFirst(int data) {
- Node* newNode = new Node(data);
- if (head == nullptr) {
- head = newNode;
- tail = newNode;
- newNode->next = head; // Point to itself
- } else {
- newNode->next = head;
- head = newNode;
- tail->next = head; // Update tail's next to new head
- }
- size++;
- }
-
- // Insert at end
- void insertLast(int data) {
- Node* newNode = new Node(data);
- if (head == nullptr) {
- head = newNode;
- tail = newNode;
- newNode->next = head;
- } else {
- tail->next = newNode;
- newNode->next = head;
- tail = newNode;
- }
- size++;
- }
-
- // Insert at index
- void insertAt(int data, int index) {
- if (index < 0 || index > size) return;
- if (index == 0) {
- insertFirst(data);
- return;
- }
- if (index == size) {
- insertLast(data);
- return;
- }
-
- Node* newNode = new Node(data);
- Node* current = head;
- for (int i = 0; i < index - 1; i++) {
- current = current->next;
- }
-
- newNode->next = current->next;
- current->next = newNode;
- size++;
- }
-
- // Remove from beginning
- int removeFirst() {
- if (head == nullptr) {
- throw out_of_range("List is empty");
- }
-
- int data = head->data;
- Node* temp = head;
-
- if (size == 1) {
- head = nullptr;
- tail = nullptr;
- } else {
- head = head->next;
- tail->next = head; // Update tail's next to new head
- }
-
- delete temp;
- size--;
- return data;
- }
-
- // Remove from end
- int removeLast() {
- if (head == nullptr) {
- throw out_of_range("List is empty");
- }
-
- int data = tail->data;
- Node* temp = tail;
-
- if (size == 1) {
- head = nullptr;
- tail = nullptr;
- } else {
- Node* current = head;
- while (current->next != tail) {
- current = current->next;
- }
- current->next = head; // Point new tail to head
- tail = current;
- }
-
- delete temp;
- size--;
- return data;
- }
-
- // Remove at index
- int removeAt(int index) {
- if (index < 0 || index >= size) {
- throw out_of_range("Index out of range");
- }
- if (index == 0) return removeFirst();
- if (index == size - 1) return removeLast();
-
- Node* current = head;
- for (int i = 0; i < index - 1; i++) {
- current = current->next;
- }
-
- Node* temp = current->next;
- int data = temp->data;
- current->next = temp->next;
- delete temp;
- size--;
- return data;
- }
-
- // Get at index
- int getAt(int index) {
- if (index < 0 || index >= size) {
- throw out_of_range("Index out of range");
- }
-
- Node* current = head;
- for (int i = 0; i < index; i++) {
- current = current->next;
- }
- return current->data;
- }
-
- // Clear list
- void clear() {
- if (head == nullptr) return;
-
- Node* current = head;
- Node* temp;
-
- do {
- temp = current;
- current = current->next;
- delete temp;
- } while (current != head);
-
- head = nullptr;
- tail = nullptr;
- size = 0;
- }
-
- // Print list
- void printList() {
- if (head == nullptr) {
- cout << "List is empty" << endl;
- return;
- }
-
- Node* current = head;
- do {
- cout << current->data << " -> ";
- current = current->next;
- } while (current != head);
- cout << "(head)" << endl;
- }
-
- // Check if list is circular
- bool isCircular() {
- if (head == nullptr) return true;
-
- Node* slow = head;
- Node* fast = head->next;
-
- while (fast != nullptr && fast->next != nullptr) {
- if (slow == fast) return true;
- slow = slow->next;
- fast = fast->next->next;
- }
- return false;
- }
-};
-
-// Usage Example
-int main() {
- CircularLinkedList cll;
- cll.insertFirst(100);
- cll.insertFirst(200);
- cll.insertLast(300);
- cll.insertAt(500, 1);
- cll.printList(); // 200 -> 500 -> 100 -> 300 -> (head)
-
- cll.removeAt(2);
- cout << cll.getAt(1) << endl; // 500
- cout << "Is circular: " << boolalpha << cll.isCircular() << endl; // true
-
- return 0;
-}`
-};
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Circular Linked List Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/circular/content.jsx b/app/visualizer/linkedList/types/circular/content.jsx
deleted file mode 100755
index a590d64a1..000000000
--- a/app/visualizer/linkedList/types/circular/content.jsx
+++ /dev/null
@@ -1,298 +0,0 @@
-const content = () => {
- const overview = [
- `A Circular Linked List is a variation of a linked list where the last node points back to the first node instead of containing a null reference. This creates a circular structure that can be traversed indefinitely.`,
- `Circular linked lists can be either singly linked (each node has one pointer) or doubly linked (each node has two pointers). The circular nature enables continuous traversal and is particularly useful in round-robin scheduling and buffer implementations.`,
- `The main advantage of circular linked lists is that any node can be a starting point, and the entire list can be traversed from any node. This makes them ideal for applications that require cyclic processing.`,
- ];
-
- const basicOperations = [
- { name: "Insertion at Head", complexity: "O(1)", description: "Add new node at beginning, point last node to new head" },
- { name: "Insertion at Tail", complexity: "O(1)", description: "Add new node at end, point it to head (with tail pointer)" },
- { name: "Deletion at Head", complexity: "O(1)", description: "Remove first node, update last node's pointer" },
- { name: "Deletion by Value", complexity: "O(n)", description: "Traverse list to find and remove specific node" },
- { name: "Traversal", complexity: "O(n)", description: "Loop through nodes until returning to starting point" },
- { name: "Search", complexity: "O(n)", description: "Traverse list to find element" },
- ];
-
- const insertionSteps = [
- { step: "1. Create new node with data" },
- { step: "2. If list is empty, set head and tail to new node" },
- { step: "3. Make new node point to itself (circular reference)" },
- { step: "4. For non-empty list, set new node's next to current head" },
- { step: "5. Update tail's next pointer to new node" },
- { step: "6. Move head pointer to new node" },
- ];
-
- const deletionSteps = [
- { step: "1. Check if list is empty" },
- { step: "2. If single node exists, set head and tail to null" },
- { step: "3. For head deletion, update head to head.next" },
- { step: "4. Update tail's next pointer to new head" },
- { step: "5. For middle deletion, find node and update previous node's pointer" },
- { step: "6. Handle special case when deleting last node" },
- ];
-
- const prosCons = [
- { point: "Continuous traversal from any node", type: "pro" },
- { point: "Efficient round-robin scheduling", type: "pro" },
- { point: "No need for null checks during traversal", type: "pro" },
- { point: "Useful for circular buffer implementations", type: "pro" },
- { point: "Risk of infinite loops if not handled carefully", type: "con" },
- { point: "Slightly more complex implementation", type: "con" },
- { point: "Harder to detect list boundaries", type: "con" },
- ];
-
- const visualization = [
- { operation: "Initialization", state: "head → null" },
- { operation: "insertFirst(10)", state: "head → [10] → (points back to head)" },
- { operation: "insertFirst(20)", state: "head → [20] → [10] → (points back to head)" },
- { operation: "insertFirst(30)", state: "head → [30] → [20] → [10] → (points back to head)" },
- { operation: "deleteFirst()", state: "head → [20] → [10] → (points back to head)" },
- { operation: "delete(10)", state: "head → [20] → (points back to itself)" },
- ];
-
- const applications = [
- "Operating system round-robin scheduling",
- "Multiplayer turn-based games",
- "Music/video playlists with repeat functionality",
- "Resource allocation in networking",
- "Circular buffer implementations",
- "Token ring networks",
- ];
-
- const comparisonTable = [
- { feature: "Structure", linear: "Linear with null termination", circular: "Circular with no null" },
- { feature: "Traversal", linear: "Stops at end", circular: "Continuous loop" },
- { feature: "Memory Overhead", linear: "Standard", circular: "Same as linear" },
- { feature: "Boundary Detection", linear: "Easy (null check)", circular: "Requires start reference" },
- { feature: "Insert/Delete at Head", linear: "O(1)", circular: "O(1)" },
- { feature: "Implementation Complexity", linear: "Simpler", circular: "More complex" },
- ];
-
- return (
-
-
- {/* Overview Section */}
-
-
-
- Circular Linked List
-
-
- {overview.map((para, index) => (
-
- {para}
-
- ))}
-
-
- Key Property: The last node's next pointer always points back to the first node, creating a continuous loop.
-
-
-
-
-
- {/* Basic Operations */}
-
- Basic Operations
-
-
-
-
- Operation
- Complexity
- Description
-
-
-
- {basicOperations.map((op, index) => (
-
- {op.name}
- {op.complexity}
- {op.description}
-
- ))}
-
-
-
-
-
- {/* Insertion Process */}
-
- Insertion Process
-
-
-
- {insertionSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
-
-
-
-
Existing circular list
-
-
↓ Insert X at head ↓
-
-
-
head
-
[X]
-
[A]
-
[B]
-
-
-
-
-
-
-
- {/* Deletion Process */}
-
- Deletion Process
-
-
-
- {deletionSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
-
-
-
-
head
-
[X]
-
[A]
-
[B]
-
-
Current circular list
-
-
↓ Delete X (head) ↓
-
-
-
-
-
-
- {/* Visualization */}
-
- Operation Visualization
-
-
-
-
- Operation
- List State
-
-
-
- {visualization.map((item, index) => (
-
- {item.operation}
- {item.state}
-
- ))}
-
-
-
-
-
- {/* Comparison with Linear Linked List */}
-
- Comparison with Linear Linked List
-
-
-
-
- Feature
- Linear Linked List
- Circular Linked List
-
-
-
- {comparisonTable.map((row, index) => (
-
- {row.feature}
- {row.linear}
- {row.circular}
-
- ))}
-
-
-
-
-
- {/* Pros and Cons */}
-
- Pros and Cons
-
-
-
Advantages
-
- {prosCons.filter(item => item.type === "pro").map((item, index) => (
-
-
-
-
- {item.point}
-
- ))}
-
-
-
-
Limitations
-
- {prosCons.filter(item => item.type === "con").map((item, index) => (
-
-
-
-
- {item.point}
-
- ))}
-
-
-
-
-
- {/* Applications */}
-
- Applications
-
-
- {applications.map((app, index) => (
-
- {app}
-
- ))}
-
-
-
- When to Choose: Prefer circular linked lists when you need continuous cycling through elements or when the application naturally follows a circular pattern (like round-robin scheduling).
-
-
-
-
-
-
- );
-};
-
-export default content;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/circular/page.jsx b/app/visualizer/linkedList/types/circular/page.jsx
deleted file mode 100755
index 7df678838..000000000
--- a/app/visualizer/linkedList/types/circular/page.jsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import Animation from "@/app/visualizer/linkedList/types/circular/animation";
-import Navbar from "@/app/components/navbarinner";
-
-export const metadata = {
- title: 'Circular Linked List Algorithm | Interactive Learning & Step-by-Step Animation',
- description:
- 'Master Circular Linked Lists with interactive visualizations, quizzes, and implementation code. Learn insertion, deletion, and traversal through animations and practice with hands-on exercises.',
- keywords: [
- 'Circular Linked List Visualizer',
- 'CLL Animation',
- 'Visualize Circular Linked List',
- 'Learn Circular Linked List',
- 'Circular Linked List DSA',
- 'Circular Linked List for Beginners',
- 'Insertion in Circular Linked List',
- 'Deletion in Circular Linked List',
- 'Circular Linked List Traversal',
- 'DSA Circular Linked List Visualization',
- 'DSA Quiz Circular Linked List',
- 'Circular Linked List Implementation Code',
- 'DSA Learning Platform',
- ],
- robots: 'index, follow',
-};
-export default function Page() {
- return (
- <>
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/circular/quiz.jsx b/app/visualizer/linkedList/types/circular/quiz.jsx
deleted file mode 100755
index 34f7c1507..000000000
--- a/app/visualizer/linkedList/types/circular/quiz.jsx
+++ /dev/null
@@ -1,531 +0,0 @@
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const Quiz = () => {
-const questions = [
- {
- question: "What is the defining characteristic of a circular linked list?",
- options: [
- "The first node points to null",
- "The last node points back to the first node",
- "It uses doubly linked nodes",
- "It cannot be traversed"
- ],
- correctAnswer: 1,
- explanation: "In a circular linked list, the last node's next pointer points back to the first node, creating a loop."
- },
- {
- question: "What is the time complexity of inserting a node at the head of a circular linked list?",
- options: [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n²)"
- ],
- correctAnswer: 0,
- explanation: "Insertion at head is O(1) as it only requires updating a couple of pointers regardless of list size."
- },
- {
- question: "In a circular singly linked list with 3 nodes (A→B→C→A), what does node C's next pointer point to?",
- options: [
- "null",
- "Node A",
- "Node B",
- "Node C"
- ],
- correctAnswer: 1,
- explanation: "In a circular list, the last node (C) points back to the first node (A)."
- },
- {
- question: "Which of these is NOT a common application of circular linked lists?",
- options: [
- "Round-robin scheduling",
- "Circular buffers",
- "Random access databases",
- "Turn-based game systems"
- ],
- correctAnswer: 2,
- explanation: "Circular linked lists don't support efficient random access, making them unsuitable for most database implementations."
- },
- {
- question: "How do you detect the end of a traversal in a circular linked list?",
- options: [
- "Check for a null pointer",
- "Check if you've returned to the starting node",
- "Count the number of nodes in advance",
- "You can't detect the end"
- ],
- correctAnswer: 1,
- explanation: "You know you've completed traversal when you return to your starting node, since there are no null pointers."
- },
- {
- question: "What is one advantage of circular linked lists over linear linked lists?",
- options: [
- "Lower memory usage",
- "Ability to traverse the entire list from any node",
- "Faster random access",
- "Simpler implementation"
- ],
- correctAnswer: 1,
- explanation: "Any node can serve as a starting point for full traversal, which is useful in many applications."
- },
- {
- question: "What special case must be handled when deleting the last node in a circular linked list?",
- options: [
- "Updating the head pointer to null",
- "No special case needed",
- "Setting the deleted node's pointers to null",
- "Rebalancing the list"
- ],
- correctAnswer: 0,
- explanation: "When deleting the last node, you must set the head pointer to null as the list becomes empty."
- },
- {
- question: "In a circular doubly linked list, what additional property exists compared to a circular singly linked list?",
- options: [
- "Each node has a previous pointer",
- "The list cannot be traversed backwards",
- "It uses less memory",
- "It must have even number of nodes"
- ],
- correctAnswer: 0,
- explanation: "Circular doubly linked lists have both next and previous pointers, enabling bidirectional traversal."
- },
- {
- question: "What is the main risk when working with circular linked lists?",
- options: [
- "Memory leaks",
- "Infinite loops during traversal",
- "Fixed size limitation",
- "Slow insertion operations"
- ],
- correctAnswer: 1,
- explanation: "Without proper termination conditions, traversals can become infinite loops since there's no null terminator."
- },
- {
- question: "Which operation has the same time complexity in both linear and circular linked lists?",
- options: [
- "Searching for a value",
- "Insertion at tail without tail pointer",
- "Deletion at head",
- "All of the above"
- ],
- correctAnswer: 3,
- explanation: "All these operations have identical time complexities in both linear and circular implementations."
- },
- {
- question: "In a circular linked list implementation of a music playlist, what feature does this structure naturally support?",
- options: [
- "Random song selection",
- "Continuous looping playback",
- "Sorting songs by length",
- "Parallel playback"
- ],
- correctAnswer: 1,
- explanation: "The circular nature perfectly supports continuous, looping playback of the playlist."
- },
- {
- question: "What is the space complexity of a circular linked list?",
- options: [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n²)"
- ],
- correctAnswer: 1,
- explanation: "Like other linked lists, space complexity is O(n) as it grows linearly with the number of elements."
- }
-];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Linked List Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default Quiz;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/doubly/animation.jsx b/app/visualizer/linkedList/types/doubly/animation.jsx
deleted file mode 100755
index b6cb408d8..000000000
--- a/app/visualizer/linkedList/types/doubly/animation.jsx
+++ /dev/null
@@ -1,234 +0,0 @@
-'use client';
-import React, { useState, useRef, useEffect } from 'react';
-import Footer from '@/app/components/footer';
-import ResetButton from '@/app/components/ui/resetButton';
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Content from "@/app/visualizer/linkedList/types/doubly/content";
-import Quiz from '@/app/visualizer/linkedList/types/doubly/quiz';
-import CodeBlock from "@/app/visualizer/linkedList/types/doubly/codeBlock";
-import BackToTop from '@/app/components/ui/backtotop';
-import GoBackButton from "@/app/components/ui/goback";
-
-const DoublyLinkedListVisualizer = () => {
- const [inputValue, setInputValue] = useState('');
- const [list, setList] = useState([]);
- const [isAnimating, setIsAnimating] = useState(false);
- const nodeIdCounter = useRef(1);
- const animationRef = useRef(null);
-
- const generateMemoryAddress = () => {
- return '0x' + Math.floor(Math.random() * 0xFFFF).toString(16).padStart(4, '0');
- };
-
- const addNode = () => {
- if (!inputValue || isAnimating) return;
- setIsAnimating(true);
-
- animationRef.current = setTimeout(() => {
- const newNode = {
- value: inputValue,
- id: nodeIdCounter.current++,
- address: generateMemoryAddress(),
- next: null,
- prev: list.length > 0 ? list[list.length - 1].address : null
- };
-
- setList(prev => {
- if (prev.length > 0) {
- const updatedList = [...prev];
- updatedList[updatedList.length - 1].next = newNode.address;
- return [...updatedList, newNode];
- }
- return [newNode];
- });
-
- setInputValue('');
- setIsAnimating(false);
- }, 500);
- };
-
- const resetList = () => {
- clearTimeout(animationRef.current);
- setList([]);
- setInputValue('');
- setIsAnimating(false);
- nodeIdCounter.current = 1;
- };
-
- useEffect(() => {
- return () => {
- clearTimeout(animationRef.current);
- };
- }, []);
-
- return (
-
-
- {/* go back block here */}
-
-
-
-
- {/* main logic here */}
-
- Doubly Linked List
-
-
-
-
- Visualize Singly Linked List Operations
-
-
- {/* Input Form */}
-
-
-
- Node Value
-
-
-
setInputValue(e.target.value)}
- className="w-full p-2 text-sm rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200"
- placeholder="Enter value"
- disabled={isAnimating}
- onKeyDown={(e) => e.key === 'Enter' && addNode()}
- />
- {inputValue && (
-
setInputValue('')}
- className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
- >
-
-
-
-
- )}
-
-
-
-
-
- {/* Linked List Visualization */}
-
-
-
-
-
- Doubly Linked List Representation
-
-
- {list.length === 0 ? (
-
-
-
-
-
No nodes in the list yet. Add your first node!
-
- ) : (
-
- {list.map((node, index) => (
-
- {/* Previous pointer arrow (only shown if not the first node) */}
- {index > 0 && (
-
- )}
-
- {/* Node Card */}
-
-
-
-
- {node.address}
-
-
- {index === 0 ? 'HEAD' : index === list.length - 1 ? 'TAIL' : `Node ${index}`}
-
-
-
-
-
-
Prev
-
- {node.prev || NULL }
-
-
-
-
-
-
-
Next
-
- {node.next || NULL }
-
-
-
-
-
-
- {/* Next pointer arrow (only shown if not the last node) */}
- {index < list.length - 1 && (
-
- )}
-
- ))}
-
- )}
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default DoublyLinkedListVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/doubly/codeBlock.jsx b/app/visualizer/linkedList/types/doubly/codeBlock.jsx
deleted file mode 100755
index ca83d1dad..000000000
--- a/app/visualizer/linkedList/types/doubly/codeBlock.jsx
+++ /dev/null
@@ -1,1159 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
-const codeExamples = {
- javascript: `// Doubly Linked List Implementation in JavaScript
-class Node {
- constructor(data) {
- this.data = data;
- this.next = null;
- this.prev = null;
- }
-}
-
-class DoublyLinkedList {
- constructor() {
- this.head = null;
- this.tail = null;
- this.size = 0;
- }
-
- // Insert at beginning
- insertFirst(data) {
- const newNode = new Node(data);
- if (!this.head) {
- this.head = newNode;
- this.tail = newNode;
- } else {
- newNode.next = this.head;
- this.head.prev = newNode;
- this.head = newNode;
- }
- this.size++;
- }
-
- // Insert at end
- insertLast(data) {
- const newNode = new Node(data);
- if (!this.head) {
- this.head = newNode;
- this.tail = newNode;
- } else {
- newNode.prev = this.tail;
- this.tail.next = newNode;
- this.tail = newNode;
- }
- this.size++;
- }
-
- // Insert at index
- insertAt(data, index) {
- if (index < 0 || index > this.size) return;
- if (index === 0) return this.insertFirst(data);
- if (index === this.size) return this.insertLast(data);
-
- const newNode = new Node(data);
- let current = this.head;
- let count = 0;
-
- while (count < index) {
- current = current.next;
- count++;
- }
-
- newNode.prev = current.prev;
- newNode.next = current;
- current.prev.next = newNode;
- current.prev = newNode;
- this.size++;
- }
-
- // Remove from beginning
- removeFirst() {
- if (!this.head) return null;
- const removedNode = this.head;
- if (this.size === 1) {
- this.head = null;
- this.tail = null;
- } else {
- this.head = this.head.next;
- this.head.prev = null;
- }
- this.size--;
- return removedNode.data;
- }
-
- // Remove from end
- removeLast() {
- if (!this.tail) return null;
- const removedNode = this.tail;
- if (this.size === 1) {
- this.head = null;
- this.tail = null;
- } else {
- this.tail = this.tail.prev;
- this.tail.next = null;
- }
- this.size--;
- return removedNode.data;
- }
-
- // Remove at index
- removeAt(index) {
- if (index < 0 || index >= this.size) return null;
- if (index === 0) return this.removeFirst();
- if (index === this.size - 1) return this.removeLast();
-
- let current = this.head;
- let count = 0;
-
- while (count < index) {
- current = current.next;
- count++;
- }
-
- current.prev.next = current.next;
- current.next.prev = current.prev;
- this.size--;
- return current.data;
- }
-
- // Get at index (forward traversal)
- getAt(index) {
- if (index < 0 || index >= this.size) return null;
- let current = this.head;
- let count = 0;
- while (count < index) {
- current = current.next;
- count++;
- }
- return current.data;
- }
-
- // Get at index (backward traversal)
- getAtFromEnd(index) {
- if (index < 0 || index >= this.size) return null;
- let current = this.tail;
- let count = 0;
- while (count < index) {
- current = current.prev;
- count++;
- }
- return current.data;
- }
-
- // Clear list
- clear() {
- this.head = null;
- this.tail = null;
- this.size = 0;
- }
-
- // Print list forward
- printForward() {
- let current = this.head;
- while (current) {
- console.log(current.data);
- current = current.next;
- }
- }
-
- // Print list backward
- printBackward() {
- let current = this.tail;
- while (current) {
- console.log(current.data);
- current = current.prev;
- }
- }
-}
-
-// Usage Example
-const dll = new DoublyLinkedList();
-dll.insertFirst(100);
-dll.insertFirst(200);
-dll.insertLast(300);
-dll.insertAt(500, 1);
-dll.printForward(); // 200, 500, 100, 300
-dll.printBackward(); // 300, 100, 500, 200
-dll.removeAt(2);
-console.log(dll.getAt(1)); // 500
-console.log(dll.getAtFromEnd(1)); // 100`,
-
- python: `# Doubly Linked List Implementation in Python
-class Node:
- def __init__(self, data):
- self.data = data
- self.next = None
- self.prev = None
-
-class DoublyLinkedList:
- def __init__(self):
- self.head = None
- self.tail = None
- self.size = 0
-
- # Insert at beginning
- def insert_first(self, data):
- new_node = Node(data)
- if not self.head:
- self.head = new_node
- self.tail = new_node
- else:
- new_node.next = self.head
- self.head.prev = new_node
- self.head = new_node
- self.size += 1
-
- # Insert at end
- def insert_last(self, data):
- new_node = Node(data)
- if not self.head:
- self.head = new_node
- self.tail = new_node
- else:
- new_node.prev = self.tail
- self.tail.next = new_node
- self.tail = new_node
- self.size += 1
-
- # Insert at index
- def insert_at(self, data, index):
- if index < 0 or index > self.size:
- return
- if index == 0:
- return self.insert_first(data)
- if index == self.size:
- return self.insert_last(data)
-
- new_node = Node(data)
- current = self.head
- count = 0
-
- while count < index:
- current = current.next
- count += 1
-
- new_node.prev = current.prev
- new_node.next = current
- current.prev.next = new_node
- current.prev = new_node
- self.size += 1
-
- # Remove from beginning
- def remove_first(self):
- if not self.head:
- return None
- removed_node = self.head
- if self.size == 1:
- self.head = None
- self.tail = None
- else:
- self.head = self.head.next
- self.head.prev = None
- self.size -= 1
- return removed_node.data
-
- # Remove from end
- def remove_last(self):
- if not self.tail:
- return None
- removed_node = self.tail
- if self.size == 1:
- self.head = None
- self.tail = None
- else:
- self.tail = self.tail.prev
- self.tail.next = None
- self.size -= 1
- return removed_node.data
-
- # Remove at index
- def remove_at(self, index):
- if index < 0 or index >= self.size:
- return None
- if index == 0:
- return self.remove_first()
- if index == self.size - 1:
- return self.remove_last()
-
- current = self.head
- count = 0
-
- while count < index:
- current = current.next
- count += 1
-
- current.prev.next = current.next
- current.next.prev = current.prev
- self.size -= 1
- return current.data
-
- # Get at index (forward traversal)
- def get_at(self, index):
- if index < 0 or index >= self.size:
- return None
- current = self.head
- count = 0
- while count < index:
- current = current.next
- count += 1
- return current.data
-
- # Get at index (backward traversal)
- def get_at_from_end(self, index):
- if index < 0 or index >= self.size:
- return None
- current = self.tail
- count = 0
- while count < index:
- current = current.prev
- count += 1
- return current.data
-
- # Clear list
- def clear(self):
- self.head = None
- self.tail = None
- self.size = 0
-
- # Print list forward
- def print_forward(self):
- current = self.head
- while current:
- print(current.data, end=" <-> ")
- current = current.next
- print("None")
-
- # Print list backward
- def print_backward(self):
- current = self.tail
- while current:
- print(current.data, end=" <-> ")
- current = current.prev
- print("None")
-
-# Usage Example
-dll = DoublyLinkedList()
-dll.insert_first(100)
-dll.insert_first(200)
-dll.insert_last(300)
-dll.insert_at(500, 1)
-dll.print_forward() # 200 <-> 500 <-> 100 <-> 300 <-> None
-dll.print_backward() # 300 <-> 100 <-> 500 <-> 200 <-> None
-dll.remove_at(2)
-print(dll.get_at(1)) # 500
-print(dll.get_at_from_end(1)) # 100`,
-
- java: `// Doubly Linked List Implementation in Java
-public class DoublyLinkedList {
- private class Node {
- int data;
- Node next;
- Node prev;
-
- Node(int data) {
- this.data = data;
- this.next = null;
- this.prev = null;
- }
- }
-
- private Node head;
- private Node tail;
- private int size;
-
- public DoublyLinkedList() {
- head = null;
- tail = null;
- size = 0;
- }
-
- // Insert at beginning
- public void insertFirst(int data) {
- Node newNode = new Node(data);
- if (head == null) {
- head = newNode;
- tail = newNode;
- } else {
- newNode.next = head;
- head.prev = newNode;
- head = newNode;
- }
- size++;
- }
-
- // Insert at end
- public void insertLast(int data) {
- Node newNode = new Node(data);
- if (tail == null) {
- head = newNode;
- tail = newNode;
- } else {
- newNode.prev = tail;
- tail.next = newNode;
- tail = newNode;
- }
- size++;
- }
-
- // Insert at index
- public void insertAt(int data, int index) {
- if (index < 0 || index > size) return;
- if (index == 0) {
- insertFirst(data);
- return;
- }
- if (index == size) {
- insertLast(data);
- return;
- }
-
- Node newNode = new Node(data);
- Node current = head;
- for (int i = 0; i < index; i++) {
- current = current.next;
- }
-
- newNode.prev = current.prev;
- newNode.next = current;
- current.prev.next = newNode;
- current.prev = newNode;
- size++;
- }
-
- // Remove from beginning
- public Integer removeFirst() {
- if (head == null) return null;
- int removedData = head.data;
- if (size == 1) {
- head = null;
- tail = null;
- } else {
- head = head.next;
- head.prev = null;
- }
- size--;
- return removedData;
- }
-
- // Remove from end
- public Integer removeLast() {
- if (tail == null) return null;
- int removedData = tail.data;
- if (size == 1) {
- head = null;
- tail = null;
- } else {
- tail = tail.prev;
- tail.next = null;
- }
- size--;
- return removedData;
- }
-
- // Remove at index
- public Integer removeAt(int index) {
- if (index < 0 || index >= size) return null;
- if (index == 0) return removeFirst();
- if (index == size - 1) return removeLast();
-
- Node current = head;
- for (int i = 0; i < index; i++) {
- current = current.next;
- }
-
- current.prev.next = current.next;
- current.next.prev = current.prev;
- size--;
- return current.data;
- }
-
- // Get at index (forward traversal)
- public Integer getAt(int index) {
- if (index < 0 || index >= size) return null;
- Node current = head;
- for (int i = 0; i < index; i++) {
- current = current.next;
- }
- return current.data;
- }
-
- // Get at index (backward traversal)
- public Integer getAtFromEnd(int index) {
- if (index < 0 || index >= size) return null;
- Node current = tail;
- for (int i = 0; i < index; i++) {
- current = current.prev;
- }
- return current.data;
- }
-
- // Clear list
- public void clear() {
- head = null;
- tail = null;
- size = 0;
- }
-
- // Print list forward
- public void printForward() {
- Node current = head;
- while (current != null) {
- System.out.print(current.data + " <-> ");
- current = current.next;
- }
- System.out.println("null");
- }
-
- // Print list backward
- public void printBackward() {
- Node current = tail;
- while (current != null) {
- System.out.print(current.data + " <-> ");
- current = current.prev;
- }
- System.out.println("null");
- }
-
- // Usage Example
- public static void main(String[] args) {
- DoublyLinkedList dll = new DoublyLinkedList();
- dll.insertFirst(100);
- dll.insertFirst(200);
- dll.insertLast(300);
- dll.insertAt(500, 1);
- dll.printForward(); // 200 <-> 500 <-> 100 <-> 300 <-> null
- dll.printBackward(); // 300 <-> 100 <-> 500 <-> 200 <-> null
- dll.removeAt(2);
- System.out.println(dll.getAt(1)); // 500
- System.out.println(dll.getAtFromEnd(1)); // 100
- }
-}`,
-
- c: `// Doubly Linked List Implementation in C
-#include
-#include
-
-typedef struct Node {
- int data;
- struct Node* next;
- struct Node* prev;
-} Node;
-
-typedef struct {
- Node* head;
- Node* tail;
- int size;
-} DoublyLinkedList;
-
-void initList(DoublyLinkedList* list) {
- list->head = NULL;
- list->tail = NULL;
- list->size = 0;
-}
-
-// Insert at beginning
-void insertFirst(DoublyLinkedList* list, int data) {
- Node* newNode = (Node*)malloc(sizeof(Node));
- newNode->data = data;
- newNode->prev = NULL;
-
- if (list->head == NULL) {
- newNode->next = NULL;
- list->head = newNode;
- list->tail = newNode;
- } else {
- newNode->next = list->head;
- list->head->prev = newNode;
- list->head = newNode;
- }
- list->size++;
-}
-
-// Insert at end
-void insertLast(DoublyLinkedList* list, int data) {
- Node* newNode = (Node*)malloc(sizeof(Node));
- newNode->data = data;
- newNode->next = NULL;
-
- if (list->tail == NULL) {
- newNode->prev = NULL;
- list->head = newNode;
- list->tail = newNode;
- } else {
- newNode->prev = list->tail;
- list->tail->next = newNode;
- list->tail = newNode;
- }
- list->size++;
-}
-
-// Insert at index
-void insertAt(DoublyLinkedList* list, int data, int index) {
- if (index < 0 || index > list->size) return;
- if (index == 0) {
- insertFirst(list, data);
- return;
- }
- if (index == list->size) {
- insertLast(list, data);
- return;
- }
-
- Node* newNode = (Node*)malloc(sizeof(Node));
- newNode->data = data;
-
- Node* current = list->head;
- for (int i = 0; i < index; i++) {
- current = current->next;
- }
-
- newNode->prev = current->prev;
- newNode->next = current;
- current->prev->next = newNode;
- current->prev = newNode;
- list->size++;
-}
-
-// Remove from beginning
-int removeFirst(DoublyLinkedList* list, int* success) {
- if (list->head == NULL) {
- *success = 0;
- return -1;
- }
-
- int data = list->head->data;
- Node* temp = list->head;
-
- if (list->size == 1) {
- list->head = NULL;
- list->tail = NULL;
- } else {
- list->head = list->head->next;
- list->head->prev = NULL;
- }
-
- free(temp);
- list->size--;
- *success = 1;
- return data;
-}
-
-// Remove from end
-int removeLast(DoublyLinkedList* list, int* success) {
- if (list->tail == NULL) {
- *success = 0;
- return -1;
- }
-
- int data = list->tail->data;
- Node* temp = list->tail;
-
- if (list->size == 1) {
- list->head = NULL;
- list->tail = NULL;
- } else {
- list->tail = list->tail->prev;
- list->tail->next = NULL;
- }
-
- free(temp);
- list->size--;
- *success = 1;
- return data;
-}
-
-// Remove at index
-int removeAt(DoublyLinkedList* list, int index, int* success) {
- if (index < 0 || index >= list->size) {
- *success = 0;
- return -1;
- }
- if (index == 0) return removeFirst(list, success);
- if (index == list->size - 1) return removeLast(list, success);
-
- Node* current = list->head;
- for (int i = 0; i < index; i++) {
- current = current->next;
- }
-
- int data = current->data;
- current->prev->next = current->next;
- current->next->prev = current->prev;
- free(current);
- list->size--;
- *success = 1;
- return data;
-}
-
-// Get at index (forward traversal)
-int getAt(DoublyLinkedList* list, int index, int* success) {
- if (index < 0 || index >= list->size) {
- *success = 0;
- return -1;
- }
-
- Node* current = list->head;
- for (int i = 0; i < index; i++) {
- current = current->next;
- }
-
- *success = 1;
- return current->data;
-}
-
-// Get at index (backward traversal)
-int getAtFromEnd(DoublyLinkedList* list, int index, int* success) {
- if (index < 0 || index >= list->size) {
- *success = 0;
- return -1;
- }
-
- Node* current = list->tail;
- for (int i = 0; i < index; i++) {
- current = current->prev;
- }
-
- *success = 1;
- return current->data;
-}
-
-// Clear list
-void clear(DoublyLinkedList* list) {
- Node* current = list->head;
- while (current != NULL) {
- Node* temp = current;
- current = current->next;
- free(temp);
- }
- list->head = NULL;
- list->tail = NULL;
- list->size = 0;
-}
-
-// Print list forward
-void printForward(DoublyLinkedList* list) {
- Node* current = list->head;
- while (current != NULL) {
- printf("%d <-> ", current->data);
- current = current->next;
- }
- printf("NULL\\n");
-}
-
-// Print list backward
-void printBackward(DoublyLinkedList* list) {
- Node* current = list->tail;
- while (current != NULL) {
- printf("%d <-> ", current->data);
- current = current->prev;
- }
- printf("NULL\\n");
-}
-
-// Usage Example
-int main() {
- DoublyLinkedList list;
- initList(&list);
-
- insertFirst(&list, 100);
- insertFirst(&list, 200);
- insertLast(&list, 300);
- insertAt(&list, 500, 1);
-
- printForward(&list); // 200 <-> 500 <-> 100 <-> 300 <-> NULL
- printBackward(&list); // 300 <-> 100 <-> 500 <-> 200 <-> NULL
-
- int success;
- removeAt(&list, 2, &success);
- int value = getAt(&list, 1, &success);
- if (success) {
- printf("%d\\n", value); // 500
- }
-
- value = getAtFromEnd(&list, 1, &success);
- if (success) {
- printf("%d\\n", value); // 100
- }
-
- clear(&list);
- return 0;
-}`,
-
- cpp: `// Doubly Linked List Implementation in C++
-#include
-using namespace std;
-
-class Node {
-public:
- int data;
- Node* next;
- Node* prev;
-
- Node(int data) : data(data), next(nullptr), prev(nullptr) {}
-};
-
-class DoublyLinkedList {
-private:
- Node* head;
- Node* tail;
- int size;
-
-public:
- DoublyLinkedList() : head(nullptr), tail(nullptr), size(0) {}
-
- ~DoublyLinkedList() {
- clear();
- }
-
- // Insert at beginning
- void insertFirst(int data) {
- Node* newNode = new Node(data);
- if (head == nullptr) {
- head = newNode;
- tail = newNode;
- } else {
- newNode->next = head;
- head->prev = newNode;
- head = newNode;
- }
- size++;
- }
-
- // Insert at end
- void insertLast(int data) {
- Node* newNode = new Node(data);
- if (tail == nullptr) {
- head = newNode;
- tail = newNode;
- } else {
- newNode->prev = tail;
- tail->next = newNode;
- tail = newNode;
- }
- size++;
- }
-
- // Insert at index
- void insertAt(int data, int index) {
- if (index < 0 || index > size) return;
- if (index == 0) {
- insertFirst(data);
- return;
- }
- if (index == size) {
- insertLast(data);
- return;
- }
-
- Node* newNode = new Node(data);
- Node* current = head;
- for (int i = 0; i < index; i++) {
- current = current->next;
- }
-
- newNode->prev = current->prev;
- newNode->next = current;
- current->prev->next = newNode;
- current->prev = newNode;
- size++;
- }
-
- // Remove from beginning
- int removeFirst() {
- if (head == nullptr) {
- throw out_of_range("List is empty");
- }
-
- int data = head->data;
- Node* temp = head;
-
- if (size == 1) {
- head = nullptr;
- tail = nullptr;
- } else {
- head = head->next;
- head->prev = nullptr;
- }
-
- delete temp;
- size--;
- return data;
- }
-
- // Remove from end
- int removeLast() {
- if (tail == nullptr) {
- throw out_of_range("List is empty");
- }
-
- int data = tail->data;
- Node* temp = tail;
-
- if (size == 1) {
- head = nullptr;
- tail = nullptr;
- } else {
- tail = tail->prev;
- tail->next = nullptr;
- }
-
- delete temp;
- size--;
- return data;
- }
-
- // Remove at index
- int removeAt(int index) {
- if (index < 0 || index >= size) {
- throw out_of_range("Index out of range");
- }
- if (index == 0) return removeFirst();
- if (index == size - 1) return removeLast();
-
- Node* current = head;
- for (int i = 0; i < index; i++) {
- current = current->next;
- }
-
- int data = current->data;
- current->prev->next = current->next;
- current->next->prev = current->prev;
- delete current;
- size--;
- return data;
- }
-
- // Get at index (forward traversal)
- int getAt(int index) {
- if (index < 0 || index >= size) {
- throw out_of_range("Index out of range");
- }
-
- Node* current = head;
- for (int i = 0; i < index; i++) {
- current = current->next;
- }
- return current->data;
- }
-
- // Get at index (backward traversal)
- int getAtFromEnd(int index) {
- if (index < 0 || index >= size) {
- throw out_of_range("Index out of range");
- }
-
- Node* current = tail;
- for (int i = 0; i < index; i++) {
- current = current->prev;
- }
- return current->data;
- }
-
- // Clear list
- void clear() {
- Node* current = head;
- while (current != nullptr) {
- Node* temp = current;
- current = current->next;
- delete temp;
- }
- head = nullptr;
- tail = nullptr;
- size = 0;
- }
-
- // Print list forward
- void printForward() {
- Node* current = head;
- while (current != nullptr) {
- cout << current->data << " <-> ";
- current = current->next;
- }
- cout << "NULL" << endl;
- }
-
- // Print list backward
- void printBackward() {
- Node* current = tail;
- while (current != nullptr) {
- cout << current->data << " <-> ";
- current = current->prev;
- }
- cout << "NULL" << endl;
- }
-};
-
-// Usage Example
-int main() {
- DoublyLinkedList dll;
- dll.insertFirst(100);
- dll.insertFirst(200);
- dll.insertLast(300);
- dll.insertAt(500, 1);
-
- dll.printForward(); // 200 <-> 500 <-> 100 <-> 300 <-> NULL
- dll.printBackward(); // 300 <-> 100 <-> 500 <-> 200 <-> NULL
-
- dll.removeAt(2);
- cout << dll.getAt(1) << endl; // 500
- cout << dll.getAtFromEnd(1) << endl; // 100
-
- return 0;
-}`
-};
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Doubly Linked List Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/doubly/content.jsx b/app/visualizer/linkedList/types/doubly/content.jsx
deleted file mode 100755
index 1eb4dd3bd..000000000
--- a/app/visualizer/linkedList/types/doubly/content.jsx
+++ /dev/null
@@ -1,337 +0,0 @@
-const content = () => {
- const overview = [
- `A Doubly Linked List is an advanced variation of the linked list where each node contains data and two pointers - one to the next node and another to the previous node. This bidirectional linkage enables traversal in both directions.`,
- `The list maintains head and tail pointers, allowing O(1) operations at both ends. Each node's previous pointer forms the backward chain, while the next pointer forms the forward chain.`,
- `Doubly linked lists are particularly useful when you need frequent backward traversal or operations at both ends of the list, providing more flexibility than singly linked lists at the cost of slightly higher memory overhead.`,
- ];
-
- const basicOperations = [
- { name: "Insertion at Head", complexity: "O(1)", description: "Add new node at beginning, update head and adjacent node's pointers" },
- { name: "Insertion at Tail", complexity: "O(1)", description: "Add new node at end using tail pointer" },
- { name: "Insertion at Position", complexity: "O(n)", description: "Traverse to position and insert with pointer updates" },
- { name: "Deletion at Head", complexity: "O(1)", description: "Remove first node and update head pointer" },
- { name: "Deletion at Tail", complexity: "O(1)", description: "Remove last node using tail pointer" },
- { name: "Deletion by Value", complexity: "O(n)", description: "Traverse to find node and update adjacent pointers" },
- { name: "Forward Traversal", complexity: "O(n)", description: "Traverse from head to tail using next pointers" },
- { name: "Backward Traversal", complexity: "O(n)", description: "Traverse from tail to head using prev pointers" },
- ];
-
- const implementationCode = [
- { code: "class DoublyNode {" },
- { code: " constructor(data) {" },
- { code: " this.data = data;" },
- { code: " this.prev = null;" },
- { code: " this.next = null;" },
- { code: " }" },
- { code: "}" },
- { code: "" },
- { code: "class DoublyLinkedList {" },
- { code: " constructor() {" },
- { code: " this.head = null;" },
- { code: " this.tail = null;" },
- { code: " this.size = 0;" },
- { code: " }" },
- { code: "" },
- { code: " isEmpty() {" },
- { code: " return this.head === null;" },
- { code: " }" },
- { code: "" },
- { code: " // Insert at head" },
- { code: " insertFirst(data) {" },
- { code: " const newNode = new DoublyNode(data);" },
- { code: " if (this.isEmpty()) {" },
- { code: " this.head = newNode;" },
- { code: " this.tail = newNode;" },
- { code: " } else {" },
- { code: " newNode.next = this.head;" },
- { code: " this.head.prev = newNode;" },
- { code: " this.head = newNode;" },
- { code: " }" },
- { code: " this.size++;" },
- { code: " }" },
- ];
-
- const insertionSteps = [
- { step: "1. Create new node with data, prev, and next pointers" },
- { step: "2. For head insertion: Set new node's next to current head" },
- { step: "3. Update current head's prev to new node" },
- { step: "4. Move head pointer to new node" },
- { step: "5. For empty list, set both head and tail to new node" },
- { step: "6. For tail insertion: Similar steps but working from tail" },
- ];
-
- const deletionSteps = [
- { step: "1. Check if list is empty" },
- { step: "2. For head deletion: Store head reference, move head to head.next" },
- { step: "3. Set new head's prev to null (if exists)" },
- { step: "4. For tail deletion: Similar steps working from tail" },
- { step: "5. For middle deletion: Find node, update adjacent nodes' pointers" },
- { step: "6. Handle special cases (single node removal)" },
- ];
-
- const prosCons = [
- { point: "Bidirectional traversal capability", type: "pro" },
- { point: "O(1) operations at both ends", type: "pro" },
- { point: "Easier node removal (no need to track previous node)", type: "pro" },
- { point: "Better for certain algorithms (e.g., LRU cache)", type: "pro" },
- { point: "Extra memory for prev pointers", type: "con" },
- { point: "More pointer operations (slightly complex implementation)", type: "con" },
- { point: "Slightly slower operations due to extra pointer updates", type: "con" },
- ];
-
- const visualization = [
- { operation: "Initialization", state: "head → null ← tail" },
- { operation: "insertFirst(10)", state: "head → [null|10|•] ← tail" },
- { operation: "insertFirst(20)", state: "head → [null|20|•] ↔ [•|10|•] ← tail" },
- { operation: "insertLast(30)", state: "head → [null|20|•] ↔ [•|10|•] ↔ [•|30|null] ← tail" },
- { operation: "deleteFirst()", state: "head → [null|10|•] ↔ [•|30|null] ← tail" },
- { operation: "deleteLast()", state: "head → [null|10|null] ← tail" },
- ];
-
- const applications = [
- "Browser forward/backward navigation",
- "Undo/Redo functionality in software",
- "LRU (Least Recently Used) cache implementation",
- "Navigation systems with bidirectional movement",
- "Music/video playlists with forward/backward controls",
- "Text editors with cursor movement in both directions",
- ];
-
- const comparisonTable = [
- { feature: "Traversal Direction", singly: "Forward only", doubly: "Both directions" },
- { feature: "Memory Overhead", singly: "Lower (1 pointer/node)", doubly: "Higher (2 pointers/node)" },
- { feature: "Insert/Delete at Head", singly: "O(1)", doubly: "O(1)" },
- { feature: "Insert/Delete at Tail", singly: "O(n) (or O(1) with tail pointer)", doubly: "O(1)" },
- { feature: "Delete Current Node", singly: "Requires previous node", doubly: "Direct access via prev pointer" },
- { feature: "Implementation Complexity", singly: "Simpler", doubly: "More complex" },
- ];
-
- return (
-
-
- {/* Overview Section */}
-
-
-
- Doubly Linked List
-
-
- {overview.map((para, index) => (
-
- {para}
-
- ))}
-
-
- Key Property: Each node is represented as [prev|data|next], showing the bidirectional links between nodes.
-
-
-
-
-
- {/* Basic Operations */}
-
- Basic Operations
-
-
-
-
- Operation
- Complexity
- Description
-
-
-
- {basicOperations.map((op, index) => (
-
- {op.name}
- {op.complexity}
- {op.description}
-
- ))}
-
-
-
-
-
- {/* Implementation */}
-
- Implementation
-
-
-
- {implementationCode.map((line, index) => (
- {line.code}
- ))}
-
-
-
-
-
- {/* Insertion Process */}
-
- Insertion Process
-
-
-
- {insertionSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
-
-
-
head →
-
[•|A|•] ↔ [•|B|•]
-
← tail
-
-
↓ Insert X at head ↓
-
-
head →
-
[null|X|•] ↔ [•|A|•] ↔ [•|B|•]
-
← tail
-
-
-
-
-
-
- {/* Deletion Process */}
-
- Deletion Process
-
-
-
- {deletionSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
-
-
-
head →
-
[•|X|•] ↔ [•|A|•] ↔ [•|B|•]
-
← tail
-
-
↓ Delete A ↓
-
-
head →
-
[•|X|•] ↔ [•|B|•]
-
← tail
-
-
-
-
-
-
- {/* Visualization */}
-
- Operation Visualization
-
-
-
-
- Operation
- List State
-
-
-
- {visualization.map((item, index) => (
-
- {item.operation}
- {item.state}
-
- ))}
-
-
-
-
-
- {/* Comparison with Singly Linked List */}
-
- Comparison with Singly Linked List
-
-
-
-
- Feature
- Singly Linked List
- Doubly Linked List
-
-
-
- {comparisonTable.map((row, index) => (
-
- {row.feature}
- {row.singly}
- {row.doubly}
-
- ))}
-
-
-
-
-
- {/* Pros and Cons */}
-
- Pros and Cons
-
-
-
Advantages
-
- {prosCons.filter(item => item.type === "pro").map((item, index) => (
-
-
-
-
- {item.point}
-
- ))}
-
-
-
-
Limitations
-
- {prosCons.filter(item => item.type === "con").map((item, index) => (
-
-
-
-
- {item.point}
-
- ))}
-
-
-
-
-
- {/* Applications */}
-
- Applications
-
-
- {applications.map((app, index) => (
-
- {app}
-
- ))}
-
-
-
- When to Choose: Prefer doubly linked lists when you need bidirectional traversal, frequent operations at both ends, or when the ability to delete arbitrary nodes without traversal is valuable.
-
-
-
-
-
-
- );
-};
-
-export default content;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/doubly/page.jsx b/app/visualizer/linkedList/types/doubly/page.jsx
deleted file mode 100755
index 2d3b3b4c6..000000000
--- a/app/visualizer/linkedList/types/doubly/page.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import Animation from "@/app/visualizer/linkedList/types/doubly/animation";
-import Navbar from "@/app/components/navbarinner";
-
-export const metadata = {
- title: 'Doubly Linked List Implementation | Visualize Doubly Linked List in JS, C, Python, Java',
- description: 'Explore Doubly Linked List implementation with interactive animations and code examples in JavaScript, C, Python, and Java. Learn insertion, deletion, and traversal from both directions. Perfect for DSA beginners and interview preparation.',
- keywords: [
- 'Doubly Linked List Implementation',
- 'DLL Visualization',
- 'Doubly Linked List in JavaScript',
- 'Doubly Linked List in C',
- 'Doubly Linked List in Python',
- 'Doubly Linked List in Java',
- 'DSA Doubly Linked List',
- 'Bidirectional Linked List',
- 'Insertion in DLL',
- 'Deletion in DLL',
- 'DLL Operations',
- 'Learn Doubly Linked List',
- 'DSA for Beginners',
- 'Interactive Linked List Visualizer',
- ],
- robots: 'index, follow',
-};
-
-export default function Page() {
- return (
- <>
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/doubly/quiz.jsx b/app/visualizer/linkedList/types/doubly/quiz.jsx
deleted file mode 100755
index cc07eee6e..000000000
--- a/app/visualizer/linkedList/types/doubly/quiz.jsx
+++ /dev/null
@@ -1,531 +0,0 @@
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const Quiz = () => {
-const questions = [
- {
- question: "What is the key difference between a node in a singly linked list and a doubly linked list?",
- options: [
- "Doubly linked list nodes have no pointers",
- "Doubly linked list nodes have both next and previous pointers",
- "Doubly linked list nodes have three pointers",
- "There is no difference"
- ],
- correctAnswer: 1,
- explanation: "Doubly linked list nodes contain both next and previous pointers, allowing bidirectional traversal."
- },
- {
- question: "What do the 'previous' and 'next' pointers of the head node in a doubly linked list point to?",
- options: [
- "previous: null, next: second node",
- "previous: tail, next: second node",
- "previous: head, next: tail",
- "previous: second node, next: null"
- ],
- correctAnswer: 0,
- explanation: "The head's previous is null (no node before it) and next points to the second node."
- },
- {
- question: "What is the time complexity of inserting a node at the tail of a doubly linked list with a tail pointer?",
- options: [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n²)"
- ],
- correctAnswer: 0,
- explanation: "With a tail pointer, insertion at tail is O(1) as we can directly access the end."
- },
- {
- question: "Which operation is more efficient in a doubly linked list compared to a singly linked list?",
- options: [
- "Forward traversal",
- "Deleting a node given only its reference",
- "Insertion at head",
- "Checking if list is empty"
- ],
- correctAnswer: 1,
- explanation: "With previous pointers, we can delete a node in O(1) time if we have its reference."
- },
- {
- question: "What is the main disadvantage of doubly linked lists compared to singly linked lists?",
- options: [
- "Slower traversal speed",
- "Higher memory usage per node",
- "Cannot implement stacks or queues",
- "Fixed size limitation"
- ],
- correctAnswer: 1,
- explanation: "Each node requires an extra pointer (previous), increasing memory overhead."
- },
- {
- question: "In a circular doubly linked list, what does the tail's next pointer point to?",
- options: [
- "null",
- "head",
- "tail itself",
- "A random node"
- ],
- correctAnswer: 1,
- explanation: "In a circular doubly linked list, tail's next points to head and head's previous points to tail."
- },
- {
- question: "What is the time complexity of finding a node's predecessor in a doubly linked list?",
- options: [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n²)"
- ],
- correctAnswer: 0,
- explanation: "We can directly access the predecessor via the previous pointer in O(1) time."
- },
- {
- question: "Which of these applications would MOST benefit from a doubly linked list?",
- options: [
- "Implementing a stack",
- "Browser forward/backward navigation",
- "Storing pixel data for an image",
- "Priority queue implementation"
- ],
- correctAnswer: 1,
- explanation: "Browser navigation benefits from bidirectional traversal capabilities."
- },
- {
- question: "How do you delete a middle node in a doubly linked list?",
- options: [
- "Set its data to null",
- "Update its neighbors' pointers to bypass it",
- "Only update the next node's pointer",
- "You cannot delete middle nodes"
- ],
- correctAnswer: 1,
- explanation: "To delete, set the previous node's next to the next node, and the next node's previous to the previous node."
- },
- {
- question: "What is the space complexity of a doubly linked list with n nodes?",
- options: [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n²)"
- ],
- correctAnswer: 1,
- explanation: "Space complexity is O(n) as it grows linearly with the number of nodes."
- },
- {
- question: "In a non-empty doubly linked list, what does the head's previous pointer and tail's next pointer point to?",
- options: [
- "head.previous: null, tail.next: null",
- "head.previous: tail, tail.next: head",
- "Both point to themselves",
- "head.previous: head, tail.next: tail"
- ],
- correctAnswer: 0,
- explanation: "In a standard (non-circular) doubly linked list, head's previous and tail's next are null."
- },
- {
- question: "What is one advantage of a sentinel node in a doubly linked list implementation?",
- options: [
- "Reduces memory usage",
- "Simplifies edge cases by eliminating null pointers",
- "Enables random access",
- "Automatically sorts the list"
- ],
- correctAnswer: 1,
- explanation: "Sentinel nodes act as dummy nodes that eliminate special cases for head/tail operations."
- }
-];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Linked List Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default Quiz;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/singly/animation.jsx b/app/visualizer/linkedList/types/singly/animation.jsx
deleted file mode 100755
index 42bd79c21..000000000
--- a/app/visualizer/linkedList/types/singly/animation.jsx
+++ /dev/null
@@ -1,240 +0,0 @@
-'use client';
-import React, { useState, useRef, useEffect } from 'react';
-import Footer from '@/app/components/footer';
-import ResetButton from '@/app/components/ui/resetButton';
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Content from "@/app/visualizer/linkedList/types/singly/content";
-import Quiz from '@/app/visualizer/linkedList/types/singly/quiz';
-import CodeBlock from "@/app/visualizer/linkedList/types/singly/codeBlock";
-import BackToTop from '@/app/components/ui/backtotop';
-import GoBackButton from "@/app/components/ui/goback";
-
-const SinglyLinkedListVisualizer = () => {
- const [inputValue, setInputValue] = useState('');
- const [list, setList] = useState([]);
- const [isAnimating, setIsAnimating] = useState(false);
- const [currentStep, setCurrentStep] = useState(0);
- const [explanation, setExplanation] = useState('Enter a value and click "Add Node" to start.');
- const nodeIdCounter = useRef(1);
- const animationRef = useRef(null);
- const isMounted = useRef(true);
-
- // Generate random memory addresses for visualization
- const generateMemoryAddress = () => {
- return '0x' + Math.floor(Math.random() * 0xFFFF).toString(16).padStart(4, '0');
- };
-
- const addNode = () => {
- if (!inputValue || isAnimating) return;
-
- setIsAnimating(true);
- setCurrentStep(0);
- setExplanation(explanations[0]);
-
- let step = 0;
- const animateStep = () => {
- if (!isMounted.current) return;
-
- setCurrentStep(step);
- setExplanation(explanations[step]);
- step++;
-
- if (step < steps.length) {
- animationRef.current = setTimeout(animateStep, 0);
- } else {
- // Animation complete - add the node
- const newNode = {
- value: inputValue,
- id: nodeIdCounter.current++,
- address: generateMemoryAddress(),
- next: null
- };
-
- setList(prev => {
- if (prev.length > 0) {
- // Update previous node's next pointer
- const updatedList = [...prev];
- updatedList[updatedList.length - 1].next = newNode.address;
- return [...updatedList, newNode];
- }
- return [newNode];
- });
-
- setInputValue('');
- setExplanation(explanations[explanations.length - 1]);
- setIsAnimating(false);
- }
- };
-
- animateStep();
- };
-
- const resetList = () => {
- clearTimeout(animationRef.current);
- setList([]);
- setInputValue('');
- setIsAnimating(false);
- setCurrentStep(0);
- nodeIdCounter.current = 1;
- setExplanation('Enter a value and click "Add Node" to start.');
- };
-
- useEffect(() => {
- isMounted.current = true;
- return () => {
- isMounted.current = false;
- clearTimeout(animationRef.current);
- };
- }, []);
-
- return (
-
-
- {/* go back block here */}
-
-
-
-
- {/* main logic here */}
-
- Singly Linked List
-
-
-
-
- Visualize Singly Linked List Operations
-
-
- {/* Input Form */}
-
-
-
- Node Value
-
-
-
setInputValue(e.target.value)}
- className="w-full p-2 text-sm rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200"
- placeholder="Enter value"
- disabled={isAnimating}
- onKeyDown={(e) => e.key === 'Enter' && addNode()}
- />
- {inputValue && (
-
setInputValue('')}
- className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
- >
-
-
-
-
- )}
-
-
-
-
- {/* Linked List Visualization */}
-
-
-
-
-
- Linked List Memory Representation
-
-
- {list.length === 0 ? (
-
-
-
-
-
No nodes in the list yet. Add your first node!
-
- ) : (
-
- {list.map((node, index) => (
-
-
- {/* Node Card */}
-
- {/* Node Header */}
-
-
- {node.address}
-
-
- {index === 0 ? 'HEAD' : `Node ${index}`}
-
-
-
- {/* Data Section */}
-
-
-
- {/* Next Pointer Section */}
-
-
Next Pointer
-
- {node.next || 0x0000 (NULL) }
-
-
-
-
-
- {/* Arrow to next node */}
- {node.next && (
-
- )}
-
-
- ))}
-
- )}
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default SinglyLinkedListVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/singly/codeBlock.jsx b/app/visualizer/linkedList/types/singly/codeBlock.jsx
deleted file mode 100755
index c6213f865..000000000
--- a/app/visualizer/linkedList/types/singly/codeBlock.jsx
+++ /dev/null
@@ -1,803 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
-const codeExamples = {
- javascript: `// Singly Linked List Implementation in JavaScript
-class Node {
- constructor(data) {
- this.data = data;
- this.next = null;
- }
-}
-
-class SinglyLinkedList {
- constructor() {
- this.head = null;
- this.size = 0;
- }
-
- // Insert at beginning
- insertFirst(data) {
- const newNode = new Node(data);
- newNode.next = this.head;
- this.head = newNode;
- this.size++;
- }
-
- // Insert at end
- insertLast(data) {
- const newNode = new Node(data);
- if (!this.head) {
- this.head = newNode;
- } else {
- let current = this.head;
- while (current.next) {
- current = current.next;
- }
- current.next = newNode;
- }
- this.size++;
- }
-
- // Insert at index
- insertAt(data, index) {
- if (index < 0 || index > this.size) return;
- if (index === 0) return this.insertFirst(data);
- if (index === this.size) return this.insertLast(data);
-
- const newNode = new Node(data);
- let current = this.head;
- let previous;
- let count = 0;
-
- while (count < index) {
- previous = current;
- current = current.next;
- count++;
- }
-
- newNode.next = current;
- previous.next = newNode;
- this.size++;
- }
-
- // Get at index
- getAt(index) {
- if (index < 0 || index >= this.size) return null;
- let current = this.head;
- let count = 0;
- while (count < index) {
- current = current.next;
- count++;
- }
- return current.data;
- }
-
- // Remove at index
- removeAt(index) {
- if (index < 0 || index >= this.size) return null;
- let current = this.head;
- if (index === 0) {
- this.head = current.next;
- } else {
- let previous;
- let count = 0;
- while (count < index) {
- previous = current;
- current = current.next;
- count++;
- }
- previous.next = current.next;
- }
- this.size--;
- return current.data;
- }
-
- // Clear list
- clear() {
- this.head = null;
- this.size = 0;
- }
-
- // Print list data
- print() {
- let current = this.head;
- while (current) {
- console.log(current.data);
- current = current.next;
- }
- }
-}
-
-// Usage Example
-const list = new SinglyLinkedList();
-list.insertFirst(100);
-list.insertFirst(200);
-list.insertLast(300);
-list.insertAt(500, 1);
-list.print(); // 200, 500, 100, 300
-list.removeAt(2);
-console.log(list.getAt(1)); // 500`,
-
- python: `# Singly Linked List Implementation in Python
-class Node:
- def __init__(self, data):
- self.data = data
- self.next = None
-
-class SinglyLinkedList:
- def __init__(self):
- self.head = None
- self.size = 0
-
- # Insert at beginning
- def insert_first(self, data):
- new_node = Node(data)
- new_node.next = self.head
- self.head = new_node
- self.size += 1
-
- # Insert at end
- def insert_last(self, data):
- new_node = Node(data)
- if not self.head:
- self.head = new_node
- else:
- current = self.head
- while current.next:
- current = current.next
- current.next = new_node
- self.size += 1
-
- # Insert at index
- def insert_at(self, data, index):
- if index < 0 or index > self.size:
- return
- if index == 0:
- return self.insert_first(data)
- if index == self.size:
- return self.insert_last(data)
-
- new_node = Node(data)
- current = self.head
- count = 0
-
- while count < index - 1:
- current = current.next
- count += 1
-
- new_node.next = current.next
- current.next = new_node
- self.size += 1
-
- # Get at index
- def get_at(self, index):
- if index < 0 or index >= self.size:
- return None
- current = self.head
- count = 0
- while count < index:
- current = current.next
- count += 1
- return current.data
-
- # Remove at index
- def remove_at(self, index):
- if index < 0 or index >= self.size:
- return None
- current = self.head
- if index == 0:
- self.head = current.next
- else:
- count = 0
- while count < index - 1:
- current = current.next
- count += 1
- current.next = current.next.next
- self.size -= 1
- return current.data
-
- # Clear list
- def clear(self):
- self.head = None
- self.size = 0
-
- # Print list data
- def print_list(self):
- current = self.head
- while current:
- print(current.data, end=" -> ")
- current = current.next
- print("None")
-
-# Usage Example
-ll = SinglyLinkedList()
-ll.insert_first(100)
-ll.insert_first(200)
-ll.insert_last(300)
-ll.insert_at(500, 1)
-ll.print_list() # 200 -> 500 -> 100 -> 300 -> None
-ll.remove_at(2)
-print(ll.get_at(1)) # 500`,
-
- java: `// Singly Linked List Implementation in Java
-public class SinglyLinkedList {
- private class Node {
- int data;
- Node next;
-
- Node(int data) {
- this.data = data;
- this.next = null;
- }
- }
-
- private Node head;
- private int size;
-
- public SinglyLinkedList() {
- head = null;
- size = 0;
- }
-
- // Insert at beginning
- public void insertFirst(int data) {
- Node newNode = new Node(data);
- newNode.next = head;
- head = newNode;
- size++;
- }
-
- // Insert at end
- public void insertLast(int data) {
- Node newNode = new Node(data);
- if (head == null) {
- head = newNode;
- } else {
- Node current = head;
- while (current.next != null) {
- current = current.next;
- }
- current.next = newNode;
- }
- size++;
- }
-
- // Insert at index
- public void insertAt(int data, int index) {
- if (index < 0 || index > size) return;
- if (index == 0) {
- insertFirst(data);
- return;
- }
- if (index == size) {
- insertLast(data);
- return;
- }
-
- Node newNode = new Node(data);
- Node current = head;
- for (int i = 0; i < index - 1; i++) {
- current = current.next;
- }
- newNode.next = current.next;
- current.next = newNode;
- size++;
- }
-
- // Get at index
- public Integer getAt(int index) {
- if (index < 0 || index >= size) return null;
- Node current = head;
- for (int i = 0; i < index; i++) {
- current = current.next;
- }
- return current.data;
- }
-
- // Remove at index
- public Integer removeAt(int index) {
- if (index < 0 || index >= size) return null;
- Node current = head;
- if (index == 0) {
- head = current.next;
- } else {
- for (int i = 0; i < index - 1; i++) {
- current = current.next;
- }
- current.next = current.next.next;
- }
- size--;
- return current.data;
- }
-
- // Clear list
- public void clear() {
- head = null;
- size = 0;
- }
-
- // Print list data
- public void printList() {
- Node current = head;
- while (current != null) {
- System.out.print(current.data + " -> ");
- current = current.next;
- }
- System.out.println("null");
- }
-
- // Usage Example
- public static void main(String[] args) {
- SinglyLinkedList list = new SinglyLinkedList();
- list.insertFirst(100);
- list.insertFirst(200);
- list.insertLast(300);
- list.insertAt(500, 1);
- list.printList(); // 200 -> 500 -> 100 -> 300 -> null
- list.removeAt(2);
- System.out.println(list.getAt(1)); // 500
- }
-}`,
-
- c: `// Singly Linked List Implementation in C
-#include
-#include
-
-typedef struct Node {
- int data;
- struct Node* next;
-} Node;
-
-typedef struct {
- Node* head;
- int size;
-} SinglyLinkedList;
-
-void initList(SinglyLinkedList* list) {
- list->head = NULL;
- list->size = 0;
-}
-
-// Insert at beginning
-void insertFirst(SinglyLinkedList* list, int data) {
- Node* newNode = (Node*)malloc(sizeof(Node));
- newNode->data = data;
- newNode->next = list->head;
- list->head = newNode;
- list->size++;
-}
-
-// Insert at end
-void insertLast(SinglyLinkedList* list, int data) {
- Node* newNode = (Node*)malloc(sizeof(Node));
- newNode->data = data;
- newNode->next = NULL;
-
- if (list->head == NULL) {
- list->head = newNode;
- } else {
- Node* current = list->head;
- while (current->next != NULL) {
- current = current->next;
- }
- current->next = newNode;
- }
- list->size++;
-}
-
-// Insert at index
-void insertAt(SinglyLinkedList* list, int data, int index) {
- if (index < 0 || index > list->size) return;
- if (index == 0) {
- insertFirst(list, data);
- return;
- }
- if (index == list->size) {
- insertLast(list, data);
- return;
- }
-
- Node* newNode = (Node*)malloc(sizeof(Node));
- newNode->data = data;
-
- Node* current = list->head;
- for (int i = 0; i < index - 1; i++) {
- current = current->next;
- }
-
- newNode->next = current->next;
- current->next = newNode;
- list->size++;
-}
-
-// Get at index
-int getAt(SinglyLinkedList* list, int index, int* success) {
- if (index < 0 || index >= list->size) {
- *success = 0;
- return -1;
- }
-
- Node* current = list->head;
- for (int i = 0; i < index; i++) {
- current = current->next;
- }
-
- *success = 1;
- return current->data;
-}
-
-// Remove at index
-int removeAt(SinglyLinkedList* list, int index, int* success) {
- if (index < 0 || index >= list->size) {
- *success = 0;
- return -1;
- }
-
- Node* current = list->head;
- int data;
-
- if (index == 0) {
- list->head = current->next;
- data = current->data;
- free(current);
- } else {
- for (int i = 0; i < index - 1; i++) {
- current = current->next;
- }
- Node* temp = current->next;
- current->next = temp->next;
- data = temp->data;
- free(temp);
- }
-
- list->size--;
- *success = 1;
- return data;
-}
-
-// Clear list
-void clear(SinglyLinkedList* list) {
- Node* current = list->head;
- while (current != NULL) {
- Node* temp = current;
- current = current->next;
- free(temp);
- }
- list->head = NULL;
- list->size = 0;
-}
-
-// Print list data
-void printList(SinglyLinkedList* list) {
- Node* current = list->head;
- while (current != NULL) {
- printf("%d -> ", current->data);
- current = current->next;
- }
- printf("NULL\n");
-}
-
-// Usage Example
-int main() {
- SinglyLinkedList list;
- initList(&list);
-
- insertFirst(&list, 100);
- insertFirst(&list, 200);
- insertLast(&list, 300);
- insertAt(&list, 500, 1);
- printList(&list); // 200 -> 500 -> 100 -> 300 -> NULL
-
- int success;
- removeAt(&list, 2, &success);
- int value = getAt(&list, 1, &success);
- if (success) {
- printf("%d\n", value); // 500
- }
-
- clear(&list);
- return 0;
-}`,
-
- cpp: `// Singly Linked List Implementation in C++
-#include
-using namespace std;
-
-class Node {
-public:
- int data;
- Node* next;
-
- Node(int data) : data(data), next(nullptr) {}
-};
-
-class SinglyLinkedList {
-private:
- Node* head;
- int size;
-
-public:
- SinglyLinkedList() : head(nullptr), size(0) {}
-
- ~SinglyLinkedList() {
- clear();
- }
-
- // Insert at beginning
- void insertFirst(int data) {
- Node* newNode = new Node(data);
- newNode->next = head;
- head = newNode;
- size++;
- }
-
- // Insert at end
- void insertLast(int data) {
- Node* newNode = new Node(data);
- if (head == nullptr) {
- head = newNode;
- } else {
- Node* current = head;
- while (current->next != nullptr) {
- current = current->next;
- }
- current->next = newNode;
- }
- size++;
- }
-
- // Insert at index
- void insertAt(int data, int index) {
- if (index < 0 || index > size) return;
- if (index == 0) {
- insertFirst(data);
- return;
- }
- if (index == size) {
- insertLast(data);
- return;
- }
-
- Node* newNode = new Node(data);
- Node* current = head;
- for (int i = 0; i < index - 1; i++) {
- current = current->next;
- }
- newNode->next = current->next;
- current->next = newNode;
- size++;
- }
-
- // Get at index
- int getAt(int index) {
- if (index < 0 || index >= size) {
- throw out_of_range("Index out of range");
- }
-
- Node* current = head;
- for (int i = 0; i < index; i++) {
- current = current->next;
- }
- return current->data;
- }
-
- // Remove at index
- int removeAt(int index) {
- if (index < 0 || index >= size) {
- throw out_of_range("Index out of range");
- }
-
- Node* current = head;
- int data;
-
- if (index == 0) {
- head = current->next;
- data = current->data;
- delete current;
- } else {
- for (int i = 0; i < index - 1; i++) {
- current = current->next;
- }
- Node* temp = current->next;
- current->next = temp->next;
- data = temp->data;
- delete temp;
- }
-
- size--;
- return data;
- }
-
- // Clear list
- void clear() {
- Node* current = head;
- while (current != nullptr) {
- Node* temp = current;
- current = current->next;
- delete temp;
- }
- head = nullptr;
- size = 0;
- }
-
- // Print list data
- void printList() {
- Node* current = head;
- while (current != nullptr) {
- cout << current->data << " -> ";
- current = current->next;
- }
- cout << "NULL" << endl;
- }
-};
-
-// Usage Example
-int main() {
- SinglyLinkedList list;
- list.insertFirst(100);
- list.insertFirst(200);
- list.insertLast(300);
- list.insertAt(500, 1);
- list.printList(); // 200 -> 500 -> 100 -> 300 -> NULL
-
- list.removeAt(2);
- cout << list.getAt(1) << endl; // 500
-
- return 0;
-}`
-};
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Singly Linked List Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/singly/content.jsx b/app/visualizer/linkedList/types/singly/content.jsx
deleted file mode 100755
index dab408f6b..000000000
--- a/app/visualizer/linkedList/types/singly/content.jsx
+++ /dev/null
@@ -1,286 +0,0 @@
-const content = () => {
- const overview = [
- `A Singly Linked List is a linear data structure where each element (node) contains data and a pointer to the next node. Unlike arrays, linked lists don't have fixed sizes and allow efficient insertion/deletion at any position.`,
- `The list maintains a head pointer that points to the first node. The last node's next pointer is null, indicating the end of the list. This structure provides O(1) insertion/deletion at the head but O(n) access time for arbitrary elements.`,
- `Singly linked lists are fundamental building blocks for more complex data structures like stacks, queues, and adjacency lists for graphs.`,
- ];
-
- const basicOperations = [
- { name: "Insertion at Head", complexity: "O(1)", description: "Add new node at beginning by updating head pointer" },
- { name: "Insertion at Tail", complexity: "O(n)", description: "Traverse to end and add new node (O(1) with tail pointer)" },
- { name: "Deletion at Head", complexity: "O(1)", description: "Remove first node by updating head pointer" },
- { name: "Deletion by Value", complexity: "O(n)", description: "Traverse list to find and remove specific node" },
- { name: "Search", complexity: "O(n)", description: "Traverse list to find element" },
- { name: "Access by Index", complexity: "O(n)", description: "Traverse list until reaching desired position" },
- ];
-
- const implementationCode = [
- { code: "class Node {" },
- { code: " constructor(data) {" },
- { code: " this.data = data;" },
- { code: " this.next = null;" },
- { code: " }" },
- { code: "}" },
- { code: "" },
- { code: "class SinglyLinkedList {" },
- { code: " constructor() {" },
- { code: " this.head = null;" },
- { code: " this.size = 0;" },
- { code: " }" },
- { code: "" },
- { code: " // Check if list is empty" },
- { code: " isEmpty() {" },
- { code: " return this.head === null;" },
- { code: " }" },
- { code: "" },
- { code: " // Insert at head" },
- { code: " insertFirst(data) {" },
- { code: " const newNode = new Node(data);" },
- { code: " newNode.next = this.head;" },
- { code: " this.head = newNode;" },
- { code: " this.size++;" },
- { code: " }" },
- ];
-
- const insertionAtHeadSteps = [
- { step: "1. Create new node with given data" },
- { step: "2. Set new node's next to current head" },
- { step: "3. Update head pointer to new node" },
- { step: "4. Increment list size counter" },
- ];
-
- const deletionSteps = [
- { step: "1. Check if list is empty (head === null)" },
- { step: "2. If deleting head, update head to head.next" },
- { step: "3. For middle deletion, find previous node and update its next pointer" },
- { step: "4. Decrement list size counter" },
- { step: "5. Return deleted data (if needed)" },
- ];
-
- const prosCons = [
- { point: "Dynamic size - grows as needed", type: "pro" },
- { point: "Efficient insertion/deletion at head", type: "pro" },
- { point: "No memory waste (only allocates needed nodes)", type: "pro" },
- { point: "No random access - must traverse from head", type: "con" },
- { point: "Extra memory for next pointers", type: "con" },
- { point: "Not cache-friendly (nodes scattered in memory)", type: "con" },
- ];
-
- const visualization = [
- { operation: "Initialization", state: "head → null" },
- { operation: "insertFirst(10)", state: "head → [10|•] → null" },
- { operation: "insertFirst(20)", state: "head → [20|•] → [10|•] → null" },
- { operation: "insertLast(30)", state: "head → [20|•] → [10|•] → [30|•] → null" },
- { operation: "deleteFirst()", state: "head → [10|•] → [30|•] → null" },
- { operation: "delete(30)", state: "head → [10|•] → null" },
- ];
-
- const applications = [
- "Implementing stacks and queues",
- "Memory management systems",
- "Undo functionality in software",
- "Hash table collision handling",
- "Polynomial representation and arithmetic",
- "Browser history navigation",
- ];
-
- return (
-
-
- {/* Overview Section */}
-
-
-
- Singly Linked List
-
-
- {overview.map((para, index) => (
-
- {para}
-
- ))}
-
-
- Key Property: Each node contains data and a single pointer to the next node, forming a unidirectional chain.
-
-
-
-
-
- {/* Basic Operations */}
-
- Basic Operations
-
-
-
-
- Operation
- Time Complexity
- Description
-
-
-
- {basicOperations.map((op, index) => (
-
- {op.name}
- {op.complexity}
- {op.description}
-
- ))}
-
-
-
-
-
- {/* Implementation */}
-
- Implementation
-
-
-
- {implementationCode.map((line, index) => (
- {line.code}
- ))}
-
-
-
-
-
- {/* Insertion at Head */}
-
- Insertion at Head
-
-
-
- {insertionAtHeadSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
-
-
-
head →
-
[A|•] → [B|•] → null
-
-
↓ Insert X at head ↓
-
-
head →
-
[X|•] → [A|•] → [B|•] → null
-
-
-
-
-
-
- {/* Deletion */}
-
- Deletion Operations
-
-
-
- {deletionSteps.map((step, index) => (
-
- {step.step}
-
- ))}
-
-
-
-
-
-
head →
-
[X|•] → [A|•] → [B|•] → null
-
-
↓ Delete A ↓
-
-
head →
-
[X|•] → [B|•] → null
-
-
-
-
-
-
- {/* Visualization */}
-
- Operation Visualization
-
-
-
-
- Operation
- List State
-
-
-
- {visualization.map((item, index) => (
-
- {item.operation}
- {item.state}
-
- ))}
-
-
-
-
-
- {/* Pros and Cons */}
-
- Pros and Cons
-
-
-
Advantages
-
- {prosCons.filter(item => item.type === "pro").map((item, index) => (
-
-
-
-
- {item.point}
-
- ))}
-
-
-
-
Limitations
-
- {prosCons.filter(item => item.type === "con").map((item, index) => (
-
-
-
-
- {item.point}
-
- ))}
-
-
-
-
-
- {/* Applications */}
-
- Applications
-
-
- {applications.map((app, index) => (
-
- {app}
-
- ))}
-
-
-
- Note: Singly linked lists are preferred when you need constant-time insertions/deletions at the beginning and don't require backward traversal.
-
-
-
-
-
-
- );
-};
-
-export default content;
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/singly/page.jsx b/app/visualizer/linkedList/types/singly/page.jsx
deleted file mode 100755
index 6cc82f64a..000000000
--- a/app/visualizer/linkedList/types/singly/page.jsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import Animation from "@/app/visualizer/linkedList/types/singly/animation";
-import Navbar from "@/app/components/navbarinner";
-
-export const metadata = {
- title: 'Singly Linked List Implementation | Visualize Linked List in JS, C, Python, Java',
- description: 'Explore Singly Linked List implementation with interactive visualizations and real-time code examples in JavaScript, C, Python, and Java. Learn insertion, deletion, and traversal with step-by-step animations. Perfect for DSA beginners and interview preparation.',
- keywords: [
- 'Singly Linked List Implementation',
- 'Singly Linked List Visualization',
- 'Linked List in JavaScript',
- 'Linked List in C',
- 'Linked List in Python',
- 'Linked List in Java',
- 'DSA Linked List',
- 'Linked List Operations',
- 'Insertion in Linked List',
- 'Deletion in Linked List',
- 'Traverse Linked List',
- 'Learn Linked List',
- 'Visualize Linked List',
- 'DSA for Beginners',
- 'Interactive Linked List Tool',
- ],
- robots: 'index, follow',
-};
-
-export default function Page() {
- return (
- <>
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/app/visualizer/linkedList/types/singly/quiz.jsx b/app/visualizer/linkedList/types/singly/quiz.jsx
deleted file mode 100755
index 3fb88d172..000000000
--- a/app/visualizer/linkedList/types/singly/quiz.jsx
+++ /dev/null
@@ -1,531 +0,0 @@
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const Quiz = () => {
-const questions = [
- {
- question: "What is the fundamental building block of a singly linked list?",
- options: [
- "Array",
- "Node containing data and a next pointer",
- "Hash table",
- "Binary tree"
- ],
- correctAnswer: 1,
- explanation: "A singly linked list is composed of nodes where each node contains data and a pointer to the next node."
- },
- {
- question: "What does the 'next' pointer of the last node in a singly linked list point to?",
- options: [
- "The head node",
- "A random node",
- "null",
- "Itself"
- ],
- correctAnswer: 2,
- explanation: "The last node's next pointer is null, indicating the end of the list."
- },
- {
- question: "What is the time complexity of inserting a new node at the head of a singly linked list?",
- options: [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n²)"
- ],
- correctAnswer: 0,
- explanation: "Insertion at head is O(1) as it only requires updating the head pointer."
- },
- {
- question: "Which operation in a singly linked list has O(n) time complexity?",
- options: [
- "Insertion at head",
- "Deletion at head",
- "Searching for an element",
- "Checking if list is empty"
- ],
- correctAnswer: 2,
- explanation: "Searching requires traversing the list from head to tail, which is O(n) in the worst case."
- },
- {
- question: "What is the advantage of a singly linked list over an array?",
- options: [
- "Constant-time random access",
- "Better cache locality",
- "Dynamic size and efficient insertions/deletions",
- "Built-in sorting capability"
- ],
- correctAnswer: 2,
- explanation: "Linked lists can grow dynamically and allow efficient insertions/deletions without shifting elements."
- },
- {
- question: "How do you check if a singly linked list is empty?",
- options: [
- "Check if size == 0",
- "Check if head == null",
- "Check if tail == null",
- "All of the above"
- ],
- correctAnswer: 1,
- explanation: "An empty list has its head pointer set to null."
- },
- {
- question: "What is the time complexity of deleting a specific value from a singly linked list?",
- options: [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n²)"
- ],
- correctAnswer: 1,
- explanation: "Deleting by value requires traversing the list to find the node, which is O(n)."
- },
- {
- question: "Which of these applications would LEAST likely use a singly linked list?",
- options: [
- "Implementing a stack",
- "Memory management system",
- "Image processing filter",
- "Browser history navigation"
- ],
- correctAnswer: 2,
- explanation: "Image processing typically requires random access to pixels, which arrays handle better."
- },
- {
- question: "What is the main disadvantage of singly linked lists compared to arrays?",
- options: [
- "Fixed size",
- "No random access to elements",
- "Inefficient insertion at head",
- "Cannot store different data types"
- ],
- correctAnswer: 1,
- explanation: "Accessing an arbitrary element requires traversal from the head, making it O(n) rather than O(1)."
- },
- {
- question: "What happens during insertion at the head of a singly linked list?",
- options: [
- "New node's next points to current head, then head updates to new node",
- "Traverse to end and add new node",
- "Find middle position and insert",
- "Replace all existing nodes"
- ],
- correctAnswer: 0,
- explanation: "Insertion at head involves creating a new node that points to the current head, then making it the new head."
- },
- {
- question: "How much extra memory per node does a singly linked list need compared to an array?",
- options: [
- "No extra memory",
- "4 bytes for size counter",
- "Pointer size (typically 4-8 bytes)",
- "Double the data storage"
- ],
- correctAnswer: 2,
- explanation: "Each node requires additional memory for the next pointer, typically 4-8 bytes depending on system."
- },
- {
- question: "What is the purpose of maintaining a 'size' variable in a linked list implementation?",
- options: [
- "To limit the maximum number of nodes",
- "To provide O(1) access to the list length",
- "To improve cache performance",
- "To enable random access"
- ],
- correctAnswer: 1,
- explanation: "A size counter allows checking the list length in constant time without traversal."
- }
-];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Linked List Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default Quiz;
\ No newline at end of file
diff --git a/app/visualizer/page.jsx b/app/visualizer/page.jsx
deleted file mode 100755
index f8320d149..000000000
--- a/app/visualizer/page.jsx
+++ /dev/null
@@ -1,549 +0,0 @@
-import React from "react";
-import Navbar from "@/app/components/navbar";
-import Footer from "@/app/components/footer";
-import VisualizerClient from "./VisualizerClient";
-import ArrayModal from "@/app/components/models/ArrayModal";
-import StackModal from "@/app/components/models/StackModel";
-import QueueModal from "@/app/components/models/QueueModal";
-import LinkedListModal from "@/app/components/models/LinkedListModal";
-import TreeModal from "@/app/components/models/TreeModal";
-import GraphModal from "@/app/components/models/GraphModal";
-import TutorialOverlay from "@/app/components/ui/TutorialOverlay";
-
-export const metadata = {
- title: "Algorithm Visualizer | AlgoBuddy",
- description:
- "Explore visual representations and source code for various DSA algorithms including searching, sorting, stacks, queues, trees, graphs, and stack-based expression evaluation like Polish Notation using arrays and linked lists. Interactive and beginner-friendly!",
- keywords: [
- "DSA Visualizer",
- "Algorithm Visualizer",
- "Data Structures",
- "Searching Algorithms",
- "Sorting Algorithms",
- "Stack",
- "Queue",
- "Tree",
- "Graph",
- "Graph Algorithms",
- "BFS",
- "DFS",
- "Linear Search",
- "Bubble Sort",
- "Tree Traversal",
- "Heap Sort",
- "Linked List",
- "Singly Linked List",
- "Doubly Linked List",
- "Circular Linked List",
- "Prefix Notation",
- "Postfix Notation",
- "Polish Notation",
- "Stack using Array",
- "Stack using Linked List",
- "Prefix using Stack",
- "Postfix using Stack",
- "Polish Notation Implementation",
- "Queue using Array",
- "Queue using Linked List",
- "Circular Queue",
- "Priority Queue",
- "Deque",
- "Queue Operations",
- "Graph Traversal",
- "Code for DSA Algorithms",
- "Code for Data Structures",
- "Interactive Code Samples",
- "DSA with Code",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/visualizer.png",
- width: 1200,
- height: 630,
- alt: "Algorithm Visualization",
- },
- ],
- },
-};
-
-const sections = [
- {
- title: "Array",
- desc: "Searching & sorting algorithms on contiguous memory",
- icon: (
-
-
-
- ),
- info: {
- About:
- "An array is a data structure that stores multiple values of the same type in a single variable. Each value is stored at a specific index, starting from 0.",
- Representation: ,
- },
- subsections: [
- {
- title: "Searching",
- items: [
- { name: "Linear Search", path: "/visualizer/searching/linearsearch" },
- { name: "Binary Search", path: "/visualizer/searching/binarysearch" },
- ],
- },
- {
- title: "Sorting",
- items: [
- { name: "Bubble Sort", path: "/visualizer/sorting/bubblesort" },
- { name: "Selection Sort", path: "/visualizer/sorting/selectionsort" },
- { name: "Insertion Sort", path: "/visualizer/sorting/insertionsort" },
- { name: "Merge Sort", path: "/visualizer/sorting/mergesort" },
- { name: "Quick Sort", path: "/visualizer/sorting/quicksort" },
- ],
- },
- ],
- },
- {
- title: "Stack",
- desc: "LIFO operations, polish notations & implementations",
- icon: (
-
-
-
- ),
- info: {
- About:
- "LIFO data structure; push adds to top; pop removes from top; peek views top; works like a stack of plates. Used in function calls, undo, expression evaluation.",
- Representation: ,
- },
- subsections: [
- {
- title: "Operations",
- items: [
- { name: "Push & Pop", path: "/visualizer/stack/push-pop" },
- { name: "Peek", path: "/visualizer/stack/peek" },
- { name: "Is Empty", path: "/visualizer/stack/isempty" },
- { name: "Is Full", path: "/visualizer/stack/isfull" },
- ],
- },
- {
- title: "Polish Notations Evaluation",
- items: [
- { name: "Postfix", path: "/visualizer/stack/polish/postfix" },
- { name: "Prefix", path: "/visualizer/stack/polish/prefix" },
- ],
- },
- {
- title: "Implementation",
- items: [
- {
- name: "Using Array",
- path: "/visualizer/stack/implementation/usingArray",
- },
- {
- name: "Using Linked List",
- path: "/visualizer/stack/implementation/usingLinkedList",
- },
- ],
- },
- ],
- },
- {
- title: "Queue",
- desc: "FIFO operations, variants & implementations",
- icon: (
-
-
-
- ),
- info: {
- About:
- "FIFO data structure; enqueue adds to rear; dequeue removes from front; peek views front; works like a line in a queue. Used in scheduling, buffering, BFS.",
- Representation: ,
- },
- subsections: [
- {
- title: "Operations",
- items: [
- {
- name: "Enqueue & Dequeue",
- path: "/visualizer/queue/operations/enqueue-dequeue",
- },
- {
- name: "Peek Front",
- path: "/visualizer/queue/operations/peek-front",
- },
- { name: "Is Empty", path: "/visualizer/queue/operations/isempty" },
- { name: "Is Full", path: "/visualizer/queue/operations/isfull" },
- ],
- },
- {
- title: "Types",
- items: [
- {
- name: "Single Ended Queue",
- path: "/visualizer/queue/types/singleEnded",
- },
- {
- name: "Double Ended Queue",
- path: "/visualizer/queue/types/deque",
- },
- { name: "Circular Queue", path: "/visualizer/queue/types/circular" },
- { name: "Priority Queue", path: "/visualizer/queue/types/priority" },
- ],
- },
- {
- title: "Implementation",
- items: [
- {
- name: "Using Array",
- path: "/visualizer/queue/implementation/array",
- },
- {
- name: "Using Linked List",
- path: "/visualizer/queue/implementation/linkedList",
- },
- ],
- },
- ],
- },
- {
- title: "Linked List",
- desc: "Singly, doubly, circular — traversal to merge",
- icon: (
-
-
-
-
- ),
- info: {
- About:
- "Linear data structure; elements (nodes) connected using pointers; each node has data + next; no fixed size; types: singly, doubly, circular. Used in dynamic memory, insert/delete operations.",
- Representation: ,
- },
- subsections: [
- {
- title: "Types",
- items: [
- {
- name: "Singly Linked List",
- path: "/visualizer/linkedList/types/singly",
- },
- {
- name: "Doubly Linked List",
- path: "/visualizer/linkedList/types/doubly",
- },
- {
- name: "Circular Linked List",
- path: "/visualizer/linkedList/types/circular",
- },
- ],
- },
- {
- title: "Operations",
- items: [
- {
- name: "Traversal",
- path: "/visualizer/linkedList/operations/traversal",
- },
- {
- name: "Insertion",
- path: "/visualizer/linkedList/operations/insertion",
- },
- {
- name: "Deletion",
- path: "/visualizer/linkedList/operations/deletion",
- },
- {
- name: "Searching",
- path: "/visualizer/linkedList/operations/search",
- },
- {
- name: "Reverse",
- path: "/visualizer/linkedList/operations/reverse",
- },
- {
- name: "Merge",
- path: "/visualizer/linkedList/operations/merge",
- },
- {
- name: "Comparison",
- path: "/visualizer/linkedList/operations/comparison",
- },
- ],
- },
- ],
- },
- {
- title: "Tree",
- desc: "BST, AVL, traversals, tries & advanced trees",
- icon: (
-
-
-
- ),
- info: {
- About:
- "Hierarchical data structure; has root, nodes, edges; each node has parent/child; no cycles; Used in hierarchies, file systems, searching.",
- Types: "binary tree, BST, AVL, etc.",
- Representation: ,
- },
- subsections: [
- {
- title: "Binary Tree",
- items: [
- {
- name: "Structure & Properties",
- path: "/visualizer/trees/binaryTree/properties",
- },
- {
- name: "Types of Binary Trees",
- path: "/visualizer/trees/binaryTree/types",
- },
- ],
- },
- {
- title: "Binary Search Tree",
- items: [
- { name: "Insertion", path: "/visualizer/trees/bst/insertion" },
- { name: "Deletion", path: "/visualizer/trees/bst/deletion" },
- { name: "Searching", path: "/visualizer/trees/bst/searching" },
- { name: "Balancing (AVL)", path: "/visualizer/trees/bst/avl" },
- ],
- },
- {
- title: "Traversal",
- items: [
- { name: "Pre-order", path: "/visualizer/trees/traversal/pre-order" },
- { name: "In-order", path: "/visualizer/trees/traversal/in-order" },
- {
- name: "Post-order",
- path: "/visualizer/trees/traversal/post-order",
- },
- {
- name: "Level-order (BFS)",
- path: "/visualizer/trees/traversal/level-order",
- },
- {
- name: "Morris Traversal",
- path: "/visualizer/trees/traversal/morris",
- },
- ],
- },
- {
- title: "Advanced Trees",
- items: [
- {
- name: "Red-Black Trees",
- path: "/visualizer/trees/advanced/red-black",
- },
- { name: "B-Trees", path: "/visualizer/trees/advanced/b-trees" },
- {
- name: "Trie (Prefix Tree)",
- path: "/visualizer/trees/advanced/trie",
- },
- { name: "Segment Trees", path: "/visualizer/trees/advanced/segment" },
- { name: "Fenwick Trees", path: "/visualizer/trees/advanced/fenwick" },
- ],
- },
- {
- title: "Algorithms",
- items: [
- {
- name: "Lowest Common Ancestor",
- path: "/visualizer/trees/algorithms/lca",
- },
- {
- name: "Tree Diameter",
- path: "/visualizer/trees/algorithms/diameter",
- },
- {
- name: "Tree Isomorphism",
- path: "/visualizer/trees/algorithms/isomorphism",
- },
- {
- name: "Serialize/Deserialize",
- path: "/visualizer/trees/algorithms/serialization",
- },
- ],
- },
- {
- title: "Applications",
- items: [
- {
- name: "Heap Sort",
- path: "/visualizer/trees/applications/heapsort",
- },
- {
- name: "Huffman Coding",
- path: "/visualizer/trees/applications/huffman",
- },
- {
- name: "Decision Trees",
- path: "/visualizer/trees/applications/decision-trees",
- },
- {
- name: "Syntax Trees",
- path: "/visualizer/trees/applications/syntax-trees",
- },
- ],
- },
- ],
- },
- {
- title: "Graph",
- desc: "BFS, DFS, Dijkstra, MST & topological sort",
- icon: (
-
-
-
- ),
- info: {
- About:
- "A graph is a data structure made up of: Nodes (also called vertices) Represent entities. Edges Represent connections between nodes.",
- Representation: ,
- },
- subsections: [
- {
- title: "Representation",
- items: [
- {
- name: "Adjacency Matrix",
- path: "/visualizer/graph/representation/adjacency-matrix",
- },
- {
- name: "Adjacency List",
- path: "/visualizer/graph/representation/adjacency-list",
- },
- ],
- },
- {
- title: "Traversal",
- items: [
- {
- name: "Breadth-First Search (BFS)",
- path: "/visualizer/graph/traversal/bfs",
- },
- {
- name: "Depth-First Search (DFS)",
- path: "/visualizer/graph/traversal/dfs",
- },
- ],
- },
- {
- title: "Algorithms",
- items: [
- {
- name: "Dijkstra's Algorithm",
- path: "/visualizer/graph/algorithms/dijkstra",
- },
- {
- name: "Prim's Algorithm",
- path: "/visualizer/graph/algorithms/prim",
- },
- {
- name: "Kruskal's Algorithm",
- path: "/visualizer/graph/algorithms/kruskal",
- },
- {
- name: "Topological Sort",
- path: "/visualizer/graph/algorithms/topological-sort",
- },
- ],
- },
- ],
- },
-];
-
-const Visualizer = () => {
- /* Strip non-serialisable `info` (contains JSX modals) before
- passing to the client component. Icons are fine — they're
- plain elements. */
- const clientSections = sections.map(({ info, ...rest }) => rest);
-
- return (
-
- );
-};
-
-export default Visualizer;
diff --git a/app/visualizer/queue/implementation/array/codeblock.jsx b/app/visualizer/queue/implementation/array/codeblock.jsx
deleted file mode 100755
index 487c04fe3..000000000
--- a/app/visualizer/queue/implementation/array/codeblock.jsx
+++ /dev/null
@@ -1,420 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
-const codeExamples = {
- javascript: `// Queue Implementation in JavaScript (Array)
-class Queue {
- constructor(size) {
- this.capacity = size;
- this.arr = new Array(size);
- this.front = this.rear = -1;
- }
-
- // Add element to the rear (enqueue)
- enqueue(item) {
- if ((this.rear + 1) % this.capacity === this.front) {
- console.log("Queue Overflow");
- return;
- }
- if (this.front === -1) {
- this.front = this.rear = 0;
- } else {
- this.rear = (this.rear + 1) % this.capacity;
- }
- this.arr[this.rear] = item;
- }
-
- // Remove element from front (dequeue)
- dequeue() {
- if (this.front === -1) {
- console.log("Queue Underflow");
- return -1;
- }
- const item = this.arr[this.front];
- if (this.front === this.rear) {
- this.front = this.rear = -1;
- } else {
- this.front = (this.front + 1) % this.capacity;
- }
- return item;
- }
-}
-
-// Usage Example
-const queue = new Queue(5);
-queue.enqueue(10);
-queue.enqueue(20);
-queue.enqueue(30);
-console.log(queue.dequeue()); // 10
-console.log(queue.dequeue()); // 20`,
-
- python: `# Queue Implementation in Python (Array)
-class Queue:
- def __init__(self, size):
- self.capacity = size
- self.arr = [None] * size
- self.front = self.rear = -1
-
- # Add element to the rear (enqueue)
- def enqueue(self, item):
- if (self.rear + 1) % self.capacity == self.front:
- print("Queue Overflow")
- return
- if self.front == -1:
- self.front = self.rear = 0
- else:
- self.rear = (self.rear + 1) % self.capacity
- self.arr[self.rear] = item
-
- # Remove element from front (dequeue)
- def dequeue(self):
- if self.front == -1:
- print("Queue Underflow")
- return -1
- item = self.arr[self.front]
- if self.front == self.rear:
- self.front = self.rear = -1
- else:
- self.front = (self.front + 1) % self.capacity
- return item
-
-# Usage Example
-q = Queue(5)
-q.enqueue(10)
-q.enqueue(20)
-q.enqueue(30)
-print(q.dequeue()) # 10
-print(q.dequeue()) # 20`,
-
- java: `// Queue Implementation in Java (Array)
-public class ArrayQueue {
- private int[] arr;
- private int front, rear, capacity;
-
- public ArrayQueue(int size) {
- capacity = size;
- arr = new int[capacity];
- front = rear = -1;
- }
-
- // Add element to the rear (enqueue)
- public void enqueue(int item) {
- if ((rear + 1) % capacity == front) {
- System.out.println("Queue Overflow");
- return;
- }
- if (front == -1) {
- front = rear = 0;
- } else {
- rear = (rear + 1) % capacity;
- }
- arr[rear] = item;
- }
-
- // Remove element from front (dequeue)
- public int dequeue() {
- if (front == -1) {
- System.out.println("Queue Underflow");
- return -1;
- }
- int item = arr[front];
- if (front == rear) {
- front = rear = -1;
- } else {
- front = (front + 1) % capacity;
- }
- return item;
- }
-
- public static void main(String[] args) {
- ArrayQueue queue = new ArrayQueue(5);
- queue.enqueue(10);
- queue.enqueue(20);
- queue.enqueue(30);
- System.out.println(queue.dequeue()); // 10
- System.out.println(queue.dequeue()); // 20
- }
-}`,
-
- c: `// Queue Implementation in C (Array)
-#include
-#include
-
-#define MAX_SIZE 100
-
-typedef struct {
- int arr[MAX_SIZE];
- int front, rear;
-} Queue;
-
-void initialize(Queue *q) {
- q->front = q->rear = -1;
-}
-
-bool isEmpty(Queue *q) {
- return q->front == -1;
-}
-
-bool isFull(Queue *q) {
- return (q->rear + 1) % MAX_SIZE == q->front;
-}
-
-// Add element to the rear (enqueue)
-void enqueue(Queue *q, int item) {
- if (isFull(q)) {
- printf("Queue Overflow\\n");
- return;
- }
- if (isEmpty(q)) {
- q->front = q->rear = 0;
- } else {
- q->rear = (q->rear + 1) % MAX_SIZE;
- }
- q->arr[q->rear] = item;
-}
-
-// Remove element from front (dequeue)
-int dequeue(Queue *q) {
- if (isEmpty(q)) {
- printf("Queue Underflow\\n");
- return -1;
- }
- int item = q->arr[q->front];
- if (q->front == q->rear) {
- q->front = q->rear = -1;
- } else {
- q->front = (q->front + 1) % MAX_SIZE;
- }
- return item;
-}
-
-int main() {
- Queue q;
- initialize(&q);
-
- enqueue(&q, 10);
- enqueue(&q, 20);
- enqueue(&q, 30);
-
- printf("%d\\n", dequeue(&q)); // 10
- printf("%d\\n", dequeue(&q)); // 20
-
- return 0;
-}`,
-
- cpp: `// Queue Implementation in C++ (Array)
-#include
-using namespace std;
-
-class Queue {
-private:
- int *arr;
- int front, rear, capacity;
-
-public:
- Queue(int size) {
- capacity = size;
- arr = new int[capacity];
- front = rear = -1;
- }
-
- ~Queue() {
- delete[] arr;
- }
-
- // Add element to the rear (enqueue)
- void enqueue(int item) {
- if ((rear + 1) % capacity == front) {
- cout << "Queue Overflow" << endl;
- return;
- }
- if (front == -1) {
- front = rear = 0;
- } else {
- rear = (rear + 1) % capacity;
- }
- arr[rear] = item;
- }
-
- // Remove element from front (dequeue)
- int dequeue() {
- if (front == -1) {
- cout << "Queue Underflow" << endl;
- return -1;
- }
- int item = arr[front];
- if (front == rear) {
- front = rear = -1;
- } else {
- front = (front + 1) % capacity;
- }
- return item;
- }
-};
-
-int main() {
- Queue q(5);
- q.enqueue(10);
- q.enqueue(20);
- q.enqueue(30);
-
- cout << q.dequeue() << endl; // 10
- cout << q.dequeue() << endl; // 20
-
- return 0;
-}`
-};
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Implementation (Enqueue & Dequeue)
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/queue/implementation/array/content.jsx b/app/visualizer/queue/implementation/array/content.jsx
deleted file mode 100755
index 1487db290..000000000
--- a/app/visualizer/queue/implementation/array/content.jsx
+++ /dev/null
@@ -1,295 +0,0 @@
-"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 = [
- `Implementing a Queue using an array is a fundamental approach where we use a fixed-size or dynamic array to store elements while maintaining FIFO order. The array implementation requires careful handling of front and rear pointers to efficiently enqueue and dequeue elements.`,
- `In a circular array implementation, we treat the array as circular to maximize space utilization. When either pointer reaches the end of the array, it wraps around to the beginning.`,
- `Queues are widely used in scenarios like printer job scheduling, call center systems, and network packet handling where order preservation is crucial.`,
- ];
-
- const implementationSteps = [
- {
- points:
- "Initialize an array of fixed size (for static implementation) or dynamic array",
- },
- {
- points:
- "Initialize two pointers: front (for dequeue) and rear (for enqueue), both set to -1 initially",
- },
- {
- points:
- "Implement boundary checks for overflow (full queue) and underflow (empty queue) conditions",
- },
- {
- points:
- "For circular queue implementation, use modulo arithmetic for pointer updates",
- },
- ];
-
- const enqueueAlgorithm = [
- {
- points:
- "Check if queue is full (if (rear == capacity - 1) for linear array)",
- },
- { points: "For empty queue, set both front and rear to 0" },
- { points: "For circular queue: rear = (rear + 1) % capacity" },
- { points: "Insert new element at items[rear]" },
- { points: "Increment size counter" },
- ];
-
- const dequeueAlgorithm = [
- { points: "Check if queue is empty (front == -1)" },
- { points: "Store the front element to return later" },
- { points: "If only one element (front == rear), reset pointers to -1" },
- { points: "For circular queue: front = (front + 1) % capacity" },
- { points: "Decrement size counter" },
- { points: "Return the stored element" },
- ];
-
- const complexity = [
- {
- points:
- "Enqueue Operation: O(1) - Amortized constant time for dynamic arrays",
- },
- {
- points:
- "Dequeue Operation: O(1) - No shifting needed with pointer approach",
- },
- { points: "Peek Operation: O(1) - Direct access via front pointer" },
- { points: "Space Usage: O(n) - Linear space for storing elements" },
- ];
-
- const prosCons = [
- {
- points:
- "Pros: Simple implementation, cache-friendly (array elements contiguous in memory)",
- },
- { points: "Pros: Efficient O(1) operations with pointer tracking" },
- { points: "Cons: Fixed size limitation in static array implementation" },
- {
- points:
- "Cons: Wasted space in linear array implementation without circular approach",
- },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* Queue Array Implementation Overview */}
-
-
-
- Queue Implementation Using Array
-
-
-
-
- {/* Implementation Steps */}
-
-
-
- Implementation Steps
-
-
-
- {implementationSteps.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Enqueue Algorithm */}
-
-
-
- Enqueue Algorithm
-
-
-
- {enqueueAlgorithm.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Dequeue Algorithm */}
-
-
-
- Dequeue Algorithm
-
-
-
- {dequeueAlgorithm.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time & Space Complexity
-
-
-
- {complexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
-
-
- {/* Pros and Cons */}
-
-
-
- Pros and Cons
-
-
-
- {prosCons.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
-
- Practical Considerations
-
-
- {paragraph[1]}
-
-
- {paragraph[2]}
-
-
-
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/queue/implementation/array/page.jsx b/app/visualizer/queue/implementation/array/page.jsx
deleted file mode 100755
index ab36c1376..000000000
--- a/app/visualizer/queue/implementation/array/page.jsx
+++ /dev/null
@@ -1,104 +0,0 @@
-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/queue/implementation/array/content";
-import Code from "@/app/visualizer/queue/implementation/array/codeblock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Footer from '@/app/components/footer';
-import BackToTop from '@/app/components/ui/backtotop';
-
-export const metadata = {
- title:
- "Queue Implementation Using Array | Visualize Queue Operations in JS, C, Python, Java",
- description:
- "Learn Queue implementation using arrays with real-time visualizations and code examples in JavaScript, C, Python, and Java. Understand how Enqueue and Dequeue work step-by-step without quizzes. Ideal for DSA beginners.",
- keywords: [
- "Queue Implementation",
- "Queue using Array",
- "Enqueue Dequeue Operations",
- "Queue Data Structure",
- "Queue Visualization",
- "DSA Queue Tutorial",
- "Queue in JavaScript",
- "Queue in C",
- "Queue in Python",
- "Queue in Java",
- "Learn Queue",
- "Interactive Queue Visualizer",
- "Array based Queue",
- "DSA for Beginners",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/queue/queueArray.png",
- width: 1200,
- height: 630,
- alt: "Implementation of Queue using Array Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Queue using Array", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/queue/implementation/linkedList/codeBlock.jsx b/app/visualizer/queue/implementation/linkedList/codeBlock.jsx
deleted file mode 100755
index 3d0a1b3ed..000000000
--- a/app/visualizer/queue/implementation/linkedList/codeBlock.jsx
+++ /dev/null
@@ -1,460 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
-const codeExamples = {
- javascript: `// Queue Implementation in JavaScript (Linked List)
-class Node {
- constructor(data) {
- this.data = data;
- this.next = null;
- }
-}
-
-class Queue {
- constructor() {
- this.front = null;
- this.rear = null;
- }
-
- // Add element to the rear (enqueue)
- enqueue(item) {
- const newNode = new Node(item);
- if (this.rear === null) {
- this.front = this.rear = newNode;
- } else {
- this.rear.next = newNode;
- this.rear = newNode;
- }
- }
-
- // Remove element from front (dequeue)
- dequeue() {
- if (this.front === null) {
- return "Queue Underflow";
- }
- const temp = this.front;
- this.front = temp.next;
-
- if (this.front === null) {
- this.rear = null;
- }
- return temp.data;
- }
-
- // Check if queue is empty
- isEmpty() {
- return this.front === null;
- }
-}
-
-// Usage Example
-const queue = new Queue();
-queue.enqueue(10);
-queue.enqueue(20);
-queue.enqueue(30);
-console.log(queue.dequeue()); // 10
-console.log(queue.dequeue()); // 20
-console.log(queue.isEmpty()); // false`,
-
- python: `# Queue Implementation in Python (Linked List)
-class Node:
- def __init__(self, data):
- self.data = data
- self.next = None
-
-class Queue:
- def __init__(self):
- self.front = None
- self.rear = None
-
- # Add element to the rear (enqueue)
- def enqueue(self, item):
- new_node = Node(item)
- if self.rear is None:
- self.front = self.rear = new_node
- else:
- self.rear.next = new_node
- self.rear = new_node
-
- # Remove element from front (dequeue)
- def dequeue(self):
- if self.front is None:
- return "Queue Underflow"
- temp = self.front
- self.front = temp.next
-
- if self.front is None:
- self.rear = None
- return temp.data
-
- # Check if queue is empty
- def is_empty(self):
- return self.front is None
-
-# Usage Example
-q = Queue()
-q.enqueue(10)
-q.enqueue(20)
-q.enqueue(30)
-print(q.dequeue()) # 10
-print(q.dequeue()) # 20
-print(q.is_empty()) # False`,
-
- java: `// Queue Implementation in Java (Linked List)
-public class LinkedListQueue {
- private class Node {
- int data;
- Node next;
-
- Node(int data) {
- this.data = data;
- this.next = null;
- }
- }
-
- private Node front, rear;
-
- public LinkedListQueue() {
- front = rear = null;
- }
-
- // Add element to the rear (enqueue)
- public void enqueue(int item) {
- Node newNode = new Node(item);
- if (rear == null) {
- front = rear = newNode;
- } else {
- rear.next = newNode;
- rear = newNode;
- }
- }
-
- // Remove element from front (dequeue)
- public int dequeue() {
- if (front == null) {
- System.out.println("Queue Underflow");
- return -1;
- }
- Node temp = front;
- front = front.next;
-
- if (front == null) {
- rear = null;
- }
- return temp.data;
- }
-
- // Check if queue is empty
- public boolean isEmpty() {
- return front == null;
- }
-
- public static void main(String[] args) {
- LinkedListQueue queue = new LinkedListQueue();
- queue.enqueue(10);
- queue.enqueue(20);
- queue.enqueue(30);
- System.out.println(queue.dequeue()); // 10
- System.out.println(queue.dequeue()); // 20
- System.out.println(queue.isEmpty()); // false
- }
-}`,
-
- c: `// Queue Implementation in C (Linked List)
-#include
-#include
-#include
-
-typedef struct Node {
- int data;
- struct Node* next;
-} Node;
-
-typedef struct {
- Node* front;
- Node* rear;
-} Queue;
-
-void initialize(Queue* q) {
- q->front = q->rear = NULL;
-}
-
-// Add element to the rear (enqueue)
-void enqueue(Queue* q, int item) {
- Node* newNode = (Node*)malloc(sizeof(Node));
- newNode->data = item;
- newNode->next = NULL;
-
- if (q->rear == NULL) {
- q->front = q->rear = newNode;
- } else {
- q->rear->next = newNode;
- q->rear = newNode;
- }
-}
-
-// Remove element from front (dequeue)
-int dequeue(Queue* q) {
- if (q->front == NULL) {
- printf("Queue Underflow\n");
- return -1;
- }
- Node* temp = q->front;
- int item = temp->data;
- q->front = q->front->next;
-
- if (q->front == NULL) {
- q->rear = NULL;
- }
- free(temp);
- return item;
-}
-
-// Check if queue is empty
-bool isEmpty(Queue* q) {
- return q->front == NULL;
-}
-
-int main() {
- Queue q;
- initialize(&q);
-
- enqueue(&q, 10);
- enqueue(&q, 20);
- enqueue(&q, 30);
-
- printf("%d\n", dequeue(&q)); // 10
- printf("%d\n", dequeue(&q)); // 20
- printf("%s\n", isEmpty(&q) ? "true" : "false"); // false
-
- return 0;
-}`,
-
- cpp: `// Queue Implementation in C++ (Linked List)
-#include
-using namespace std;
-
-class Node {
-public:
- int data;
- Node* next;
-
- Node(int val) : data(val), next(nullptr) {}
-};
-
-class Queue {
-private:
- Node* front;
- Node* rear;
-
-public:
- Queue() : front(nullptr), rear(nullptr) {}
-
- ~Queue() {
- while (!isEmpty()) {
- dequeue();
- }
- }
-
- // Add element to the rear (enqueue)
- void enqueue(int item) {
- Node* newNode = new Node(item);
- if (rear == nullptr) {
- front = rear = newNode;
- } else {
- rear->next = newNode;
- rear = newNode;
- }
- }
-
- // Remove element from front (dequeue)
- int dequeue() {
- if (front == nullptr) {
- cout << "Queue Underflow" << endl;
- return -1;
- }
- Node* temp = front;
- int item = temp->data;
- front = front->next;
-
- if (front == nullptr) {
- rear = nullptr;
- }
-
- delete temp;
- return item;
- }
-
- // Check if queue is empty
- bool isEmpty() const {
- return front == nullptr;
- }
-};
-
-int main() {
- Queue q;
- q.enqueue(10);
- q.enqueue(20);
- q.enqueue(30);
-
- cout << q.dequeue() << endl; // 10
- cout << q.dequeue() << endl; // 20
- cout << boolalpha << q.isEmpty() << endl; // false
-
- return 0;
-}`
-};
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Implementation Enqueue & Dequeue
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/queue/implementation/linkedList/content.jsx b/app/visualizer/queue/implementation/linkedList/content.jsx
deleted file mode 100755
index dd7f6c070..000000000
--- a/app/visualizer/queue/implementation/linkedList/content.jsx
+++ /dev/null
@@ -1,254 +0,0 @@
-"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 = [
- `Implementing a Queue using a linked list provides dynamic memory allocation and efficient insertion/removal operations. Unlike array implementation, linked list queues don't have fixed capacity limitations and can grow dynamically as needed.`,
- `Each node in the linked list contains the data and a pointer to the next node. The front pointer points to the first node (for dequeue), while the rear pointer points to the last node (for enqueue).`,
- `Linked list queues are particularly useful when the maximum size isn't known in advance or when frequent insertions/deletions are required.`,
- ];
-
- const implementationSteps = [
- { points: "Define a Node class with data and next pointer attributes" },
- { points: "Create Queue class with front and rear pointers initialized to null" },
- { points: "Implement enqueue by adding nodes at the rear" },
- { points: "Implement dequeue by removing nodes from the front" },
- { points: "Maintain proper pointer connections during operations" },
- ];
-
- const enqueueAlgorithm = [
- { points: "Create a new node with the given data" },
- { points: "If queue is empty, set both front and rear to the new node" },
- { points: "Else, set rear.next to the new node and update rear pointer" },
- { points: "Increment the size counter" },
- ];
-
- const dequeueAlgorithm = [
- { points: "Check if queue is empty (front === null)" },
- { points: "Store the front node to return later" },
- { points: "Move front pointer to front.next" },
- { points: "If front becomes null (queue is now empty), set rear to null" },
- { points: "Decrement the size counter" },
- { points: "Return the stored node's data" },
- ];
-
- const complexity = [
- { points: "Enqueue Operation: O(1) - Constant time to add at tail" },
- { points: "Dequeue Operation: O(1) - Constant time to remove from head" },
- { points: "Peek Operation: O(1) - Direct access via front pointer" },
- { points: "Space Usage: O(n) - Linear space for storing elements plus pointer overhead" },
- ];
-
- const prosCons = [
- { points: "Pros: No fixed size limitation - grows dynamically" },
- { points: "Pros: Efficient O(1) operations for both enqueue and dequeue" },
- { points: "Pros: No wasted memory (only allocates what's needed)" },
- { points: "Cons: Extra memory for node pointers (next references)" },
- { points: "Cons: Not cache-friendly (nodes may be scattered in memory)" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* Queue Linked List Implementation Overview */}
-
-
-
- Queue Implementation Using Linked List
-
-
-
-
- {/* Implementation Steps */}
-
-
-
- Implementation Steps
-
-
-
- {implementationSteps.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Enqueue Algorithm */}
-
-
-
- Enqueue Algorithm
-
-
-
- {enqueueAlgorithm.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Dequeue Algorithm */}
-
-
-
- Dequeue Algorithm
-
-
-
- {dequeueAlgorithm.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time & Space Complexity
-
-
-
- {complexity.map((item, index) => (
-
-
- {item.points.split(':')[0]}:
-
- {item.points.split(':')[1]}
-
- ))}
-
-
-
-
- {/* Pros and Cons */}
-
-
-
- Pros and Cons
-
-
-
- {prosCons.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
-
When to Use Linked List Queue
-
- {paragraph[2]}
-
-
- When the maximum queue size is unpredictable
- When memory efficiency is more important than cache performance
- In applications with frequent dynamic memory allocation/deallocation
-
-
-
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
\ No newline at end of file
diff --git a/app/visualizer/queue/implementation/linkedList/page.jsx b/app/visualizer/queue/implementation/linkedList/page.jsx
deleted file mode 100755
index 95c3d2952..000000000
--- a/app/visualizer/queue/implementation/linkedList/page.jsx
+++ /dev/null
@@ -1,105 +0,0 @@
-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/queue/implementation/linkedList/content";
-import Code from "@/app/visualizer/queue/implementation/linkedList/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import Footer from "@/app/components/footer";
-import BackToTop from "@/app/components/ui/backtotop";
-
-export const metadata = {
- title:
- "Queue Implementation Using Linked List | Visualize Queue in JS, C, Python, Java",
- description:
- "Explore Queue implementation using Linked List with real-time visualizations and code examples in JavaScript, C, Python, and Java. Understand how Enqueue and Dequeue work in a dynamic memory structure. Perfect for DSA beginners and interview prep.",
- keywords: [
- "Queue Implementation",
- "Queue using Linked List",
- "Enqueue Dequeue Operations",
- "Queue Data Structure",
- "Linked List Queue",
- "Queue Visualization",
- "DSA Queue Tutorial",
- "Queue in JavaScript",
- "Queue in C",
- "Queue in Python",
- "Queue in Java",
- "Learn Queue",
- "Interactive DSA Tools",
- "DSA with Linked List",
- "DSA for Beginners",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/queue/queueLinkedList.png",
- width: 1200,
- height: 630,
- alt: "Implementation of Queue using Linked List Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Queue using Linked List", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- Using Linked List
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/queue/operations/enqueue-dequeue/animation.jsx b/app/visualizer/queue/operations/enqueue-dequeue/animation.jsx
deleted file mode 100755
index ed0409108..000000000
--- a/app/visualizer/queue/operations/enqueue-dequeue/animation.jsx
+++ /dev/null
@@ -1,230 +0,0 @@
-"use client";
-import React, { useState } from "react";
-
-const QueueVisualizer = () => {
- const [queue, setQueue] = useState([]);
- const [inputValue, setInputValue] = useState("");
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("");
- const [isAnimating, setIsAnimating] = useState(false);
-
- const enqueue = () => {
- if (!inputValue.trim()) {
- setMessage("Please enter a value");
- return;
- }
- setIsAnimating(true);
- setOperation(`Enqueuing "${inputValue}" to rear...`);
- setTimeout(() => {
- setQueue((prev) => [...prev, inputValue]);
- setOperation(null);
- setMessage(`"${inputValue}" added to rear`);
- setInputValue("");
- setIsAnimating(false);
- }, 1000);
- };
-
- const dequeue = () => {
- if (queue.length === 0) {
- setMessage("Queue is empty!");
- return;
- }
- setIsAnimating(true);
- const dequeuedValue = queue[0];
- setOperation(`Dequeuing "${dequeuedValue}" from front...`);
- setTimeout(() => {
- setQueue((prev) => prev.slice(1));
- setOperation(null);
- setMessage(`"${dequeuedValue}" removed from front`);
- setIsAnimating(false);
- }, 1000);
- };
-
- const reset = () => {
- setQueue([]);
- setInputValue("");
- setOperation(null);
- };
-
- return (
-
-
- Visualize First-In-First-Out (FIFO) operations in real-time
-
-
- {/* ------- Controls ------- */}
-
-
-
-
setInputValue(e.target.value)}
- placeholder="Enter value..."
- className="flex-1 p-3 border border-neutral-300 dark:border-gray-500 rounded-lg dark:bg-neutral-900 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all min-w-[180px] max-w-xs"
- disabled={isAnimating}
- onKeyDown={(e) => e.key === "Enter" && enqueue()}
- />
-
-
- Enqueue
-
-
- Dequeue
-
-
- Reset
-
-
-
-
- {/* status row */}
-
- {operation && (
-
- )}
- {message && (
-
-
- {message.includes("added") ? (
-
- ) : message.includes("removed") ? (
-
- ) : (
-
- )}
-
-
{message}
-
- )}
-
-
-
- {/* ------- Queue Visualization (hidden when empty) ------- */}
- {queue.length > 0 && (
-
-
Queue Visualization
-
- {/* Queue row with Front / Rear labels on the sides */}
-
- {/* Front label */}
-
-
- {/* Elements */}
-
- {queue.map((item, index) => (
-
- ))}
-
-
- {/* Rear label */}
-
-
-
- )}
-
-
- );
-};
-
-export default QueueVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/enqueue-dequeue/codeBlock.jsx b/app/visualizer/queue/operations/enqueue-dequeue/codeBlock.jsx
deleted file mode 100755
index 261ddf2bf..000000000
--- a/app/visualizer/queue/operations/enqueue-dequeue/codeBlock.jsx
+++ /dev/null
@@ -1,433 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Queue Implementation in JavaScript (Linked List)
-class Node {
- constructor(data) {
- this.data = data;
- this.next = null;
- }
-}
-
-class Queue {
- constructor() {
- this.front = null;
- this.rear = null;
- }
-
- // Add element to the rear (enqueue)
- enqueue(item) {
- const newNode = new Node(item);
- if (this.rear === null) {
- this.front = this.rear = newNode;
- } else {
- this.rear.next = newNode;
- this.rear = newNode;
- }
- }
-
- // Remove element from front (dequeue)
- dequeue() {
- if (this.front === null) {
- return "Queue Underflow";
- }
- const temp = this.front;
- this.front = temp.next;
-
- if (this.front === null) {
- this.rear = null;
- }
- return temp.data;
- }
-}
-
-// Usage Example
-const queue = new Queue();
-queue.enqueue(10);
-queue.enqueue(20);
-queue.enqueue(30);
-console.log(queue.dequeue()); // 10
-console.log(queue.dequeue()); // 20`,
-
- python: `# Queue Implementation in Python (Linked List)
-class Node:
- def __init__(self, data):
- self.data = data
- self.next = None
-
-class Queue:
- def __init__(self):
- self.front = None
- self.rear = None
-
- # Add element to the rear (enqueue)
- def enqueue(self, item):
- new_node = Node(item)
- if self.rear is None:
- self.front = self.rear = new_node
- else:
- self.rear.next = new_node
- self.rear = new_node
-
- # Remove element from front (dequeue)
- def dequeue(self):
- if self.front is None:
- return "Queue Underflow"
- temp = self.front
- self.front = temp.next
-
- if self.front is None:
- self.rear = None
- return temp.data
-
-# Usage Example
-q = Queue()
-q.enqueue(10)
-q.enqueue(20)
-q.enqueue(30)
-print(q.dequeue()) # 10
-print(q.dequeue()) # 20`,
-
- java: `// Queue Implementation in Java (Array)
-public class ArrayQueue {
- private int[] arr;
- private int front, rear, capacity;
-
- public ArrayQueue(int size) {
- capacity = size;
- arr = new int[capacity];
- front = rear = -1;
- }
-
- // Add element to the rear (enqueue)
- public void enqueue(int item) {
- if ((rear + 1) % capacity == front) {
- System.out.println("Queue Overflow");
- return;
- }
- if (front == -1) {
- front = rear = 0;
- } else {
- rear = (rear + 1) % capacity;
- }
- arr[rear] = item;
- }
-
- // Remove element from front (dequeue)
- public int dequeue() {
- if (front == -1) {
- System.out.println("Queue Underflow");
- return -1;
- }
- int item = arr[front];
- if (front == rear) {
- front = rear = -1;
- } else {
- front = (front + 1) % capacity;
- }
- return item;
- }
-
- public static void main(String[] args) {
- ArrayQueue queue = new ArrayQueue(5);
- queue.enqueue(10);
- queue.enqueue(20);
- queue.enqueue(30);
- System.out.println(queue.dequeue()); // 10
- System.out.println(queue.dequeue()); // 20
- }
-}`,
-
- c: `// Queue Implementation in C (Array)
-#include
-#include
-
-#define MAX_SIZE 100
-
-typedef struct {
- int arr[MAX_SIZE];
- int front, rear;
-} Queue;
-
-void initialize(Queue *q) {
- q->front = q->rear = -1;
-}
-
-bool isEmpty(Queue *q) {
- return q->front == -1;
-}
-
-bool isFull(Queue *q) {
- return (q->rear + 1) % MAX_SIZE == q->front;
-}
-
-// Add element to the rear (enqueue)
-void enqueue(Queue *q, int item) {
- if (isFull(q)) {
- printf("Queue Overflow\\n");
- return;
- }
- if (isEmpty(q)) {
- q->front = q->rear = 0;
- } else {
- q->rear = (q->rear + 1) % MAX_SIZE;
- }
- q->arr[q->rear] = item;
-}
-
-// Remove element from front (dequeue)
-int dequeue(Queue *q) {
- if (isEmpty(q)) {
- printf("Queue Underflow\\n");
- return -1;
- }
- int item = q->arr[q->front];
- if (q->front == q->rear) {
- q->front = q->rear = -1;
- } else {
- q->front = (q->front + 1) % MAX_SIZE;
- }
- return item;
-}
-
-int main() {
- Queue q;
- initialize(&q);
-
- enqueue(&q, 10);
- enqueue(&q, 20);
- enqueue(&q, 30);
-
- printf("%d\\n", dequeue(&q)); // 10
- printf("%d\\n", dequeue(&q)); // 20
-
- return 0;
-}`,
-
- cpp: `// Queue Implementation in C++ (Linked List)
-#include
-using namespace std;
-
-class Node {
-public:
- int data;
- Node* next;
-
- Node(int val) : data(val), next(nullptr) {}
-};
-
-class Queue {
-private:
- Node* front;
- Node* rear;
-
-public:
- Queue() : front(nullptr), rear(nullptr) {}
-
- ~Queue() {
- while (!isEmpty()) {
- dequeue();
- }
- }
-
- // Add element to the rear (enqueue)
- void enqueue(int item) {
- Node* newNode = new Node(item);
- if (rear == nullptr) {
- front = rear = newNode;
- } else {
- rear->next = newNode;
- rear = newNode;
- }
- }
-
- // Remove element from front (dequeue)
- int dequeue() {
- if (front == nullptr) {
- cout << "Queue Underflow" << endl;
- return -1;
- }
- Node* temp = front;
- int item = temp->data;
- front = front->next;
-
- if (front == nullptr) {
- rear = nullptr;
- }
-
- delete temp;
- return item;
- }
-
- bool isEmpty() const {
- return front == nullptr;
- }
-};
-
-int main() {
- Queue q;
- q.enqueue(10);
- q.enqueue(20);
- q.enqueue(30);
-
- cout << q.dequeue() << endl; // 10
- cout << q.dequeue() << endl; // 20
-
- return 0;
-}`,
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Queue (Enqueue & Dequeue)
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/enqueue-dequeue/content.jsx b/app/visualizer/queue/operations/enqueue-dequeue/content.jsx
deleted file mode 100755
index 5b3f7c770..000000000
--- a/app/visualizer/queue/operations/enqueue-dequeue/content.jsx
+++ /dev/null
@@ -1,283 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 = [
- `A Queue is a linear data structure that follows the First-In-First-Out (FIFO) principle. Elements are added at the rear (enqueue) and removed from the front (dequeue). It operates much like a real-world queue (line) where the first person to arrive is the first to be served.`,
- `The space complexity is O(n) where n is the number of elements in the queue, as it needs to store all elements.`,
- `Queues are fundamental in computer science and are used in various applications like CPU scheduling, disk scheduling, handling interrupts, breadth-first search, and any scenario where you need to maintain order of processing.`,
- ];
-
- const enqueue = [
- { points : "Check if the queue is full (in case of fixed-size implementation)" },
- { points : "If full, return overflow error (or resize in dynamic implementation)" },
- { points : "Increment the rear pointer" },
- { points : "Add the new element at the rear position" },
- ];
-
- const opeartionEnqueue = [
- { points : "Before Enqueue: [10, 20, 30]" },
- { points : "Enqueue(40): Add 40 to the rear" },
- { points : "Enqueue(40): Add 40 to the rear" },
- ];
-
- const dequeue = [
- { points : "Check if the queue is empty" },
- { points : "If empty, return underflow error" },
- { points : "Access the data at the front of the queue" },
- { points : "Increment the front pointer to the next element" },
- { points : "Return the accessed data" },
- ];
-
- const operationDequeue = [
- { points : "Before Dequeue: [10, 20, 30, 40]" },
- { points : "Dequeue(): Remove and return 10" },
- { points : "After Dequeue: [20, 30, 40]" },
- ];
-
- const complexity = [
- { points : "Enqueue Operation: O(1) - Constant time to add to the end" },
- { points : "Dequeue Operation: O(1) - Constant time to remove from the front" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is a Queue? */}
-
-
-
- What is a Queue?
-
-
-
-
- {/* Enqueue Operation */}
-
-
-
- Enqueue Operation
-
-
-
- Enqueue adds an element to the end (rear) of the queue. Example with queue: [10, 20, 30]
-
-
-
- {opeartionEnqueue.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
- The new element always goes to the end of the queue.
-
-
-
-
- {/* Dequeue Operation */}
-
-
-
- Dequeue Operation
-
-
-
- Dequeue removes and returns the element from the front (head) of the queue.
-
-
- Example with queue: [10, 20, 30, 40]
-
-
-
- {operationDequeue.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
- The oldest element (first one added) is always removed first.
-
-
-
-
- {/* Algorithm Steps for Enqueue */}
-
-
-
- Algorithm Steps for Enqueue
-
-
-
- {enqueue.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Algorithm Steps for Dequeue */}
-
-
-
- Algorithm Steps for Dequeue
-
-
-
- {dequeue.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {complexity.map((item, index) => (
-
-
- {item.points.split(':')[0]}:
-
- {item.points.split(':')[1]}
-
- ))}
-
-
-
- 1}
- averageCase={(n) => 1}
- worstCase={(n) => 1}
- maxN={25}
- />
-
-
-
-
- {/* Space Complexity */}
-
-
-
- Space Complexity
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
- };
-
- export default content;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/enqueue-dequeue/page.jsx b/app/visualizer/queue/operations/enqueue-dequeue/page.jsx
deleted file mode 100755
index e3c45a8a5..000000000
--- a/app/visualizer/queue/operations/enqueue-dequeue/page.jsx
+++ /dev/null
@@ -1,121 +0,0 @@
-import Animation from "@/app/visualizer/queue/operations/enqueue-dequeue/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/queue/operations/enqueue-dequeue/content";
-import Quiz from "@/app/visualizer/queue/operations/enqueue-dequeue/quiz";
-import Code from "@/app/visualizer/queue/operations/enqueue-dequeue/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import Footer from "@/app/components/footer";
-import BackToTop from "@/app/components/ui/backtotop";
-
-export const metadata = {
- title:
- "Enqueue and Dequeue Operations in Queue | Learn Queue with JS, C, Python, Java Code",
- description:
- "Visualize and understand the Enqueue and Dequeue operations in a Queue with real-time animations and code examples in JavaScript, C, Python, and Java. Perfect for DSA beginners and interview preparation.",
- keywords: [
- "Enqueue Operation",
- "Dequeue Operation",
- "Queue Operations",
- "Queue DSA",
- "Queue Enqueue Dequeue",
- "Learn Queue",
- "Queue Visualization",
- "Interactive DSA Tools",
- "Queue Data Structure",
- "Queue Code Examples",
- "Enqueue Dequeue in JavaScript",
- "Enqueue Dequeue in C",
- "Enqueue Dequeue in Python",
- "Enqueue Dequeue in Java",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/queue/enqueueDequeue.png",
- width: 1200,
- height: 630,
- alt: "Enqueue Dequeue Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Enqueue-Dequeue", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- Enqueue & Dequeue
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/queue/operations/enqueue-dequeue/quiz.jsx b/app/visualizer/queue/operations/enqueue-dequeue/quiz.jsx
deleted file mode 100755
index b9b0d1518..000000000
--- a/app/visualizer/queue/operations/enqueue-dequeue/quiz.jsx
+++ /dev/null
@@ -1,379 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const QueueQuiz = () => {
- const questions = [
- {
- question: "What principle does a Queue data structure follow?",
- options: [
- "Last-In-First-Out (LIFO)",
- "First-In-First-Out (FIFO)",
- "Random Access",
- "Priority-Based"
- ],
- correctAnswer: 1,
- explanation: "Queues follow FIFO: The first element added is the first one removed."
- },
- {
- question: "Where is a new element added in a Queue?",
- options: [
- "At the front",
- "At the rear",
- "In the middle",
- "At any random position"
- ],
- correctAnswer: 1,
- explanation: "Enqueue adds elements to the **rear** (end) of the queue."
- },
- {
- question: "What is the time complexity of the enqueue operation?",
- options: ["O(n)", "O(1)", "O(log n)", "O(n²)"],
- correctAnswer: 1,
- explanation: "Enqueue is O(1) as it only requires adding an element to the end."
- },
- {
- question: "Given a queue [5, 10, 15], what will it look like after enqueue(20) and dequeue()?",
- options: [
- "[10, 15, 20]",
- "[5, 10, 15]",
- "[20, 10, 15]",
- "[5, 10, 20]"
- ],
- correctAnswer: 0,
- explanation: "Enqueue(20) → [5,10,15,20]; Dequeue() removes 5 → [10,15,20]."
- },
- {
- question: "What happens if you try to dequeue from an empty queue?",
- options: [
- "Returns null",
- "Returns 0",
- "Causes an underflow error",
- "Automatically resizes the queue"
- ],
- correctAnswer: 2,
- explanation: "Dequeueing from an empty queue results in an **underflow** error."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic FIFO principle");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("queue operations (enqueue/dequeue)");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("practical queue manipulation");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("edge case handling");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Queue concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Queue Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? 'Finish' : 'Next'}
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length ? "Perfect Score!" :
- score >= questions.length * 0.8 ? "Excellent Work!" :
- score >= questions.length * 0.6 ? "Good Job!" :
- score >= questions.length * 0.4 ? "Keep Practicing!" : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}% correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
Question Breakdown:
- {questions.map((q, index) => (
-
-
{q.question}
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
Your answer: {answers[index] !== null ? q.options[answers[index]] : "Not answered"}
- {answers[index] !== q.correctAnswer && (
-
Correct answer: {q.options[q.correctAnswer]}
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default QueueQuiz;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/isempty/animation.jsx b/app/visualizer/queue/operations/isempty/animation.jsx
deleted file mode 100755
index 8ffb762b8..000000000
--- a/app/visualizer/queue/operations/isempty/animation.jsx
+++ /dev/null
@@ -1,227 +0,0 @@
-"use client";
-import React, { useState } from "react";
-
-const QueueVisualizer = () => {
- const [queue, setQueue] = useState([]);
- const [inputValue, setInputValue] = useState("");
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("Queue is empty");
- const [isAnimating, setIsAnimating] = useState(false);
-
- /* ---------- helpers ---------- */
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
- const showOp = async (txt, ms = 800) => {
- setOperation(txt);
- await sleep(ms);
- setOperation(null);
- };
-
- /* ---------- enqueue ---------- */
- const enqueue = async () => {
- if (!inputValue.trim()) {
- setMessage("Please enter a value");
- return;
- }
- setIsAnimating(true);
- await showOp(`Enqueuing “${inputValue}” …`);
- setQueue((q) => [...q, inputValue]);
- setMessage(`“${inputValue}” added to rear`);
- setInputValue("");
- setIsAnimating(false);
- };
-
- /* ---------- dequeue ---------- */
- const dequeue = async () => {
- if (queue.length === 0) {
- setMessage("Queue is empty!");
- return;
- }
- setIsAnimating(true);
- const front = queue[0];
- await showOp(`Dequeuing “${front}” …`);
- setQueue((q) => q.slice(1));
- setMessage(`“${front}” removed from front`);
- setIsAnimating(false);
- };
-
- /* ---------- isEmpty ---------- */
- const checkEmpty = async () => {
- setIsAnimating(true);
- await showOp("Checking if queue is empty …");
- const empty = queue.length === 0;
- setMessage(empty ? "Queue is empty" : "Queue is NOT empty");
- setIsAnimating(false);
- };
-
- /* ---------- reset ---------- */
- const reset = () => {
- setQueue([]);
- setInputValue("");
- setOperation(null);
- setMessage("Queue cleared");
- };
-
- /* ---------- UI ---------- */
- return (
-
-
- Visualise isEmpty operation in real-time
-
-
-
- {/* ----- Controls card ----- */}
-
-
- setInputValue(e.target.value)}
- placeholder="Enter value"
- className="flex-1 p-3 border border-gray-400 rounded-lg dark:bg-neutral-900 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
- disabled={isAnimating}
- onKeyDown={(e) => e.key === "Enter" && enqueue()}
- />
-
-
-
-
- Enqueue
-
-
- Dequeue
-
-
- IsEmpty
-
-
- Reset
-
-
-
- {/* status banners */}
-
- {operation && (
-
- )}
- {message && (
-
- {message}
-
- )}
-
-
-
- {/* ----- Visualisation card (hidden when empty) ----- */}
- {queue.length > 0 && (
-
-
Queue Visualisation
-
-
- {/* Front pointer */}
-
-
- {/* Elements */}
-
- {queue.map((item, index) => (
-
- ))}
-
-
- {/* Rear pointer */}
-
-
-
- )}
-
-
- );
-};
-
-export default QueueVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/isempty/codeBlock.jsx b/app/visualizer/queue/operations/isempty/codeBlock.jsx
deleted file mode 100755
index c839aeec2..000000000
--- a/app/visualizer/queue/operations/isempty/codeBlock.jsx
+++ /dev/null
@@ -1,244 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Queue Implementation in JavaScript (Linked List)
-class Queue {
- constructor() {
- this.front = null;
- this.rear = null;
- }
-
- // Check if queue is empty
- isEmpty() {
- return this.front === null;
- }
-}`,
-
- python: `# Queue Implementation in Python (Linked List)
-class Queue:
- def __init__(self):
- self.front = None
- self.rear = None
-
- # Check if queue is empty
- def is_empty(self):
- return self.front is None`,
-
- java: `// Queue Implementation in Java (Array)
-public class ArrayQueue {
- private int front, rear;
- private int[] arr;
-
- public ArrayQueue(int size) {
- arr = new int[size];
- front = rear = -1;
- }
-
- // Check if queue is empty
- public boolean isEmpty() {
- return front == -1;
- }
-}`,
-
- c: `// Queue Implementation in C (Array)
-#include
-#define MAX_SIZE 100
-
-typedef struct {
- int arr[MAX_SIZE];
- int front, rear;
-} Queue;
-
-// Check if queue is empty
-bool isEmpty(Queue *q) {
- return q->front == -1;
-}`,
-
- cpp: `// Queue Implementation in C++ (Linked List)
-#include
-
-class Node {
-public:
- int data;
- Node* next;
-
- Node(int val) : data(val), next(nullptr) {}
-};
-
-class Queue {
-private:
- Node* front;
- Node* rear;
-
-public:
- Queue() : front(nullptr), rear(nullptr) {}
-
- ~Queue() {
- while (front != nullptr) {
- Node* temp = front;
- front = front->next;
- delete temp;
- }
- }
-
- // Check if queue is empty
- bool isEmpty() const {
- return front == nullptr;
- }
-};`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Queue Implementation (IsEmpty)
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/isempty/content.jsx b/app/visualizer/queue/operations/isempty/content.jsx
deleted file mode 100755
index ff90ca7eb..000000000
--- a/app/visualizer/queue/operations/isempty/content.jsx
+++ /dev/null
@@ -1,306 +0,0 @@
-"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 paragraphs = [
- `The isEmpty operation checks whether a queue contains any elements or not. It returns true if the queue is empty (no elements) and false if it contains elements. This is a fundamental operation used to prevent underflow when performing dequeue operations.`,
- `The isEmpty operation is a simple but crucial part of queue functionality, serving as a safety check before removal operations and helping manage queue processing flow in algorithms and applications.`,
- ];
-
- const example = [
- { points: "Empty Queue: []", subpoints: ["isEmpty() → returns true"] },
- {
- points: "Non-empty Queue: [10, 20, 30]",
- subpoints: ["isEmpty() → returns false"],
- },
- ];
-
- const implementation = [
- {
- points: "Array-based Implementation:",
- subpoints: [
- "Check if front pointer == rear pointer",
- "Or maintain a separate size counter",
- ],
- },
- {
- points: "Linked List Implementation:",
- subpoints: ["Check if head pointer == null"],
- },
- ];
-
- const steps = [
- { points: "Examine the front of the queue" },
- { points: "If front is null (or front == rear in array implementation)" },
- { points: "Return true (queue is empty)" },
- { points: "Else return false (queue has elements)" },
- ];
-
- const complexity = [
- { points: "It only requires a simple pointer comparison" },
- { points: "No iteration through elements is needed" },
- { points: "Performance doesn't depend on queue size" },
- ];
-
- const usage = [
- { points: "Before dequeue operations to prevent underflow" },
- { points: "In queue processing loops" },
- { points: "As a termination condition in algorithms" },
- { points: "To initialize queue operations safely" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is the isEmpty Operation? */}
-
-
-
- What is the isEmpty Operation?
-
-
-
-
- {/* How Does It Work? */}
-
-
-
- How Does It Work?
-
-
-
- The isEmpty operation simply checks the current state of the
- queue. Example scenarios:
-
-
-
- {example.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
- The operation doesn't modify the queue in any way - it only checks
- its state.
-
-
-
-
- {/* Implementation Details */}
-
-
-
- Implementation Details
-
-
-
- Different implementations check emptiness differently:
-
-
-
- {implementation.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Algorithm Steps */}
-
-
-
- Algorithm Steps
-
-
-
- {steps.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- The isEmpty operation always runs in O(1) constant time because:
-
-
- {complexity.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Practical Usage */}
-
-
-
- Practical Usage
-
-
-
- isEmpty is commonly used:
-
-
- {usage.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/queue/operations/isempty/page.jsx b/app/visualizer/queue/operations/isempty/page.jsx
deleted file mode 100755
index 88747b945..000000000
--- a/app/visualizer/queue/operations/isempty/page.jsx
+++ /dev/null
@@ -1,118 +0,0 @@
-import Animation from "@/app/visualizer/queue/operations/isempty/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/queue/operations/isempty/content";
-import Quiz from "@/app/visualizer/queue/operations/isempty/quiz";
-import Code from "@/app/visualizer/queue/operations/isempty/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Footer from '@/app/components/footer';
-import BackToTop from '@/app/components/ui/backtotop';
-
-export const metadata = {
- title: "Queue Is Empty Operation | Learn with JS, C, Python, Java Code",
- description:
- "Learn how to check if a Queue is empty using interactive visualizations and complete code examples in JavaScript, C, Python, and Java. Ideal for DSA beginners and interview prep.",
- keywords: [
- "Queue Is Empty",
- "Is Empty Operation Queue",
- "Queue Empty Condition",
- "Queue Code in JavaScript",
- "Queue Code in C",
- "Queue Code in Python",
- "Queue Code in Java",
- "DSA Queue Check",
- "Queue Operations",
- "Visualize Queue",
- "Learn Queue DSA",
- "Queue Data Structure",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/queue/isEmpty.png",
- width: 1200,
- height: 630,
- alt: "isEmpty Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Queue : IsEmpty", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/queue/operations/isempty/quiz.jsx b/app/visualizer/queue/operations/isempty/quiz.jsx
deleted file mode 100755
index 8d50e66e8..000000000
--- a/app/visualizer/queue/operations/isempty/quiz.jsx
+++ /dev/null
@@ -1,374 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const QueueQuiz = () => {
- const questions = [
- {
- question: "What does the isEmpty operation in a queue determine?",
- options: [
- "The total capacity of the queue",
- "Whether the queue contains any elements",
- "The position of the front element",
- "The time complexity of other operations"
- ],
- correctAnswer: 1,
- explanation: "isEmpty checks if the queue has zero elements (returns true if empty, false otherwise)."
- },
- {
- question: "What does isEmpty() return for a queue with elements [10, 20]?",
- options: ["true", "false", "null", "10"],
- correctAnswer: 1,
- explanation: "The queue contains elements, so isEmpty returns false."
- },
- {
- question: "Why is isEmpty crucial before calling dequeue()?",
- options: [
- "To improve time complexity",
- "To prevent queue underflow errors",
- "To resize the queue",
- "To count the elements"
- ],
- correctAnswer: 1,
- explanation: "Checking isEmpty first avoids errors when attempting to dequeue from an empty queue."
- },
- {
- question: "What is the time complexity of isEmpty?",
- options: ["O(n)", "O(1)", "O(log n)", "O(n²)"],
- correctAnswer: 1,
- explanation: "isEmpty runs in O(1) time as it only checks if front == rear or head == null."
- },
- {
- question: "How would you implement isEmpty for a linked list-based queue?",
- options: [
- "Check if head.next == null",
- "Check if head == null",
- "Count all nodes",
- "Compare head and tail values"
- ],
- correctAnswer: 1,
- explanation: "For linked list queues, isEmpty simply verifies if the head pointer is null."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the isEmpty operation purpose");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("determining isEmpty return values");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("understanding isEmpty importance in error prevention");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("linked list queue implementation");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Queue isEmpty operation concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Queue isEmpty Operation Quiz
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? 'Finish' : 'Next'}
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length ? "Perfect Score!" :
- score >= questions.length * 0.8 ? "Excellent Work!" :
- score >= questions.length * 0.6 ? "Good Job!" :
- score >= questions.length * 0.4 ? "Keep Practicing!" : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}% correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
Question Breakdown:
- {questions.map((q, index) => (
-
-
{q.question}
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
Your answer: {answers[index] !== null ? q.options[answers[index]] : "Not answered"}
- {answers[index] !== q.correctAnswer && (
-
Correct answer: {q.options[q.correctAnswer]}
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default QueueQuiz;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/isfull/animation.jsx b/app/visualizer/queue/operations/isfull/animation.jsx
deleted file mode 100755
index e7aa23c8e..000000000
--- a/app/visualizer/queue/operations/isfull/animation.jsx
+++ /dev/null
@@ -1,254 +0,0 @@
-"use client";
-import { useState, useEffect } from "react";
-
-const QueueVisualizer = () => {
- const [queue, setQueue] = useState([]);
- const [inputValue, setInputValue] = useState("");
- const [maxSize, setMaxSize] = useState(5); // capacity
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("Queue is empty");
- const [isAnimating, setIsAnimating] = useState(false);
-
- const isFull = queue.length >= maxSize;
-
- /* ---------- helpers ---------- */
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
- const showOp = async (txt, ms = 800) => {
- setOperation(txt);
- await sleep(ms);
- setOperation(null);
- };
-
- /* ---------- enqueue ---------- */
- const enqueue = async () => {
- if (!inputValue.trim()) {
- setMessage("Please enter a value");
- return;
- }
- if (isFull) {
- setMessage("Queue is full!");
- return;
- }
- setIsAnimating(true);
- await showOp(`Enqueuing “${inputValue}” …`);
- setQueue((q) => [...q, inputValue]);
- setMessage(`“${inputValue}” added to rear`);
- setInputValue("");
- setIsAnimating(false);
- };
-
- /* ---------- dequeue ---------- */
- const dequeue = async () => {
- if (queue.length === 0) {
- setMessage("Queue is empty!");
- return;
- }
- setIsAnimating(true);
- const front = queue[0];
- await showOp(`Dequeuing “${front}” …`);
- setQueue((q) => q.slice(1));
- setMessage(`“${front}” removed from front`);
- setIsAnimating(false);
- };
-
- /* ---------- isFull ---------- */
- const checkFull = async () => {
- setIsAnimating(true);
- await showOp("Checking if queue is full …");
- setMessage(isFull ? "Queue is FULL" : "Queue is NOT full");
- setIsAnimating(false);
- };
-
- /* ---------- reset ---------- */
- const reset = () => {
- setQueue([]);
- setInputValue("");
- setOperation(null);
- setMessage("Queue cleared");
- };
-
- /* ---------- UI ---------- */
- return (
-
-
- Visualise isFull operation in real-time
-
-
-
- {/* ----- Controls card ----- */}
-
- {/* Value input + Enqueue */}
-
- setInputValue(e.target.value)}
- placeholder="Enter value"
- className="flex-1 p-3 border dark:border-gray-700 rounded-lg dark:bg-neutral-900 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
- disabled={isAnimating}
- onKeyDown={(e) => e.key === "Enter" && enqueue()}
- />
-
-
- {/* Max-size input */}
-
-
- Queue size (capacity):
- {
- const val = Number(e.target.value);
- if (val > 0) setMaxSize(val);
- }}
- className="w-20 p-2 border dark:border-gray-700 rounded dark:bg-neutral-900"
- disabled={isAnimating}
- />
-
-
-
- {/* Action buttons */}
-
-
- Enqueue
-
-
- Dequeue
-
-
- IsFull
-
-
- Reset
-
-
-
- {/* Status banners */}
-
- {operation && (
-
- )}
- {message && (
-
- {message}
-
- )}
-
-
-
- {/* ----- Visualisation card (hidden when empty) ----- */}
- {queue.length > 0 && (
-
-
Queue Visualisation
-
-
- {/* Front pointer */}
-
-
- {/* Elements */}
-
- {queue.map((item, index) => (
-
- ))}
-
-
- {/* Rear pointer */}
-
-
-
- )}
-
-
- );
-};
-
-export default QueueVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/isfull/codeBlock.jsx b/app/visualizer/queue/operations/isfull/codeBlock.jsx
deleted file mode 100755
index e11b57889..000000000
--- a/app/visualizer/queue/operations/isfull/codeBlock.jsx
+++ /dev/null
@@ -1,236 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Array Queue isFull in JavaScript
-class ArrayQueue {
- constructor(capacity) {
- this.arr = new Array(capacity);
- this.front = -1;
- this.rear = -1;
- this.capacity = capacity;
- }
-
- isFull() {
- return (this.rear + 1) % this.capacity === this.front;
- }
-}`,
-
- python: `# Array Queue isFull in Python
-class ArrayQueue:
- def __init__(self, capacity):
- self.arr = [None] * capacity
- self.front = -1
- self.rear = -1
- self.capacity = capacity
-
- def is_full(self):
- return (self.rear + 1) % self.capacity == self.front`,
-
- java: `// Array Queue isFull in Java
-public class ArrayQueue {
- private int[] arr;
- private int front, rear, capacity;
-
- public ArrayQueue(int size) {
- capacity = size;
- arr = new int[capacity];
- front = rear = -1;
- }
-
- public boolean isFull() {
- return (rear + 1) % capacity == front;
- }
-}`,
-
- c: `// Array Queue isFull in C
-#include
-#define MAX_SIZE 100
-
-typedef struct {
- int arr[MAX_SIZE];
- int front, rear;
-} Queue;
-
-bool isFull(Queue *q) {
- return (q->rear + 1) % MAX_SIZE == q->front;
-}`,
-
- cpp: `// Array Queue isFull in C++
-#include
-
-class ArrayQueue {
-private:
- int* arr;
- int front;
- int rear;
- int capacity;
-
-public:
- ArrayQueue(int size) : front(-1), rear(-1), capacity(size) {
- arr = new int[capacity];
- }
-
- ~ArrayQueue() {
- delete[] arr;
- }
-
- bool isFull() const {
- return (rear + 1) % capacity == front;
- }
-};`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Queue IsFull Operation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/isfull/content.jsx b/app/visualizer/queue/operations/isfull/content.jsx
deleted file mode 100755
index b8aba25e3..000000000
--- a/app/visualizer/queue/operations/isfull/content.jsx
+++ /dev/null
@@ -1,322 +0,0 @@
-"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 paragraphs = [
- `The isFull operation checks whether a queue has reached its maximum capacity in fixed-size implementations. It returns true if no more elements can be added (queue is full) and false if space remains. This operation is crucial for preventing overflow in array-based queue implementations.`,
- `The isFull operation is critical for robust queue implementations in fixed-capacity scenarios, ensuring data integrity by preventing buffer overflow conditions in system programming and embedded applications.`,
- ];
-
- const example = [
- {
- points: "Full Queue: [10, 20, 30]",
- subpoints: ["isFull() → returns true"],
- },
- {
- points: "Non-full Queue: [10, 20]",
- subpoints: ["isFull() → returns false"],
- },
- ];
-
- const implementation = [
- {
- points: "Linear Array Implementation:",
- subpoints: [
- "Check if rear == capacity - 1",
- "Simple but wastes space when front ≠ 0",
- ],
- },
- {
- points: "Circular Array Implementation:",
- subpoints: [
- "Check if (rear + 1) % capacity == front",
- "More space-efficient",
- ],
- },
- {
- points: "Size Counter Approach:",
- subpoints: ["Maintain a size variable", "Check if size == capacity"],
- },
- ];
-
- const steps = [
- { points: "Calculate next rear position: (rear + 1) % capacity" },
- { points: "Compare with front position" },
- { points: "If equal, return true (queue is full)" },
- { points: "Else return false (space available)" },
- ];
-
- const complexity = [
- { points: "It only requires simple pointer arithmetic and comparison" },
- { points: "No iteration through elements is needed" },
- { points: "Performance is independent of queue size" },
- ];
-
- const usage = [
- { points: "Bounded buffer problems" },
- { points: "Producer-consumer scenarios" },
- { points: "Memory-constrained systems" },
- { points: "Before enqueue operations to prevent overflow" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is the isFull Operation? */}
-
-
-
- What is the isFull Operation?
-
-
-
-
- {/* How Does It Work? */}
-
-
-
- How Does It Work?
-
-
-
- The isFull operation examines the queue's capacity and current
- state.
-
-
- Example scenarios (for a queue with capacity 3):
-
-
-
- {example.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
- Note: Dynamic implementations (like linked lists) typically don't
- need this operation as they can grow indefinitely.
-
-
-
-
- {/* Implementation Details */}
-
-
-
- Implementation Details
-
-
-
- Different approaches to check if a queue is full:
-
-
-
- {implementation.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Algorithm Steps */}
-
-
-
- Algorithm Steps
-
-
-
- For circular array implementation:
-
-
- {steps.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- The isFull operation always runs in O(1) constant time because:
-
-
- {complexity.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Practical Usage */}
-
-
-
- Practical Usage
-
-
-
- isFull is essential in:
-
-
- {usage.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/queue/operations/isfull/page.jsx b/app/visualizer/queue/operations/isfull/page.jsx
deleted file mode 100755
index a836d01ff..000000000
--- a/app/visualizer/queue/operations/isfull/page.jsx
+++ /dev/null
@@ -1,118 +0,0 @@
-import Animation from "@/app/visualizer/queue/operations/isfull/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/queue/operations/isfull/content";
-import Quiz from '@/app/visualizer/queue/operations/isfull/quiz';
-import Code from "@/app/visualizer/queue/operations/isfull/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Footer from '@/app/components/footer';
-import BackToTop from '@/app/components/ui/backtotop';
-
-export const metadata = {
- title: "Queue Is Full Operation | Learn with JS, C, Python, Java Code",
- description:
- "Understand how to check if a Queue is full using interactive visualizations and detailed code examples in JavaScript, C, Python, and Java. Perfect for mastering DSA and technical interviews.",
- keywords: [
- "Queue Is Full",
- "Is Full Operation Queue",
- "Queue Full Condition",
- "Queue Capacity Check",
- "Queue Code in JavaScript",
- "Queue Code in C",
- "Queue Code in Python",
- "Queue Code in Java",
- "Queue DSA",
- "Learn Queue Operations",
- "Queue Data Structure",
- "Visualize Queue",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/queue/isFull.png",
- width: 1200,
- height: 630,
- alt: "isFull Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Queue : IsFull", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/queue/operations/isfull/quiz.jsx b/app/visualizer/queue/operations/isfull/quiz.jsx
deleted file mode 100755
index 867e46ca9..000000000
--- a/app/visualizer/queue/operations/isfull/quiz.jsx
+++ /dev/null
@@ -1,374 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const QueueQuiz = () => {
- const questions = [
- {
- question: "What does the isFull operation determine in a queue?",
- options: [
- "Whether the queue contains any elements",
- "Whether the queue has reached its maximum capacity",
- "The position of the front element",
- "The time complexity of other operations"
- ],
- correctAnswer: 1,
- explanation: "isFull checks if the queue has reached its maximum capacity in fixed-size implementations."
- },
- {
- question: "In which type of queue implementation is isFull most commonly needed?",
- options: [
- "Linked list-based queues",
- "Dynamic arrays",
- "Array-based queues with fixed capacity",
- "All queue implementations"
- ],
- correctAnswer: 2,
- explanation: "isFull is crucial for array-based queues with fixed capacity to prevent overflow."
- },
- {
- question: "What is the time complexity of the isFull operation?",
- options: ["O(n)", "O(1)", "O(log n)", "O(n²)"],
- correctAnswer: 1,
- explanation: "isFull runs in O(1) constant time as it only requires simple pointer comparisons."
- },
- {
- question: "In a circular array implementation, when is the queue considered full?",
- options: [
- "When front == 0",
- "When rear == capacity - 1",
- "When (rear + 1) % capacity == front",
- "When front == rear"
- ],
- correctAnswer: 2,
- explanation: "In circular arrays, the queue is full when the next position after rear equals front."
- },
- {
- question: "What would isFull() return for a queue with capacity 3 containing [10, 20, 30]?",
- options: ["true", "false", "null", "Error"],
- correctAnswer: 0,
- explanation: "The queue has reached its maximum capacity of 3 elements, so isFull returns true."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the purpose of isFull operation");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("identifying when isFull is needed");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("circular array implementation details");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("practical application of isFull");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Queue isFull operation concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Queue isFull Operation Quiz
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? 'Finish' : 'Next'}
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length ? "Perfect Score!" :
- score >= questions.length * 0.8 ? "Excellent Work!" :
- score >= questions.length * 0.6 ? "Good Job!" :
- score >= questions.length * 0.4 ? "Keep Practicing!" : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}% correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
Question Breakdown:
- {questions.map((q, index) => (
-
-
{q.question}
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
Your answer: {answers[index] !== null ? q.options[answers[index]] : "Not answered"}
- {answers[index] !== q.correctAnswer && (
-
Correct answer: {q.options[q.correctAnswer]}
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default QueueQuiz;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/peek-front/animation.jsx b/app/visualizer/queue/operations/peek-front/animation.jsx
deleted file mode 100755
index 9abc8c56e..000000000
--- a/app/visualizer/queue/operations/peek-front/animation.jsx
+++ /dev/null
@@ -1,238 +0,0 @@
-"use client";
-import React, { useState } from "react";
-
-const QueueVisualizer = () => {
- const [queue, setQueue] = useState([]);
- const [inputValue, setInputValue] = useState("");
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("");
- const [isAnimating, setIsAnimating] = useState(false);
-
- /* ---------- core helpers ---------- */
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
-
- const showOp = async (text, ms = 1000) => {
- setOperation(text);
- await sleep(ms);
- setOperation(null);
- };
-
- /* ---------- enqueue ---------- */
- const enqueue = async () => {
- if (!inputValue.trim()) {
- setMessage("Please enter a value");
- return;
- }
- setIsAnimating(true);
- await showOp(`Enqueuing "${inputValue}" to rear...`);
- setQueue((q) => [...q, inputValue]);
- setMessage(`"${inputValue}" added to rear`);
- setInputValue("");
- setIsAnimating(false);
- };
-
- /* ---------- peek front ---------- */
- const peekFront = () => {
- if (queue.length === 0) {
- setMessage("Queue is empty – nothing to peek");
- return;
- }
- setMessage(`Front element is "${queue[0]}"`);
- };
-
- /* ---------- random queue ---------- */
- const generateRandomQueue = () => {
- if (isAnimating) return;
- const len = Math.floor(Math.random() * 5) + 3; // 3-7 items
- const nums = Array.from({ length: len }, () =>
- String(Math.floor(Math.random() * 90) + 10)
- ); // 10-99
- setQueue(nums);
- setMessage("Random queue generated");
- };
-
- /* ---------- reset ---------- */
- const reset = () => {
- if (isAnimating) return;
- setQueue([]);
- setInputValue("");
- setOperation(null);
- setMessage("");
- };
-
- /* ---------- UI ---------- */
- return (
-
-
- Visualize First-In-First-Out (FIFO) operations in real-time
-
-
- {/* ------- Controls ------- */}
-
-
- {/* input + classic buttons */}
-
-
-
-
- Random Queue
-
-
- Peek Front
-
-
- Reset
-
-
-
-
- {/* status / operation banners */}
-
- {operation && (
-
- )}
- {message && (
-
-
- {message.includes("added") ? (
-
- ) : message.includes("removed") || message.includes("Front element") ? (
-
- ) : (
-
- )}
-
-
{message}
-
- )}
-
-
-
- {/* ------- Queue Visualization (only when not empty) ------- */}
- {queue.length > 0 && (
-
-
Queue Visualization
-
- {/* Front – items – Rear */}
-
- {/* Front label */}
-
-
- {/* Elements */}
-
- {queue.map((item, index) => (
-
- ))}
-
-
- {/* Rear label */}
-
-
-
- )}
-
-
- );
-};
-
-export default QueueVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/peek-front/codeBlock.jsx b/app/visualizer/queue/operations/peek-front/codeBlock.jsx
deleted file mode 100755
index 882d98d22..000000000
--- a/app/visualizer/queue/operations/peek-front/codeBlock.jsx
+++ /dev/null
@@ -1,279 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Queue peek (front) in JavaScript
-class Queue {
- constructor() {
- this.items = [];
- }
-
- // Get front element without removing
- peek() {
- if (this.isEmpty()) {
- return "Queue is empty";
- }
- return this.items[0];
- }
-
- // Helper method
- isEmpty() {
- return this.items.length === 0;
- }
-}`,
-
- python: `# Queue peek (front) in Python
-class Queue:
- def __init__(self):
- self.items = []
-
- # Get front element without removing
- def peek(self):
- if self.is_empty():
- return "Queue is empty"
- return self.items[0]
-
- # Helper method
- def is_empty(self):
- return len(self.items) == 0`,
-
- java: `// Queue peek (front) in Java
-import java.util.LinkedList;
-import java.util.Queue;
-
-public class Main {
- public static void main(String[] args) {
- Queue queue = new LinkedList<>();
-
- // Peek at front element
- Integer front = queue.peek();
- System.out.println("Front element: " + front);
- }
-}`,
-
- c: `// Queue peek (front) in C
-#include
-#define MAX_SIZE 100
-
-typedef struct {
- int items[MAX_SIZE];
- int front, rear;
-} Queue;
-
-int peek(Queue *q) {
- if (q->front == -1) {
- printf("Queue is empty\n");
- return -1;
- }
- return q->items[q->front];
-}`,
-
- cpp: `// Queue peek (front) in C++
-#include
-#include
-
-int main() {
- std::queue q;
-
- // Using STL queue's front() method
- if (!q.empty()) {
- std::cout << "Front element: " << q.front() << std::endl;
- } else {
- std::cout << "Queue is empty" << std::endl;
- }
-
- // Custom queue implementation
- class CustomQueue {
- private:
- struct Node {
- int data;
- Node* next;
- Node(int val) : data(val), next(nullptr) {}
- };
- Node* front;
- Node* rear;
-
- public:
- CustomQueue() : front(nullptr), rear(nullptr) {}
-
- ~CustomQueue() {
- while (front != nullptr) {
- Node* temp = front;
- front = front->next;
- delete temp;
- }
- }
-
- int peek() const {
- if (front == nullptr) {
- std::cout << "Queue is empty" << std::endl;
- return -1;
- }
- return front->data;
- }
-
- bool isEmpty() const {
- return front == nullptr;
- }
- };
-
- CustomQueue customQ;
- std::cout << "Custom queue front: " << customQ.peek() << std::endl;
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Queue Peek Front
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/queue/operations/peek-front/content.jsx b/app/visualizer/queue/operations/peek-front/content.jsx
deleted file mode 100755
index 915b016b8..000000000
--- a/app/visualizer/queue/operations/peek-front/content.jsx
+++ /dev/null
@@ -1,294 +0,0 @@
-"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 = [
- `The peek front operation (also called front) retrieves the element at the front of the queue without removing it. This operation allows you to examine the next element to be processed while maintaining the queue's integrity.`,
- `The peek front operation is essential for non-destructive queue inspection, enabling more flexible queue processing patterns while maintaining FIFO order. It's particularly valuable in scenarios where decision-making depends on the next item's properties without committing to its removal.`,
- ];
-
- const example = [
- { points: "Current Queue: [A, B, C, D]" },
- { points: "peekFront(): Returns 'A'" },
- { points: "Queue After Peek: [A, B, C, D] (unchanged)" },
- ];
-
- const implementation = [
- {
- points: "Array-based Queue:",
- subpoints: ["Return array[front]", "Check for empty queue first"],
- },
- { points: "Linked List Queue:", subpoints: ["Return head.data"] },
- {
- points: "Circular Buffer:",
- subpoints: ["Return buffer[front]", "Handle wrap-around cases"],
- },
- ];
-
- const steps = [
- { points: "Check if queue is empty (use isEmpty())" },
- { points: "If empty, return error/exception (or null)" },
- { points: "Access the data at front position" },
- { points: "Return the data without modifying pointers" },
- ];
-
- const complexity = [
- { points: "Direct access to front element" },
- { points: "No iteration needed" },
- { points: "No structural changes to queue" },
- ];
-
- const application = [
- { points: "Previewing next item before processing" },
- { points: "Priority checking in priority queues" },
- { points: "Conditional processing logic" },
- { points: "Debugging queue contents" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is Peek Front Operation? */}
-
-
-
- What is Peek Front Operation?
-
-
-
-
- {/* How Does It Work? */}
-
-
-
- How Does It Work?
-
-
-
- Peek returns the front element while keeping the queue unchanged.
-
-
- Example with queue: [A, B, C, D]
-
-
-
- {example.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
- Contrast with dequeue() which would remove 'A' from the queue.
-
-
-
-
- {/* Implementation Details */}
-
-
-
- Implementation Details
-
-
-
- Different implementations handle peek similarly:
-
-
-
- {implementation.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Algorithm Steps */}
-
-
-
- Algorithm Steps
-
-
-
- Basic peek operation algorithm:
-
-
- {steps.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- Peek operation always runs in O(1) constant time because:
-
-
- {complexity.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Practical Applications */}
-
-
-
- Practical Applications
-
-
-
- Common use cases for peek:
-
-
- {application.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/queue/operations/peek-front/page.jsx b/app/visualizer/queue/operations/peek-front/page.jsx
deleted file mode 100755
index b27dbca51..000000000
--- a/app/visualizer/queue/operations/peek-front/page.jsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import Animation from "@/app/visualizer/queue/operations/peek-front/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/queue/operations/peek-front/content";
-import Quiz from "@/app/visualizer/queue/operations/peek-front/quiz";
-import Code from "@/app/visualizer/queue/operations/peek-front/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Footer from '@/app/components/footer';
-import BackToTop from '@/app/components/ui/backtotop';
-
-export const metadata = {
- title: "Queue Peek Front Operation | Learn with JS, C, Java, Python Code",
- description:
- "Understand the Peek Front operation in Queue with interactive animations and code examples in JavaScript, C, Python, and Java. Ideal for DSA beginners and interview preparation.",
- keywords: [
- "Queue Peek Front",
- "Queue peek front Visulaization",
- "Peek Front Operation",
- "Queue DSA",
- "Queue Front Element",
- "Queue Peek in JavaScript",
- "Queue Peek in C",
- "Queue Peek in Python",
- "Queue Peek in Java",
- "Queue Data Structure",
- "DSA Queue Operations",
- "Peek Front Code Examples",
- "Queue Visualization",
- "Learn Queue DSA",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/queue/peekFront.png",
- width: 1200,
- height: 630,
- alt: "Peek Front Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Peek Front", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/queue/operations/peek-front/quiz.jsx b/app/visualizer/queue/operations/peek-front/quiz.jsx
deleted file mode 100755
index fa1eed8ec..000000000
--- a/app/visualizer/queue/operations/peek-front/quiz.jsx
+++ /dev/null
@@ -1,379 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const QueueQuiz = () => {
- const questions = [
- {
- question: "What does the peek front operation do in a queue?",
- options: [
- "Removes the front element",
- "Adds an element to the front",
- "Retrieves the front element without removing it",
- "Priority-Based"
- ],
- correctAnswer: 2,
- explanation: "Peek retrieves the front element but doesn't remove it."
- },
- {
- question: "What is the main difference between peekFront() and dequeue()?",
- options: [
- "peekFront() removes the element, dequeue() does not",
- "dequeue() accesses the rear",
- "peekFront() leaves the queue unchanged",
- "They are the same"
- ],
- correctAnswer: 2,
- explanation: "peekFront() retrieves without removal; dequeue() removes the front element."
- },
- {
- question: "What will the queue look like after calling peekFront() on [A, B, C, D]",
- options: ["[B, C, D]", "[A, B, C]", "[A, B, C, D]", "[D, C, B, A]"],
- correctAnswer: 2,
- explanation: "peekFront() does not modify the queue."
- },
- {
- question: "What is the time complexity of the peek operation?",
- options: [
- "O(1)",
- "O(log n)",
- "O(n)",
- "O(n²)"
- ],
- correctAnswer: 0,
- explanation: "Direct access makes it constant time."
- },
- {
- question: "In an array-based queue, how is peekFront() typically implemented?",
- options: [
- "Return array[0]",
- "Return array[front]",
- "Return array[rear]",
- "Remove array[front]"
- ],
- correctAnswer: 1,
- explanation: "The front index gives the first element."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the peek operation");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("differentiating peekFront() and dequeue()");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("understanding queue state after peek");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("array-based queue implementation");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Queue peek operation concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Queue Peek Operation Quiz
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? 'Finish' : 'Next'}
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length ? "Perfect Score!" :
- score >= questions.length * 0.8 ? "Excellent Work!" :
- score >= questions.length * 0.6 ? "Good Job!" :
- score >= questions.length * 0.4 ? "Keep Practicing!" : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}% correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
Question Breakdown:
- {questions.map((q, index) => (
-
-
{q.question}
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
Your answer: {answers[index] !== null ? q.options[answers[index]] : "Not answered"}
- {answers[index] !== q.correctAnswer && (
-
Correct answer: {q.options[q.correctAnswer]}
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default QueueQuiz;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/circular/animation.jsx b/app/visualizer/queue/types/circular/animation.jsx
deleted file mode 100755
index 4df120e69..000000000
--- a/app/visualizer/queue/types/circular/animation.jsx
+++ /dev/null
@@ -1,299 +0,0 @@
-"use client";
-import React, { useState } from "react";
-
-const CircularQueueVisualizer = () => {
- const [maxSize, setMaxSize] = useState(5); // capacity
- const [queue, setQueue] = useState(Array(5).fill(null));
- const [front, setFront] = useState(0);
- const [rear, setRear] = useState(-1);
- const [count, setCount] = useState(0);
- const [inputValue, setInputValue] = useState("");
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("Circular queue is empty");
- const [isAnimating, setIsAnimating] = useState(false);
-
- const isEmpty = count === 0;
- const isFull = count === maxSize;
-
- /* ---------- helpers ---------- */
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
- const showOp = async (txt, ms = 800) => {
- setOperation(txt);
- await sleep(ms);
- setOperation(null);
- };
- const wrap = (idx) => (idx + maxSize) % maxSize;
-
- /* ---------- enqueue rear ---------- */
- const enqueue = async () => {
- if (!inputValue.trim()) {
- setMessage("Please enter a value");
- return;
- }
- if (isFull) {
- setMessage("Circular queue is full!");
- return;
- }
- setIsAnimating(true);
- await showOp(`Enqueuing "${inputValue}" at rear …`);
- const newRear = wrap(rear + 1);
- const newQ = [...queue];
- newQ[newRear] = inputValue;
- setQueue(newQ);
- setRear(newRear);
- setCount(count + 1);
- setMessage(`"${inputValue}" added`);
- setInputValue("");
- setIsAnimating(false);
- };
-
- /* ---------- dequeue front ---------- */
- const dequeue = async () => {
- if (isEmpty) {
- setMessage("Circular queue is empty!");
- return;
- }
- setIsAnimating(true);
- const item = queue[front];
- await showOp(`Dequeuing "${item}" from front …`);
- const newQ = [...queue];
- newQ[front] = null;
- setQueue(newQ);
- setFront(wrap(front + 1));
- setCount(count - 1);
- setMessage(`"${item}" removed`);
- setIsAnimating(false);
- };
-
- /* ---------- isEmpty ---------- */
- const checkEmpty = async () => {
- setIsAnimating(true);
- await showOp("Checking if empty …");
- setMessage(
- isEmpty ? "Circular queue is EMPTY" : "Circular queue is NOT empty"
- );
- setIsAnimating(false);
- };
-
- /* ---------- isFull ---------- */
- const checkFull = async () => {
- setIsAnimating(true);
- await showOp("Checking if full …");
- setMessage(
- isFull ? "Circular queue is FULL" : "Circular queue is NOT full"
- );
- setIsAnimating(false);
- };
-
- /* ---------- reset ---------- */
- const reset = () => {
- setQueue(Array(maxSize).fill(null));
- setFront(0);
- setRear(-1);
- setCount(0);
- setInputValue("");
- setOperation(null);
- setMessage("Circular queue cleared");
- };
-
- /* ---------- change capacity ---------- */
- const resize = (newCap) => {
- if (newCap < 1) return;
- const newQ = Array(newCap).fill(null);
- let idx = 0;
- for (let i = 0; i < Math.min(count, newCap); i++) {
- newQ[idx++] = queue[wrap(front + i)];
- }
- setQueue(newQ);
- setMaxSize(newCap);
- setFront(0);
- setRear(idx - 1);
- setCount(idx);
- setMessage(`Capacity set to ${newCap}`);
- };
-
- /* ---------- UI ---------- */
- return (
-
-
- Circular Queue Visualiser (Fixed Capacity)
-
-
-
- {/* ----- Controls card ----- */}
-
- {/* Value input + Enqueue */}
-
-
- {/* Action buttons */}
-
-
- Enqueue Rear
-
-
- Dequeue Front
-
-
- IsEmpty
-
-
- IsFull
-
-
- Reset
-
-
-
- {/* Status banners */}
-
- {operation && (
-
- )}
- {message && (
-
- {message}
-
- )}
-
-
-
- {/* ----- Visualisation card (hidden when empty) ----- */}
- {!isEmpty && (
-
-
- {/* Front pointer */}
-
-
- {/* Elements (circular order) */}
-
- {Array.from({ length: maxSize }).map((_, idx) => {
- const itemIdx = wrap(front + idx);
- const item = queue[itemIdx];
- const isFront = itemIdx === front;
- const isRear = itemIdx === rear;
- return (
-
-
- {item ?? "·"}
-
-
- #{itemIdx}
-
-
- );
- })}
-
-
- {/* Rear pointer */}
-
-
-
- )}
-
-
- );
-};
-
-export default CircularQueueVisualizer;
diff --git a/app/visualizer/queue/types/circular/codeBlock.jsx b/app/visualizer/queue/types/circular/codeBlock.jsx
deleted file mode 100755
index cc8da1282..000000000
--- a/app/visualizer/queue/types/circular/codeBlock.jsx
+++ /dev/null
@@ -1,664 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Circular Queue Implementation (JavaScript)
-class CircularQueue {
- constructor(capacity) {
- this.queue = new Array(capacity);
- this.capacity = capacity;
- this.front = -1;
- this.rear = -1;
- this.size = 0;
- }
-
- // Check if queue is full
- isFull() {
- return this.size === this.capacity;
- }
-
- // Check if queue is empty
- isEmpty() {
- return this.size === 0;
- }
-
- // Add element to the queue
- enqueue(item) {
- if (this.isFull()) {
- console.log("Queue is full");
- return false;
- }
-
- if (this.isEmpty()) {
- this.front = 0;
- }
-
- this.rear = (this.rear + 1) % this.capacity;
- this.queue[this.rear] = item;
- this.size++;
- return true;
- }
-
- // Remove element from the queue
- dequeue() {
- if (this.isEmpty()) {
- console.log("Queue is empty");
- return null;
- }
-
- const item = this.queue[this.front];
- this.queue[this.front] = null;
-
- if (this.front === this.rear) {
- this.front = -1;
- this.rear = -1;
- } else {
- this.front = (this.front + 1) % this.capacity;
- }
-
- this.size--;
- return item;
- }
-
- // Get front element without removing it
- peek() {
- if (this.isEmpty()) {
- console.log("Queue is empty");
- return null;
- }
- return this.queue[this.front];
- }
-
- // Print queue contents
- print() {
- if (this.isEmpty()) {
- console.log("Queue is empty");
- return;
- }
-
- let i = this.front;
- let output = [];
-
- while (true) {
- output.push(this.queue[i]);
- if (i === this.rear) break;
- i = (i + 1) % this.capacity;
- }
-
- console.log("Queue contents:", output.join(' -> '));
- console.log("Front index:", this.front, "Rear index:", this.rear);
- }
-}
-
-// Usage
-const queue = new CircularQueue(5);
-queue.enqueue(10);
-queue.enqueue(20);
-queue.enqueue(30);
-queue.enqueue(40);
-queue.enqueue(50);
-queue.print(); // 10 -> 20 -> 30 -> 40 -> 50
-console.log("Dequeued:", queue.dequeue()); // 10
-queue.enqueue(60);
-queue.print(); // 20 -> 30 -> 40 -> 50 -> 60
-console.log("Front element:", queue.peek()); // 20`,
-
- python: `# Circular Queue Implementation (Python)
-class CircularQueue:
- def __init__(self, capacity):
- self.queue = [None] * capacity
- self.capacity = capacity
- self.front = -1
- self.rear = -1
- self.size = 0
-
- def is_full(self):
- return self.size == self.capacity
-
- def is_empty(self):
- return self.size == 0
-
- def enqueue(self, item):
- if self.is_full():
- print("Queue is full")
- return False
-
- if self.is_empty():
- self.front = 0
-
- self.rear = (self.rear + 1) % self.capacity
- self.queue[self.rear] = item
- self.size += 1
- return True
-
- def dequeue(self):
- if self.is_empty():
- print("Queue is empty")
- return None
-
- item = self.queue[self.front]
- self.queue[self.front] = None
-
- if self.front == self.rear:
- self.front = -1
- self.rear = -1
- else:
- self.front = (self.front + 1) % self.capacity
-
- self.size -= 1
- return item
-
- def peek(self):
- if self.is_empty():
- print("Queue is empty")
- return None
- return self.queue[self.front]
-
- def print_queue(self):
- if self.is_empty():
- print("Queue is empty")
- return
-
- i = self.front
- output = []
-
- while True:
- output.append(str(self.queue[i]))
- if i == self.rear:
- break
- i = (i + 1) % self.capacity
-
- print("Queue contents:", " -> ".join(output))
- print(f"Front index: {self.front}, Rear index: {self.rear}")
-
-# Usage
-queue = CircularQueue(5)
-queue.enqueue(10)
-queue.enqueue(20)
-queue.enqueue(30)
-queue.enqueue(40)
-queue.enqueue(50)
-queue.print_queue() # 10 -> 20 -> 30 -> 40 -> 50
-print("Dequeued:", queue.dequeue()) # 10
-queue.enqueue(60)
-queue.print_queue() # 20 -> 30 -> 40 -> 50 -> 60
-print("Front element:", queue.peek()) # 20`,
-
- java: `// Circular Queue Implementation (Java)
-public class CircularQueue {
- private int[] queue;
- private int capacity;
- private int front;
- private int rear;
- private int size;
-
- public CircularQueue(int capacity) {
- this.queue = new int[capacity];
- this.capacity = capacity;
- this.front = -1;
- this.rear = -1;
- this.size = 0;
- }
-
- public boolean isFull() {
- return size == capacity;
- }
-
- public boolean isEmpty() {
- return size == 0;
- }
-
- public boolean enqueue(int item) {
- if (isFull()) {
- System.out.println("Queue is full");
- return false;
- }
-
- if (isEmpty()) {
- front = 0;
- }
-
- rear = (rear + 1) % capacity;
- queue[rear] = item;
- size++;
- return true;
- }
-
- public Integer dequeue() {
- if (isEmpty()) {
- System.out.println("Queue is empty");
- return null;
- }
-
- int item = queue[front];
-
- if (front == rear) {
- front = -1;
- rear = -1;
- } else {
- front = (front + 1) % capacity;
- }
-
- size--;
- return item;
- }
-
- public Integer peek() {
- if (isEmpty()) {
- System.out.println("Queue is empty");
- return null;
- }
- return queue[front];
- }
-
- public void print() {
- if (isEmpty()) {
- System.out.println("Queue is empty");
- return;
- }
-
- int i = front;
- StringBuilder output = new StringBuilder();
-
- while (true) {
- output.append(queue[i]);
- if (i == rear) break;
- output.append(" -> ");
- i = (i + 1) % capacity;
- }
-
- System.out.println("Queue contents: " + output);
- System.out.println("Front index: " + front + ", Rear index: " + rear);
- }
-
- public static void main(String[] args) {
- CircularQueue queue = new CircularQueue(5);
- queue.enqueue(10);
- queue.enqueue(20);
- queue.enqueue(30);
- queue.enqueue(40);
- queue.enqueue(50);
- queue.print(); // 10 -> 20 -> 30 -> 40 -> 50
- System.out.println("Dequeued: " + queue.dequeue()); // 10
- queue.enqueue(60);
- queue.print(); // 20 -> 30 -> 40 -> 50 -> 60
- System.out.println("Front element: " + queue.peek()); // 20
- }
-}`,
-
- c: `// Circular Queue Implementation (C)
-#include
-#include
-
-typedef struct {
- int* queue;
- int capacity;
- int front;
- int rear;
- int size;
-} CircularQueue;
-
-void initialize(CircularQueue* q, int capacity) {
- q->queue = (int*)malloc(capacity * sizeof(int));
- q->capacity = capacity;
- q->front = -1;
- q->rear = -1;
- q->size = 0;
-}
-
-bool isFull(CircularQueue* q) {
- return q->size == q->capacity;
-}
-
-bool isEmpty(CircularQueue* q) {
- return q->size == 0;
-}
-
-bool enqueue(CircularQueue* q, int item) {
- if (isFull(q)) {
- printf("Queue is full\n");
- return false;
- }
-
- if (isEmpty(q)) {
- q->front = 0;
- }
-
- q->rear = (q->rear + 1) % q->capacity;
- q->queue[q->rear] = item;
- q->size++;
- return true;
-}
-
-int dequeue(CircularQueue* q) {
- if (isEmpty(q)) {
- printf("Queue is empty\n");
- return -1;
- }
-
- int item = q->queue[q->front];
-
- if (q->front == q->rear) {
- q->front = -1;
- q->rear = -1;
- } else {
- q->front = (q->front + 1) % q->capacity;
- }
-
- q->size--;
- return item;
-}
-
-int peek(CircularQueue* q) {
- if (isEmpty(q)) {
- printf("Queue is empty\n");
- return -1;
- }
- return q->queue[q->front];
-}
-
-void print(CircularQueue* q) {
- if (isEmpty(q)) {
- printf("Queue is empty\n");
- return;
- }
-
- int i = q->front;
- printf("Queue contents: ");
-
- while (true) {
- printf("%d", q->queue[i]);
- if (i == q->rear) break;
- printf(" -> ");
- i = (i + 1) % q->capacity;
- }
-
- printf("\nFront index: %d, Rear index: %d\n", q->front, q->rear);
-}
-
-void destroy(CircularQueue* q) {
- free(q->queue);
-}
-
-int main() {
- CircularQueue queue;
- initialize(&queue, 5);
-
- enqueue(&queue, 10);
- enqueue(&queue, 20);
- enqueue(&queue, 30);
- enqueue(&queue, 40);
- enqueue(&queue, 50);
- print(&queue); // 10 -> 20 -> 30 -> 40 -> 50
- printf("Dequeued: %d\n", dequeue(&queue)); // 10
- enqueue(&queue, 60);
- print(&queue); // 20 -> 30 -> 40 -> 50 -> 60
- printf("Front element: %d\n", peek(&queue)); // 20
-
- destroy(&queue);
- return 0;
-}`,
-
- cpp: `// Circular Queue Implementation (C++)
-#include
-using namespace std;
-
-class CircularQueue {
-private:
- int* queue;
- int capacity;
- int front;
- int rear;
- int size;
-
-public:
- CircularQueue(int cap) : capacity(cap), front(-1), rear(-1), size(0) {
- queue = new int[capacity];
- }
-
- ~CircularQueue() {
- delete[] queue;
- }
-
- bool isFull() const {
- return size == capacity;
- }
-
- bool isEmpty() const {
- return size == 0;
- }
-
- bool enqueue(int item) {
- if (isFull()) {
- cout << "Queue is full" << endl;
- return false;
- }
-
- if (isEmpty()) {
- front = 0;
- }
-
- rear = (rear + 1) % capacity;
- queue[rear] = item;
- size++;
- return true;
- }
-
- int dequeue() {
- if (isEmpty()) {
- cout << "Queue is empty" << endl;
- return -1;
- }
-
- int item = queue[front];
-
- if (front == rear) {
- front = -1;
- rear = -1;
- } else {
- front = (front + 1) % capacity;
- }
-
- size--;
- return item;
- }
-
- int peek() const {
- if (isEmpty()) {
- cout << "Queue is empty" << endl;
- return -1;
- }
- return queue[front];
- }
-
- void print() const {
- if (isEmpty()) {
- cout << "Queue is empty" << endl;
- return;
- }
-
- int i = front;
- cout << "Queue contents: ";
-
- while (true) {
- cout << queue[i];
- if (i == rear) break;
- cout << " -> ";
- i = (i + 1) % capacity;
- }
-
- cout << "\nFront index: " << front << ", Rear index: " << rear << endl;
- }
-};
-
-int main() {
- CircularQueue queue(5);
-
- queue.enqueue(10);
- queue.enqueue(20);
- queue.enqueue(30);
- queue.enqueue(40);
- queue.enqueue(50);
- queue.print(); // 10 -> 20 -> 30 -> 40 -> 50
- cout << "Dequeued: " << queue.dequeue() << endl; // 10
- queue.enqueue(60);
- queue.print(); // 20 -> 30 -> 40 -> 50 -> 60
- cout << "Front element: " << queue.peek() << endl; // 20
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Double Ended Queue Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/circular/content.jsx b/app/visualizer/queue/types/circular/content.jsx
deleted file mode 100755
index b0544e3cc..000000000
--- a/app/visualizer/queue/types/circular/content.jsx
+++ /dev/null
@@ -1,291 +0,0 @@
-"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 = [
- `A Circular Queue is an advanced version of a linear queue that connects the end of the queue back to the front, forming a circle. This efficient structure prevents memory wastage and allows better utilization of fixed-size buffers.`,
- `The circular queue is an essential data structure for systems requiring efficient, fixed-size buffers with constant-time operations. Its circular nature solves the memory wastage problem of linear queues while maintaining simple and predictable performance characteristics, making it ideal for low-level system programming and real-time applications.`,
- ];
-
- const characteristics = [
- { points : "Fixed capacity: Size is predetermined at creation" },
- { points : "Two pointers:",
- subpoints : [
- "Front: Points to the first element",
- "Rear: Points to the last element",
- ],
- },
- { points : "Circular behavior: When pointers reach the end, they wrap around to the start" },
- { points : "Efficient space utilization: Reuses empty spaces created after dequeues" },
- ];
-
- const implementation = [
- { points : "Pointer Movement:",
- subpoints : [
- "front = (front + 1) % capacity",
- "rear = (rear + 1) % capacity",
- ],
- },
- { points : "Full/Empty Conditions:",
- subpoints : [
- "Full: (rear + 1) % capacity == front",
- "Empty: front == rear",
- ],
- },
- { points : "Always one empty slot:",
- subpoints : [
- "Needed to distinguish between full and empty states",
- ],
- },
- ];
-
- const complexity = [
- { points : "enqueue(): O(1)" },
- { points : "dequeue(): O(1)" },
- { points : "peekFront(): O(1)" },
- { points : "peekRear(): O(1)" },
- { points : "isEmpty(): O(1)" },
- { points : "isFull(): O(1)" },
- ];
-
- const application = [
- { points : "CPU Scheduling: Round-robin scheduling algorithms" },
- { points : "Memory Management: Circular buffers in memory systems" },
- { points : "Traffic Systems: Controlling the flow of traffic signals" },
- { points : "Data Streams: Handling continuous data streams (audio/video buffers)" },
- { points : "Producer-Consumer Problems: Where producers and consumers operate at different rates" },
- ];
-
- const advantages = [
- { points : "Better memory utilization: Reuses empty spaces" },
- { points : "Efficient operations: No need to shift elements" },
- { points : "Fixed memory footprint: Predictable memory usage" },
- { points : "Real-time systems friendly: Bounded execution time" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is a Circular Queue? */}
-
-
-
- What is a Circular Queue?
-
-
-
-
- {/* Key Characteristics */}
-
-
-
- Key Characteristics
-
-
-
- Circular queues have these fundamental properties:
-
-
- {characteristics.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Implementation Details */}
-
-
-
- Implementation Details
-
-
-
- Key implementation aspects:
-
-
- {implementation.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {complexity.map((item, index) => (
-
-
- {item.points.split(':')[0]}:
-
- {item.points.split(':')[1]}
-
- ))}
-
-
-
-
- {/* Applications */}
-
-
-
- Applications
-
-
-
- Circular queues are used in:
-
-
- {application.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Advantages Over Linear Queue */}
-
-
-
- Advantages Over Linear Queue
-
-
-
- {advantages.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
- };
-
- export default content;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/circular/page.jsx b/app/visualizer/queue/types/circular/page.jsx
deleted file mode 100755
index cc37a8d57..000000000
--- a/app/visualizer/queue/types/circular/page.jsx
+++ /dev/null
@@ -1,119 +0,0 @@
-import Animation from "@/app/visualizer/queue/types/circular/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/queue/types/circular/content";
-import Quiz from "@/app/visualizer/queue/types/circular/quiz";
-import Code from "@/app/visualizer/queue/types/circular/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import Footer from "@/app/components/footer";
-import BackToTop from "@/app/components/ui/backtotop";
-
-export const metadata = {
- title: "Circular Queue | Learn with JS, C, Python, Java Code",
- description:
- "Understand how Circular Queue works in Data Structures using animations and complete code examples in JavaScript, C, Python, and Java. Ideal for DSA beginners and interview preparation.",
- keywords: [
- "Circular Queue",
- "Circular Queue Visualizer",
- "Circular Queue DSA",
- "Circular Queue in JavaScript",
- "Circular Queue in C",
- "Circular Queue in Python",
- "Circular Queue in Java",
- "Queue Data Structure",
- "DSA Queue Operations",
- "Learn Circular Queue",
- "Circular Queue Code Examples",
- "DSA Visualizer",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/queue/circularQueue.png",
- width: 1200,
- height: 630,
- alt: "Circular Queue Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Circular Queue", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- Circular Queue
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/queue/types/circular/quiz.jsx b/app/visualizer/queue/types/circular/quiz.jsx
deleted file mode 100755
index 9b88db919..000000000
--- a/app/visualizer/queue/types/circular/quiz.jsx
+++ /dev/null
@@ -1,384 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const QueueQuiz = () => {
- const questions = [
- {
- question: "What is the primary advantage of a circular queue over a linear queue?",
- options: [
- "Unlimited capacity",
- "Better memory utilization by reusing empty spaces",
- "Faster sorting capability",
- "Built-in search functionality"
- ],
- correctAnswer: 1,
- explanation: "Circular queues efficiently reuse empty spaces created by dequeue operations, preventing memory wastage."
- },
- {
- question: "How is the rear pointer calculated after an enqueue operation in a circular queue?",
- options: [
- "rear = rear + 1",
- "rear = (rear + 1) % capacity",
- "rear = front + 1",
- "rear = capacity - 1"
- ],
- correctAnswer: 1,
- explanation: "The rear pointer wraps around using modulo arithmetic: rear = (rear + 1) % capacity."
- },
- {
- question: "What condition indicates that a circular queue is full?",
- options: [
- "front == rear",
- "(rear + 1) % capacity == front",
- "front == 0 && rear == capacity - 1",
- "rear == capacity - 1"
- ],
- correctAnswer: 1,
- explanation: "The queue is full when the next position after rear (wrapped around) equals front."
- },
- {
- question: "Why do circular queues typically maintain one empty slot?",
- options: [
- "To reduce memory usage",
- "To distinguish between full and empty states",
- "For temporary storage during operations",
- "It's required by the implementation language"
- ],
- correctAnswer: 1,
- explanation: "Without one empty slot, the conditions for full and empty states would be identical (front == rear)."
- },
- {
- question: "What is the time complexity of peekFront() in a circular queue?",
- options: [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n²)"
- ],
- correctAnswer: 0,
- explanation: "All basic operations (enqueue, dequeue, peek) are O(1) in a circular queue."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding circular queue advantages");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("pointer arithmetic in circular queues");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("full/empty conditions");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("circular queue implementation details");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Circular Queue concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Circular Queue Quiz
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? 'Finish' : 'Next'}
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length ? "Perfect Score!" :
- score >= questions.length * 0.8 ? "Excellent Work!" :
- score >= questions.length * 0.6 ? "Good Job!" :
- score >= questions.length * 0.4 ? "Keep Practicing!" : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}% correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
Question Breakdown:
- {questions.map((q, index) => (
-
-
{q.question}
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
Your answer: {answers[index] !== null ? q.options[answers[index]] : "Not answered"}
- {answers[index] !== q.correctAnswer && (
-
Correct answer: {q.options[q.correctAnswer]}
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default QueueQuiz;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/deque/animation.jsx b/app/visualizer/queue/types/deque/animation.jsx
deleted file mode 100755
index b5f980f45..000000000
--- a/app/visualizer/queue/types/deque/animation.jsx
+++ /dev/null
@@ -1,297 +0,0 @@
-"use client";
-import React, { useState } from "react";
-
-const DequeVisualizer = () => {
- const [deque, setDeque] = useState([]);
- const [inputValue, setInputValue] = useState("");
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("Deque is empty");
- const [isAnimating, setIsAnimating] = useState(false);
-
- /* ---------- helpers ---------- */
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
- const showOp = async (txt, ms = 800) => {
- setOperation(txt);
- await sleep(ms);
- setOperation(null);
- };
-
- /* ---------- enqueue front ---------- */
- const enqueueFront = async () => {
- if (!inputValue.trim()) {
- setMessage("Please enter a value");
- return;
- }
- setIsAnimating(true);
- await showOp(`Enqueuing "${inputValue}" at front …`);
- setDeque((d) => [inputValue, ...d]);
- setMessage(`"${inputValue}" added to front`);
- setInputValue("");
- setIsAnimating(false);
- };
-
- /* ---------- enqueue rear ---------- */
- const enqueueRear = async () => {
- if (!inputValue.trim()) {
- setMessage("Please enter a value");
- return;
- }
- setIsAnimating(true);
- await showOp(`Enqueuing "${inputValue}" at rear …`);
- setDeque((d) => [...d, inputValue]);
- setMessage(`"${inputValue}" added to rear`);
- setInputValue("");
- setIsAnimating(false);
- };
-
- /* ---------- dequeue front ---------- */
- const dequeueFront = async () => {
- if (deque.length === 0) {
- setMessage("Deque is empty!");
- return;
- }
- setIsAnimating(true);
- const front = deque[0];
- await showOp(`Dequeuing "${front}" from front …`);
- setDeque((d) => d.slice(1));
- setMessage(`"${front}" removed from front`);
- setIsAnimating(false);
- };
-
- /* ---------- dequeue rear ---------- */
- const dequeueRear = async () => {
- if (deque.length === 0) {
- setMessage("Deque is empty!");
- return;
- }
- setIsAnimating(true);
- const rear = deque[deque.length - 1];
- await showOp(`Dequeuing "${rear}" from rear …`);
- setDeque((d) => d.slice(0, -1));
- setMessage(`"${rear}" removed from rear`);
- setIsAnimating(false);
- };
-
- /* ---------- peek front ---------- */
- const peekFront = async () => {
- if (deque.length === 0) {
- setMessage("Deque is empty!");
- return;
- }
- setIsAnimating(true);
- setMessage(`Front element: "${deque[0]}"`);
- await sleep(1500);
- setIsAnimating(false);
- };
-
- /* ---------- peek rear ---------- */
- const peekRear = async () => {
- if (deque.length === 0) {
- setMessage("Deque is empty!");
- return;
- }
- setIsAnimating(true);
- setMessage(`Rear element: "${deque[deque.length - 1]}"`);
- await sleep(1500);
- setIsAnimating(false);
- };
-
- /* ---------- reset ---------- */
- const reset = () => {
- setDeque([]);
- setInputValue("");
- setOperation(null);
- setMessage("Deque cleared");
- };
-
- /* ---------- UI ---------- */
- return (
-
-
- Double-Ended Queue Visualiser
-
-
-
- {/* ----- Controls card ----- */}
-
- {/* Value input + dual enqueue buttons */}
-
- setInputValue(e.target.value)}
- placeholder="Enter value"
- className="flex-1 p-3 border dark:border-gray-700 rounded-lg dark:bg-neutral-900 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
- disabled={isAnimating}
- onKeyDown={(e) => e.key === "Enter" && enqueueRear()}
- />
-
- Enqueue Front
-
-
- Enqueue Rear
-
-
-
- {/* Action buttons */}
-
-
- Dequeue Front
-
-
- Dequeue Rear
-
-
- Peek Front
-
-
- Peek Rear
-
-
- Reset
-
-
-
- {/* Status banners */}
-
- {operation && (
-
- )}
- {message && (
-
- {message}
-
- )}
-
-
-
- {/* ----- Visualisation card (hidden when empty) ----- */}
- {deque.length > 0 && (
-
-
Deque Visualisation
-
-
- {/* Front pointer */}
-
-
- {/* Elements */}
-
- {deque.map((item, index) => (
-
- ))}
-
-
- {/* Rear pointer */}
-
-
-
- )}
-
-
- );
-};
-
-export default DequeVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/deque/codeBlock.jsx b/app/visualizer/queue/types/deque/codeBlock.jsx
deleted file mode 100755
index 28209705c..000000000
--- a/app/visualizer/queue/types/deque/codeBlock.jsx
+++ /dev/null
@@ -1,869 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Double-Ended Queue Implementation (JavaScript)
-class Deque {
- constructor(size = 10) {
- this.items = new Array(size);
- this.front = -1;
- this.rear = 0;
- this.size = 0;
- this.capacity = size;
- }
-
- // Add to front
- addFront(item) {
- if (this.isFull()) {
- console.log("Deque Overflow");
- return;
- }
- if (this.front === -1) {
- this.front = 0;
- this.rear = 0;
- } else if (this.front === 0) {
- this.front = this.capacity - 1;
- } else {
- this.front--;
- }
- this.items[this.front] = item;
- this.size++;
- }
-
- // Add to rear
- addRear(item) {
- if (this.isFull()) {
- console.log("Deque Overflow");
- return;
- }
- if (this.front === -1) {
- this.front = 0;
- this.rear = 0;
- } else if (this.rear === this.capacity - 1) {
- this.rear = 0;
- } else {
- this.rear++;
- }
- this.items[this.rear] = item;
- this.size++;
- }
-
- // Remove from front
- removeFront() {
- if (this.isEmpty()) {
- console.log("Deque Underflow");
- return undefined;
- }
- const item = this.items[this.front];
- if (this.front === this.rear) {
- this.front = -1;
- this.rear = -1;
- } else if (this.front === this.capacity - 1) {
- this.front = 0;
- } else {
- this.front++;
- }
- this.size--;
- return item;
- }
-
- // Remove from rear
- removeRear() {
- if (this.isEmpty()) {
- console.log("Deque Underflow");
- return undefined;
- }
- const item = this.items[this.rear];
- if (this.front === this.rear) {
- this.front = -1;
- this.rear = -1;
- } else if (this.rear === 0) {
- this.rear = this.capacity - 1;
- } else {
- this.rear--;
- }
- this.size--;
- return item;
- }
-
- // Peek front
- peekFront() {
- if (this.isEmpty()) {
- console.log("Deque is empty");
- return undefined;
- }
- return this.items[this.front];
- }
-
- // Peek rear
- peekRear() {
- if (this.isEmpty()) {
- console.log("Deque is empty");
- return undefined;
- }
- return this.items[this.rear];
- }
-
- // Check if empty
- isEmpty() {
- return this.size === 0;
- }
-
- // Check if full
- isFull() {
- return this.size === this.capacity;
- }
-
- // Get current size
- getSize() {
- return this.size;
- }
-
- // Print deque contents
- print() {
- if (this.isEmpty()) {
- console.log("Deque is empty");
- return;
- }
- console.log("Deque contents (front to rear):");
- let i = this.front;
- let count = 0;
- while (count < this.size) {
- console.log(this.items[i]);
- i = (i + 1) % this.capacity;
- count++;
- }
- }
-}
-
-// Usage
-const deque = new Deque(5);
-deque.addRear(10);
-deque.addFront(20);
-deque.addRear(30);
-console.log("Front element:", deque.peekFront()); // 20
-console.log("Rear element:", deque.peekRear()); // 30
-console.log("Deque size:", deque.getSize()); // 3
-deque.print();
-deque.removeFront();
-console.log("After removeFront, front element:", deque.peekFront()); // 10`,
-
- python: `# Double-Ended Queue Implementation (Python)
-class Deque:
- def __init__(self, size=10):
- self.items = [None] * size
- self.front = -1
- self.rear = 0
- self.size = 0
- self.capacity = size
-
- def add_front(self, item):
- if self.is_full():
- print("Deque Overflow")
- return
- if self.front == -1:
- self.front = 0
- self.rear = 0
- elif self.front == 0:
- self.front = self.capacity - 1
- else:
- self.front -= 1
- self.items[self.front] = item
- self.size += 1
-
- def add_rear(self, item):
- if self.is_full():
- print("Deque Overflow")
- return
- if self.front == -1:
- self.front = 0
- self.rear = 0
- elif self.rear == self.capacity - 1:
- self.rear = 0
- else:
- self.rear += 1
- self.items[self.rear] = item
- self.size += 1
-
- def remove_front(self):
- if self.is_empty():
- print("Deque Underflow")
- return None
- item = self.items[self.front]
- if self.front == self.rear:
- self.front = -1
- self.rear = -1
- elif self.front == self.capacity - 1:
- self.front = 0
- else:
- self.front += 1
- self.size -= 1
- return item
-
- def remove_rear(self):
- if self.is_empty():
- print("Deque Underflow")
- return None
- item = self.items[self.rear]
- if self.front == self.rear:
- self.front = -1
- self.rear = -1
- elif self.rear == 0:
- self.rear = self.capacity - 1
- else:
- self.rear -= 1
- self.size -= 1
- return item
-
- def peek_front(self):
- if self.is_empty():
- print("Deque is empty")
- return None
- return self.items[self.front]
-
- def peek_rear(self):
- if self.is_empty():
- print("Deque is empty")
- return None
- return self.items[self.rear]
-
- def is_empty(self):
- return self.size == 0
-
- def is_full(self):
- return self.size == self.capacity
-
- def get_size(self):
- return self.size
-
- def print_deque(self):
- if self.is_empty():
- print("Deque is empty")
- return
- print("Deque contents (front to rear):")
- i = self.front
- count = 0
- while count < self.size:
- print(self.items[i])
- i = (i + 1) % self.capacity
- count += 1
-
-# Usage
-deque = Deque(5)
-deque.add_rear(10)
-deque.add_front(20)
-deque.add_rear(30)
-print("Front element:", deque.peek_front()) # 20
-print("Rear element:", deque.peek_rear()) # 30
-print("Deque size:", deque.get_size()) # 3
-deque.print_deque()
-deque.remove_front()
-print("After removeFront, front element:", deque.peek_front()) # 10`,
-
- java: `// Double-Ended Queue Implementation (Java)
-public class ArrayDeque {
- private int[] items;
- private int front;
- private int rear;
- private int size;
- private int capacity;
-
- public ArrayDeque(int size) {
- items = new int[size];
- front = -1;
- rear = 0;
- size = 0;
- capacity = size;
- }
-
- public void addFront(int item) {
- if (isFull()) {
- System.out.println("Deque Overflow");
- return;
- }
- if (front == -1) {
- front = 0;
- rear = 0;
- } else if (front == 0) {
- front = capacity - 1;
- } else {
- front--;
- }
- items[front] = item;
- size++;
- }
-
- public void addRear(int item) {
- if (isFull()) {
- System.out.println("Deque Overflow");
- return;
- }
- if (front == -1) {
- front = 0;
- rear = 0;
- } else if (rear == capacity - 1) {
- rear = 0;
- } else {
- rear++;
- }
- items[rear] = item;
- size++;
- }
-
- public int removeFront() {
- if (isEmpty()) {
- System.out.println("Deque Underflow");
- return -1;
- }
- int item = items[front];
- if (front == rear) {
- front = -1;
- rear = -1;
- } else if (front == capacity - 1) {
- front = 0;
- } else {
- front++;
- }
- size--;
- return item;
- }
-
- public int removeRear() {
- if (isEmpty()) {
- System.out.println("Deque Underflow");
- return -1;
- }
- int item = items[rear];
- if (front == rear) {
- front = -1;
- rear = -1;
- } else if (rear == 0) {
- rear = capacity - 1;
- } else {
- rear--;
- }
- size--;
- return item;
- }
-
- public int peekFront() {
- if (isEmpty()) {
- System.out.println("Deque is empty");
- return -1;
- }
- return items[front];
- }
-
- public int peekRear() {
- if (isEmpty()) {
- System.out.println("Deque is empty");
- return -1;
- }
- return items[rear];
- }
-
- public boolean isEmpty() {
- return size == 0;
- }
-
- public boolean isFull() {
- return size == capacity;
- }
-
- public int getSize() {
- return size;
- }
-
- public void print() {
- if (isEmpty()) {
- System.out.println("Deque is empty");
- return;
- }
- System.out.println("Deque contents (front to rear):");
- int i = front;
- int count = 0;
- while (count < size) {
- System.out.println(items[i]);
- i = (i + 1) % capacity;
- count++;
- }
- }
-
- public static void main(String[] args) {
- ArrayDeque deque = new ArrayDeque(5);
- deque.addRear(10);
- deque.addFront(20);
- deque.addRear(30);
- System.out.println("Front element: " + deque.peekFront()); // 20
- System.out.println("Rear element: " + deque.peekRear()); // 30
- System.out.println("Deque size: " + deque.getSize()); // 3
- deque.print();
- deque.removeFront();
- System.out.println("After removeFront, front element: " + deque.peekFront()); // 10
- }
-}`,
-
- c: `// Double-Ended Queue Implementation (C)
-#include
-#include
-#include
-
-typedef struct {
- int *items;
- int front;
- int rear;
- int size;
- int capacity;
-} Deque;
-
-void initialize(Deque *dq, int capacity) {
- dq->items = (int*)malloc(capacity * sizeof(int));
- dq->front = -1;
- dq->rear = 0;
- dq->size = 0;
- dq->capacity = capacity;
-}
-
-bool isFull(Deque *dq) {
- return dq->size == dq->capacity;
-}
-
-bool isEmpty(Deque *dq) {
- return dq->size == 0;
-}
-
-void addFront(Deque *dq, int item) {
- if (isFull(dq)) {
- printf("Deque Overflow\n");
- return;
- }
- if (dq->front == -1) {
- dq->front = 0;
- dq->rear = 0;
- } else if (dq->front == 0) {
- dq->front = dq->capacity - 1;
- } else {
- dq->front--;
- }
- dq->items[dq->front] = item;
- dq->size++;
-}
-
-void addRear(Deque *dq, int item) {
- if (isFull(dq)) {
- printf("Deque Overflow\n");
- return;
- }
- if (dq->front == -1) {
- dq->front = 0;
- dq->rear = 0;
- } else if (dq->rear == dq->capacity - 1) {
- dq->rear = 0;
- } else {
- dq->rear++;
- }
- dq->items[dq->rear] = item;
- dq->size++;
-}
-
-int removeFront(Deque *dq) {
- if (isEmpty(dq)) {
- printf("Deque Underflow\n");
- return -1;
- }
- int item = dq->items[dq->front];
- if (dq->front == dq->rear) {
- dq->front = -1;
- dq->rear = -1;
- } else if (dq->front == dq->capacity - 1) {
- dq->front = 0;
- } else {
- dq->front++;
- }
- dq->size--;
- return item;
-}
-
-int removeRear(Deque *dq) {
- if (isEmpty(dq)) {
- printf("Deque Underflow\n");
- return -1;
- }
- int item = dq->items[dq->rear];
- if (dq->front == dq->rear) {
- dq->front = -1;
- dq->rear = -1;
- } else if (dq->rear == 0) {
- dq->rear = dq->capacity - 1;
- } else {
- dq->rear--;
- }
- dq->size--;
- return item;
-}
-
-int peekFront(Deque *dq) {
- if (isEmpty(dq)) {
- printf("Deque is empty\n");
- return -1;
- }
- return dq->items[dq->front];
-}
-
-int peekRear(Deque *dq) {
- if (isEmpty(dq)) {
- printf("Deque is empty\n");
- return -1;
- }
- return dq->items[dq->rear];
-}
-
-int size(Deque *dq) {
- return dq->size;
-}
-
-void print(Deque *dq) {
- if (isEmpty(dq)) {
- printf("Deque is empty\n");
- return;
- }
- printf("Deque contents (front to rear):\n");
- int i = dq->front;
- int count = 0;
- while (count < dq->size) {
- printf("%d\n", dq->items[i]);
- i = (i + 1) % dq->capacity;
- count++;
- }
-}
-
-void destroy(Deque *dq) {
- free(dq->items);
-}
-
-int main() {
- Deque deque;
- initialize(&deque, 5);
-
- addRear(&deque, 10);
- addFront(&deque, 20);
- addRear(&deque, 30);
- printf("Front element: %d\n", peekFront(&deque)); // 20
- printf("Rear element: %d\n", peekRear(&deque)); // 30
- printf("Deque size: %d\n", size(&deque)); // 3
- print(&deque);
- removeFront(&deque);
- printf("After removeFront, front element: %d\n", peekFront(&deque)); // 10
-
- destroy(&deque);
- return 0;
-}`,
-
- cpp: `// Double-Ended Queue Implementation (C++)
-#include
-using namespace std;
-
-class Deque {
-private:
- int *items;
- int front;
- int rear;
- int size;
- int capacity;
-
-public:
- Deque(int size) {
- items = new int[size];
- front = -1;
- rear = 0;
- size = 0;
- capacity = size;
- }
-
- ~Deque() {
- delete[] items;
- }
-
- void addFront(int item) {
- if (isFull()) {
- cout << "Deque Overflow" << endl;
- return;
- }
- if (front == -1) {
- front = 0;
- rear = 0;
- } else if (front == 0) {
- front = capacity - 1;
- } else {
- front--;
- }
- items[front] = item;
- size++;
- }
-
- void addRear(int item) {
- if (isFull()) {
- cout << "Deque Overflow" << endl;
- return;
- }
- if (front == -1) {
- front = 0;
- rear = 0;
- } else if (rear == capacity - 1) {
- rear = 0;
- } else {
- rear++;
- }
- items[rear] = item;
- size++;
- }
-
- int removeFront() {
- if (isEmpty()) {
- cout << "Deque Underflow" << endl;
- return -1;
- }
- int item = items[front];
- if (front == rear) {
- front = -1;
- rear = -1;
- } else if (front == capacity - 1) {
- front = 0;
- } else {
- front++;
- }
- size--;
- return item;
- }
-
- int removeRear() {
- if (isEmpty()) {
- cout << "Deque Underflow" << endl;
- return -1;
- }
- int item = items[rear];
- if (front == rear) {
- front = -1;
- rear = -1;
- } else if (rear == 0) {
- rear = capacity - 1;
- } else {
- rear--;
- }
- size--;
- return item;
- }
-
- int peekFront() {
- if (isEmpty()) {
- cout << "Deque is empty" << endl;
- return -1;
- }
- return items[front];
- }
-
- int peekRear() {
- if (isEmpty()) {
- cout << "Deque is empty" << endl;
- return -1;
- }
- return items[rear];
- }
-
- bool isEmpty() {
- return size == 0;
- }
-
- bool isFull() {
- return size == capacity;
- }
-
- int getSize() {
- return size;
- }
-
- void print() {
- if (isEmpty()) {
- cout << "Deque is empty" << endl;
- return;
- }
- cout << "Deque contents (front to rear):" << endl;
- int i = front;
- int count = 0;
- while (count < size) {
- cout << items[i] << endl;
- i = (i + 1) % capacity;
- count++;
- }
- }
-};
-
-int main() {
- Deque deque(5);
- deque.addRear(10);
- deque.addFront(20);
- deque.addRear(30);
- cout << "Front element: " << deque.peekFront() << endl; // 20
- cout << "Rear element: " << deque.peekRear() << endl; // 30
- cout << "Deque size: " << deque.getSize() << endl; // 3
- deque.print();
- deque.removeFront();
- cout << "After removeFront, front element: " << deque.peekFront() << endl; // 10
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Double Ended Queue Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/deque/content.jsx b/app/visualizer/queue/types/deque/content.jsx
deleted file mode 100755
index 758d43d32..000000000
--- a/app/visualizer/queue/types/deque/content.jsx
+++ /dev/null
@@ -1,326 +0,0 @@
-"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 = [
- `A Double-Ended Queue (Deque) is a versatile data structure that allows insertion and deletion of elements from both ends (front and rear). Unlike a single-ended queue, it provides more flexibility while maintaining efficient O(1) operations.`,
- `The double-ended queue is a powerful hybrid data structure that combines the best features of stacks and queues. Its flexibility makes it invaluable for algorithms requiring access to both ends of a dataset, while maintaining efficient constant-time operations for all key functions.`,
- ];
-
- const characteristics = [
- {
- points: "Two open ends:",
- subpoints: ["Supports operations at both front and rear"],
- },
- {
- points: "Four core operations:",
- subpoints: [
- "addFront() - Insert at front",
- "addRear() - Insert at rear",
- "removeFront() - Delete from front",
- "removeRear() - Delete from rear",
- ],
- },
- {
- points: "Hybrid nature:",
- subpoints: ["Combines features of both stacks and queues"],
- },
- ];
-
- const variations = [
- {
- points: "Doubly Linked List:",
- subpoints: [
- "Natural fit with head and tail pointers",
- "All operations are O(1)",
- "Extra memory for previous/next pointers",
- ],
- },
- {
- points: "Circular Array:",
- subpoints: [
- "Fixed capacity but efficient",
- "Requires careful index management",
- "Good for memory-constrained environments",
- ],
- },
- {
- points: "Dynamic Array:",
- subpoints: ["Amortized O(1) operations", "May need occasional resizing"],
- },
- ];
-
- const complexity = [
- { points: "addFront(): O(1)" },
- { points: "addRear(): O(1)" },
- { points: "removeFront(): O(1)" },
- { points: "removeRear(): O(1)" },
- { points: "peekFront(): O(1)" },
- { points: "peekRear(): O(1)" },
- ];
-
- const application = [
- { points: "Undo/Redo operations: Store history at both ends" },
- { points: "Palindrome checking: Compare front and rear elements" },
- { points: "Steal algorithms: Work stealing in parallel processing" },
- { points: "Sliding window problems: Efficient maximum/minimum tracking" },
- { points: "Browser history: Navigation in both directions" },
- ];
-
- const cases = [
- { points: "Input-Restricted Deque: Insertion only at one end" },
- { points: "Output-Restricted Deque: Deletion only at one end" },
- { points: "Palindrome Checker: Using deque properties" },
- { points: "Priority Deque: Combines deque and priority queue features" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is a Double-Ended Queue (Deque)? */}
-
-
-
- What is a Double-Ended Queue (Deque)?
-
-
-
-
- {/* Key Characteristics */}
-
-
-
- Key Characteristics
-
-
-
- Deques have these fundamental properties:
-
-
- {characteristics.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Implementation Variations */}
-
-
-
- Implementation Variations
-
-
-
- Common implementation approaches:
-
-
- {variations.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {complexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
-
-
- {/* Applications */}
-
-
-
- Applications
-
-
-
- Deques are used in:
-
-
- {application.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Special Cases */}
-
-
-
- Special Cases
-
-
-
- Interesting deque variations:
-
-
- {cases.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/queue/types/deque/page.jsx b/app/visualizer/queue/types/deque/page.jsx
deleted file mode 100755
index f385ffec8..000000000
--- a/app/visualizer/queue/types/deque/page.jsx
+++ /dev/null
@@ -1,119 +0,0 @@
-import Animation from "@/app/visualizer/queue/types/deque/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/queue/types/deque/content";
-import Quiz from "@/app/visualizer/queue/types/deque/quiz";
-import Code from "@/app/visualizer/queue/types/deque/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Footer from '@/app/components/footer';
-import BackToTop from '@/app/components/ui/backtotop';
-
-export const metadata = {
- title: "Double Ended Queue (Deque) | Learn with JS, C, Python, Java Code",
- description:
- "Explore Double Ended Queue (Deque) in Data Structures with visual animations and full code implementations in JavaScript, C, Python, and Java. Perfect for mastering DSA concepts and interview preparation.",
- keywords: [
- "Double Ended Queue",
- "Double Ended Queue Visualizer",
- "Deque in DSA",
- "DSA Deque",
- "Double Ended Queue in JavaScript",
- "Deque in C",
- "Deque in Python",
- "Deque in Java",
- "DSA Queue Operations",
- "Learn Deque DSA",
- "Deque Code Examples",
- "DSA Visualizer",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/queue/deque.png",
- width: 1200,
- height: 630,
- alt: "Double Ended Queue Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Queue : Double Ended", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/queue/types/deque/quiz.jsx b/app/visualizer/queue/types/deque/quiz.jsx
deleted file mode 100755
index f87b9b9b1..000000000
--- a/app/visualizer/queue/types/deque/quiz.jsx
+++ /dev/null
@@ -1,384 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const QueueQuiz = () => {
- const questions = [
- {
- question: "What is the key characteristic that distinguishes a deque from a single-ended queue?",
- options: [
- "Allows operations at only one end",
- "Allows operations at both ends",
- "Only allows insertion at one end and removal at the other",
- "Uses LIFO principle exclusively"
- ],
- correctAnswer: 1,
- explanation: "Deques allow insertion and removal at both front and rear ends, unlike single-ended queues which are restricted to rear insertion and front removal."
- },
- {
- question: "Which of the following is NOT a standard deque operation?",
- options: [
- "addFront()",
- "addRear()",
- "removeMiddle()",
- "removeRear()"
- ],
- correctAnswer: 2,
- explanation: "Deques don't typically support direct middle removal - their core operations work at the two ends only."
- },
- {
- question: "What would be the result of these operations on an empty deque? addFront(10), addRear(20), removeFront()",
- options: [
- "10",
- "20",
- "[10, 20]",
- "Empty deque"
- ],
- correctAnswer: 1,
- explanation: "addFront(10) → [10], addRear(20) → [10, 20], removeFront() removes 10, leaving 20 as the return value."
- },
- {
- question: "Which data structure is most commonly used to implement a deque efficiently?",
- options: [
- "Singly Linked List",
- "Binary Tree",
- "Doubly Linked List",
- "Hash Table"
- ],
- correctAnswer: 2,
- explanation: "Doubly linked lists are ideal for deque implementation as they allow O(1) operations at both ends."
- },
- {
- question: "What is the time complexity for removeRear() in a properly implemented deque?",
- options: [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n²)"
- ],
- correctAnswer: 0,
- explanation: "All core deque operations (addFront, addRear, removeFront, removeRear) should be O(1) in a proper implementation."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding deque characteristics");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("deque operations");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("deque operation sequences");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("deque implementation");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Deque concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Deque Quiz
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? 'Finish' : 'Next'}
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length ? "Perfect Score!" :
- score >= questions.length * 0.8 ? "Excellent Work!" :
- score >= questions.length * 0.6 ? "Good Job!" :
- score >= questions.length * 0.4 ? "Keep Practicing!" : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}% correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
Question Breakdown:
- {questions.map((q, index) => (
-
-
{q.question}
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
Your answer: {answers[index] !== null ? q.options[answers[index]] : "Not answered"}
- {answers[index] !== q.correctAnswer && (
-
Correct answer: {q.options[q.correctAnswer]}
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default QueueQuiz;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/priority/animation.jsx b/app/visualizer/queue/types/priority/animation.jsx
deleted file mode 100755
index e4a02e4d5..000000000
--- a/app/visualizer/queue/types/priority/animation.jsx
+++ /dev/null
@@ -1,209 +0,0 @@
-"use client";
-import React, { useState } from "react";
-
-const PriorityQueueVisualizer = () => {
- /* ---------- state ---------- */
- const [pq, setPq] = useState([]); // sorted: [0] = highest priority (min-val)
- const [inputValue, setInputValue] = useState("");
- const [inputPriority, setInputPriority] = useState("");
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("Priority queue is empty");
- const [isAnimating, setIsAnimating] = useState(false);
-
- /* ---------- helpers ---------- */
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
- const showOp = async (txt, ms = 800) => {
- setOperation(txt);
- await sleep(ms);
- setOperation(null);
- };
-
- /* ---------- insert ---------- */
- const insert = async () => {
- if (!inputValue.trim() || inputPriority === "") {
- setMessage("Please enter both value and priority");
- return;
- }
- const pri = Number(inputPriority);
- if (isNaN(pri)) {
- setMessage("Priority must be a number");
- return;
- }
- setIsAnimating(true);
- await showOp(`Inserting "${inputValue}" with priority ${pri} …`);
- const newEl = { val: inputValue, pri };
- const newPq = [...pq, newEl].sort((a, b) => a.pri - b.pri);
- setPq(newPq);
- setMessage(`"${inputValue}" inserted`);
- setInputValue("");
- setInputPriority("");
- setIsAnimating(false);
- };
-
- /* ---------- extract-min ---------- */
- const extractMin = async () => {
- if (pq.length === 0) {
- setMessage("Priority queue is empty!");
- return;
- }
- setIsAnimating(true);
- const minEl = pq[0];
- await showOp(`Extracting min element "${minEl.val}" …`);
- setPq((p) => p.slice(1));
- setMessage(`"${minEl.val}" (priority ${minEl.pri}) removed`);
- setIsAnimating(false);
- };
-
- /* ---------- peek-min ---------- */
- const peekMin = async () => {
- if (pq.length === 0) {
- setMessage("Priority queue is empty!");
- return;
- }
- setIsAnimating(true);
- const minEl = pq[0];
- setMessage(`Min element: "${minEl.val}" (priority ${minEl.pri})`);
- await sleep(1500);
- setIsAnimating(false);
- };
-
- /* ---------- clear ---------- */
- const clear = () => {
- setPq([]);
- setInputValue("");
- setInputPriority("");
- setOperation(null);
- setMessage("Priority queue cleared");
- };
-
- /* ---------- UI ---------- */
- return (
-
-
- Min-Priority Queue Visualiser (lower number = higher priority)
-
-
-
- {/* ----- Controls card ----- */}
-
- {/* Inputs row */}
-
- setInputValue(e.target.value)}
- placeholder="Value"
- className="flex-1 p-3 border dark:border-gray-700 rounded-lg dark:bg-neutral-900 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
- disabled={isAnimating}
- />
- setInputPriority(e.target.value)}
- placeholder="Priority number"
- className="flex-1 p-3 border dark:border-gray-700 rounded-lg dark:bg-neutral-900 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
- disabled={isAnimating}
- />
-
-
- {/* Action buttons */}
-
-
- Insert
-
-
- Extract-Min
-
-
- Peek-Min
-
-
- Reset
-
-
-
- {/* Status banners */}
-
- {operation && (
-
- )}
- {message && (
-
- {message}
-
- )}
-
-
-
- {/* ----- Visualisation card (hidden when empty) ----- */}
- {pq.length > 0 && (
-
-
Visualisation
-
-
- {pq.map((el, idx) => (
-
-
- {el.val}
- pri: {el.pri}
-
-
- ))}
-
-
- )}
-
-
- );
-};
-
-export default PriorityQueueVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/priority/codeBlock.jsx b/app/visualizer/queue/types/priority/codeBlock.jsx
deleted file mode 100755
index be83f38c4..000000000
--- a/app/visualizer/queue/types/priority/codeBlock.jsx
+++ /dev/null
@@ -1,523 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Priority Queue Implementation in JavaScript (Min-Heap)
-class PriorityQueue {
- constructor(comparator = (a, b) => a.priority - b.priority) {
- this.heap = [];
- this.comparator = comparator;
- }
-
- // Add element to the queue
- enqueue(value, priority) {
- const element = { value, priority };
- this.heap.push(element);
- this.bubbleUp(this.heap.length - 1);
- }
-
- // Remove and return the highest priority element
- dequeue() {
- if (this.isEmpty()) return null;
- const root = this.heap[0];
- const last = this.heap.pop();
- if (this.heap.length > 0) {
- this.heap[0] = last;
- this.bubbleDown(0);
- }
- return root.value;
- }
-
- // Peek at the highest priority element without removing it
- peek() {
- if (this.isEmpty()) return null;
- return this.heap[0].value;
- }
-
- // Get current size of the queue
- size() {
- return this.heap.length;
- }
-
- // Check if the queue is empty
- isEmpty() {
- return this.heap.length === 0;
- }
-
- // Move element up the heap to maintain heap property
- bubbleUp(index) {
- while (index > 0) {
- const parentIndex = Math.floor((index - 1) / 2);
- if (this.comparator(this.heap[index], this.heap[parentIndex]) >= 0) break;
- [this.heap[parentIndex], this.heap[index]] = [this.heap[index], this.heap[parentIndex]];
- index = parentIndex;
- }
- }
-
- // Move element down the heap to maintain heap property
- bubbleDown(index) {
- const lastIndex = this.heap.length - 1;
- while (true) {
- const leftChildIndex = 2 * index + 1;
- const rightChildIndex = 2 * index + 2;
- let smallestIndex = index;
-
- if (leftChildIndex <= lastIndex &&
- this.comparator(this.heap[leftChildIndex], this.heap[smallestIndex]) < 0) {
- smallestIndex = leftChildIndex;
- }
-
- if (rightChildIndex <= lastIndex &&
- this.comparator(this.heap[rightChildIndex], this.heap[smallestIndex]) < 0) {
- smallestIndex = rightChildIndex;
- }
-
- if (smallestIndex === index) break;
- [this.heap[index], this.heap[smallestIndex]] = [this.heap[smallestIndex], this.heap[index]];
- index = smallestIndex;
- }
- }
-}
-
-// Usage
-const pq = new PriorityQueue();
-pq.enqueue("Task 1", 3); // Lower numbers = higher priority
-pq.enqueue("Task 2", 1);
-pq.enqueue("Task 3", 2);
-
-console.log(pq.dequeue()); // "Task 2" (highest priority)
-console.log(pq.peek()); // "Task 3" (next highest priority)
-console.log(pq.size()); // 2`,
-
- python: `# Priority Queue Implementation in Python (Min-Heap)
-import heapq
-
-class PriorityQueue:
- def __init__(self):
- self.heap = []
- self.index = 0 # Used to properly order elements with same priority
-
- def enqueue(self, value, priority):
- heapq.heappush(self.heap, (priority, self.index, value))
- self.index += 1
-
- def dequeue(self):
- if self.is_empty():
- return None
- return heapq.heappop(self.heap)[2] # Return the value
-
- def peek(self):
- if self.is_empty():
- return None
- return self.heap[0][2] # Return the value without removing
-
- def size(self):
- return len(self.heap)
-
- def is_empty(self):
- return len(self.heap) == 0
-
-# Usage
-pq = PriorityQueue()
-pq.enqueue("Task 1", 3) # Lower numbers = higher priority
-pq.enqueue("Task 2", 1)
-pq.enqueue("Task 3", 2)
-
-print(pq.dequeue()) # "Task 2" (highest priority)
-print(pq.peek()) # "Task 3" (next highest priority)
-print(pq.size()) # 2`,
-
- java: `// Priority Queue Implementation in Java
-import java.util.PriorityQueue;
-import java.util.Comparator;
-
-public class Main {
- static class PriorityItem {
- T value;
- int priority;
-
- public PriorityItem(T value, int priority) {
- this.value = value;
- this.priority = priority;
- }
- }
-
- static class PriorityQueue {
- private java.util.PriorityQueue> queue;
-
- public PriorityQueue() {
- this.queue = new java.util.PriorityQueue<>(
- Comparator.comparingInt(item -> item.priority)
- );
- }
-
- public void enqueue(T value, int priority) {
- queue.add(new PriorityItem<>(value, priority));
- }
-
- public T dequeue() {
- if (isEmpty()) return null;
- return queue.poll().value;
- }
-
- public T peek() {
- if (isEmpty()) return null;
- return queue.peek().value;
- }
-
- public int size() {
- return queue.size();
- }
-
- public boolean isEmpty() {
- return queue.isEmpty();
- }
- }
-
- public static void main(String[] args) {
- PriorityQueue pq = new PriorityQueue<>();
- pq.enqueue("Task 1", 3); // Lower numbers = higher priority
- pq.enqueue("Task 2", 1);
- pq.enqueue("Task 3", 2);
-
- System.out.println(pq.dequeue()); // "Task 2" (highest priority)
- System.out.println(pq.peek()); // "Task 3" (next highest priority)
- System.out.println(pq.size()); // 2
- }
-}`,
-
- c: `// Priority Queue Implementation in C (Min-Heap)
-#include
-#include
-
-typedef struct {
- void* value;
- int priority;
-} PriorityItem;
-
-typedef struct {
- PriorityItem* heap;
- int capacity;
- int size;
-} PriorityQueue;
-
-PriorityQueue* createPriorityQueue(int capacity) {
- PriorityQueue* pq = (PriorityQueue*)malloc(sizeof(PriorityQueue));
- pq->heap = (PriorityItem*)malloc(capacity * sizeof(PriorityItem));
- pq->capacity = capacity;
- pq->size = 0;
- return pq;
-}
-
-void swap(PriorityItem* a, PriorityItem* b) {
- PriorityItem temp = *a;
- *a = *b;
- *b = temp;
-}
-
-void heapifyUp(PriorityQueue* pq, int index) {
- while (index > 0) {
- int parentIndex = (index - 1) / 2;
- if (pq->heap[parentIndex].priority <= pq->heap[index].priority) break;
- swap(&pq->heap[parentIndex], &pq->heap[index]);
- index = parentIndex;
- }
-}
-
-void heapifyDown(PriorityQueue* pq, int index) {
- while (1) {
- int leftChild = 2 * index + 1;
- int rightChild = 2 * index + 2;
- int smallest = index;
-
- if (leftChild < pq->size &&
- pq->heap[leftChild].priority < pq->heap[smallest].priority) {
- smallest = leftChild;
- }
-
- if (rightChild < pq->size &&
- pq->heap[rightChild].priority < pq->heap[smallest].priority) {
- smallest = rightChild;
- }
-
- if (smallest == index) break;
- swap(&pq->heap[index], &pq->heap[smallest]);
- index = smallest;
- }
-}
-
-void enqueue(PriorityQueue* pq, void* value, int priority) {
- if (pq->size >= pq->capacity) return; // Handle resizing in real implementation
-
- PriorityItem item = {value, priority};
- pq->heap[pq->size] = item;
- heapifyUp(pq, pq->size);
- pq->size++;
-}
-
-void* dequeue(PriorityQueue* pq) {
- if (pq->size == 0) return NULL;
-
- void* result = pq->heap[0].value;
- pq->size--;
- pq->heap[0] = pq->heap[pq->size];
- heapifyDown(pq, 0);
- return result;
-}
-
-void* peek(PriorityQueue* pq) {
- if (pq->size == 0) return NULL;
- return pq->heap[0].value;
-}
-
-int size(PriorityQueue* pq) {
- return pq->size;
-}
-
-int isEmpty(PriorityQueue* pq) {
- return pq->size == 0;
-}
-
-void destroyPriorityQueue(PriorityQueue* pq) {
- free(pq->heap);
- free(pq);
-}
-
-int main() {
- PriorityQueue* pq = createPriorityQueue(10);
-
- // In a real implementation, you would need to manage memory for the values
- char task1[] = "Task 1";
- char task2[] = "Task 2";
- char task3[] = "Task 3";
-
- enqueue(pq, task1, 3); // Lower numbers = higher priority
- enqueue(pq, task2, 1);
- enqueue(pq, task3, 2);
-
- printf("%s\\n", (char*)dequeue(pq)); // "Task 2" (highest priority)
- printf("%s\\n", (char*)peek(pq)); // "Task 3" (next highest priority)
- printf("%d\\n", size(pq)); // 2
-
- destroyPriorityQueue(pq);
- return 0;
-}`,
-
- cpp: `// Priority Queue Implementation in C++ (Min-Heap)
-#include
-#include
-#include
-
-template
-class PriorityQueue {
-private:
- struct PriorityItem {
- T value;
- int priority;
-
- bool operator<(const PriorityItem& other) const {
- return priority > other.priority; // Min-heap (lower priority numbers come first)
- }
- };
-
- std::vector heap;
-
-public:
- void enqueue(const T& value, int priority) {
- heap.push_back({value, priority});
- std::push_heap(heap.begin(), heap.end());
- }
-
- T dequeue() {
- if (isEmpty()) {
- throw std::out_of_range("Priority queue is empty");
- }
- std::pop_heap(heap.begin(), heap.end());
- T value = heap.back().value;
- heap.pop_back();
- return value;
- }
-
- const T& peek() const {
- if (isEmpty()) {
- throw std::out_of_range("Priority queue is empty");
- }
- return heap.front().value;
- }
-
- size_t size() const {
- return heap.size();
- }
-
- bool isEmpty() const {
- return heap.empty();
- }
-};
-
-int main() {
- PriorityQueue pq;
- pq.enqueue("Task 1", 3); // Lower numbers = higher priority
- pq.enqueue("Task 2", 1);
- pq.enqueue("Task 3", 2);
-
- std::cout << pq.dequeue() << std::endl; // "Task 2" (highest priority)
- std::cout << pq.peek() << std::endl; // "Task 3" (next highest priority)
- std::cout << pq.size() << std::endl; // 2
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Double Ended Queue Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/priority/content.jsx b/app/visualizer/queue/types/priority/content.jsx
deleted file mode 100755
index 134be8e73..000000000
--- a/app/visualizer/queue/types/priority/content.jsx
+++ /dev/null
@@ -1,317 +0,0 @@
-"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 paragraphs = [
- `A Priority Queue is an abstract data type where each element has a priority value, and elements are served based on priority rather than insertion order. Unlike a standard queue (FIFO), higher-priority elements are dequeued before lower-priority ones, regardless of when they were added.`,
- `The priority queue is a fundamental data structure that enables efficient management of elements based on their importance or urgency. Its ability to always provide access to the highest (or lowest) priority item makes it indispensable in algorithms where processing order significantly impacts performance or correctness. The choice of implementation (heap, BST, etc.) depends on the specific application's requirements for insertion, extraction, and auxiliary operations.`,
- ];
-
- const characteristic = [
- {
- points: "Priority-based ordering:",
- subpoints: [
- "Elements are processed by priority (highest first or lowest first)",
- ],
- },
- {
- points: "Two core operations:",
- subpoints: [
- "insert(item, priority) - Add with priority",
- "extractMax()/extractMin() - Remove highest/lowest priority item",
- ],
- },
- {
- points: "Peek operation:",
- subpoints: ["View highest/lowest priority item without removal"],
- },
- {
- points: "No FIFO guarantee:",
- subpoints: [
- "Equal priority elements may be processed in arbitrary order",
- ],
- },
- ];
-
- const implementation = [
- {
- points: "Binary Heap:",
- subpoints: [
- "Most common implementation",
- "O(log n) insert and extract",
- "O(1) peek",
- "Memory efficient",
- ],
- },
- {
- points: "Balanced Binary Search Tree:",
- subpoints: [
- "O(log n) all operations",
- "Supports more operations (like delete-by-value)",
- "Higher memory overhead",
- ],
- },
- {
- points: "Array (Unsorted):",
- subpoints: [
- "O(1) insert, O(n) extract",
- "Simple but inefficient for large datasets",
- ],
- },
- {
- points: "Fibonacci Heap:",
- subpoints: [
- "Amortized O(1) insert",
- "O(log n) extract",
- "Complex implementation",
- ],
- },
- ];
-
- const application = [
- { points: "Dijkstra's Algorithm: Finding shortest paths in graphs" },
- { points: "Huffman Coding: Data compression" },
- { points: "Operating Systems: Process scheduling" },
- { points: "Event-driven Simulation: Processing events in time order" },
- { points: "A* Search: Pathfinding in AI" },
- { points: "Bandwidth Management: Prioritizing network packets" },
- ];
-
- const special = [
- { points: "Min-Priority Queue: Extracts minimum priority first" },
- { points: "Max-Priority Queue: Extracts maximum priority first" },
- {
- points:
- "Double-Ended Priority Queue: Supports both min and max extraction",
- },
- { points: "Indexed Priority Queue: Allows priority updates by key" },
- { points: "Bounded Priority Queue: Fixed capacity with eviction policies" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is a Priority Queue? */}
-
-
-
- What is a Priority Queue?
-
-
-
-
- {/* Key Characteristics */}
-
-
-
- Key Characteristics
-
-
-
- Priority queues have these fundamental properties:
-
-
- {characteristic.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Implementation Variations */}
-
-
-
- Implementation Variations
-
-
-
- Common implementation approaches:
-
-
- {implementation.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Applications */}
-
-
-
- Applications
-
-
-
- Priority queues are used in:
-
-
- {application.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Special Cases */}
-
-
-
- Special Cases
-
-
-
- Interesting priority queue variations:
-
-
- {special.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/queue/types/priority/page.jsx b/app/visualizer/queue/types/priority/page.jsx
deleted file mode 100755
index 6e31ee3bf..000000000
--- a/app/visualizer/queue/types/priority/page.jsx
+++ /dev/null
@@ -1,123 +0,0 @@
-import Animation from "@/app/visualizer/queue/types/priority/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/queue/types/priority/content";
-import Quiz from "@/app/visualizer/queue/types/priority/quiz";
-import Code from "@/app/visualizer/queue/types/priority/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import Footer from "@/app/components/footer";
-import BackToTop from "@/app/components/ui/backtotop";
-
-export const metadata = {
- title:
- "Priority Queue Algorithm | Visual Guide with Code in JavaScript, C, Python, Java",
- description:
- "Master Priority Queue in Data Structures with easy-to-understand visualizations and complete code examples in JavaScript, C, Python, and Java. Perfect for DSA learners and coding interview prep.",
- keywords: [
- "Priority Queue",
- "Priority Queue DSA",
- "Priority Queue Data Structure",
- "Priority Queue in JavaScript",
- "Priority Queue in C",
- "Priority Queue in Python",
- "Priority Queue in Java",
- "Priority Queue Examples",
- "DSA Queue Operations",
- "Learn Priority Queue",
- "Priority Queue Code",
- "Priority Queue Visualization",
- "DSA Visualizer",
- "Priority Queue for Interviews",
- "Priority Queue Tutorial",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/queue/priorityQueue.png",
- width: 1200,
- height: 630,
- alt: "Priority Queue Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Priority Queue", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- Priority Queue
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/queue/types/priority/quiz.jsx b/app/visualizer/queue/types/priority/quiz.jsx
deleted file mode 100755
index 87cf00c50..000000000
--- a/app/visualizer/queue/types/priority/quiz.jsx
+++ /dev/null
@@ -1,384 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const QueueQuiz = () => {
- const questions = [
- {
- question: "What is the fundamental difference between a priority queue and a standard queue?",
- options: [
- "Priority queues use LIFO ordering",
- "Elements are processed based on priority rather than insertion order",
- "Priority queues can only store numeric values",
- "Standard queues are always faster"
- ],
- correctAnswer: 1,
- explanation: "Priority queues process elements by their priority value rather than following strict FIFO order like standard queues."
- },
- {
- question: "Which operation in a max-priority queue returns the highest priority element without removing it?",
- options: [
- "extractMax()",
- "insert()",
- "peek()",
- "remove()"
- ],
- correctAnswer: 2,
- explanation: "peek() allows viewing the highest priority element while leaving it in the queue."
- },
- {
- question: "What is the time complexity of insert() and extractMax() operations in a binary heap implementation?",
- options: [
- "O(1) for both",
- "O(log n) for both",
- "O(n) for insert, O(1) for extractMax",
- "O(1) for insert, O(n) for extractMax"
- ],
- correctAnswer: 1,
- explanation: "Binary heap implementations provide O(log n) time for both insertion and extraction operations."
- },
- {
- question: "Which data structure is MOST commonly used to implement a priority queue?",
- options: [
- "Linked List",
- "Hash Table",
- "Binary Heap",
- "Graph"
- ],
- correctAnswer: 2,
- explanation: "Binary heaps are the most common implementation due to their balance of efficiency and simplicity."
- },
- {
- question: "In Dijkstra's algorithm, why is a priority queue used?",
- options: [
- "To store visited nodes in FIFO order",
- "To always process the node with the current shortest path estimate",
- "To sort all nodes alphabetically",
- "To implement depth-first search"
- ],
- correctAnswer: 1,
- explanation: "The priority queue ensures the node with the smallest current distance estimate is processed next, which is crucial for Dijkstra's algorithm."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding priority queue fundamentals");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("priority queue operations");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("priority queue implementation");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("practical applications of priority queues");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Priority Queue concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Priority Queue Quiz
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? 'Finish' : 'Next'}
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length ? "Perfect Score!" :
- score >= questions.length * 0.8 ? "Excellent Work!" :
- score >= questions.length * 0.6 ? "Good Job!" :
- score >= questions.length * 0.4 ? "Keep Practicing!" : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}% correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
Question Breakdown:
- {questions.map((q, index) => (
-
-
{q.question}
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
Your answer: {answers[index] !== null ? q.options[answers[index]] : "Not answered"}
- {answers[index] !== q.correctAnswer && (
-
Correct answer: {q.options[q.correctAnswer]}
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default QueueQuiz;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/singleEnded/animation.jsx b/app/visualizer/queue/types/singleEnded/animation.jsx
deleted file mode 100755
index 5b2176d02..000000000
--- a/app/visualizer/queue/types/singleEnded/animation.jsx
+++ /dev/null
@@ -1,251 +0,0 @@
-"use client";
-import React, { useState } from "react";
-
-const SingleEndedQueueVisualizer = () => {
- const [queue, setQueue] = useState([]);
- const [inputValue, setInputValue] = useState("");
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("Queue is empty");
- const [isAnimating, setIsAnimating] = useState(false);
-
- /* ---------- helpers ---------- */
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
- const showOp = async (txt, ms = 800) => {
- setOperation(txt);
- await sleep(ms);
- setOperation(null);
- };
-
- /* ---------- enqueue (rear) ---------- */
- const enqueueRear = async () => {
- if (!inputValue.trim()) {
- setMessage("Please enter a value");
- return;
- }
- setIsAnimating(true);
- await showOp(`Enqueuing "${inputValue}" at rear …`);
- setQueue((q) => [...q, inputValue]);
- setMessage(`"${inputValue}" added to rear`);
- setInputValue("");
- setIsAnimating(false);
- };
-
- /* ---------- dequeue (front) ---------- */
- const dequeueFront = async () => {
- if (queue.length === 0) {
- setMessage("Queue is empty!");
- return;
- }
- setIsAnimating(true);
- const front = queue[0];
- await showOp(`Dequeuing "${front}" from front …`);
- setQueue((q) => q.slice(1));
- setMessage(`"${front}" removed from front`);
- setIsAnimating(false);
- };
-
- /* ---------- peek front ---------- */
- const peekFront = async () => {
- if (queue.length === 0) {
- setMessage("Queue is empty!");
- return;
- }
- setIsAnimating(true);
- setMessage(`Front element: "${queue[0]}"`);
- await sleep(1500);
- setIsAnimating(false);
- };
-
- /* ---------- peek rear ---------- */
- const peekRear = async () => {
- if (queue.length === 0) {
- setMessage("Queue is empty!");
- return;
- }
- setIsAnimating(true);
- setMessage(`Rear element: "${queue[queue.length - 1]}"`);
- await sleep(1500);
- setIsAnimating(false);
- };
-
- /* ---------- reset ---------- */
- const reset = () => {
- setQueue([]);
- setInputValue("");
- setOperation(null);
- setMessage("Queue cleared");
- };
-
- /* ---------- UI ---------- */
- return (
-
-
- Single-Ended Queue Visualiser (FIFO)
-
-
-
- {/* ----- Controls card ----- */}
-
- {/* Value input + Enqueue */}
-
- setInputValue(e.target.value)}
- placeholder="Enter value"
- className="flex-1 p-3 border dark:border-gray-700 rounded-lg dark:bg-neutral-900 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
- disabled={isAnimating}
- onKeyDown={(e) => e.key === "Enter" && enqueueRear()}
- />
-
-
- {/* Action buttons */}
-
-
- Enqueue Rear
-
-
- Dequeue Front
-
-
- Peek Front
-
-
- Peek Rear
-
-
- Reset
-
-
-
- {/* Status banners */}
-
- {operation && (
-
- )}
- {message && (
-
- {message}
-
- )}
-
-
-
- {/* ----- Visualisation card (hidden when empty) ----- */}
- {queue.length > 0 && (
-
-
Queue Visualisation
-
-
- {/* Front pointer */}
-
-
- {/* Elements */}
-
- {queue.map((item, index) => (
-
- ))}
-
-
- {/* Rear pointer */}
-
-
-
- )}
-
-
- );
-};
-
-export default SingleEndedQueueVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/singleEnded/codeBlock.jsx b/app/visualizer/queue/types/singleEnded/codeBlock.jsx
deleted file mode 100755
index cfce87f2a..000000000
--- a/app/visualizer/queue/types/singleEnded/codeBlock.jsx
+++ /dev/null
@@ -1,571 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Queue Implementation (JavaScript)
-class Queue {
- constructor(size = 10) {
- this.items = new Array(size);
- this.front = 0;
- this.rear = -1;
- this.size = 0;
- this.capacity = size;
- }
-
- // Add to rear (enqueue)
- enqueue(item) {
- if (this.isFull()) {
- console.log("Queue Overflow");
- return;
- }
- this.rear = (this.rear + 1) % this.capacity;
- this.items[this.rear] = item;
- this.size++;
- }
-
- // Remove from front (dequeue)
- dequeue() {
- if (this.isEmpty()) {
- console.log("Queue Underflow");
- return undefined;
- }
- const item = this.items[this.front];
- this.front = (this.front + 1) % this.capacity;
- this.size--;
- return item;
- }
-
- // Peek front element
- peek() {
- if (this.isEmpty()) {
- console.log("Queue is empty");
- return undefined;
- }
- return this.items[this.front];
- }
-
- // Check if empty
- isEmpty() {
- return this.size === 0;
- }
-
- // Check if full
- isFull() {
- return this.size === this.capacity;
- }
-
- // Get current size
- getSize() {
- return this.size;
- }
-
- // Print queue contents
- print() {
- if (this.isEmpty()) {
- console.log("Queue is empty");
- return;
- }
- console.log("Queue contents (front to rear):");
- for (let i = 0; i < this.size; i++) {
- const index = (this.front + i) % this.capacity;
- console.log(this.items[index]);
- }
- }
-}
-
-// Usage
-const queue = new Queue(5);
-queue.enqueue(10);
-queue.enqueue(20);
-queue.enqueue(30);
-console.log("Front element:", queue.peek()); // 10
-console.log("Queue size:", queue.getSize()); // 3
-queue.print();
-queue.dequeue();
-console.log("After dequeue, front element:", queue.peek()); // 20`,
-
- python: `# Queue Implementation (Python)
-class Queue:
- def __init__(self, size=10):
- self.items = [None] * size
- self.front = 0
- self.rear = -1
- self.size = 0
- self.capacity = size
-
- def enqueue(self, item):
- if self.is_full():
- print("Queue Overflow")
- return
- self.rear = (self.rear + 1) % self.capacity
- self.items[self.rear] = item
- self.size += 1
-
- def dequeue(self):
- if self.is_empty():
- print("Queue Underflow")
- return None
- item = self.items[self.front]
- self.front = (self.front + 1) % self.capacity
- self.size -= 1
- return item
-
- def peek(self):
- if self.is_empty():
- print("Queue is empty")
- return None
- return self.items[self.front]
-
- def is_empty(self):
- return self.size == 0
-
- def is_full(self):
- return self.size == self.capacity
-
- def get_size(self):
- return self.size
-
- def print_queue(self):
- if self.is_empty():
- print("Queue is empty")
- return
- print("Queue contents (front to rear):")
- for i in range(self.size):
- index = (self.front + i) % self.capacity
- print(self.items[index])
-
-# Usage
-queue = Queue(5)
-queue.enqueue(10)
-queue.enqueue(20)
-queue.enqueue(30)
-print("Front element:", queue.peek()) # 10
-print("Queue size:", queue.get_size()) # 3
-queue.print_queue()
-queue.dequeue()
-print("After dequeue, front element:", queue.peek()) # 20`,
-
- java: `// Queue Implementation (Java)
-public class ArrayQueue {
- private int[] items;
- private int front;
- private int rear;
- private int size;
- private int capacity;
-
- public ArrayQueue(int size) {
- items = new int[size];
- front = 0;
- rear = -1;
- size = 0;
- capacity = size;
- }
-
- public void enqueue(int item) {
- if (isFull()) {
- System.out.println("Queue Overflow");
- return;
- }
- rear = (rear + 1) % capacity;
- items[rear] = item;
- size++;
- }
-
- public int dequeue() {
- if (isEmpty()) {
- System.out.println("Queue Underflow");
- return -1;
- }
- int item = items[front];
- front = (front + 1) % capacity;
- size--;
- return item;
- }
-
- public int peek() {
- if (isEmpty()) {
- System.out.println("Queue is empty");
- return -1;
- }
- return items[front];
- }
-
- public boolean isEmpty() {
- return size == 0;
- }
-
- public boolean isFull() {
- return size == capacity;
- }
-
- public int getSize() {
- return size;
- }
-
- public void print() {
- if (isEmpty()) {
- System.out.println("Queue is empty");
- return;
- }
- System.out.println("Queue contents (front to rear):");
- for (int i = 0; i < size; i++) {
- int index = (front + i) % capacity;
- System.out.println(items[index]);
- }
- }
-
- public static void main(String[] args) {
- ArrayQueue queue = new ArrayQueue(5);
- queue.enqueue(10);
- queue.enqueue(20);
- queue.enqueue(30);
- System.out.println("Front element: " + queue.peek()); // 10
- System.out.println("Queue size: " + queue.getSize()); // 3
- queue.print();
- queue.dequeue();
- System.out.println("After dequeue, front element: " + queue.peek()); // 20
- }
-}`,
-
- c: `// Queue Implementation (C)
-#include
-#include
-#include
-
-typedef struct {
- int *items;
- int front;
- int rear;
- int size;
- int capacity;
-} Queue;
-
-void initialize(Queue *q, int capacity) {
- q->items = (int*)malloc(capacity * sizeof(int));
- q->front = 0;
- q->rear = -1;
- q->size = 0;
- q->capacity = capacity;
-}
-
-bool isFull(Queue *q) {
- return q->size == q->capacity;
-}
-
-bool isEmpty(Queue *q) {
- return q->size == 0;
-}
-
-void enqueue(Queue *q, int item) {
- if (isFull(q)) {
- printf("Queue Overflow\n");
- return;
- }
- q->rear = (q->rear + 1) % q->capacity;
- q->items[q->rear] = item;
- q->size++;
-}
-
-int dequeue(Queue *q) {
- if (isEmpty(q)) {
- printf("Queue Underflow\n");
- return -1;
- }
- int item = q->items[q->front];
- q->front = (q->front + 1) % q->capacity;
- q->size--;
- return item;
-}
-
-int peek(Queue *q) {
- if (isEmpty(q)) {
- printf("Queue is empty\n");
- return -1;
- }
- return q->items[q->front];
-}
-
-int size(Queue *q) {
- return q->size;
-}
-
-void print(Queue *q) {
- if (isEmpty(q)) {
- printf("Queue is empty\n");
- return;
- }
- printf("Queue contents (front to rear):\n");
- for (int i = 0; i < q->size; i++) {
- int index = (q->front + i) % q->capacity;
- printf("%d\n", q->items[index]);
- }
-}
-
-void destroy(Queue *q) {
- free(q->items);
-}
-
-int main() {
- Queue queue;
- initialize(&queue, 5);
-
- enqueue(&queue, 10);
- enqueue(&queue, 20);
- enqueue(&queue, 30);
- printf("Front element: %d\n", peek(&queue)); // 10
- printf("Queue size: %d\n", size(&queue)); // 3
- print(&queue);
- dequeue(&queue);
- printf("After dequeue, front element: %d\n", peek(&queue)); // 20
-
- destroy(&queue);
- return 0;
-}`,
-
- cpp: `// Queue Implementation (C++)
-#include
-using namespace std;
-
-class Queue {
-private:
- int *items;
- int front;
- int rear;
- int size;
- int capacity;
-
-public:
- Queue(int size) {
- items = new int[size];
- front = 0;
- rear = -1;
- size = 0;
- capacity = size;
- }
-
- ~Queue() {
- delete[] items;
- }
-
- void enqueue(int item) {
- if (isFull()) {
- cout << "Queue Overflow" << endl;
- return;
- }
- rear = (rear + 1) % capacity;
- items[rear] = item;
- size++;
- }
-
- int dequeue() {
- if (isEmpty()) {
- cout << "Queue Underflow" << endl;
- return -1;
- }
- int item = items[front];
- front = (front + 1) % capacity;
- size--;
- return item;
- }
-
- int peek() {
- if (isEmpty()) {
- cout << "Queue is empty" << endl;
- return -1;
- }
- return items[front];
- }
-
- bool isEmpty() {
- return size == 0;
- }
-
- bool isFull() {
- return size == capacity;
- }
-
- int getSize() {
- return size;
- }
-
- void print() {
- if (isEmpty()) {
- cout << "Queue is empty" << endl;
- return;
- }
- cout << "Queue contents (front to rear):" << endl;
- for (int i = 0; i < size; i++) {
- int index = (front + i) % capacity;
- cout << items[index] << endl;
- }
- }
-};
-
-int main() {
- Queue queue(5);
- queue.enqueue(10);
- queue.enqueue(20);
- queue.enqueue(30);
- cout << "Front element: " << queue.peek() << endl; // 10
- cout << "Queue size: " << queue.getSize() << endl; // 3
- queue.print();
- queue.dequeue();
- cout << "After dequeue, front element: " << queue.peek() << endl; // 20
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Single Ended Queue Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/queue/types/singleEnded/content.jsx b/app/visualizer/queue/types/singleEnded/content.jsx
deleted file mode 100755
index b6c5cd166..000000000
--- a/app/visualizer/queue/types/singleEnded/content.jsx
+++ /dev/null
@@ -1,352 +0,0 @@
-"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 paragraphs = [
- `A single-ended queue (often just called a queue) is a linear data structure that follows the FIFO (First-In-First-Out) principle. Elements are added (enqueued) at the rear and removed (dequeued) from the front, maintaining strict ordering.`,
- `The single-ended queue is a fundamental data structure in computer science, providing predictable ordering that's essential for many algorithms and system design patterns where processing order matters.`,
- ];
-
- const characteristics = [
- {
- points: "Two ends:",
- subpoints: ["Front (for removal) and rear (for insertion)"],
- },
- {
- points: "Basic Operations:",
- subpoints: [
- "enqueue() - Add to rear",
- "dequeue() - Remove from front",
- "peek() - View front element",
- "isEmpty() - Check if empty",
- ],
- },
- {
- points: "Fixed Order:",
- subpoints: ["Elements are processed in exact arrival sequence"],
- },
- ];
-
- const example = [
- { points: "enqueue(10): [10]" },
- { points: "enqueue(20): [10, 20]" },
- { points: "enqueue(30): [10, 20, 30]" },
- { points: "dequeue(): Returns 10 → [20, 30]" },
- { points: "peek(): Returns 20 → [20, 30] (unchanged)" },
- ];
-
- const implementation = [
- {
- points: "Array-Based:",
- subpoints: [
- "Fixed or dynamic array",
- "Need to handle wrap-around for circular queues",
- ],
- },
- {
- points: "Linked List:",
- subpoints: [
- "Head pointer as front",
- "Tail pointer as rear",
- "Efficient O(1) operations",
- ],
- },
- ];
-
- const complexity = [
- { points: "enqueue(): O(1)" },
- { points: "dequeue(): O(1)" },
- { points: "peek(): O(1)" },
- { points: "isEmpty(): O(1)" },
- ];
-
- const application = [
- { points: "CPU task scheduling" },
- { points: "Print job management" },
- { points: "Breadth-First Search (BFS) algorithms" },
- { points: "Buffering data streams" },
- { points: "Handling requests in web servers" },
- ];
-
- const differences = [
- {
- points: "Single-ended only allows insertion at rear and removal at front",
- },
- { points: "Double-ended (deque) allows insertion/removal at both ends" },
- { points: "Single-ended has stricter FIFO enforcement" },
- { points: "Single-ended is simpler to implement" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is a Single-Ended Queue? */}
-
-
-
- What is a Single-Ended Queue?
-
-
-
-
- {/* Key Characteristics */}
-
-
-
- Key Characteristics
-
-
-
- Single-ended queues have these fundamental properties:
-
-
- {characteristics.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Visual Example */}
-
-
-
- Visual Example
-
-
-
- Operation sequence on an initially empty queue:
-
-
- {example.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Implementation Variations */}
-
-
-
- Implementation Variations
-
-
-
- Common implementation approaches:
-
-
- {implementation.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {complexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
-
-
- {/* Applications */}
-
-
-
- Applications
-
-
-
- Single-ended queues are used in:
-
-
- {application.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Comparison with Double-Ended Queue */}
-
-
-
- Comparison with Double-Ended Queue
-
-
-
- Key differences:
-
-
- {differences.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/queue/types/singleEnded/page.jsx b/app/visualizer/queue/types/singleEnded/page.jsx
deleted file mode 100755
index 8369134bb..000000000
--- a/app/visualizer/queue/types/singleEnded/page.jsx
+++ /dev/null
@@ -1,118 +0,0 @@
-import Animation from "@/app/visualizer/queue/types/singleEnded/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/queue/types/singleEnded/content";
-import Quiz from "@/app/visualizer/queue/types/singleEnded/quiz";
-import Code from "@/app/visualizer/queue/types/singleEnded/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Footer from '@/app/components/footer';
-import BackToTop from '@/app/components/ui/backtotop';
-
-export const metadata = {
- title: "Single Ended Queue | Learn with JS, C, Python, Java Code",
- description:
- "Understand Single Ended Queue in Data Structures with animations and full code examples in JavaScript, C, Python, and Java. Ideal for beginners learning queue operations and preparing for interviews.",
- keywords: [
- "Single Ended Queue",
- "Single Ended Queue DSA",
- "Queue Data Structure",
- "Single Ended Queue in JavaScript",
- "Single Ended Queue in C",
- "Single Ended Queue in Python",
- "Single Ended Queue in Java",
- "DSA Queue Operations",
- "Learn Queue DSA",
- "Queue Code Examples",
- "DSA Visualizer",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/queue/singleEnded.png",
- width: 1200,
- height: 630,
- alt: "Single Ended Queue Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Queue : Single Ended", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/queue/types/singleEnded/quiz.jsx b/app/visualizer/queue/types/singleEnded/quiz.jsx
deleted file mode 100755
index fe85cb74a..000000000
--- a/app/visualizer/queue/types/singleEnded/quiz.jsx
+++ /dev/null
@@ -1,384 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const QueueQuiz = () => {
- const questions = [
- {
- question: "What principle does a single-ended queue follow?",
- options: [
- "LIFO (Last-In-First-Out)",
- "FIFO (First-In-First-Out)",
- "Priority-Based",
- "Random Access"
- ],
- correctAnswer: 1,
- explanation: "Single-ended queues strictly follow the First-In-First-Out (FIFO) principle."
- },
- {
- question: "Where are elements added in a single-ended queue?",
- options: [
- "At the front",
- "At the rear",
- "At any position",
- "In the middle"
- ],
- correctAnswer: 1,
- explanation: "Elements are always added (enqueued) at the rear of the queue."
- },
- {
- question: "What operation removes an element from a single-ended queue?",
- options: [
- "enqueue()",
- "dequeue()",
- "peek()",
- "isEmpty()"
- ],
- correctAnswer: 1,
- explanation: "dequeue() removes and returns the element from the front of the queue."
- },
- {
- question: "What would the queue [10, 20, 30] look like after dequeue()?",
- options: [
- "[10, 20]",
- "[20, 30]",
- "[10, 20, 30]",
- "[30, 20]"
- ],
- correctAnswer: 1,
- explanation: "dequeue() removes the front element (10), leaving [20, 30]."
- },
- {
- question: "What is the time complexity of enqueue() and dequeue() operations?",
- options: [
- "O(1) for both",
- "O(n) for both",
- "O(1) for enqueue, O(n) for dequeue",
- "O(n) for enqueue, O(1) for dequeue"
- ],
- correctAnswer: 0,
- explanation: "Both operations are O(1) in a properly implemented queue."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding FIFO principle");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("queue insertion point");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("queue removal operations");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("queue state after operations");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Single-Ended Queue concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Single-Ended Queue Quiz
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? 'Finish' : 'Next'}
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length ? "Perfect Score!" :
- score >= questions.length * 0.8 ? "Excellent Work!" :
- score >= questions.length * 0.6 ? "Good Job!" :
- score >= questions.length * 0.4 ? "Keep Practicing!" : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}% correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
Question Breakdown:
- {questions.map((q, index) => (
-
-
{q.question}
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
Your answer: {answers[index] !== null ? q.options[answers[index]] : "Not answered"}
- {answers[index] !== q.correctAnswer && (
-
Correct answer: {q.options[q.correctAnswer]}
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default QueueQuiz;
\ No newline at end of file
diff --git a/app/visualizer/searching/binarysearch/animation.jsx b/app/visualizer/searching/binarysearch/animation.jsx
deleted file mode 100755
index 8e973ab78..000000000
--- a/app/visualizer/searching/binarysearch/animation.jsx
+++ /dev/null
@@ -1,338 +0,0 @@
-"use client";
-import React, { useState, useEffect, useRef } from "react";
-import { gsap } from "gsap";
-import ResetButton from "@/app/components/ui/resetButton";
-import GoButton from "@/app/components/ui/goButton";
-
-const BinarySearch = () => {
- const [arrayElements, setArrayElements] = useState("");
- const [target, setTarget] = useState("");
- const [array, setArray] = useState([]);
- const [i, setI] = useState(-1);
- const [j, setJ] = useState(-1);
- const [mid, setMid] = useState(-1);
- const [foundIndex, setFoundIndex] = useState(-1);
- const [isAnimating, setIsAnimating] = useState(false);
- const [message, setMessage] = useState("");
- const [speed, setSpeed] = useState(1);
- const animationRef = useRef(null);
- const searchStateRef = useRef({ l: 0, h: 0, arr: [], targetValue: 0 });
- const formRef = useRef(null);
- const elementRefs = useRef([]);
-
- const handleReset = () => {
- clearTimeout(animationRef.current);
- setArray([]);
- setI(-1);
- setJ(-1);
- setMid(-1);
- setFoundIndex(-1);
- setMessage("");
- setIsAnimating(false);
- setArrayElements("");
- setTarget("");
- if (formRef.current) {
- formRef.current.reset();
- }
- // Reset GSAP animations
- elementRefs.current.forEach((ref) => {
- gsap.to(ref, {
- backgroundColor: "#E5E7EB",
- borderColor: "#D1D5DB",
- duration: 0,
- });
- });
- };
-
- const generateRandomArray = () => {
- if (isAnimating) return;
- const size = Math.floor(Math.random() * 4) + 2; // Random size between 2 and 5
- const elements = Array.from({ length: size }, () =>
- Math.floor(Math.random() * 100)
- ).sort((a, b) => a - b);
- setArrayElements(elements.join(", "));
- };
-
- const handleGo = (e) => {
- e.preventDefault();
- handleReset();
-
- if (!arrayElements || !target) {
- setMessage("Please fill in all fields.");
- return;
- }
-
- const elements = arrayElements.split(",").map((el) => parseInt(el.trim()));
- const targetValue = parseInt(target);
-
- if (elements.some(isNaN) || isNaN(targetValue)) {
- setMessage("Invalid array elements or target.");
- return;
- }
-
- const isSorted = elements.every(
- (el, idx) => idx === 0 || el >= elements[idx - 1]
- );
- if (!isSorted) {
- setMessage("Array must be sorted in ascending order.");
- return;
- }
-
- setArray(elements);
- setI(0);
- setJ(elements.length - 1);
- setMid(-1);
- setFoundIndex(-1);
- setMessage("");
- setIsAnimating(true);
-
- searchStateRef.current = {
- l: 0,
- h: elements.length - 1,
- arr: elements,
- targetValue: targetValue,
- };
-
- animateBinarySearch();
- };
-
- const animateBinarySearch = () => {
- const { l, h, arr, targetValue } = searchStateRef.current;
- const delay = 1500 / speed;
-
- if (l > h) {
- setMessage(`Element ${targetValue} not found in the array.`);
- setIsAnimating(false);
- return;
- }
-
- const m = Math.floor((l + h) / 2);
- setI(l);
- setJ(h);
- setMid(m);
-
- // GSAP animations for i, j, and mid
- elementRefs.current.forEach((ref, index) => {
- if (index === m) {
- gsap.to(ref, {
- backgroundColor: "#EAB308",
- borderColor: "#A16207",
- duration: 0.3,
- });
- } else if (index >= l && index <= h) {
- gsap.to(ref, {
- backgroundColor: "#93C5FD",
- borderColor: "#3B82F6",
- duration: 0.3,
- });
- } else {
- gsap.to(ref, {
- backgroundColor: "#E5E7EB",
- borderColor: "#D1D5DB",
- duration: 0.3,
- });
- }
- });
-
- animationRef.current = setTimeout(() => {
- if (arr[m] === targetValue) {
- setFoundIndex(m);
- setMessage(`Element ${targetValue} found at index ${m}!`);
- setIsAnimating(false);
- gsap.to(elementRefs.current[m], {
- backgroundColor: "#22C55E",
- borderColor: "#15803D",
- duration: 0.3,
- });
- } else if (arr[m] < targetValue) {
- searchStateRef.current.l = m + 1;
- animateBinarySearch();
- } else {
- searchStateRef.current.h = m - 1;
- animateBinarySearch();
- }
- }, delay);
- };
-
- const increaseSpeed = () => {
- setSpeed((prev) => Math.min(prev + 0.5, 5));
- };
-
- const decreaseSpeed = () => {
- setSpeed((prev) => Math.max(prev - 0.5, 0.5));
- };
-
- useEffect(() => {
- return () => {
- clearTimeout(animationRef.current);
- };
- }, []);
-
- return (
-
-
- Visualize how Binary Search efficiently finds an element in a sorted
- array.
-
-
-
-
- {message && (
-
- )}
-
- {array.length > 0 && (
-
-
- Array Visualization
-
-
- {array.map((element, index) => {
- const labels = [];
- if (index === i) labels.push("i");
- if (index === mid) labels.push("Mid");
- if (index === j) labels.push("j");
-
- return (
-
-
(elementRefs.current[index] = el)}
- className={`w-16 h-16 flex items-center justify-center rounded-lg border-2 transition-all duration-300 text-lg font-medium ${
- index === foundIndex
- ? "bg-green-500 dark:bg-green-600 border-green-700 dark:border-green-400 text-gray-800 dark:text-white"
- : index === mid
- ? "bg-yellow-500 dark:bg-yellow-600 border-yellow-700 dark:border-yellow-400 text-gray-800 dark:text-white"
- : index >= i && index <= j
- ? "bg-blue-300 dark:bg-blue-700 border-blue-500 dark:border-blue-400 text-gray-800 dark:text-white"
- : "bg-gray-200 dark:bg-gray-900 border-gray-300 dark:border-gray-600 text-gray-800 dark:text-white"
- }`}
- >
- {element}
-
-
- {labels.map((label, idx) => (
-
{label}
- ))}
-
-
- );
- })}
-
-
-
-
- )}
-
- );
-};
-
-export default BinarySearch;
diff --git a/app/visualizer/searching/binarysearch/codeBlock.jsx b/app/visualizer/searching/binarysearch/codeBlock.jsx
deleted file mode 100755
index e19c1991e..000000000
--- a/app/visualizer/searching/binarysearch/codeBlock.jsx
+++ /dev/null
@@ -1,323 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState('javascript');
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: 'javascript', name: 'JavaScript' },
- { id: 'python', name: 'Python' },
- { id: 'java', name: 'Java' },
- { id: 'c', name: 'C' },
- { id: 'cpp', name: 'C++' }
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error('Failed to copy text: ', err);
- }
- };
-
- const codeExamples = {
- javascript: `// Binary Search in JavaScript (Iterative)
-function binarySearch(arr, target) {
- let left = 0;
- let right = arr.length - 1;
-
- while (left <= right) {
- const mid = Math.floor((left + right) / 2);
-
- if (arr[mid] === target) {
- return mid; // Target found
- } else if (arr[mid] < target) {
- left = mid + 1; // Search right half
- } else {
- right = mid - 1; // Search left half
- }
- }
-
- return -1; // Target not found
-}
-
-// Usage example
-const sortedNumbers = [10, 20, 30, 40, 50, 60, 70];
-const target = 40;
-const result = binarySearch(sortedNumbers, target);
-
-if (result !== -1) {
- console.log(\`Element found at index: \${result}\`);
-} else {
- console.log("Element not found");
-}`,
-
- python: `# Binary Search in Python (Iterative)
-def binary_search(arr, target):
- left, right = 0, len(arr) - 1
-
- while left <= right:
- mid = (left + right) // 2
-
- if arr[mid] == target:
- return mid # Target found
- elif arr[mid] < target:
- left = mid + 1 # Search right half
- else:
- right = mid - 1 # Search left half
-
- return -1 # Target not found
-
-# Usage example
-sorted_numbers = [10, 20, 30, 40, 50, 60, 70]
-target = 40
-result = binary_search(sorted_numbers, target)
-
-if result != -1:
- print(f"Element found at index: {result}")
-else:
- print("Element not found")`,
-
- java: `// Binary Search in Java (Iterative)
-public class BinarySearch {
- public static int binarySearch(int[] arr, int target) {
- int left = 0;
- int right = arr.length - 1;
-
- while (left <= right) {
- int mid = left + (right - left) / 2;
-
- if (arr[mid] == target) {
- return mid; // Target found
- } else if (arr[mid] < target) {
- left = mid + 1; // Search right half
- } else {
- right = mid - 1; // Search left half
- }
- }
-
- return -1; // Target not found
- }
-
- public static void main(String[] args) {
- int[] sortedNumbers = {10, 20, 30, 40, 50, 60, 70};
- int target = 40;
- int result = binarySearch(sortedNumbers, target);
-
- if (result != -1) {
- System.out.println("Element found at index: " + result);
- } else {
- System.out.println("Element not found");
- }
- }
-}`,
-
- c: `// Binary Search in C (Iterative)
-#include
-
-int binarySearch(int arr[], int size, int target) {
- int left = 0;
- int right = size - 1;
-
- while (left <= right) {
- int mid = left + (right - left) / 2;
-
- if (arr[mid] == target) {
- return mid; // Target found
- } else if (arr[mid] < target) {
- left = mid + 1; // Search right half
- } else {
- right = mid - 1; // Search left half
- }
- }
-
- return -1; // Target not found
-}
-
-int main() {
- int sortedNumbers[] = {10, 20, 30, 40, 50, 60, 70};
- int size = sizeof(sortedNumbers) / sizeof(sortedNumbers[0]);
- int target = 40;
-
- int result = binarySearch(sortedNumbers, size, target);
-
- if (result != -1) {
- printf("Element found at index: %d\\n", result);
- } else {
- printf("Element not found\\n");
- }
-
- return 0;
-}`,
-
- cpp: `// Binary Search in C++ (Iterative)
-#include
-#include
-using namespace std;
-
-int binarySearch(const vector& arr, int target) {
- int left = 0;
- int right = arr.size() - 1;
-
- while (left <= right) {
- int mid = left + (right - left) / 2;
-
- if (arr[mid] == target) {
- return mid; // Target found
- } else if (arr[mid] < target) {
- left = mid + 1; // Search right half
- } else {
- right = mid - 1; // Search left half
- }
- }
-
- return -1; // Target not found
-}
-
-int main() {
- vector sortedNumbers = {10, 20, 30, 40, 50, 60, 70};
- int target = 40;
-
- int result = binarySearch(sortedNumbers, target);
-
- if (result != -1) {
- cout << "Element found at index: " << result << endl;
- } else {
- cout << "Element not found" << endl;
- }
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Binary Search Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? 'bg-blue-500 text-white shadow-md'
- : 'bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600'
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/searching/binarysearch/content.jsx b/app/visualizer/searching/binarysearch/content.jsx
deleted file mode 100755
index 567ffc66d..000000000
--- a/app/visualizer/searching/binarysearch/content.jsx
+++ /dev/null
@@ -1,249 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 paragraphs = [
- `Binary Search is an efficient algorithm for finding an item in a sorted list. It works by repeatedly dividing the search interval in half. If the target value is less than the middle element, the search continues in the lower half. Otherwise, it continues in the upper half. This process repeats until the value is found.`,
- `If the number is not in the list (e.g., searching for 8), the search ends when the subarray becomes empty.`,
- `Binary Search is extremely fast for large datasets but requires the list to be sorted beforehand. It's much more efficient than Linear Search for sorted data.`,
- ];
-
- const searching = [
- { points: "First middle is 7 (too high)" },
- { points: "Search left half: [1, 3, 5]" },
- { points: "New middle is 3 (too low)" },
- { points: "Search right portion: [5]" },
- { points: "Found at position 2" },
- ];
-
- const steps = [
- { points: "Start with the entire sorted array" },
- {
- points: "Compare the target with the middle element:",
- subpoints: [
- "If equal, return the position",
- "If target is smaller, search the left half",
- "If target is larger, search the right half",
- ],
- },
- { points: "Repeat until the element is found or the subarray is empty" },
- { points: 'If not found, return "Not Found"' },
- ];
-
- const complexity = [
- { points: "Best Case: Target is the middle element → O(1)." },
- {
- points:
- "Worst Case: Element not present → O(log n) (halves search space each step).",
- },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is Binary Search */}
-
-
-
- What is Binary Search?
-
-
-
-
- {/* How Does It Work */}
-
-
-
- How Does It Work?
-
-
-
- Imagine you have a sorted list of numbers: [1, 3, 5, 7, 9, 11, 13]
- and you want to find the number 7.
-
-
-
-
- Compare 7 with the middle element (7). It matches! Return the
- position.
-
-
- If searching for 5:
-
- {searching.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
-
- {paragraphs[1]}
-
-
-
-
- {/* Algorithm Steps */}
-
-
-
- Algorithm Steps
-
-
-
- {steps.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {complexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
-
- 1}
- averageCase={(n) => Math.log2(n)}
- worstCase={(n) => Math.log2(n)}
- maxN={25}
- />
-
-
-
-
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/searching/binarysearch/page.jsx b/app/visualizer/searching/binarysearch/page.jsx
deleted file mode 100755
index ea0eb0611..000000000
--- a/app/visualizer/searching/binarysearch/page.jsx
+++ /dev/null
@@ -1,125 +0,0 @@
-import Animation from "@/app/visualizer/searching/binarysearch/animation";
-import Navbar from "@/app/components/navbarinner";
-import Footer from "@/app/components/footer";
-import BackToTop from "@/app/components/ui/backtotop";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import Code from "@/app/visualizer/searching/binarysearch/codeBlock";
-import Quiz from "@/app/visualizer/searching/binarysearch/quiz";
-import Content from '@/app/visualizer/searching/binarysearch/content';
-import Breadcrumbs from "@/app/components/ui/Breadcrumbs";
-import ArticleActions from "@/app/components/ui/ArticleActions";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-
-export const metadata = {
- title: "Binary Search Algorithm | Step-by-Step Animation",
- description:
- "Visualize the Binary Search algorithm with intuitive step-by-step animations, code examples in JavaScript, C, Python, and Java, and an interactive Binary Search Quiz to test your knowledge. Perfect for DSA preparation and beginners learning efficient search algorithms.",
- keywords: [
- "Binary Search Visualizer",
- "Binary Search Visualization",
- "Binary Search Animation",
- "Learn Binary Search",
- "Binary Search for Beginners",
- "Binary Search Step-by-Step",
- "Visualize Binary Search Algorithm",
- "DSA Binary Search",
- "Binary Search Explanation",
- "Binary Search Visualization Tool",
- "Efficient Searching Algorithms",
- "Binary Search in JavaScript",
- "Binary Search in C",
- "Binary Search in Python",
- "Binary Search in Java",
- "Binary Search Code Examples",
- "Binary Search Quiz",
- "Interactive Binary Search Quiz",
- "DSA Quiz",
- "Quiz for Binary Search",
- "Learn DSA with Quizzes",
- "Binary Search Practice",
- "Test Your Binary Search Skills",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/searching/binarySearch.png",
- width: 1200,
- height: 630,
- alt: "Binary Search Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Binary Search", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- Binary Search
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/searching/binarysearch/quiz.jsx b/app/visualizer/searching/binarysearch/quiz.jsx
deleted file mode 100755
index 38001bb53..000000000
--- a/app/visualizer/searching/binarysearch/quiz.jsx
+++ /dev/null
@@ -1,384 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const BinarySearchQuiz = () => {
- const questions = [
- {
- question: "What is the primary requirement for binary search to work?",
- options: [
- "The list must be unsorted",
- "The list must be sorted",
- "The list must contain only numbers",
- "The list must be small in size"
- ],
- correctAnswer: 1,
- explanation: "Binary search requires the list to be sorted beforehand because it relies on comparing the target value to the middle element to determine which half of the list to search next."
- },
- {
- question: "What is the time complexity of binary search in the worst case?",
- options: [
- "O(1)",
- "O(log n)",
- "O(n)",
- "O(n²)"
- ],
- correctAnswer: 1,
- explanation: "In the worst case (when the target is not present), binary search has a time complexity of O(log n) because it halves the search space with each comparison."
- },
- {
- question: "In the array [1, 3, 5, 7, 9, 11, 13], how many comparisons are needed to find the number 5?",
- options: [
- "1",
- "2",
- "3",
- "4"
- ],
- correctAnswer: 2,
- explanation: "First comparison: middle is 7 (too high). Second comparison: new middle is 3 (too low). Third comparison: finds 5."
- },
- {
- question: "What is the best-case scenario for binary search?",
- options: [
- "Target is at the beginning of the list",
- "Target is at the end of the list",
- "Target is the middle element",
- "Target is not in the list"
- ],
- correctAnswer: 2,
- explanation: "The best case occurs when the target is the middle element of the array, requiring only one comparison (O(1))."
- },
- {
- question: "What would binary search return if the target value is not in the list?",
- options: [
- "The first element",
- "The last element",
- "An error message",
- "A 'not found' indication"
- ],
- correctAnswer: 3,
- explanation: "When the target isn't found, binary search typically returns a special value (like -1 or 'not found') to indicate this."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the requirements for binary search");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting comparisons in binary search");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("performance characteristics");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("edge case handling");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all binary search concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Binary Search Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? 'Finish' : 'Next'}
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length ? "Perfect Score!" :
- score >= questions.length * 0.8 ? "Excellent Work!" :
- score >= questions.length * 0.6 ? "Good Job!" :
- score >= questions.length * 0.4 ? "Keep Practicing!" : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}% correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
Question Breakdown:
- {questions.map((q, index) => (
-
-
{q.question}
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
Your answer: {answers[index] !== null ? q.options[answers[index]] : "Not answered"}
- {answers[index] !== q.correctAnswer && (
-
Correct answer: {q.options[q.correctAnswer]}
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default BinarySearchQuiz;
\ No newline at end of file
diff --git a/app/visualizer/searching/linearsearch/animation.jsx b/app/visualizer/searching/linearsearch/animation.jsx
deleted file mode 100755
index 76544cee1..000000000
--- a/app/visualizer/searching/linearsearch/animation.jsx
+++ /dev/null
@@ -1,268 +0,0 @@
-"use client";
-import React, { useState, useEffect, useRef } from "react";
-import { gsap } from "gsap";
-import ResetButton from "@/app/components/ui/resetButton";
-import GoButton from "@/app/components/ui/goButton";
-
-const LinearSearch = () => {
- const [arrayElements, setArrayElements] = useState("");
- const [target, setTarget] = useState("");
- const [array, setArray] = useState([]);
- const [currentIndex, setCurrentIndex] = useState(-1);
- const [foundIndex, setFoundIndex] = useState(-1);
- const [isAnimating, setIsAnimating] = useState(false);
- const [message, setMessage] = useState("");
- const [speed] = useState(1);
- const animationRef = useRef(null);
- const formRef = useRef(null);
- const elementRefs = useRef([]);
-
- // Clean up animation on unmount
- useEffect(() => {
- return () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
- }, []);
-
- const handleReset = () => {
- setArray([]);
- setCurrentIndex(-1);
- setFoundIndex(-1);
- setMessage("");
- setIsAnimating(false);
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- animationRef.current = null;
- }
- setArrayElements("");
- setTarget("");
- if (formRef.current) {
- formRef.current.reset();
- }
- // Reset GSAP animations
- elementRefs.current.forEach((ref) => {
- gsap.to(ref, {
- backgroundColor: "#E5E7EB",
- borderColor: "#D1D5DB",
- duration: 0,
- });
- });
- };
-
- const generateRandomArray = () => {
- if (isAnimating) return;
- const size = Math.floor(Math.random() * 4) + 2; // Random size between 2 and 5
- const elements = Array.from({ length: size }, () =>
- Math.floor(Math.random() * 100)
- );
- setArrayElements(elements.join(", "));
- };
-
- const handleGo = (e) => {
- e.preventDefault();
- handleReset();
-
- if (!arrayElements || !target) {
- setMessage("Please fill in all fields.");
- return;
- }
-
- const elements = arrayElements.split(",").map((el) => parseInt(el.trim()));
- const targetValue = parseInt(target);
-
- if (elements.some(isNaN) || isNaN(targetValue)) {
- setMessage("Invalid array elements or target.");
- return;
- }
-
- setArray(elements);
- setIsAnimating(true);
- animateLinearSearch(elements, targetValue);
- };
-
- const animateLinearSearch = (arr, targetValue) => {
- let index = 0;
-
- const step = () => {
- if (index < arr.length) {
- setCurrentIndex(index);
-
- // GSAP animation for current element
- gsap.to(elementRefs.current[index], {
- backgroundColor: "#EAB308",
- borderColor: "#A16207",
- duration: 0.3,
- onComplete: () => {
- if (arr[index] === targetValue) {
- finishSearch(index, targetValue);
- } else if (index === arr.length - 1) {
- finishSearch(-1, targetValue);
- } else {
- // Reset previous element's style
- gsap.to(elementRefs.current[index], {
- backgroundColor: "#E5E7EB",
- borderColor: "#D1D5DB",
- duration: 0.3,
- });
- index++;
- animationRef.current = setTimeout(step, 1000 / speed);
- }
- },
- });
- }
- };
-
- step();
- };
-
- const finishSearch = (foundIdx, targetValue) => {
- setIsAnimating(false);
-
- if (foundIdx !== -1) {
- setFoundIndex(foundIdx);
- setMessage(`Element ${targetValue} found at index ${foundIdx}!`);
- gsap.to(elementRefs.current[foundIdx], {
- backgroundColor: "#22C55E",
- borderColor: "#15803D",
- duration: 0.3,
- });
- } else {
- setMessage(`Element ${targetValue} not found in the array.`);
- }
- };
-
- return (
-
-
- Visualize how Linear Search works by sequentially checking each element
- in an array.
-
-
- {/* Input Form */}
-
-
- {/* Output Screen */}
- {message && (
-
- )}
-
- {/* Visualization */}
- {array.length > 0 && (
-
-
- Array Visualization
-
-
- {array.map((element, index) => (
-
(elementRefs.current[index] = el)}
- className={`relative w-20 h-20 flex flex-col items-center justify-center rounded-lg border-2 transition-all duration-300 ${
- currentIndex === index && foundIndex === -1
- ? "bg-yellow-600 dark:bg-yellow-600 border-yellow-700 dark:border-yellow-400 text-gray-800 dark:text-white"
- : foundIndex === index
- ? "bg-green-500 dark:bg-green-600 border-green-700 dark:border-green-400 text-gray-800 dark:text-white"
- : "bg-gray-200 dark:bg-gray-900 border-gray-300 dark:border-gray-600 text-gray-800 dark:text-white"
- }`}
- >
- {element}
-
- [{index}]
-
-
- ))}
-
-
- {/* Legend */}
-
-
- )}
-
- );
-};
-
-export default LinearSearch;
diff --git a/app/visualizer/searching/linearsearch/codeBlock.jsx b/app/visualizer/searching/linearsearch/codeBlock.jsx
deleted file mode 100755
index 380a67675..000000000
--- a/app/visualizer/searching/linearsearch/codeBlock.jsx
+++ /dev/null
@@ -1,274 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState('javascript');
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: 'javascript', name: 'JavaScript' },
- { id: 'python', name: 'Python' },
- { id: 'java', name: 'Java' },
- { id: 'c', name: 'C' },
- { id: 'cpp', name: 'C++' }
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error('Failed to copy text: ', err);
- }
- };
-
- const codeExamples = {
- javascript: `// Linear Search in JavaScript
-function linearSearch(arr, target) {
- for (let i = 0; i < arr.length; i++) {
- if (arr[i] === target) {
- return i; // Return index if found
- }
- }
- return -1; // Return -1 if not found
-}
-
-// Usage example
-const numbers = [10, 20, 30, 40, 50];
-const target = 30;
-const result = linearSearch(numbers, target);
-
-if (result !== -1) {
- console.log(\`Element found at index: \${result}\`);
-} else {
- console.log("Element not found");
-}`,
-
- python: `# Linear Search in Python
-def linear_search(arr, target):
- for i in range(len(arr)):
- if arr[i] == target:
- return i # Return index if found
- return -1 # Return -1 if not found
-
-# Usage example
-numbers = [10, 20, 30, 40, 50]
-target = 30
-result = linear_search(numbers, target)
-
-if result != -1:
- print(f"Element found at index: {result}")
-else:
- print("Element not found")`,
-
- java: `// Linear Search in Java
-public class LinearSearch {
- public static int linearSearch(int[] arr, int target) {
- for (int i = 0; i < arr.length; i++) {
- if (arr[i] == target) {
- return i; // Return index if found
- }
- }
- return -1; // Return -1 if not found
- }
-
- public static void main(String[] args) {
- int[] numbers = {10, 20, 30, 40, 50};
- int target = 30;
- int result = linearSearch(numbers, target);
-
- if (result != -1) {
- System.out.println("Element found at index: " + result);
- } else {
- System.out.println("Element not found");
- }
- }
-}`,
-
- c: `// Linear Search in C
-#include
-
-int linearSearch(int arr[], int size, int target) {
- for (int i = 0; i < size; i++) {
- if (arr[i] == target) {
- return i; // Return index if found
- }
- }
- return -1; // Return -1 if not found
-}
-
-int main() {
- int numbers[] = {10, 20, 30, 40, 50};
- int size = sizeof(numbers) / sizeof(numbers[0]);
- int target = 30;
-
- int result = linearSearch(numbers, size, target);
-
- if (result != -1) {
- printf("Element found at index: %d\\n", result);
- } else {
- printf("Element not found\\n");
- }
-
- return 0;
-}`,
-
- cpp: `// Linear Search in C++
-#include
-#include
-using namespace std;
-
-int linearSearch(const vector& arr, int target) {
- for (int i = 0; i < arr.size(); i++) {
- if (arr[i] == target) {
- return i; // Return index if found
- }
- }
- return -1; // Return -1 if not found
-}
-
-int main() {
- vector numbers = {10, 20, 30, 40, 50};
- int target = 30;
-
- int result = linearSearch(numbers, target);
-
- if (result != -1) {
- cout << "Element found at index: " << result << endl;
- } else {
- cout << "Element not found" << endl;
- }
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Linear Search Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? 'bg-blue-500 text-white shadow-md'
- : 'bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600'
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/searching/linearsearch/content.jsx b/app/visualizer/searching/linearsearch/content.jsx
deleted file mode 100755
index c8a6e88d8..000000000
--- a/app/visualizer/searching/linearsearch/content.jsx
+++ /dev/null
@@ -1,239 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 paragraphs = [
- `Linear Search is a simple method to find a particular value in a list. It checks each element one by one from the start until it finds the target value. If the value is found, it returns its position; otherwise, it says the value is not present.`,
- `Imagine you have a list of numbers: [5, 3, 8, 1, 9] and you want to find the number 8.`,
- `If the number is not in the list (e.g., searching for 10), the search ends without success.`,
- `Linear Search is easy to understand but can be slow for large lists compared to faster methods like Binary Search.`,
- ];
-
- const working = [
- { points: "Start from the first number (5). Is 5 equal to 8? No." },
- { points: "Move to the next number (3). Is 3 equal to 8? No." },
- {
- points:
- "Move to the next number (8). Is 8 equal to 8? Yes! Stop here. The position is 2 (or 3 if counting starts from 1).",
- },
- ];
-
- const complexity = [
- { data: "Best Case: Target is the first element → O(1)" },
- {
- data: "Worst Case: Target is last or not present → O(n) (checks all elements)",
- },
- ];
-
- const algorithm = [
- { points: "Start from the first element." },
- {
- points: "Compare the current element with the target value.",
- subpoints: [
- "If they match, return the position.",
- "If not, move to the next element.",
- ],
- },
- { points: "Repeat until the end of the list." },
- { points: 'If the element is not found, return "Not Found".' },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is Linear Search */}
-
-
-
- What is Linear Search?
-
-
-
-
- {/* How Does It Work */}
-
-
-
- How Does It Work?
-
-
-
- {paragraphs[1]}
-
-
-
- {working.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
- {paragraphs[2]}
-
-
-
-
- {/* Algorithm Steps */}
-
-
-
- Algorithm Steps
-
-
-
- {algorithm.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {complexity.map((item, index) => (
-
-
- {item.data.split(":")[0]}:
-
- {item.data.split(":")[1]}
-
- ))}
-
-
-
- 1}
- averageCase={(n) => n}
- worstCase={(n) => n}
- maxN={25}
- />
-
-
-
-
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
\ No newline at end of file
diff --git a/app/visualizer/searching/linearsearch/page.jsx b/app/visualizer/searching/linearsearch/page.jsx
deleted file mode 100755
index 0fea1a8ff..000000000
--- a/app/visualizer/searching/linearsearch/page.jsx
+++ /dev/null
@@ -1,125 +0,0 @@
-import LinearSearchAnimation from "@/app/visualizer/searching/linearsearch/animation";
-import Navbar from "@/app/components/navbarinner";
-import BackToTopButton from "@/app/components/ui/backtotop";
-import Footer from "@/app/components/footer";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import Code from "@/app/visualizer/searching/linearsearch/codeBlock";
-import Quiz from "@/app/visualizer/searching/linearsearch/quiz";
-import Content from "@/app/visualizer/searching/linearsearch/content";
-import Breadcrumbs from "@/app/components/ui/Breadcrumbs";
-import ArticleActions from "@/app/components/ui/ArticleActions";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-
-export const metadata = {
- title: "Linear Search Algorithm | Step-by-Step Animation",
- description:
- "Visualize the Linear Search algorithm with step-by-step animations, code examples in JavaScript, C, Python, and Java, and a Linear Search Quiz to test your understanding. Build a strong foundation in DSA through interactive learning.",
- keywords: [
- "Linear Search Visualizer",
- "Linear Search Visualization",
- "Linear Search Animation",
- "Learn Linear Search",
- "Linear Search for Beginners",
- "Step-by-Step Linear Search",
- "Visualize Linear Search Algorithm",
- "DSA Linear Search",
- "Algorithm Visualizer",
- "DSA Searching Algorithms",
- "Search Algorithms DSA",
- "Linear Search in JavaScript",
- "Linear Search in C",
- "Linear Search in Python",
- "Linear Search in Java",
- "Linear Search Code Examples",
- "Linear Search Quiz",
- "Interactive Linear Search Quiz",
- "DSA Quiz",
- "Quiz for Searching Algorithms",
- "Learn DSA with Quizzes",
- "Linear Search Practice",
- "Test Your Linear Search Skills",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/searching/linearSearch.png",
- width: 1200,
- height: 630,
- alt: "Linear Search Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Linear Search", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- Linear Search
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/searching/linearsearch/quiz.jsx b/app/visualizer/searching/linearsearch/quiz.jsx
deleted file mode 100755
index a7ff93d99..000000000
--- a/app/visualizer/searching/linearsearch/quiz.jsx
+++ /dev/null
@@ -1,385 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const LinearSearchQuiz = () => {
- const questions = [
- {
- question: "What is the basic principle of linear search?",
- options: [
- "Dividing the list in half repeatedly",
- "Checking each element one by one from the start",
- "Sorting the list first then searching",
- "Starting from the middle of the list"
- ],
- correctAnswer: 1,
- explanation: "Linear search works by checking each element sequentially from the beginning until it finds the target value."
- },
- {
- question: "What is the time complexity of linear search in the worst case?",
- options: [
- "O(1)",
- "O(log n)",
- "O(n)",
- "O(n²)"
- ],
- correctAnswer: 2,
- explanation: "In the worst case (when the target is last or not present), linear search checks all n elements, resulting in O(n) complexity."
- },
- {
- question: "In the array [5, 3, 8, 1, 9], how many comparisons are needed to find the number 1?",
- options: [
- "1",
- "2",
- "3",
- "4"
- ],
- correctAnswer: 3,
- explanation: "The search checks 5 (1st), 3 (2nd), 8 (3rd), and finally finds 1 on the 4th comparison."
- },
- {
- question: "When would linear search perform at its best?",
- options: [
- "When the target is at the end of the list",
- "When the target is at the middle of the list",
- "When the target is at the beginning of the list",
- "When the list is sorted"
- ],
- correctAnswer: 2,
- explanation: "Linear search performs best (O(1)) when the target is the first element, as it only needs one comparison."
- },
- {
- question: "What would a linear search algorithm return if the target value is not in the list?",
- options: [
- "The first element",
- "The last element",
- "An error message",
- "A 'not found' indication"
- ],
- correctAnswer: 3,
- explanation: "When the target isn't found, linear search typically returns a special value (like -1 or 'not found') to indicate this."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of linear search");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting comparisons in linear search");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("performance characteristics");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("edge case handling");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all linear search concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Linear Search Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? 'Finish' : 'Next'}
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length ? "Perfect Score!" :
- score >= questions.length * 0.8 ? "Excellent Work!" :
- score >= questions.length * 0.6 ? "Good Job!" :
- score >= questions.length * 0.4 ? "Keep Practicing!" : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}% correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
Question Breakdown:
- {questions.map((q, index) => (
-
-
{q.question}
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
Your answer: {answers[index] !== null ? q.options[answers[index]] : "Not answered"}
- {answers[index] !== q.correctAnswer && (
-
Correct answer: {q.options[q.correctAnswer]}
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default LinearSearchQuiz;
\ No newline at end of file
diff --git a/app/visualizer/sorting/bubblesort/animation.jsx b/app/visualizer/sorting/bubblesort/animation.jsx
deleted file mode 100755
index f273b4a2b..000000000
--- a/app/visualizer/sorting/bubblesort/animation.jsx
+++ /dev/null
@@ -1,239 +0,0 @@
-"use client";
-import React, { useState, useRef, useEffect } from "react";
-import { gsap } from "gsap";
-import ArrayGenerator from "@/app/components/ui/randomArray";
-import CustomArrayInput from "@/app/components/ui/customArrayInput";
-
-const BubbleSortVisualizer = () => {
- const [array, setArray] = useState([]);
- const [sorting, setSorting] = useState(false);
- const [sorted, setSorted] = useState(false);
- const [speed, setSpeed] = useState(1);
- const [comparisons, setComparisons] = useState(0);
- const [swaps, setSwaps] = useState(0);
- const [currentIndices, setCurrentIndices] = useState({ i: -1, j: -1 });
- const animationRef = useRef(null);
-
- // Handle array generation from child component
- const handleArrayGenerated = (newArray) => {
- setArray(newArray);
- setSorted(false);
- resetStats();
- };
-
- // Reset all stats and state
- const resetStats = () => {
- setComparisons(0);
- setSwaps(0);
- setCurrentIndices({ i: -1, j: -1 });
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
-
- // Optimized bubble sort
- const bubbleSort = async () => {
- if (sorted || sorting || array.length === 0) return;
-
- setSorting(true);
- let arr = [...array];
- let n = arr.length;
- let tempSwaps = 0;
- let tempComparisons = 0;
-
- for (let i = 0; i < n - 1; i++) {
- let swapped = false;
-
- for (let j = 0; j < n - i - 1; j++) {
- setCurrentIndices({ i: j, j: j + 1 });
- tempComparisons++;
- setComparisons(tempComparisons);
-
- await new Promise(
- (resolve) =>
- (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
-
- if (arr[j] > arr[j + 1]) {
- const bars = document.querySelectorAll(".bar");
- const bar1 = bars[j];
- const bar2 = bars[j + 1];
- if (bar1 && bar2) {
- await gsap.to(bar1, {
- x: "+=40",
- duration: 0.3,
- yoyo: true,
- });
- await gsap.to(bar2, {
- x: "-=40",
- duration: 0.3,
- yoyo: true,
- });
- await gsap.to([bar1, bar2], {
- x: "0",
- duration: 0,
- });
- }
-
- [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
- swapped = true;
- tempSwaps++;
- setSwaps(tempSwaps);
- setArray([...arr]);
-
- await new Promise(
- (resolve) =>
- (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
- }
- }
-
- if (!swapped) break;
- }
-
- setSorting(false);
- setSorted(true);
- };
-
- // Reset everything
- const reset = () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- setArray([]);
- setSorting(false);
- setSorted(false);
- resetStats();
- };
-
- // Clean up on unmount
- useEffect(() => {
- return () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
- }, []);
-
- return (
-
-
- Watch Bubble Sort in action as it repeatedly swaps adjacent elements to
- sort the array step by step.
-
-
-
- {/* Controls */}
-
-
-
-
-
{
- setArray(arr);
- setSorted(false);
- resetStats();
- }}
- disabled={sorting}
- className="w-full"
- />
-
-
-
- {sorting ? "Sorting..." : "Start Bubble Sort"}
-
-
- Reset All
-
-
-
-
- {/* Speed controls */}
-
-
- Speed:
-
- setSpeed(parseFloat(e.target.value))}
- className="w-24 sm:w-32"
- disabled={sorting}
- />
-
- {speed}x
-
-
-
- {/* Stats */}
-
-
-
Comparisons:
-
{comparisons}
-
-
-
-
-
- {/* Visualization */}
-
-
- Array Visualization
-
- {array.length > 0 ? (
-
- {array.map((value, index) => {
- const isComparing =
- index === currentIndices.i || index === currentIndices.j;
- const isSorted = sorted;
-
- return (
-
-
- {value}
-
-
- {index === currentIndices.i && "i"}
- {index === currentIndices.j && "j"}
-
-
- );
- })}
-
- ) : (
-
- {sorting ? "Sorting..." : "Generate or enter an array to begin"}
-
- )}
-
-
-
- );
-};
-
-export default BubbleSortVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/sorting/bubblesort/codeBlock.jsx b/app/visualizer/sorting/bubblesort/codeBlock.jsx
deleted file mode 100755
index 7a65e0ecd..000000000
--- a/app/visualizer/sorting/bubblesort/codeBlock.jsx
+++ /dev/null
@@ -1,324 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState('javascript');
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: 'javascript', name: 'JavaScript' },
- { id: 'python', name: 'Python' },
- { id: 'java', name: 'Java' },
- { id: 'c', name: 'C' },
- { id: 'cpp', name: 'C++' }
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error('Failed to copy text: ', err);
- }
- };
-
- const codeExamples = {
- javascript: `// Bubble Sort in JavaScript
-function bubbleSort(arr) {
- let n = arr.length;
-
- // Outer loop for passes
- for (let i = 0; i < n - 1; i++) {
- // Inner loop for comparisons
- for (let j = 0; j < n - i - 1; j++) {
- // Swap if current element is greater than next
- if (arr[j] > arr[j + 1]) {
- // ES6 destructuring assignment for swap
- [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
- }
- }
- }
- return arr;
-}
-
-// Usage example
-const unsortedArray = [64, 34, 25, 12, 22, 11, 90];
-console.log("Unsorted array:", unsortedArray);
-const sortedArray = bubbleSort(unsortedArray);
-console.log("Sorted array:", sortedArray);`,
-
- python: `# Bubble Sort in Python
-def bubble_sort(arr):
- n = len(arr)
-
- # Outer loop for passes
- for i in range(n - 1):
- # Inner loop for comparisons
- for j in range(n - i - 1):
- # Swap if current element is greater than next
- if arr[j] > arr[j + 1]:
- # Python tuple unpacking for swap
- arr[j], arr[j + 1] = arr[j + 1], arr[j]
- return arr
-
-# Usage example
-unsorted_array = [64, 34, 25, 12, 22, 11, 90]
-print("Unsorted array:", unsorted_array)
-sorted_array = bubble_sort(unsorted_array)
-print("Sorted array:", sorted_array)`,
-
- java: `// Bubble Sort in Java
-public class BubbleSort {
- public static void bubbleSort(int[] arr) {
- int n = arr.length;
-
- // Outer loop for passes
- for (int i = 0; i < n - 1; i++) {
- // Inner loop for comparisons
- for (int j = 0; j < n - i - 1; j++) {
- // Swap if current element is greater than next
- if (arr[j] > arr[j + 1]) {
- // Traditional swap using temp variable
- int temp = arr[j];
- arr[j] = arr[j + 1];
- arr[j + 1] = temp;
- }
- }
- }
- }
-
- public static void main(String[] args) {
- int[] unsortedArray = {64, 34, 25, 12, 22, 11, 90};
- System.out.print("Unsorted array: ");
- printArray(unsortedArray);
-
- bubbleSort(unsortedArray);
-
- System.out.print("Sorted array: ");
- printArray(unsortedArray);
- }
-
- // Helper method to print array
- private static void printArray(int[] arr) {
- for (int num : arr) {
- System.out.print(num + " ");
- }
- System.out.println();
- }
-}`,
-
- c: `// Bubble Sort in C
-#include
-
-void bubbleSort(int arr[], int n) {
- // Outer loop for passes
- for (int i = 0; i < n - 1; i++) {
- // Inner loop for comparisons
- for (int j = 0; j < n - i - 1; j++) {
- // Swap if current element is greater than next
- if (arr[j] > arr[j + 1]) {
- // Traditional swap using temp variable
- int temp = arr[j];
- arr[j] = arr[j + 1];
- arr[j + 1] = temp;
- }
- }
- }
-}
-
-// Function to print an array
-void printArray(int arr[], int size) {
- for (int i = 0; i < size; i++) {
- printf("%d ", arr[i]);
- }
- printf("\\n");
-}
-
-int main() {
- int unsortedArray[] = {64, 34, 25, 12, 22, 11, 90};
- int n = sizeof(unsortedArray) / sizeof(unsortedArray[0]);
-
- printf("Unsorted array: ");
- printArray(unsortedArray, n);
-
- bubbleSort(unsortedArray, n);
-
- printf("Sorted array: ");
- printArray(unsortedArray, n);
-
- return 0;
-}`,
-
- cpp: `// Bubble Sort in C++
-#include
-#include
-using namespace std;
-
-void bubbleSort(vector& arr) {
- int n = arr.size();
-
- // Outer loop for passes
- for (int i = 0; i < n - 1; i++) {
- // Inner loop for comparisons
- for (int j = 0; j < n - i - 1; j++) {
- // Swap if current element is greater than next
- if (arr[j] > arr[j + 1]) {
- // Using std::swap for cleaner code
- swap(arr[j], arr[j + 1]);
- }
- }
- }
-}
-
-// Function to print an array
-void printArray(const vector& arr) {
- for (int num : arr) {
- cout << num << " ";
- }
- cout << endl;
-}
-
-int main() {
- vector unsortedArray = {64, 34, 25, 12, 22, 11, 90};
-
- cout << "Unsorted array: ";
- printArray(unsortedArray);
-
- bubbleSort(unsortedArray);
-
- cout << "Sorted array: ";
- printArray(unsortedArray);
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Bubble Sort Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? 'bg-blue-500 text-white shadow-md'
- : 'bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600'
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/sorting/bubblesort/content.jsx b/app/visualizer/sorting/bubblesort/content.jsx
deleted file mode 100755
index c0de71553..000000000
--- a/app/visualizer/sorting/bubblesort/content.jsx
+++ /dev/null
@@ -1,288 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 = [
- `Bubble Sort is a simple sorting algorithm that repeatedly steps through the list, compares adjacent elements and swaps them if they are in the wrong order. The pass through the list is repeated until the list is sorted. It gets its name because smaller elements "bubble" to the top of the list.`,
- `Bubble Sort is an in-place sorting algorithm, meaning it requires only O(1) additional space (for temporary storage during swaps).`,
- `Bubble Sort is simple to understand and implement but inefficient for large datasets. It's mainly used for educational purposes to introduce sorting algorithms. In practice, more efficient algorithms like QuickSort or MergeSort are preferred.`,
- ];
-
- const working = [
- {
- passes: "First Pass:",
- points: [
- "(5, 1) → Swap → [1, 5, 4, 2, 8]",
- "(5, 4) → Swap → [1, 4, 5, 2, 8]",
- "(5, 2) → Swap → [1, 4, 2, 5, 8]",
- "(5, 8) → No swap",
- ],
- },
- {
- passes: "Second Pass:",
- points: [
- "(1, 4) → No swap",
- "(4, 2) → Swap → [1, 2, 4, 5, 8]",
- "(4, 5) → No swap",
- ],
- },
- { passes: "Third Pass:", points: ["No swaps needed → List is sorted"] },
- ];
-
- const algorithm = [
- { points: "Start with an unsorted array" },
- { points: "Set a flag to track if any swaps occur" },
- {
- points: "For each pair of adjacent elements:",
- subpoints: [
- "Compare the two elements",
- "If they are in the wrong order, swap them",
- "Set the swap flag to true",
- ],
- },
- {
- points:
- "Repeat the process until a complete pass is made without any swaps",
- },
- { points: "The array is now sorted" },
- ];
-
- const complexity = [
- {
- points:
- "Best Case: Array is already sorted → O(n) (only one pass needed).",
- },
- { points: "Average Case: Randomly ordered array → O(n²)." },
- { points: "Worst Case: Array is sorted in reverse order → O(n²)." },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is Bubble Sort */}
-
-
-
- What is Bubble Sort?
-
-
-
-
- {/* How Does It Work */}
-
-
-
- How Does It Work?
-
-
-
- Imagine you have an unsorted list of numbers: [5, 1, 4, 2, 8]
-
-
-
- {working.map((items, index) => (
-
- {items.passes}
- {items.points && (
-
- {items.points.map((subitems, subindex) => (
-
- {subitems}
-
- ))}
-
- )}
-
- ))}
-
-
-
- The algorithm stops when a complete pass is made without any
- swaps.
-
-
-
-
- {/* Algorithm Steps */}
-
-
-
- Algorithm Steps
-
-
-
- {algorithm.map((items, index) => (
-
- {items.points}
- {items.subpoints && (
-
- {items.subpoints.map((subitems, subindex) => (
-
- {subitems}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {complexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
-
-
- 1}
- averageCase={(n) => n * n}
- worstCase={(n) => n * n}
- maxN={25}
- />
-
-
-
- {/* Space Complexity */}
-
-
-
- Space Complexity
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/sorting/bubblesort/page.jsx b/app/visualizer/sorting/bubblesort/page.jsx
deleted file mode 100755
index be3579a90..000000000
--- a/app/visualizer/sorting/bubblesort/page.jsx
+++ /dev/null
@@ -1,133 +0,0 @@
-import Animation from "@/app/visualizer/sorting/bubblesort/animation";
-import Navbar from "@/app/components/navbarinner";
-import BackToTopButton from "@/app/components/ui/backtotop";
-import Footer from "@/app/components/footer";
-import Breadcrumbs from "@/app/components/ui/Breadcrumbs";
-import ArticleActions from "@/app/components/ui/ArticleActions";
-import Content from "@/app/visualizer/sorting/bubblesort/content";
-import Quiz from "@/app/visualizer/sorting/bubblesort/quiz";
-import Code from "@/app/visualizer/sorting/bubblesort/codeBlock";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-
-export const metadata = {
- title: "Bubble Sort Algorithm | Step-by-Step Animation",
- description:
- "Visualize Bubble Sort in action with interactive animations, code examples in JavaScript, C, Python, and Java, and test your understanding with a dedicated Bubble Sort quiz. Learn how Bubble Sort works through comparisons and swaps in an easy-to-understand format.",
- keywords: [
- "Bubble Sort Visualizer",
- "Bubble Sort Animation",
- "Bubble Sort Algorithm",
- "Bubble Sort Quiz",
- "Sorting Algorithm Quiz",
- "Sorting Algorithm Visualization",
- "DSA Bubble Sort",
- "Learn Bubble Sort",
- "Sorting for Beginners",
- "Step by Step Bubble Sort",
- "Interactive Sorting Tool",
- "Bubble Sort in JavaScript",
- "Bubble Sort in C",
- "Bubble Sort in Python",
- "Bubble Sort in Java",
- "Bubble Sort Code Examples",
- "Practice Bubble Sort",
- "DSA Bubble Sort Quiz",
- "Interactive DSA Quiz",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/sorting/bubbleSort.png",
- width: 1200,
- height: 630,
- alt: "Bubble Sort Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Bubble Sort", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/sorting/bubblesort/quiz.jsx b/app/visualizer/sorting/bubblesort/quiz.jsx
deleted file mode 100755
index 635d980f6..000000000
--- a/app/visualizer/sorting/bubblesort/quiz.jsx
+++ /dev/null
@@ -1,448 +0,0 @@
-"use client";
-import React, { useState } from "react";
-import {
- FaCheck,
- FaTimes,
- FaArrowRight,
- FaArrowLeft,
- FaInfoCircle,
- FaRedo,
- FaTrophy,
- FaStar,
- FaAward,
-} from "react-icons/fa";
-import { motion, AnimatePresence } from "framer-motion";
-
-const BubbleSortQuiz = () => {
- const questions = [
- {
- question: "What is the basic principle of Bubble Sort?",
- options: [
- "Dividing the list into smaller sublists",
- "Repeatedly swapping adjacent elements if they are in the wrong order",
- "Selecting the smallest element and moving it to the front",
- "Merging two sorted lists into one",
- ],
- correctAnswer: 1,
- explanation:
- "Bubble Sort works by repeatedly stepping through the list, comparing adjacent elements and swapping them if they are in the wrong order.",
- },
- {
- question: "What is the time complexity of Bubble Sort in the worst case?",
- options: ["O(n)", "O(n log n)", "O(n²)", "O(1)"],
- correctAnswer: 2,
- explanation:
- "In the worst case (when the list is sorted in reverse order), Bubble Sort requires O(n²) comparisons and swaps.",
- },
- {
- question:
- "In the array [5, 1, 4, 2, 8], how many swaps occur during the first pass of Bubble Sort?",
- options: ["1", "2", "3", "4"],
- correctAnswer: 2,
- explanation:
- "First pass swaps (5,1), (5,4), and (5,2) - totaling 3 swaps. The pair (5,8) doesn't need swapping.",
- },
- {
- question: "When would Bubble Sort perform at its best?",
- options: [
- "When the array is in random order",
- "When the array is sorted in reverse order",
- "When the array is already sorted",
- "When the array contains duplicate values",
- ],
- correctAnswer: 2,
- explanation:
- "Bubble Sort performs best (O(n)) when the array is already sorted, as it only needs one pass through the array without any swaps.",
- },
- {
- question: "What is the space complexity of Bubble Sort?",
- options: ["O(n)", "O(n log n)", "O(n²)", "O(1)"],
- correctAnswer: 3,
- explanation:
- "Bubble Sort is an in-place algorithm that only requires O(1) additional space for temporary storage during swaps.",
- },
- {
- question:
- "How can you optimize Bubble Sort to stop early if the array becomes sorted?",
- options: [
- "By counting the number of swaps",
- "By using a flag to check if any swaps occurred in a pass",
- "By reducing the array size after each pass",
- "By sorting the array in both directions",
- ],
- correctAnswer: 1,
- explanation:
- "Using a flag to track if any swaps occurred during a pass allows the algorithm to terminate early if the array is already sorted.",
- },
- {
- question:
- "Why is Bubble Sort rarely used in practice for large datasets?",
- options: [
- "Because it's too complex to implement",
- "Because it's not a stable sorting algorithm",
- "Because of its O(n²) time complexity for average cases",
- "Because it requires O(n) additional space",
- ],
- correctAnswer: 2,
- explanation:
- "While simple to implement, Bubble Sort's O(n²) time complexity makes it inefficient for large datasets compared to algorithms like QuickSort or MergeSort.",
- },
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Bubble Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Bubble Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("performance characteristics");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("optimization techniques");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(
- ", "
- )}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Bubble Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Bubble Sort Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default BubbleSortQuiz;
\ No newline at end of file
diff --git a/app/visualizer/sorting/insertionsort/animation.jsx b/app/visualizer/sorting/insertionsort/animation.jsx
deleted file mode 100755
index a72f2e156..000000000
--- a/app/visualizer/sorting/insertionsort/animation.jsx
+++ /dev/null
@@ -1,323 +0,0 @@
-"use client";
-import React, { useState, useRef, useEffect } from "react";
-import { gsap } from "gsap";
-import RandomArray from "@/app/components/ui/randomArray";
-import CustomArrayInput from "@/app/components/ui/customArrayInput";
-
-const InsertionSortVisualizer = () => {
- const [array, setArray] = useState([]);
- const [sorting, setSorting] = useState(false);
- const [sorted, setSorted] = useState(false);
- const [speed, setSpeed] = useState(1);
- const [comparisons, setComparisons] = useState(0);
- const [swaps, setSwaps] = useState(0);
- const [currentIndices, setCurrentIndices] = useState({
- current: -1, // The element being inserted
- comparing: -1, // The element being compared against
- sortedUpTo: -1, // Up to which index is sorted
- });
- const animationRef = useRef(null);
- const barRefs = useRef([]);
-
- // Handle array generation from RandomArray component
- const handleRandomArray = (newArray) => {
- setArray(newArray);
- setSorted(false);
- resetStats();
- };
-
- // Handle custom array from CustomArrayInput component
- const handleCustomArray = (newArray) => {
- setArray(newArray);
- setSorted(false);
- resetStats();
- };
-
- // Reset all stats and state
- const resetStats = () => {
- setComparisons(0);
- setSwaps(0);
- setCurrentIndices({ current: -1, comparing: -1, sortedUpTo: -1 });
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
-
- // Insertion sort algorithm
- const insertionSort = async () => {
- if (sorted || sorting || array.length === 0) return;
-
- // Normalize all bars: Reset x-position before rendering starts
- barRefs.current.forEach((bar) => {
- if (bar) gsap.set(bar, { x: 0, y: 0 });
- });
-
- setSorting(true);
- let arr = [...array];
- let n = arr.length;
-
- // The first element is considered sorted
- setCurrentIndices({
- current: 1,
- comparing: 0,
- sortedUpTo: 0,
- });
-
- for (let i = 1; i < n; i++) {
- let current = arr[i];
- let j = i - 1;
-
- setCurrentIndices({
- current: i,
- comparing: j,
- sortedUpTo: i - 1,
- });
-
- await new Promise(
- (resolve) => (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
-
- while (j >= 0 && arr[j] > current) {
- setComparisons((prev) => prev + 1);
- arr[j + 1] = arr[j];
-
- // Animate only the current bar with vertical and horizontal movement
- const movingBar = barRefs.current[j + 1];
- if (movingBar) {
- await gsap.to(movingBar, { y: -20, duration: 0.2 });
- await gsap.to(movingBar, {
- x: "+=70",
- duration: 0.3,
- ease: "power2.inOut",
- });
- await gsap.to(movingBar, { y: 0, duration: 0.2 });
- gsap.set(movingBar, { clearProps: "transform" });
- }
-
- setSwaps((prev) => prev + 1);
- j--;
-
- setCurrentIndices({
- current: i,
- comparing: j,
- sortedUpTo: i - 1,
- });
-
- setArray([...arr]);
- await new Promise(
- (resolve) =>
- (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
- }
-
- arr[j + 1] = current;
-
- // Animate the insertion of the current element
- const insertBar = barRefs.current[i];
- if (insertBar) {
- const moveX = (j + 1 - i) * 70;
- await gsap.to(insertBar, { y: -20, duration: 0.2 });
- await gsap.to(insertBar, {
- x: moveX,
- duration: 0.3,
- ease: "power2.inOut",
- });
- await gsap.to(insertBar, { y: 0, duration: 0.2 });
- gsap.set(insertBar, { clearProps: "transform" });
- }
-
- setArray([...arr]);
-
- setCurrentIndices({
- current: i + 1,
- comparing: j,
- sortedUpTo: i,
- });
-
- await new Promise(
- (resolve) => (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
- }
-
- setArray([...arr]);
- setSorting(false);
- setSorted(true);
- setCurrentIndices({
- current: -1,
- comparing: -1,
- sortedUpTo: n - 1,
- });
- };
-
- // Reset everything
- const reset = () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- setArray([]);
- setSorting(false);
- setSorted(false);
- resetStats();
- };
-
- // Clean up on unmount
- useEffect(() => {
- return () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
- }, []);
-
- return (
-
-
- Visualize how Insertion Sort builds the final sorted array.
-
-
-
- {/* Controls */}
-
-
-
-
-
-
-
-
- {sorting ? "Sorting..." : "Start Insertion Sort"}
-
-
- Reset All
-
-
-
-
- {/* Speed controls */}
-
- Speed:
- setSpeed(parseFloat(e.target.value))}
- className="w-32"
- disabled={sorting}
- />
- {speed}x
-
-
- {/* Stats */}
-
-
-
Comparisons:
-
{comparisons}
-
-
-
-
-
- {/* Visualization */}
-
-
Array Visualization
- {array.length > 0 ? (
-
- {array.map((value, index) => {
- const isCurrent = index === currentIndices.current;
- const isComparing = index === currentIndices.comparing;
- const isSorted = index <= currentIndices.sortedUpTo || sorted;
-
- return (
-
-
(barRefs.current[index] = el)}
- className={`bar w-16 h-16 flex items-center justify-center rounded-lg border-2 transition-all duration-300 text-lg font-medium
- ${
- isCurrent
- ? "bg-yellow-400 dark:bg-yellow-400 border-yellow-600 dark:border-yellow-600 dark:text-gray-800"
- : isComparing
- ? "bg-red-400 dark:bg-red-400 border-red-600 dark:border-red-600 dark:text-gray-800"
- : isSorted
- ? "bg-green-400 dark:bg-green-400 border-green-600 dark:border-green-600 dark:text-gray-800"
- : "bg-blue-400 dark:bg-blue-400 border-blue-600 dark:border-blue-600 dark:text-gray-800"
- }`}
- >
- {value}
-
-
- {index}
- {isCurrent && " (current)"}
- {isComparing && " (comparing)"}
- {isSorted && !isCurrent && !isComparing && " (sorted)"}
-
-
- );
- })}
-
- ) : (
-
- {sorting ? "Sorting..." : "Generate or enter an array to begin"}
-
- )}
-
- {/* Algorithm Steps Visualization */}
- {sorting && array.length > 0 && (
-
-
Current Step
-
-
-
-
Current element being inserted
-
-
-
-
Element being compared
-
-
-
-
-
-
- {currentIndices.current >= 0 ? (
- <>
- Inserting{" "}
-
- array[{currentIndices.current}] ={" "}
- {array[currentIndices.current]}
- {" "}
- into the sorted portion (indexes 0 to{" "}
- {currentIndices.sortedUpTo})
- >
- ) : (
- "Starting sort..."
- )}
-
-
-
- )}
-
-
-
- );
-};
-
-export default InsertionSortVisualizer;
diff --git a/app/visualizer/sorting/insertionsort/codeBlock.jsx b/app/visualizer/sorting/insertionsort/codeBlock.jsx
deleted file mode 100755
index 22eeda97f..000000000
--- a/app/visualizer/sorting/insertionsort/codeBlock.jsx
+++ /dev/null
@@ -1,333 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState('javascript');
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: 'javascript', name: 'JavaScript' },
- { id: 'python', name: 'Python' },
- { id: 'java', name: 'Java' },
- { id: 'c', name: 'C' },
- { id: 'cpp', name: 'C++' }
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error('Failed to copy text: ', err);
- }
- };
-
- const codeExamples = {
- javascript: `// Insertion Sort in JavaScript
-function insertionSort(arr) {
- // Start from the second element (index 1)
- for (let i = 1; i < arr.length; i++) {
- // Current element to be inserted
- let current = arr[i];
- // Compare with the sorted portion
- let j = i - 1;
-
- // Shift elements greater than current to the right
- while (j >= 0 && arr[j] > current) {
- arr[j + 1] = arr[j];
- j--;
- }
- // Insert the current element in correct position
- arr[j + 1] = current;
- }
- return arr;
-}
-
-// Usage example
-const unsortedArray = [12, 11, 13, 5, 6];
-console.log("Unsorted array:", unsortedArray);
-const sortedArray = insertionSort(unsortedArray);
-console.log("Sorted array:", sortedArray);`,
-
- python: `# Insertion Sort in Python
-def insertion_sort(arr):
- # Start from the second element (index 1)
- for i in range(1, len(arr)):
- # Current element to be inserted
- current = arr[i]
- # Compare with the sorted portion
- j = i - 1
-
- # Shift elements greater than current to the right
- while j >= 0 and arr[j] > current:
- arr[j + 1] = arr[j]
- j -= 1
- # Insert the current element in correct position
- arr[j + 1] = current
- return arr
-
-# Usage example
-unsorted_array = [12, 11, 13, 5, 6]
-print("Unsorted array:", unsorted_array)
-sorted_array = insertion_sort(unsorted_array)
-print("Sorted array:", sorted_array)`,
-
- java: `// Insertion Sort in Java
-public class InsertionSort {
- public static void insertionSort(int[] arr) {
- // Start from the second element (index 1)
- for (int i = 1; i < arr.length; i++) {
- // Current element to be inserted
- int current = arr[i];
- // Compare with the sorted portion
- int j = i - 1;
-
- // Shift elements greater than current to the right
- while (j >= 0 && arr[j] > current) {
- arr[j + 1] = arr[j];
- j--;
- }
- // Insert the current element in correct position
- arr[j + 1] = current;
- }
- }
-
- public static void main(String[] args) {
- int[] unsortedArray = {12, 11, 13, 5, 6};
- System.out.print("Unsorted array: ");
- printArray(unsortedArray);
-
- insertionSort(unsortedArray);
-
- System.out.print("Sorted array: ");
- printArray(unsortedArray);
- }
-
- // Helper method to print array
- private static void printArray(int[] arr) {
- for (int num : arr) {
- System.out.print(num + " ");
- }
- System.out.println();
- }
-}`,
-
- c: `// Insertion Sort in C
-#include
-
-void insertionSort(int arr[], int n) {
- // Start from the second element (index 1)
- for (int i = 1; i < n; i++) {
- // Current element to be inserted
- int current = arr[i];
- // Compare with the sorted portion
- int j = i - 1;
-
- // Shift elements greater than current to the right
- while (j >= 0 && arr[j] > current) {
- arr[j + 1] = arr[j];
- j--;
- }
- // Insert the current element in correct position
- arr[j + 1] = current;
- }
-}
-
-// Function to print an array
-void printArray(int arr[], int size) {
- for (int i = 0; i < size; i++) {
- printf("%d ", arr[i]);
- }
- printf("\\n");
-}
-
-int main() {
- int unsortedArray[] = {12, 11, 13, 5, 6};
- int n = sizeof(unsortedArray) / sizeof(unsortedArray[0]);
-
- printf("Unsorted array: ");
- printArray(unsortedArray, n);
-
- insertionSort(unsortedArray, n);
-
- printf("Sorted array: ");
- printArray(unsortedArray, n);
-
- return 0;
-}`,
-
- cpp: `// Insertion Sort in C++
-#include
-#include
-using namespace std;
-
-void insertionSort(vector& arr) {
- // Start from the second element (index 1)
- for (int i = 1; i < arr.size(); i++) {
- // Current element to be inserted
- int current = arr[i];
- // Compare with the sorted portion
- int j = i - 1;
-
- // Shift elements greater than current to the right
- while (j >= 0 && arr[j] > current) {
- arr[j + 1] = arr[j];
- j--;
- }
- // Insert the current element in correct position
- arr[j + 1] = current;
- }
-}
-
-// Function to print an array
-void printArray(const vector& arr) {
- for (int num : arr) {
- cout << num << " ";
- }
- cout << endl;
-}
-
-int main() {
- vector unsortedArray = {12, 11, 13, 5, 6};
-
- cout << "Unsorted array: ";
- printArray(unsortedArray);
-
- insertionSort(unsortedArray);
-
- cout << "Sorted array: ";
- printArray(unsortedArray);
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Insertion Sort Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? 'bg-blue-500 text-white shadow-md'
- : 'bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600'
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/sorting/insertionsort/content.jsx b/app/visualizer/sorting/insertionsort/content.jsx
deleted file mode 100755
index c0ae732aa..000000000
--- a/app/visualizer/sorting/insertionsort/content.jsx
+++ /dev/null
@@ -1,306 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 = [
- `Insertion Sort is a simple sorting algorithm that builds the final sorted array one item at a time. It works similarly to how you might sort playing cards in your hands - you take each new card and insert it into its proper position among the already sorted cards.`,
- `The algorithm maintains a "sorted sublist" that grows with each iteration.`,
- `Insertion Sort is often used when the data is nearly sorted (where it approaches O(n) time) or when the dataset is small. Some hybrid algorithms like TimSort use Insertion Sort for small subarrays due to its low overhead.`,
- ];
-
- const working = [
- {
- points: "First Element (7):",
- subpoints: ['Already "sorted" as the first item', "→ [7, 3, 5, 2, 1]"],
- },
- {
- points: "Second Element (3):",
- subpoints: ["Insert before 7", "→ [3, 7, 5, 2, 1]"],
- },
- {
- points: "Third Element (5):",
- subpoints: ["Insert between 3 and 7", "→ [3, 5, 7, 2, 1]"],
- },
- {
- points: "Fourth Element (2):",
- subpoints: ["Insert at beginning", "→ [2, 3, 5, 7, 1]"],
- },
- {
- points: "Fifth Element (1):",
- subpoints: ["Insert at beginning", "→ [1, 2, 3, 5, 7]"],
- },
- ];
-
- const algorithm = [
- {
- steps: "Start with the second element (consider first element as sorted)",
- },
- { steps: "Pick the next element (key) from the unsorted portion" },
- {
- steps: "Compare the key with elements in the sorted portion:",
- points: [
- "Shift elements greater than the key one position right",
- "Stop when you find an element ≤ the key",
- ],
- },
- { steps: "Insert the key in its correct position" },
- { steps: "Repeat until all elements are processed" },
- ];
-
- const timeComplexity = [
- {
- points:
- "Best Case: Already sorted array → O(n) (only comparisons, no shifts).",
- },
- { points: "Average Case: Randomly ordered array → O(n²)." },
- {
- points:
- "Worst Case: Reverse sorted array → O(n²) (maximum comparisons and shifts).",
- },
- ];
-
- const advantages = [
- {
- points:
- "Efficient for small datasets (often faster than more complex algorithms for n ≤ 10)",
- },
- { points: "Stable (doesn't change relative order of equal elements)" },
- { points: "Adaptive (performs well with partially sorted data)" },
- { points: "Online (can sort as it receives input)" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is Insertion Sort */}
-
-
-
- What is Insertion Sort?
-
-
-
-
- {/* How Does It Work */}
-
-
-
- How Does It Work?
-
-
-
- Consider this unsorted array: [7, 3, 5, 2, 1]
-
-
-
- {working.map((items, index) => (
-
- {items.points}
- {items.subpoints && (
-
- {items.subpoints.map((subitems, subindex) => (
-
- {subitems}
-
- ))}
-
- )}
-
- ))}
-
-
-
- {paragraph[1]}
-
-
-
-
- {/* Algorithm Steps */}
-
-
-
- Algorithm Steps
-
-
-
- {algorithm.map((item, index) => (
-
- {item.steps}
- {item.points && (
-
- {item.points.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {timeComplexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
-
- n}
- averageCase={(n) => n * n}
- worstCase={(n) => n * n}
- maxN={25}
- />
-
-
-
- {/* Advantages */}
-
-
-
- Advantages
-
-
-
- {advantages.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/sorting/insertionsort/page.jsx b/app/visualizer/sorting/insertionsort/page.jsx
deleted file mode 100755
index a08842953..000000000
--- a/app/visualizer/sorting/insertionsort/page.jsx
+++ /dev/null
@@ -1,127 +0,0 @@
-import Animation from "@/app/visualizer/sorting/insertionsort/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/sorting/insertionsort/content";
-import Quiz from "@/app/visualizer/sorting/insertionsort/quiz";
-import Code from "@/app/visualizer/sorting/insertionsort/codeBlock";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import BackToTopButton from "@/app/components/ui/backtotop";
-import Footer from "@/app/components/footer";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-
-export const metadata = {
- title: "Insertion Sort Algorithm | Learn with Interactive Animations",
- description:
- "Understand how Insertion Sort works through step-by-step animations and test your knowledge with an interactive quiz. Includes code examples in JavaScript, C, Python, and Java. Perfect for beginners learning data structures and algorithms visually and through hands-on coding.",
- keywords: [
- "Insertion Sort Visualizer",
- "Insertion Sort Animation",
- "Insertion Sort Visualization",
- "DSA Insertion Sort",
- "Learn Insertion Sort",
- "Insertion Sort Quiz",
- "Sorting Algorithm Quiz",
- "Sorting Algorithm Visualization",
- "Step by Step Insertion Sort",
- "Interactive DSA Tool",
- "DSA for Beginners",
- "Insertion Sort Explained",
- "Practice Insertion Sort",
- "Interactive Insertion Sort Quiz",
- "Insertion Sort in JavaScript",
- "Insertion Sort in C",
- "Insertion Sort in Python",
- "Insertion Sort in Java",
- "Insertion Sort Code Examples",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/sorting/insertionSort.png",
- width: 1200,
- height: 630,
- alt: "Insertion Sort Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Insertion Sort", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- Insertion Sort
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
\ No newline at end of file
diff --git a/app/visualizer/sorting/insertionsort/quiz.jsx b/app/visualizer/sorting/insertionsort/quiz.jsx
deleted file mode 100755
index 642ce012c..000000000
--- a/app/visualizer/sorting/insertionsort/quiz.jsx
+++ /dev/null
@@ -1,440 +0,0 @@
-"use client";
-import React, { useState, useEffect } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const InsertionSortQuiz = () => {
- const questions = [
- {
- question: "What is the basic principle of Insertion Sort?",
- options: [
- "Dividing the list into smaller sublists and merging them",
- "Building the final sorted array one item at a time by inserting each element in its correct position",
- "Repeatedly swapping adjacent elements if they are in the wrong order",
- "Selecting the smallest element and moving it to the front"
- ],
- correctAnswer: 1,
- explanation: "Insertion Sort works by building the final sorted array one item at a time, similar to how you might sort playing cards in your hands."
- },
- {
- question: "What is the time complexity of Insertion Sort in the worst case?",
- options: [
- "O(n)",
- "O(n log n)",
- "O(n²)",
- "O(1)"
- ],
- correctAnswer: 2,
- explanation: "In the worst case (when the list is sorted in reverse order), Insertion Sort requires O(n²) comparisons and shifts."
- },
- {
- question: "In the array [7, 3, 5, 2, 1], how many shifts occur when inserting the element '2'?",
- options: [
- "1",
- "2",
- "3",
- "4"
- ],
- correctAnswer: 2,
- explanation: "When inserting '2', we need to shift '7', '5', and '3' to the right (3 shifts) before inserting '2' at the beginning."
- },
- {
- question: "When would Insertion Sort perform at its best?",
- options: [
- "When the array is in random order",
- "When the array is sorted in reverse order",
- "When the array is already sorted",
- "When the array contains duplicate values"
- ],
- correctAnswer: 2,
- explanation: "Insertion Sort performs best (O(n)) when the array is already sorted, as it only needs to make comparisons without any shifts."
- },
- {
- question: "What is the space complexity of Insertion Sort?",
- options: [
- "O(n)",
- "O(n log n)",
- "O(n²)",
- "O(1)"
- ],
- correctAnswer: 3,
- explanation: "Insertion Sort is an in-place algorithm that only requires O(1) additional space for temporary storage during shifts."
- },
- {
- question: "Which of these is NOT an advantage of Insertion Sort?",
- options: [
- "Efficient for small datasets",
- "Stable (maintains relative order of equal elements)",
- "Online (can sort as it receives input)",
- "Efficient for large, randomly ordered datasets"
- ],
- correctAnswer: 3,
- explanation: "Insertion Sort is not efficient for large, randomly ordered datasets due to its O(n²) average time complexity."
- },
- {
- question: "Why might hybrid algorithms like TimSort use Insertion Sort?",
- options: [
- "Because it's the fastest sorting algorithm for all cases",
- "Because it has excellent cache performance",
- "Because of its low overhead for small subarrays",
- "Because it's the easiest to implement"
- ],
- correctAnswer: 2,
- explanation: "Hybrid algorithms often use Insertion Sort for small subarrays (typically ≤ 10 elements) due to its low overhead and good performance on small datasets."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- // Update answers and recalculate score from scratch
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = selectedAnswer;
- setAnswers(newAnswers);
-
- const newScore = newAnswers.reduce((acc, ans, idx) => {
- return ans === questions[idx].correctAnswer ? acc + 1 : acc;
- }, 0);
- setScore(newScore);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Insertion Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting shifts in Insertion Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("performance characteristics");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("advantages and limitations");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Insertion Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Insertion Sort Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default InsertionSortQuiz;
\ No newline at end of file
diff --git a/app/visualizer/sorting/mergesort/animation.jsx b/app/visualizer/sorting/mergesort/animation.jsx
deleted file mode 100755
index 3ffdf495d..000000000
--- a/app/visualizer/sorting/mergesort/animation.jsx
+++ /dev/null
@@ -1,352 +0,0 @@
-"use client";
-import React, { useState, useRef, useEffect } from "react";
-import { gsap } from "gsap";
-import ArrayGenerator from "@/app/components/ui/randomArray";
-import CustomArrayInput from "@/app/components/ui/customArrayInput";
-
-const MergeSortVisualizer = () => {
- const [array, setArray] = useState([]);
- const [sorting, setSorting] = useState(false);
- const [sorted, setSorted] = useState(false);
- const [speed, setSpeed] = useState(1);
- const [comparisons, setComparisons] = useState(0);
- const [swaps, setSwaps] = useState(0);
- const [currentIndices, setCurrentIndices] = useState({
- left: -1,
- right: -1,
- mergeStart: -1,
- mergeEnd: -1,
- comparing: [],
- levels: [],
- currentLevel: -1,
- });
- const animationRef = useRef(null);
-
- // Reset all stats and state
- const resetStats = () => {
- setComparisons(0);
- setSwaps(0);
- setCurrentIndices({
- left: -1,
- right: -1,
- mergeStart: -1,
- mergeEnd: -1,
- comparing: [],
- levels: [],
- currentLevel: -1,
- });
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
-
- // Merge function for Merge Sort
- const merge = async (arr, l, m, r) => {
- let n1 = m - l + 1;
- let n2 = r - m;
-
- // Create temp arrays
- let L = new Array(n1);
- let R = new Array(n2);
-
- // Copy data to temp arrays
- for (let i = 0; i < n1; i++) L[i] = arr[l + i];
- for (let j = 0; j < n2; j++) R[j] = arr[m + 1 + j];
-
- // Merge the temp arrays back into arr[l..r]
- let i = 0,
- j = 0,
- k = l;
-
- while (i < n1 && j < n2) {
- setCurrentIndices((prev) => ({
- ...prev,
- comparing: [l + i, m + 1 + j],
- mergeStart: l,
- mergeEnd: r,
- }));
-
- setComparisons((prev) => prev + 1);
- await new Promise(
- (resolve) => (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
-
- if (L[i] <= R[j]) {
- arr[k] = L[i];
- i++;
- } else {
- arr[k] = R[j];
- j++;
- }
- setSwaps((prev) => prev + 1);
-
- setArray([...arr]);
- // GSAP pop animation for the merged bar
- {
- const bars = document.querySelectorAll(".bar");
- const bar = bars[k];
- if (bar) {
- await gsap.to(bar, { scale: 1.2, duration: 0.2 });
- await gsap.to(bar, { scale: 1.0, duration: 0.2 });
- }
- }
-
- k++;
- await new Promise(
- (resolve) => (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
- }
-
- // Copy remaining elements of L[]
- while (i < n1) {
- arr[k] = L[i];
- i++;
- setArray([...arr]);
- // GSAP pop animation for the merged bar
- {
- const bars = document.querySelectorAll(".bar");
- const bar = bars[k];
- if (bar) {
- await gsap.to(bar, { scale: 1.2, duration: 0.2 });
- await gsap.to(bar, { scale: 1.0, duration: 0.2 });
- }
- }
- k++;
- await new Promise(
- (resolve) => (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
- }
-
- // Copy remaining elements of R[]
- while (j < n2) {
- arr[k] = R[j];
- j++;
- setArray([...arr]);
- // GSAP pop animation for the merged bar
- {
- const bars = document.querySelectorAll(".bar");
- const bar = bars[k];
- if (bar) {
- await gsap.to(bar, { scale: 1.2, duration: 0.2 });
- await gsap.to(bar, { scale: 1.0, duration: 0.2 });
- }
- }
- k++;
- await new Promise(
- (resolve) => (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
- }
- };
-
- // Merge Sort algorithm
- const mergeSortHelper = async (arr, l, r, level = 0, path = []) => {
- if (l >= r) return;
-
- const currentPath = [...path, { l, r }];
- const m = l + Math.floor((r - l) / 2);
-
- // Update current level and path
- setCurrentIndices((prev) => ({
- ...prev,
- currentLevel: level,
- recursionPath: currentPath,
- left: l,
- right: r,
- mid: m,
- }));
-
- await new Promise(
- (resolve) => (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
-
- await mergeSortHelper(arr, l, m, level + 1, currentPath);
- await mergeSortHelper(arr, m + 1, r, level + 1, currentPath);
-
- await merge(arr, l, m, r);
- };
-
- // Main merge sort function
- const mergeSort = async () => {
- if (sorted || sorting || array.length === 0) return;
-
- setSorting(true);
- let arr = [...array];
- await mergeSortHelper(arr, 0, arr.length - 1);
-
- setArray([...arr]);
- setSorting(false);
- setSorted(true);
- setCurrentIndices({
- left: -1,
- right: -1,
- mergeStart: -1,
- mergeEnd: -1,
- comparing: [],
- levels: [],
- currentLevel: -1,
- });
- };
-
- // Reset everything
- const reset = () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- setArray([]);
- setSorting(false);
- setSorted(false);
- resetStats();
- };
-
- // Clean up on unmount
- useEffect(() => {
- return () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
- }, []);
-
- // Function to check if index is in current range
- const isInCurrentRange = (index) => {
- return index >= currentIndices.left && index <= currentIndices.right;
- };
-
- // Function to check if index is being merged
- const isBeingMerged = (index) => {
- return (
- index >= currentIndices.mergeStart && index <= currentIndices.mergeEnd
- );
- };
-
-
- return (
-
-
- Visualize the divide-and-conquer approach of Merge Sort with recursive
- splitting and merging.
-
-
-
- {/* Controls */}
-
-
-
-
{
- setArray(newArray);
- setSorted(false);
- resetStats();
- }}
- disabled={sorting}
- />
- {
- setArray(newArray);
- setSorted(false);
- resetStats();
- }}
- disabled={sorting}
- className="mb-4"
- />
-
-
-
- {sorting ? "Sorting..." : "Start Merge Sort"}
-
-
- Reset All
-
-
-
-
- {/* Speed controls */}
-
- Speed:
- setSpeed(parseFloat(e.target.value))}
- className="w-32"
- disabled={sorting}
- />
- {speed}x
-
-
- {/* Stats */}
-
-
-
Comparisons:
-
{comparisons}
-
-
-
-
-
- {/* Main Array Visualization */}
-
-
Main Array
- {array.length > 0 ? (
-
- {array.map((value, index) => {
- const isComparing = currentIndices.comparing.includes(index);
- const isInRange = isInCurrentRange(index);
- const isMerging = isBeingMerged(index);
- const isSorted = sorted;
-
- return (
-
-
- {value}
-
-
- {index}
- {isComparing && " (comparing)"}
- {isMerging && !isComparing && " (merging)"}
- {isInRange &&
- !isMerging &&
- !isComparing &&
- " (current)"}
-
-
- );
- })}
-
- ) : (
-
- {sorting ? "Sorting..." : "Generate or enter an array to begin"}
-
- )}
-
-
-
- );
-};
-
-export default MergeSortVisualizer;
diff --git a/app/visualizer/sorting/mergesort/codeBlock.jsx b/app/visualizer/sorting/mergesort/codeBlock.jsx
deleted file mode 100755
index e6b6b344f..000000000
--- a/app/visualizer/sorting/mergesort/codeBlock.jsx
+++ /dev/null
@@ -1,422 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState('javascript');
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: 'javascript', name: 'JavaScript' },
- { id: 'python', name: 'Python' },
- { id: 'java', name: 'Java' },
- { id: 'c', name: 'C' },
- { id: 'cpp', name: 'C++' }
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error('Failed to copy text: ', err);
- }
- };
-
- const codeExamples = {
- javascript: `// Merge Sort in JavaScript
-function mergeSort(arr) {
- if (arr.length <= 1) return arr;
-
- const mid = Math.floor(arr.length / 2);
- const left = mergeSort(arr.slice(0, mid));
- const right = mergeSort(arr.slice(mid));
-
- return merge(left, right);
-}
-
-function merge(left, right) {
- let result = [];
- let leftIndex = 0;
- let rightIndex = 0;
-
- while (leftIndex < left.length && rightIndex < right.length) {
- if (left[leftIndex] < right[rightIndex]) {
- result.push(left[leftIndex++]);
- } else {
- result.push(right[rightIndex++]);
- }
- }
-
- return result.concat(left.slice(leftIndex)).concat(right.slice(rightIndex));
-}
-
-// Usage
-const arr = [38, 27, 43, 3, 9, 82, 10];
-console.log("Original:", arr);
-console.log("Sorted:", mergeSort(arr));`,
-
- python: `# Merge Sort in Python
-def merge_sort(arr):
- if len(arr) <= 1:
- return arr
-
- mid = len(arr) // 2
- left = merge_sort(arr[:mid])
- right = merge_sort(arr[mid:])
-
- return merge(left, right)
-
-def merge(left, right):
- result = []
- left_idx, right_idx = 0, 0
-
- while left_idx < len(left) and right_idx < len(right):
- if left[left_idx] < right[right_idx]:
- result.append(left[left_idx])
- left_idx += 1
- else:
- result.append(right[right_idx])
- right_idx += 1
-
- result.extend(left[left_idx:])
- result.extend(right[right_idx:])
- return result
-
-# Usage
-arr = [38, 27, 43, 3, 9, 82, 10]
-print("Original:", arr)
-print("Sorted:", merge_sort(arr))`,
-
- java: `// Merge Sort in Java
-public class MergeSort {
- public static void mergeSort(int[] arr) {
- if (arr.length <= 1) return;
-
- int mid = arr.length / 2;
- int[] left = new int[mid];
- int[] right = new int[arr.length - mid];
-
- System.arraycopy(arr, 0, left, 0, mid);
- System.arraycopy(arr, mid, right, 0, arr.length - mid);
-
- mergeSort(left);
- mergeSort(right);
- merge(arr, left, right);
- }
-
- private static void merge(int[] arr, int[] left, int[] right) {
- int i = 0, j = 0, k = 0;
-
- while (i < left.length && j < right.length) {
- if (left[i] < right[j]) {
- arr[k++] = left[i++];
- } else {
- arr[k++] = right[j++];
- }
- }
-
- while (i < left.length) {
- arr[k++] = left[i++];
- }
-
- while (j < right.length) {
- arr[k++] = right[j++];
- }
- }
-
- public static void main(String[] args) {
- int[] arr = {38, 27, 43, 3, 9, 82, 10};
- System.out.print("Original: ");
- printArray(arr);
-
- mergeSort(arr);
-
- System.out.print("Sorted: ");
- printArray(arr);
- }
-
- private static void printArray(int[] arr) {
- for (int num : arr) {
- System.out.print(num + " ");
- }
- System.out.println();
- }
-}`,
-
- c: `// Merge Sort in C
-#include
-#include
-
-void merge(int arr[], int l, int m, int r) {
- int i, j, k;
- int n1 = m - l + 1;
- int n2 = r - m;
-
- int L[n1], R[n2];
-
- for (i = 0; i < n1; i++)
- L[i] = arr[l + i];
- for (j = 0; j < n2; j++)
- R[j] = arr[m + 1 + j];
-
- i = 0; j = 0; k = l;
-
- while (i < n1 && j < n2) {
- if (L[i] <= R[j]) {
- arr[k] = L[i];
- i++;
- } else {
- arr[k] = R[j];
- j++;
- }
- k++;
- }
-
- while (i < n1) {
- arr[k] = L[i];
- i++;
- k++;
- }
-
- while (j < n2) {
- arr[k] = R[j];
- j++;
- k++;
- }
-}
-
-void mergeSort(int arr[], int l, int r) {
- if (l < r) {
- int m = l + (r - l) / 2;
- mergeSort(arr, l, m);
- mergeSort(arr, m + 1, r);
- merge(arr, l, m, r);
- }
-}
-
-void printArray(int arr[], int size) {
- for (int i = 0; i < size; i++)
- printf("%d ", arr[i]);
- printf("\\n");
-}
-
-int main() {
- int arr[] = {38, 27, 43, 3, 9, 82, 10};
- int size = sizeof(arr) / sizeof(arr[0]);
-
- printf("Original: ");
- printArray(arr, size);
-
- mergeSort(arr, 0, size - 1);
-
- printf("Sorted: ");
- printArray(arr, size);
-
- return 0;
-}`,
-
- cpp: `// Merge Sort in C++
-#include
-#include
-using namespace std;
-
-void merge(vector& arr, int l, int m, int r) {
- int n1 = m - l + 1;
- int n2 = r - m;
-
- vector L(n1), R(n2);
-
- for (int i = 0; i < n1; i++)
- L[i] = arr[l + i];
- for (int j = 0; j < n2; j++)
- R[j] = arr[m + 1 + j];
-
- int i = 0, j = 0, k = l;
-
- while (i < n1 && j < n2) {
- if (L[i] <= R[j]) {
- arr[k] = L[i];
- i++;
- } else {
- arr[k] = R[j];
- j++;
- }
- k++;
- }
-
- while (i < n1) {
- arr[k] = L[i];
- i++;
- k++;
- }
-
- while (j < n2) {
- arr[k] = R[j];
- j++;
- k++;
- }
-}
-
-void mergeSort(vector& arr, int l, int r) {
- if (l < r) {
- int m = l + (r - l) / 2;
- mergeSort(arr, l, m);
- mergeSort(arr, m + 1, r);
- merge(arr, l, m, r);
- }
-}
-
-void printArray(const vector& arr) {
- for (int num : arr) {
- cout << num << " ";
- }
- cout << endl;
-}
-
-int main() {
- vector arr = {38, 27, 43, 3, 9, 82, 10};
-
- cout << "Original: ";
- printArray(arr);
-
- mergeSort(arr, 0, arr.size() - 1);
-
- cout << "Sorted: ";
- printArray(arr);
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Merge Sort Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/sorting/mergesort/content.jsx b/app/visualizer/sorting/mergesort/content.jsx
deleted file mode 100755
index 32ae7dd15..000000000
--- a/app/visualizer/sorting/mergesort/content.jsx
+++ /dev/null
@@ -1,295 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 = [
- `Merge Sort is an efficient, stable, comparison-based sorting algorithm that follows the divide-and-conquer approach. It works by recursively dividing the unsorted list into sublists until each sublist contains a single element, then repeatedly merges these sublists to produce new sorted sublists until there is only one sorted list remaining.`,
- `The log n factor comes from the division steps, while the n factor comes from the merge steps.`,
- `Merge Sort requires O(n) additional space for the temporary arrays during merging. This makes it not an in-place sorting algorithm, unlike Insertion Sort or Bubble Sort.`,
- `Merge Sort is particularly useful when sorting linked lists (where random access is expensive) and is the algorithm of choice for many standard library sorting implementations when stability is required. It's also commonly used in external sorting where data doesn't fit in memory.`,
- ];
-
- const algorithm = [
- {
- points: "Divide:",
- subpoints: [
- "Find the middle point to divide the array into two halves",
- "Recursively call merge sort on the first half",
- "Recursively call merge sort on the second half",
- ],
- },
- {
- points: "Merge:",
- subpoints: [
- "Create temporary arrays for both halves",
- "Compare elements from each half and merge them in order",
- "Copy any remaining elements from either half",
- ],
- },
- ];
-
- const timeComplexity = [
- {
- points:
- "Best Case: O(n log n) (already sorted, but still needs all comparisons)",
- },
- { points: "Average Case: O(n log n)" },
- { points: "Worst Case: O(n log n) (consistent performance)" },
- ];
-
- const advantages = [
- { points: "Stable sorting (maintains relative order of equal elements)" },
- {
- points:
- "Excellent for large datasets (consistent O(n log n) performance)",
- },
- {
- points:
- "Well-suited for external sorting (sorting data too large for RAM)",
- },
- { points: "Easily parallelizable (divide steps can be done concurrently)" },
- ];
-
- const disadvantages = [
- { points: "Requires O(n) additional space (not in-place)" },
- {
- points:
- "Slower than O(n²) algorithms for very small datasets due to recursion overhead",
- },
- {
- points:
- "Not as cache-efficient as some other algorithms (e.g., QuickSort)",
- },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is Merge Sort */}
-
-
-
- What is Merge Sort?
-
-
-
-
- {/* Algorithm Steps */}
-
-
-
- Algorithm Steps
-
-
-
- {algorithm.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {timeComplexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
- {paragraph[1]}
-
-
- n * Math.log2(n)}
- averageCase={(n) => n * Math.log2(n)}
- worstCase={(n) => n * Math.log2(n)}
- maxN={25}
- />
-
-
-
-
- {/* Space Complexity */}
-
-
-
- Space Complexity
-
-
-
-
- {/* Advantages */}
-
-
-
- Advantages
-
-
-
- {advantages.map((items, index) => (
-
- {items.points}
-
- ))}
-
-
-
-
- {/* Disadvantages */}
-
-
-
- Disadvantages
-
-
-
- {disadvantages.map((items, index) => (
-
- {items.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
\ No newline at end of file
diff --git a/app/visualizer/sorting/mergesort/page.jsx b/app/visualizer/sorting/mergesort/page.jsx
deleted file mode 100755
index aba711137..000000000
--- a/app/visualizer/sorting/mergesort/page.jsx
+++ /dev/null
@@ -1,131 +0,0 @@
-import Animation from "@/app/visualizer/sorting/mergesort/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/sorting/mergesort/content";
-import Quiz from "@/app/visualizer/sorting/mergesort/quiz";
-import Code from "@/app/visualizer/sorting/mergesort/codeBlock";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import BackToTopButton from "@/app/components/ui/backtotop";
-import Footer from "@/app/components/footer";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-
-export const metadata = {
- title: "Merge Sort Algorithm | Learn with Interactive Animations",
- description:
- "Understand how Merge Sort works through step-by-step animations and test your knowledge with an interactive quiz. Includes code examples in JavaScript, C, Python, and Java. Perfect for beginners learning efficient divide-and-conquer sorting algorithms both visually and through hands-on coding.",
- keywords: [
- "Merge Sort Visualizer",
- "Merge Sort Animation",
- "Merge Sort Visualization",
- "Merge Sort Algorithm",
- "Merge Sort Quiz",
- "Sorting Algorithm Quiz",
- "Divide and Conquer Sorting",
- "Sorting Algorithm Visualization",
- "Learn Merge Sort",
- "DSA Merge Sort",
- "Practice Merge Sort",
- "Interactive Merge Sort Tool",
- "Test Merge Sort Knowledge",
- "Merge Sort in JavaScript",
- "Merge Sort in C",
- "Merge Sort in Python",
- "Merge Sort in Java",
- "Merge Sort Code Examples",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/sorting/mergeSort.png",
- width: 1200,
- height: 630,
- alt: "Merge Sort Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Merge Sort", href: "" },
- ];
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/sorting/mergesort/quiz.jsx b/app/visualizer/sorting/mergesort/quiz.jsx
deleted file mode 100755
index 8ef796c95..000000000
--- a/app/visualizer/sorting/mergesort/quiz.jsx
+++ /dev/null
@@ -1,438 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const MergeSortQuiz = () => {
- const questions = [
- {
- question: "What is the fundamental principle behind Merge Sort?",
- options: [
- "Repeatedly swapping adjacent elements if they are in the wrong order",
- "Dividing the array into smaller subarrays and merging them back in sorted order",
- "Selecting the smallest element and moving it to the front",
- "Building the sorted array one element at a time by insertion"
- ],
- correctAnswer: 1,
- explanation: "Merge Sort follows the divide-and-conquer approach by recursively dividing the array into halves until single elements remain, then merging them back in sorted order."
- },
- {
- question: "What is the time complexity of Merge Sort in all cases (best, average, worst)?",
- options: [
- "O(n)",
- "O(n log n)",
- "O(n²)",
- "O(log n)"
- ],
- correctAnswer: 1,
- explanation: "Merge Sort has consistent O(n log n) performance in all cases because it always divides the array in half and performs linear-time merges regardless of input order."
- },
- {
- question: "In the array [38, 27, 43, 3, 9, 82, 10], how many times is the array divided before reaching single elements?",
- options: [
- "2 times",
- "3 times",
- "4 times",
- "5 times"
- ],
- correctAnswer: 1,
- explanation: "The array is divided 3 times: 1) [38,27,43] and [3,9,82,10], 2) [38], [27,43], [3,9], [82,10], 3) All subarrays are single elements."
- },
- {
- question: "What is the space complexity of Merge Sort?",
- options: [
- "O(1)",
- "O(log n)",
- "O(n)",
- "O(n²)"
- ],
- correctAnswer: 2,
- explanation: "Merge Sort requires O(n) additional space for temporary arrays during the merging phase, making it not an in-place sorting algorithm."
- },
- {
- question: "Which of these is NOT an advantage of Merge Sort?",
- options: [
- "Stable sorting (maintains relative order of equal elements)",
- "Excellent for large datasets",
- "Requires minimal additional memory (O(1) space)",
- "Well-suited for external sorting"
- ],
- correctAnswer: 2,
- explanation: "Merge Sort requires O(n) additional space, not O(1). Its advantages include stability, consistent O(n log n) performance, and suitability for external sorting."
- },
- {
- question: "Why is Merge Sort particularly good for sorting linked lists?",
- options: [
- "Because it doesn't require random access to elements",
- "Because it's the fastest sorting algorithm for all cases",
- "Because it can sort in O(1) space with linked lists",
- "Because it doesn't require comparisons"
- ],
- correctAnswer: 0,
- explanation: "Merge Sort works well with linked lists because it primarily requires sequential access (not random access) during the merge phase, and it can be implemented with O(1) space for linked lists."
- },
- {
- question: "What makes Merge Sort suitable for external sorting (sorting data too large for RAM)?",
- options: [
- "Its ability to sort with minimal comparisons",
- "Its divide-and-conquer approach that works well with sequential access",
- "Its in-place sorting capability",
- "Its O(n) best-case time complexity"
- ],
- correctAnswer: 1,
- explanation: "Merge Sort's divide-and-conquer approach works well with sequential access patterns needed for external storage, and it can efficiently merge sorted runs from disk."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = selectedAnswer;
- setAnswers(newAnswers);
-
- const newScore = newAnswers.reduce((acc, ans, idx) => {
- return ans === questions[idx].correctAnswer ? acc + 1 : acc;
- }, 0);
- setScore(newScore);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(newAnswers[currentQuestion + 1]);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the divide-and-conquer principle");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("understanding the division phase");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("advantages and limitations");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("application with linked lists");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("external sorting applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Merge Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Merge Sort Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default MergeSortQuiz;
\ No newline at end of file
diff --git a/app/visualizer/sorting/quicksort/animation.jsx b/app/visualizer/sorting/quicksort/animation.jsx
deleted file mode 100755
index 7bbf0f122..000000000
--- a/app/visualizer/sorting/quicksort/animation.jsx
+++ /dev/null
@@ -1,393 +0,0 @@
-"use client";
-import React, { useState, useRef, useEffect } from "react";
-import { gsap } from "gsap";
-import ArrayGenerator from "@/app/components/ui/randomArray";
-import CustomArrayInput from "@/app/components/ui/customArrayInput";
-
-const QuickSortVisualizer = () => {
- const [array, setArray] = useState([]);
- const [sorting, setSorting] = useState(false);
- const [sorted, setSorted] = useState(false);
- const [speed, setSpeed] = useState(1);
- const [comparisons, setComparisons] = useState(0);
- const [swaps, setSwaps] = useState(0);
- const [currentIndices, setCurrentIndices] = useState({
- pivot: -1,
- left: -1,
- right: -1,
- partitionIndex: -1,
- stack: [],
- partitions: [],
- });
- const animationRef = useRef(null);
-
- // Reset all stats and state
- const resetStats = () => {
- setComparisons(0);
- setSwaps(0);
- setCurrentIndices({
- pivot: -1,
- left: -1,
- right: -1,
- partitionIndex: -1,
- stack: [],
- partitions: [],
- });
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
-
- // Partition function for Quick Sort
- const partition = async (arr, low, high) => {
- const pivot = arr[high];
- let i = low - 1;
-
- setCurrentIndices((prev) => ({
- ...prev,
- pivot: high,
- left: low,
- right: high - 1,
- }));
-
- for (let j = low; j < high; j++) {
- setCurrentIndices((prev) => ({
- ...prev,
- left: j,
- right: i,
- }));
-
- setComparisons((prev) => prev + 1);
- await new Promise(
- (resolve) => (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
-
- if (arr[j] < pivot) {
- i++;
- [arr[i], arr[j]] = [arr[j], arr[i]];
- setSwaps((prev) => prev + 1);
- setArray([...arr]);
- // GSAP animation after swap/visual update
- const bars = document.querySelectorAll(".array-bar");
- if (bars.length > 0) {
- gsap.fromTo(
- bars,
- { scale: 1, opacity: 0.5 },
- { scale: 1.1, opacity: 1, duration: 0.3, stagger: 0.05 }
- );
- }
- await new Promise(
- (resolve) =>
- (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
- }
- }
-
- [arr[i + 1], arr[high]] = [arr[high], arr[i + 1]];
- setSwaps((prev) => prev + 1);
- setArray([...arr]);
- // GSAP animation after swap/visual update
- const bars = document.querySelectorAll(".array-bar");
- if (bars.length > 0) {
- gsap.fromTo(
- bars,
- { scale: 1, opacity: 0.5 },
- { scale: 1.1, opacity: 1, duration: 0.3, stagger: 0.05 }
- );
- }
- await new Promise(
- (resolve) => (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
-
- return i + 1;
- };
-
- // Quick Sort algorithm
- const quickSort = async () => {
- if (sorted || sorting || array.length === 0) return;
-
- setSorting(true);
- let arr = [...array];
- let stack = [];
- let low = 0;
- let high = arr.length - 1;
-
- stack.push({ low, high });
-
- while (stack.length > 0) {
- const { low, high } = stack.pop();
-
- if (low < high) {
- // Show current partition being processed
- setCurrentIndices((prev) => ({
- ...prev,
- partitions: [...prev.partitions, { low, high }],
- }));
-
- const pi = await partition(arr, low, high);
-
- setCurrentIndices((prev) => ({
- ...prev,
- partitionIndex: pi,
- stack: [...stack],
- pivot: -1,
- left: -1,
- right: -1,
- }));
-
- // Push right subarray first so left is processed first
- stack.push({ low: pi + 1, high });
- stack.push({ low, high: pi - 1 });
-
- await new Promise(
- (resolve) =>
- (animationRef.current = setTimeout(resolve, 1000 / speed))
- );
-
- // Remove completed partition
- setCurrentIndices((prev) => ({
- ...prev,
- partitions: prev.partitions.filter(
- (p) => !(p.low === low && p.high === high)
- ),
- }));
- }
- }
-
- setArray([...arr]);
- setSorting(false);
- setSorted(true);
- setCurrentIndices({
- pivot: -1,
- left: -1,
- right: -1,
- partitionIndex: -1,
- stack: [],
- partitions: [],
- });
- };
-
- // Reset everything
- const reset = () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- setArray([]);
- setSorting(false);
- setSorted(false);
- resetStats();
- };
-
- // Clean up on unmount
- useEffect(() => {
- return () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
- }, []);
-
- // Function to render partition visualization
- const renderPartitions = () => {
- if (currentIndices.partitions.length === 0) return null;
-
- return (
-
-
- {currentIndices.partitions.map((partition, idx) => {
- const subArray = array.slice(partition.low, partition.high + 1);
- return (
-
-
-
- Partition {idx + 1}: Indexes {partition.low} to{" "}
- {partition.high}
-
-
- {subArray.length} elements
-
-
-
- {subArray.map((value, subIdx) => {
- const originalIndex = partition.low + subIdx;
- const isPivot = originalIndex === currentIndices.pivot;
- const isLeft = originalIndex === currentIndices.left;
- const isRight = originalIndex === currentIndices.right;
-
- return (
-
-
- {value}
-
-
- [{originalIndex}]
-
-
- );
- })}
-
-
- );
- })}
-
-
- );
- };
-
- return (
-
-
- Visualize Quick Sort's divide-and-conquer approach with interactive
- partitions
-
-
-
- {/* Controls */}
-
-
-
-
{
- setArray(newArray);
- setSorted(false);
- resetStats();
- }}
- disabled={sorting}
- />
- {
- setArray(newArray);
- setSorted(false);
- resetStats();
- }}
- disabled={sorting}
- />
-
-
-
- {sorting ? "Sorting..." : "Start Quick Sort"}
-
-
- Reset All
-
-
-
-
- {/* Speed controls */}
-
- Speed:
- setSpeed(parseFloat(e.target.value))}
- className="w-32"
- disabled={sorting}
- />
- {speed}x
-
-
- {/* Stats */}
-
-
-
Comparisons:
-
{comparisons}
-
-
-
-
-
- {/* Main Array Visualization */}
-
-
Array Visualization
- {array.length > 0 ? (
-
- {array.map((value, index) => {
- const isPivot = index === currentIndices.pivot;
- const isLeft = index === currentIndices.left;
- const isRight = index === currentIndices.right;
- const isPartition = index === currentIndices.partitionIndex;
- const isInPartition = currentIndices.partitions.some(
- (p) => index >= p.low && index <= p.high
- );
-
- return (
-
-
- {value}
-
-
- {index}
- {isPivot && " (pivot)"}
- {isLeft && " (left)"}
- {isRight && " (right)"}
- {isPartition && " (partition)"}
-
-
- );
- })}
-
- ) : (
-
- {sorting ? "Sorting..." : "Generate or enter an array to begin"}
-
- )}
-
-
- {/* Partition Visualization */}
-
-
Partion Array
- {renderPartitions()}
-
-
-
- );
-};
-
-export default QuickSortVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/sorting/quicksort/codeBlock.jsx b/app/visualizer/sorting/quicksort/codeBlock.jsx
deleted file mode 100755
index 69c87d01e..000000000
--- a/app/visualizer/sorting/quicksort/codeBlock.jsx
+++ /dev/null
@@ -1,369 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Quick Sort in JavaScript
-function quickSort(arr, left = 0, right = arr.length - 1) {
- if (left < right) {
- const pivotIndex = partition(arr, left, right);
- quickSort(arr, left, pivotIndex - 1);
- quickSort(arr, pivotIndex + 1, right);
- }
- return arr;
-}
-
-function partition(arr, left, right) {
- const pivot = arr[right];
- let i = left;
-
- for (let j = left; j < right; j++) {
- if (arr[j] < pivot) {
- [arr[i], arr[j]] = [arr[j], arr[i]];
- i++;
- }
- }
-
- [arr[i], arr[right]] = [arr[right], arr[i]];
- return i;
-}
-
-// Usage
-const arr = [10, 7, 8, 9, 1, 5];
-console.log("Original:", arr);
-console.log("Sorted:", quickSort([...arr]));`,
-
- python: `# Quick Sort in Python
-def quick_sort(arr, low=0, high=None):
- if high is None:
- high = len(arr) - 1
-
- if low < high:
- pivot_index = partition(arr, low, high)
- quick_sort(arr, low, pivot_index - 1)
- quick_sort(arr, pivot_index + 1, high)
- return arr
-
-def partition(arr, low, high):
- pivot = arr[high]
- i = low
-
- for j in range(low, high):
- if arr[j] < pivot:
- arr[i], arr[j] = arr[j], arr[i]
- i += 1
-
- arr[i], arr[high] = arr[high], arr[i]
- return i
-
-# Usage
-arr = [10, 7, 8, 9, 1, 5]
-print("Original:", arr)
-print("Sorted:", quick_sort(arr.copy()))`,
-
- java: `// Quick Sort in Java
-public class QuickSort {
- public static void quickSort(int[] arr, int low, int high) {
- if (low < high) {
- int pivotIndex = partition(arr, low, high);
- quickSort(arr, low, pivotIndex - 1);
- quickSort(arr, pivotIndex + 1, high);
- }
- }
-
- private static int partition(int[] arr, int low, int high) {
- int pivot = arr[high];
- int i = low;
-
- for (int j = low; j < high; j++) {
- if (arr[j] < pivot) {
- swap(arr, i, j);
- i++;
- }
- }
-
- swap(arr, i, high);
- return i;
- }
-
- private static void swap(int[] arr, int i, int j) {
- int temp = arr[i];
- arr[i] = arr[j];
- arr[j] = temp;
- }
-
- public static void main(String[] args) {
- int[] arr = {10, 7, 8, 9, 1, 5};
- System.out.print("Original: ");
- printArray(arr);
-
- quickSort(arr, 0, arr.length - 1);
-
- System.out.print("Sorted: ");
- printArray(arr);
- }
-
- private static void printArray(int[] arr) {
- for (int num : arr) {
- System.out.print(num + " ");
- }
- System.out.println();
- }
-}`,
-
- c: `// Quick Sort in C
-#include
-
-void swap(int* a, int* b) {
- int temp = *a;
- *a = *b;
- *b = temp;
-}
-
-int partition(int arr[], int low, int high) {
- int pivot = arr[high];
- int i = low;
-
- for (int j = low; j < high; j++) {
- if (arr[j] < pivot) {
- swap(&arr[i], &arr[j]);
- i++;
- }
- }
-
- swap(&arr[i], &arr[high]);
- return i;
-}
-
-void quickSort(int arr[], int low, int high) {
- if (low < high) {
- int pivotIndex = partition(arr, low, high);
- quickSort(arr, low, pivotIndex - 1);
- quickSort(arr, pivotIndex + 1, high);
- }
-}
-
-void printArray(int arr[], int size) {
- for (int i = 0; i < size; i++) {
- printf("%d ", arr[i]);
- }
- printf("\\n");
-}
-
-int main() {
- int arr[] = {10, 7, 8, 9, 1, 5};
- int size = sizeof(arr) / sizeof(arr[0]);
-
- printf("Original: ");
- printArray(arr, size);
-
- quickSort(arr, 0, size - 1);
-
- printf("Sorted: ");
- printArray(arr, size);
-
- return 0;
-}`,
-
- cpp: `// Quick Sort in C++
-#include
-#include
-using namespace std;
-
-int partition(vector& arr, int low, int high) {
- int pivot = arr[high];
- int i = low;
-
- for (int j = low; j < high; j++) {
- if (arr[j] < pivot) {
- swap(arr[i], arr[j]);
- i++;
- }
- }
-
- swap(arr[i], arr[high]);
- return i;
-}
-
-void quickSort(vector& arr, int low, int high) {
- if (low < high) {
- int pivotIndex = partition(arr, low, high);
- quickSort(arr, low, pivotIndex - 1);
- quickSort(arr, pivotIndex + 1, high);
- }
-}
-
-void printArray(const vector& arr) {
- for (int num : arr) {
- cout << num << " ";
- }
- cout << endl;
-}
-
-int main() {
- vector arr = {10, 7, 8, 9, 1, 5};
-
- cout << "Original: ";
- printArray(arr);
-
- quickSort(arr, 0, arr.size() - 1);
-
- cout << "Sorted: ";
- printArray(arr);
-
- return 0;
-}`,
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Quick Sort Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/sorting/quicksort/content.jsx b/app/visualizer/sorting/quicksort/content.jsx
deleted file mode 100755
index fb825132f..000000000
--- a/app/visualizer/sorting/quicksort/content.jsx
+++ /dev/null
@@ -1,390 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 paragraphs = [
- `Quick Sort is an efficient, comparison-based sorting algorithm that follows the divide-and-conquer approach. It works by selecting a 'pivot' element from the array and partitioning the other elements into two sub-arrays according to whether they are less than or greater than the pivot. The sub-arrays are then recursively sorted.`,
- `The log n factor comes from the division steps when partitions are balanced. The n² occurs when the pivot selection consistently creates unbalanced partitions.`,
- `Quick Sort is O(log n) space complexity for the call stack in the average case, but can degrade to O(n) in the worst case with unbalanced partitions. It is generally considered an in-place algorithm as it doesn't require significant additional space.`,
- `Quick Sort is the algorithm of choice for most standard library sorting implementations (like C's qsort, Java's Arrays.sort for primitives) due to its excellent average-case performance. It's particularly effective for large datasets that fit in memory.`,
- ];
-
- const working = [
- {
- steps: "Partitioning Phase:",
- points: [
- "Choose last element as pivot (70)",
- "Rearrange: elements < pivot on left, > pivot on right → [10, 30, 40, 50] [70] [80, 90]",
- ],
- },
- {
- steps: "Recursive Phase:",
- points: [
- "Apply same process to left sub-array [10, 30, 40, 50]",
- "Apply same process to right sub-array [80, 90]",
- "Combine results: [10, 30, 40, 50, 70, 80, 90]",
- ],
- },
- ];
-
- const algorithm = [
- {
- steps: "Choose Pivot:",
- points: [
- "Select an element as pivot (commonly last/first/random element)",
- ],
- },
- {
- steps: "Partition:",
- points: [
- "Reorder array so elements < pivot come before it",
- "Elements > pivot come after it",
- "Pivot is now in its final sorted position",
- ],
- },
- {
- steps: "Recurse:",
- points: [
- "Apply quick sort to left sub-array (elements < pivot)",
- "Apply quick sort to right sub-array (elements > pivot)",
- ],
- },
- ];
-
- const timeComplexity = [
- { points: "Best Case: O(n log n) (balanced partitions)" },
- { points: "Average Case: O(n log n)" },
- { points: "Worst Case: O(n²) (unbalanced partitions)" },
- ];
-
- const strategies = [
- { strategy: "Last element" },
- { strategy: "First element" },
- { strategy: "Random element" },
- { strategy: "Median-of-three" },
- { strategy: "Middle element" },
- ];
-
- const strategiesDetails = [
- { details: "Simple but can lead to worst-case on sorted arrays" },
- { details: "Similar issues as last element" },
- { details: "Reduces chance of worst-case scenarios" },
- { details: "Takes median of first, middle, last elements" },
- { details: "Often provides good balance" },
- ];
-
- const CombinedDeatils = strategies.map((item, index) => ({
- strategy: item.strategy,
- details: strategiesDetails[index].details,
- }));
-
- {
- /* Advantages */
- }
- const advantages = [
- {
- points: "Fastest general-purpose in-memory sorting algorithm in practice",
- },
- { points: "In-place algorithm (requires minimal additional memory)" },
- { points: "Cache-efficient due to sequential memory access" },
- { points: "Can be easily parallelized for better performance" },
- ];
-
- {
- /* Disadvantages */
- }
- const disadvantages = [
- { points: "Not stable (relative order of equal elements may change)" },
- {
- points:
- "Worst-case O(n²) performance (though rare with proper pivot selection)",
- },
- { points: "Performance depends heavily on pivot selection strategy" },
- { points: "Not ideal for linked lists (works best with arrays)" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is Quick Sort */}
-
-
-
- What is Quick Sort?
-
-
-
-
- {/* How Does It Work */}
-
-
-
- How Does It Work?
-
-
-
- Consider this unsorted array: [10, 80, 30, 90, 40, 50, 70]
-
-
-
- {working.map((item, index) => (
-
- {item.steps}
- {item.points && (
-
- {item.points.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Algorithm Steps */}
-
-
-
- Algorithm Steps
-
-
-
- {algorithm.map((item, index) => (
-
- {item.steps}
- {item.points && (
-
- {item.points.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {timeComplexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
- {paragraphs[1]}
-
-
- n * Math.log2(n)}
- averageCase={(n) => n * Math.log2(n)}
- worstCase={(n) => n * n}
- maxN={25}
- />
-
-
-
-
- {/* Space Complexity */}
-
-
-
- Space Complexity
-
-
-
-
- {/* Advantages */}
-
-
-
- Advantages
-
-
-
- {advantages.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Disadvantages */}
-
-
-
- Disadvantages
-
-
-
- {disadvantages.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Pivot Selection Strategies */}
-
-
-
- Pivot Selection Strategies
-
-
-
- {CombinedDeatils.map((item, index) => (
-
- {item.strategy}: {" "}
- {item.details}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/sorting/quicksort/page.jsx b/app/visualizer/sorting/quicksort/page.jsx
deleted file mode 100755
index 6f67429ca..000000000
--- a/app/visualizer/sorting/quicksort/page.jsx
+++ /dev/null
@@ -1,132 +0,0 @@
-import Animation from "@/app/visualizer/sorting/quicksort/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/sorting/quicksort/content";
-import Quiz from "@/app/visualizer/sorting/quicksort/quiz";
-import Code from "@/app/visualizer/sorting/quicksort/codeBlock";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import BackToTopButton from "@/app/components/ui/backtotop";
-import Footer from "@/app/components/footer";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-
-export const metadata = {
- title:
- "Quick Sort Algorithm | Learn with Interactive Animations",
- description:
- "Learn how Quick Sort works with step-by-step animations and test your knowledge with an interactive quiz. Includes code examples in JavaScript, C, Python, and Java. Perfect for beginners learning this efficient divide-and-conquer sorting algorithm visually and through hands-on coding.",
- keywords: [
- "Quick Sort Visualizer",
- "Quick Sort Animation",
- "Quick Sort Visualization",
- "Quick Sort Algorithm",
- "Quick Sort Quiz",
- "Sorting Algorithm Quiz",
- "Divide and Conquer Sorting",
- "Sorting Algorithm Visualization",
- "Learn Quick Sort",
- "DSA Quick Sort",
- "Practice Quick Sort",
- "Interactive Quick Sort Tool",
- "Test Quick Sort Knowledge",
- "Quick Sort in JavaScript",
- "Quick Sort in C",
- "Quick Sort in Python",
- "Quick Sort in Java",
- "Quick Sort Code Examples",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/sorting/quickSort.png",
- width: 1200,
- height: 630,
- alt: "Quick Sort Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Quick Sort", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/sorting/quicksort/quiz.jsx b/app/visualizer/sorting/quicksort/quiz.jsx
deleted file mode 100755
index 793716ffe..000000000
--- a/app/visualizer/sorting/quicksort/quiz.jsx
+++ /dev/null
@@ -1,480 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const QuickSortQuiz = () => {
- const questions = [
- {
- question: "What is the fundamental principle behind Quick Sort?",
- options: [
- "Merging two sorted lists into one",
- "Building a heap structure from the array",
- "Dividing the array around a pivot element",
- "Finding the minimum element repeatedly"
- ],
- correctAnswer: 2,
- explanation: "Quick Sort uses a divide-and-conquer approach by selecting a pivot element and partitioning the array into elements less than and greater than the pivot."
- },
- {
- question: "What is the average-case time complexity of Quick Sort?",
- options: [
- "O(n)",
- "O(n log n)",
- "O(n²)",
- "O(log n)"
- ],
- correctAnswer: 1,
- explanation: "With good pivot selection that creates balanced partitions, Quick Sort averages O(n log n) time complexity."
- },
- {
- question: "Which pivot selection strategy helps avoid the worst-case O(n²) scenario?",
- options: [
- "Always choosing the first element",
- "Always choosing the last element",
- "Median-of-three method",
- "Always choosing the middle element"
- ],
- correctAnswer: 2,
- explanation: "The median-of-three strategy (choosing the median of first, middle, and last elements) helps prevent consistently bad pivot choices that lead to unbalanced partitions."
- },
- {
- question: "What is the space complexity of Quick Sort in the average case?",
- options: [
- "O(1)",
- "O(n)",
- "O(log n)",
- "O(n log n)"
- ],
- correctAnswer: 2,
- explanation: "Quick Sort requires O(log n) space for the call stack in the average case due to recursive calls, but can degrade to O(n) in worst-case scenarios."
- },
- {
- question: "In the array [10, 80, 30, 90, 40, 50, 70], if we choose the last element as pivot, what is the array after the first partition?",
- options: [
- "[10, 30, 40, 50, 70, 80, 90]",
- "[10, 30, 40] [50] [70, 80, 90]",
- "[10, 30, 40, 50] [70] [80, 90]",
- "[10, 80, 30, 90, 40, 50, 70]"
- ],
- correctAnswer: 2,
- explanation: "With pivot=70, elements less than 70 (10,30,40,50) go left, elements greater (80,90) go right, and 70 is in its final position."
- },
- {
- question: "Which of these is NOT an advantage of Quick Sort?",
- options: [
- "Excellent average-case performance",
- "Stable sorting (maintains relative order of equal elements)",
- "In-place sorting (requires minimal additional memory)",
- "Cache-efficient due to sequential memory access"
- ],
- correctAnswer: 1,
- explanation: "Quick Sort is not stable - the relative order of equal elements may change during partitioning."
- },
- {
- question: "What causes Quick Sort's worst-case O(n²) time complexity?",
- options: [
- "When the array contains duplicate elements",
- "When the pivot consistently creates highly unbalanced partitions",
- "When the array size is very small",
- "When using extra space for merging"
- ],
- correctAnswer: 1,
- explanation: "The worst case occurs when the pivot selection consistently creates partitions of size n-1 and 0 (extremely unbalanced), leading to n nested calls."
- },
- {
- question: "Why is Quick Sort often preferred over Merge Sort for in-memory sorting?",
- options: [
- "It has better worst-case time complexity",
- "It is a stable sorting algorithm",
- "It has better cache performance due to sequential access",
- "It requires less code to implement"
- ],
- correctAnswer: 2,
- explanation: "Quick Sort's sequential memory access pattern makes it more cache-friendly than Merge Sort, contributing to its better real-world performance despite having the same average time complexity."
- },
- {
- question: "Which of these standard library implementations typically uses Quick Sort?",
- options: [
- "Python's sorted() function",
- "Java's Arrays.sort() for primitive types",
- "C++ STL's stable_sort()",
- "JavaScript's Array.prototype.sort()"
- ],
- correctAnswer: 1,
- explanation: "Java's Arrays.sort() uses a dual-pivot Quick Sort for primitive types (which don't need stability), while object sorting uses a stable Merge Sort variant."
- },
- {
- question: "What is the primary purpose of the partition step in Quick Sort?",
- options: [
- "To divide the array into exactly equal halves",
- "To place the pivot element in its correct final position",
- "To sort the array in one pass",
- "To identify duplicate elements in the array"
- ],
- correctAnswer: 1,
- explanation: "The partition step's main goal is to place the pivot in its correct sorted position while arranging other elements to be less than or greater than the pivot."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = selectedAnswer;
- setAnswers(newAnswers);
-
- const newScore = newAnswers.reduce((acc, ans, idx) => {
- return ans === questions[idx].correctAnswer ? acc + 1 : acc;
- }, 0);
- setScore(newScore);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(newAnswers[currentQuestion + 1]);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the divide-and-conquer principle");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("pivot selection strategies");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("partitioning process");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("advantages of Quick Sort");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("worst-case scenarios");
- }
- if (answers[7] !== questions[7].correctAnswer) {
- weakAreas.push("practical performance considerations");
- }
- if (answers[8] !== questions[8].correctAnswer) {
- weakAreas.push("standard library implementations");
- }
- if (answers[9] !== questions[9].correctAnswer) {
- weakAreas.push("partition step purpose");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Quick Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Quick Sort Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default QuickSortQuiz;
\ No newline at end of file
diff --git a/app/visualizer/sorting/selectionsort/animation.jsx b/app/visualizer/sorting/selectionsort/animation.jsx
deleted file mode 100755
index 00fbb6956..000000000
--- a/app/visualizer/sorting/selectionsort/animation.jsx
+++ /dev/null
@@ -1,274 +0,0 @@
-'use client';
-import React, { useState, useRef, useEffect } from 'react';
-import { gsap } from "gsap";
-import ArrayGenerator from '@/app/components/ui/randomArray';
-import CustomArrayInput from '@/app/components/ui/customArrayInput';
-
-const SelectionSortVisualizer = () => {
- const [array, setArray] = useState([]);
- const [sorting, setSorting] = useState(false);
- const [sorted, setSorted] = useState(false);
- const [speed, setSpeed] = useState(1);
- const [comparisons, setComparisons] = useState(0);
- const [swaps, setSwaps] = useState(0);
- const [currentIndices, setCurrentIndices] = useState({
- i: -1, // Current outer loop index
- j: -1, // Current inner loop index
- min: -1 // Current minimum element index
- });
- const animationRef = useRef(null);
-
- // Generate random array
- const handleGenerateRandomArray = (newArray) => {
- setArray(newArray);
- setSorted(false);
- resetStats();
- };
-
- // Use custom array input
- const handleCustomArray = (newArray) => {
- setArray(newArray);
- setSorted(false);
- resetStats();
- };
-
- // Reset all stats and state
- const resetStats = () => {
- setComparisons(0);
- setSwaps(0);
- setCurrentIndices({ i: -1, j: -1, min: -1 });
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
-
- // Selection sort algorithm
- const selectionSort = async () => {
- if (sorted || sorting || array.length === 0) return;
-
- setSorting(true);
- let arr = [...array];
- let n = arr.length;
- let tempSwaps = 0;
- let tempComparisons = 0;
-
- for (let i = 0; i < n - 1; i++) {
- let minIndex = i;
- setCurrentIndices({ i, j: i + 1, min: minIndex });
-
- for (let j = i + 1; j < n; j++) {
- setCurrentIndices(prev => ({ ...prev, j, min: minIndex }));
- tempComparisons++;
- setComparisons(tempComparisons);
-
- await new Promise(resolve =>
- animationRef.current = setTimeout(resolve, 1000 / speed)
- );
-
- if (arr[j] < arr[minIndex]) {
- minIndex = j;
- setCurrentIndices(prev => ({ ...prev, min: minIndex }));
-
- await new Promise(resolve =>
- animationRef.current = setTimeout(resolve, 1000 / speed)
- );
- }
- }
-
- if (minIndex !== i) {
- [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
- tempSwaps++;
- setSwaps(tempSwaps);
- setArray([...arr]);
-
- const barI = document.querySelectorAll(".array-bar")[i];
- const barMin = document.querySelectorAll(".array-bar")[minIndex];
- if (barI && barMin) {
- gsap.to([barI, barMin], {
- opacity: 0,
- scale: 0.5,
- duration: 0.2,
- onComplete: () => {
- gsap.to([barI, barMin], {
- opacity: 1,
- scale: 1,
- duration: 0.2
- });
- }
- });
- }
-
- await new Promise(resolve =>
- animationRef.current = setTimeout(resolve, 1000 / speed)
- );
- }
- }
-
- setArray([...arr]);
-
- const barI = document.querySelectorAll(".array-bar")[currentIndices.i];
- const barMin = document.querySelectorAll(".array-bar")[currentIndices.min];
- if (barI && barMin) {
- gsap.to([barI, barMin], {
- opacity: 0,
- scale: 0.5,
- duration: 0.2,
- onComplete: () => {
- gsap.to([barI, barMin], {
- opacity: 1,
- scale: 1,
- duration: 0.2
- });
- }
- });
- }
-
- setSorting(false);
- setSorted(true);
- setCurrentIndices({ i: -1, j: -1, min: -1 });
- };
-
- // Reset everything
- const reset = () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- setArray([]);
- setSorting(false);
- setSorted(false);
- resetStats();
- };
-
- // Clean up on unmount
- useEffect(() => {
- return () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
- }, []);
-
- return (
-
-
- Visualize Selection Sort as it repeatedly selects the smallest
- element and swaps it to its correct position in the array.
-
-
-
- {/* Controls */}
-
-
-
-
-
- {sorting ? "Sorting..." : "Start Selection Sort"}
-
-
- Reset All
-
-
-
-
- {/* Speed controls */}
-
- Speed:
- setSpeed(parseFloat(e.target.value))}
- className="w-32"
- disabled={sorting}
- />
-
- {speed}x
-
-
-
- {/* Stats */}
-
-
-
Comparisons:
-
{comparisons}
-
-
-
-
-
- {/* Visualization */}
-
-
- Array Visualization
-
- {array.length > 0 ? (
-
- {array.map((value, index) => {
- const isCurrent = index === currentIndices.j;
- const isMin = index === currentIndices.min;
- const isSorted = sorted || index < currentIndices.i;
-
- return (
-
-
- {value}
-
-
- {index === currentIndices.i && "i"}
- {index === currentIndices.j && "j"}
- {index === currentIndices.min && "min"}
-
-
- );
- })}
-
- ) : (
-
- {sorting
- ? "Sorting..."
- : "Generate or enter an array to begin"}
-
- )}
-
-
-
- );
- };
-
- export default SelectionSortVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/sorting/selectionsort/codeBlock.jsx b/app/visualizer/sorting/selectionsort/codeBlock.jsx
deleted file mode 100755
index f39d0885a..000000000
--- a/app/visualizer/sorting/selectionsort/codeBlock.jsx
+++ /dev/null
@@ -1,327 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Selection Sort in JavaScript
-function selectionSort(arr) {
- const n = arr.length;
-
- for (let i = 0; i < n - 1; i++) {
- // Find the minimum element in unsorted array
- let minIdx = i;
- for (let j = i + 1; j < n; j++) {
- if (arr[j] < arr[minIdx]) {
- minIdx = j;
- }
- }
-
- // Swap the found minimum with the first element
- [arr[i], arr[minIdx]] = [arr[minIdx], arr[i]];
- }
- return arr;
-}
-
-// Usage
-const arr = [64, 25, 12, 22, 11];
-console.log("Original:", arr);
-console.log("Sorted:", selectionSort([...arr]));`,
-
- python: `# Selection Sort in Python
-def selection_sort(arr):
- n = len(arr)
-
- for i in range(n - 1):
- # Find the minimum element in unsorted array
- min_idx = i
- for j in range(i + 1, n):
- if arr[j] < arr[min_idx]:
- min_idx = j
-
- # Swap the found minimum with the first element
- arr[i], arr[min_idx] = arr[min_idx], arr[i]
- return arr
-
-# Usage
-arr = [64, 25, 12, 22, 11]
-print("Original:", arr)
-print("Sorted:", selection_sort(arr.copy()))`,
-
- java: `// Selection Sort in Java
-public class SelectionSort {
- public static void selectionSort(int[] arr) {
- int n = arr.length;
-
- for (int i = 0; i < n - 1; i++) {
- // Find the minimum element in unsorted array
- int minIdx = i;
- for (int j = i + 1; j < n; j++) {
- if (arr[j] < arr[minIdx]) {
- minIdx = j;
- }
- }
-
- // Swap the found minimum with the first element
- int temp = arr[minIdx];
- arr[minIdx] = arr[i];
- arr[i] = temp;
- }
- }
-
- public static void main(String[] args) {
- int[] arr = {64, 25, 12, 22, 11};
- System.out.print("Original: ");
- printArray(arr);
-
- selectionSort(arr);
-
- System.out.print("Sorted: ");
- printArray(arr);
- }
-
- private static void printArray(int[] arr) {
- for (int num : arr) {
- System.out.print(num + " ");
- }
- System.out.println();
- }
-}`,
-
- c: `// Selection Sort in C
-#include
-
-void selectionSort(int arr[], int n) {
- for (int i = 0; i < n - 1; i++) {
- // Find the minimum element in unsorted array
- int minIdx = i;
- for (int j = i + 1; j < n; j++) {
- if (arr[j] < arr[minIdx]) {
- minIdx = j;
- }
- }
-
- // Swap the found minimum with the first element
- int temp = arr[minIdx];
- arr[minIdx] = arr[i];
- arr[i] = temp;
- }
-}
-
-void printArray(int arr[], int size) {
- for (int i = 0; i < size; i++) {
- printf("%d ", arr[i]);
- }
- printf("\\n");
-}
-
-int main() {
- int arr[] = {64, 25, 12, 22, 11};
- int n = sizeof(arr) / sizeof(arr[0]);
-
- printf("Original: ");
- printArray(arr, n);
-
- selectionSort(arr, n);
-
- printf("Sorted: ");
- printArray(arr, n);
-
- return 0;
-}`,
-
- cpp: `// Selection Sort in C++
-#include
-#include
-using namespace std;
-
-void selectionSort(vector& arr) {
- int n = arr.size();
-
- for (int i = 0; i < n - 1; i++) {
- // Find the minimum element in unsorted array
- int minIdx = i;
- for (int j = i + 1; j < n; j++) {
- if (arr[j] < arr[minIdx]) {
- minIdx = j;
- }
- }
-
- // Swap the found minimum with the first element
- swap(arr[i], arr[minIdx]);
- }
-}
-
-void printArray(const vector& arr) {
- for (int num : arr) {
- cout << num << " ";
- }
- cout << endl;
-}
-
-int main() {
- vector arr = {64, 25, 12, 22, 11};
-
- cout << "Original: ";
- printArray(arr);
-
- selectionSort(arr);
-
- cout << "Sorted: ";
- printArray(arr);
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Selection Sort Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/sorting/selectionsort/content.jsx b/app/visualizer/sorting/selectionsort/content.jsx
deleted file mode 100755
index 68947c54f..000000000
--- a/app/visualizer/sorting/selectionsort/content.jsx
+++ /dev/null
@@ -1,343 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 = [
- `Selection Sort is an in-place comparison sorting algorithm that divides the input list into two parts: a sorted sublist which is built up from left to right, and a remaining unsorted sublist. It repeatedly selects the smallest (or largest) element from the unsorted portion and moves it to the sorted portion.`,
- `The quadratic time complexity occurs because it performs O(n) comparisons for each of the O(n) elements.`,
- `Selection Sort is an in-place algorithm, requiring only O(1) additional space for temporary variables during swaps.`,
- `Selection Sort is primarily used for educational purposes to introduce sorting concepts. In practice, it's outperformed by more advanced algorithms like QuickSort and MergeSort, but can be useful when memory writes are expensive (since it makes only O(n) swaps).`,
- ];
-
- const working = [
- {
- pass: "First Pass:",
- points: [
- "Find the minimum in [64, 25, 12, 22, 11] → 11 at index 4",
- "Swap with first element → [11, 25, 12, 22, 64]",
- ],
- },
- {
- pass: "Second Pass:",
- points: [
- "Find minimum in [25, 12, 22, 64] → 12 at index 2",
- "Swap with first element → [11, 12, 25, 22, 64]",
- ],
- },
- {
- pass: "Third Pass:",
- points: [
- "Find minimum in [25, 22, 64] → 22 at index 2",
- "Swap with first element → [11, 12, 22, 25, 64]",
- ],
- },
- {
- pass: "Fourth Pass:",
- points: [
- "Find minimum in [25, 64] → 25 at index 0",
- "No swap needed → [11, 12, 22, 25, 64]",
- ],
- },
- { pass: "Result:", points: ["[11, 12, 22, 25, 64]"] },
- ];
-
- const algorithm = [
- { points: "Set the first element as minimum" },
- {
- points: "Compare minimum with the second element:",
- subpoints: ["If second element is smaller, set it as new minimum"],
- },
- { points: "Continue until last element is reached" },
- { points: "Swap minimum with first element" },
- { points: "Repeat for remaining unsorted portion" },
- ];
-
- const timeComplexity = [
- { points: "Best Case: ", subpoints: ["O(n²)"] },
- { points: "Average Case: ", subpoints: ["O(n²)"] },
- { points: "Worst Case: ", subpoints: ["O(n²)"] },
- ];
-
- const Advantages = [
- { points: "Simple to understand and implement" },
- { points: "Performs well on small lists" },
- { points: "Minimal memory usage (in-place sorting)" },
- { points: "Only O(n) swaps required (better than Bubble Sort)" },
- ];
-
- const Disadvantages = [
- { points: "Poor performance on large lists (quadratic time complexity)" },
- { points: "Not stable (may change relative order of equal elements)" },
- { points: "Less efficient than Insertion Sort for nearly sorted data" },
- { points: "Always performs O(n²) comparisons regardless of input" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is Selection Sort */}
-
-
-
- What is Selection Sort?
-
-
-
-
- {/* How Does It Work */}
-
-
-
- How Does It Work?
-
-
-
- Consider this unsorted array: [64, 25, 12, 22, 11]
-
-
-
- {working.map((items, index) => (
-
- {items.pass}
- {items.points && (
-
- {items.points.map((subitems, subindex) => (
-
- {subitems}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Algorithm Steps */}
-
-
-
- Algorithm Steps
-
-
-
- {algorithm.map((items, index) => (
-
- {items.points}
- {items.subpoints && (
-
- {items.subpoints.map((subitems, subindex) => (
-
- {subitems}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {timeComplexity.map((items, index) => (
-
-
- {items.points}
-
- {items.subpoints}
-
- ))}
-
-
-
- {paragraph[1]}
-
-
-
- n * n}
- averageCase={(n) => n * n}
- worstCase={(n) => n * n}
- maxN={25}
- />
-
-
-
-
- {/* Space Complexity */}
-
-
-
- Space Complexity
-
-
-
-
- {/* Advantages */}
-
-
-
- Advantages
-
-
-
- {Advantages.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Disadvantages */}
-
-
-
- Disadvantages
-
-
-
- {Disadvantages.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/sorting/selectionsort/page.jsx b/app/visualizer/sorting/selectionsort/page.jsx
deleted file mode 100755
index 0739e6dc4..000000000
--- a/app/visualizer/sorting/selectionsort/page.jsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import Animation from "@/app/visualizer/sorting/selectionsort/animation";
-import Navbar from "@/app/components/navbarinner";
-import BackToTopButton from "@/app/components/ui/backtotop";
-import Footer from "@/app/components/footer";
-import Content from '@/app/visualizer/sorting/selectionsort/content';
-import ExploreOther from "@/app/components/ui/exploreOther";
-import Code from "@/app/visualizer/sorting/selectionsort/codeBlock";
-import Quiz from "@/app/visualizer/sorting/selectionsort/quiz";
-import Breadcrumbs from "@/app/components/ui/Breadcrumbs";
-import ArticleActions from "@/app/components/ui/ArticleActions";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-
-export const metadata = {
- title:
- "Selection Sort Visualizer | Simple Sorting Animation with Code in JS, C, Python, Java",
- description:
- "Visualize Selection Sort in action with step-by-step animations and code examples in JavaScript, C, Python, and Java. A beginner-friendly way to understand this simple sorting algorithm using comparisons and swaps.",
- keywords: [
- "Selection Sort Visualizer",
- "Selection Sort Animation",
- "Selection Sort Algorithm",
- "DSA Selection Sort",
- "Learn Selection Sort",
- "Sorting Algorithm Visualization",
- "Interactive Sorting Tool",
- "Sorting for Beginners",
- "Step by Step Sorting",
- "Selection Sort in JavaScript",
- "Selection Sort in C",
- "Selection Sort in Python",
- "Selection Sort in Java",
- "Selection Sort Code Examples",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/sorting/selectionSort.png",
- width: 1200,
- height: 630,
- alt: "Selection Sort Algorithm Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visulaizer", href: "/visualizer" },
- { name: "Selection Sort", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
- Selection Sort
-
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/sorting/selectionsort/quiz.jsx b/app/visualizer/sorting/selectionsort/quiz.jsx
deleted file mode 100755
index 9fdd28dc1..000000000
--- a/app/visualizer/sorting/selectionsort/quiz.jsx
+++ /dev/null
@@ -1,438 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const SelectionSortQuiz = () => {
- const questions = [
- {
- question: "What is the basic principle of Selection Sort?",
- options: [
- "Dividing the list into smaller sublists",
- "Repeatedly finding the minimum element and swapping it with the current position",
- "Comparing adjacent elements and swapping if they're in the wrong order",
- "Merging two sorted lists into one"
- ],
- correctAnswer: 1,
- explanation: "Selection Sort works by repeatedly finding the minimum element from the unsorted part and putting it at the beginning."
- },
- {
- question: "What is the time complexity of Selection Sort in all cases?",
- options: [
- "O(n)",
- "O(n log n)",
- "O(n²)",
- "O(1)"
- ],
- correctAnswer: 2,
- explanation: "Selection Sort always requires O(n²) comparisons regardless of input order because it must scan all remaining elements for each position."
- },
- {
- question: "In the array [64, 25, 12, 22, 11], how many swaps occur during the entire sorting process?",
- options: [
- "1",
- "2",
- "4",
- "5"
- ],
- correctAnswer: 2,
- explanation: "Selection Sort makes only 4 swaps total (one for each element except the last): 64↔11, 25↔12, 22↔22 (no swap), and 64↔25."
- },
- {
- question: "What makes Selection Sort different from Bubble Sort?",
- options: [
- "Selection Sort is stable while Bubble Sort is not",
- "Selection Sort makes fewer swaps (O(n) vs O(n²))",
- "Bubble Sort has better worst-case time complexity",
- "Selection Sort requires additional O(n) space"
- ],
- correctAnswer: 1,
- explanation: "The key advantage of Selection Sort is that it makes only O(n) swaps compared to Bubble Sort's O(n²) swaps in worst case."
- },
- {
- question: "What is the space complexity of Selection Sort?",
- options: [
- "O(n)",
- "O(n log n)",
- "O(n²)",
- "O(1)"
- ],
- correctAnswer: 3,
- explanation: "Like Bubble Sort, Selection Sort is an in-place algorithm that only requires O(1) additional space for temporary storage during swaps."
- },
- {
- question: "Why is Selection Sort not considered stable?",
- options: [
- "Because it changes the relative order of equal elements",
- "Because its time complexity varies with input",
- "Because it requires recursive implementation",
- "Because it uses additional memory"
- ],
- correctAnswer: 0,
- explanation: "Selection Sort isn't stable because the swapping of elements can change the relative order of equal keys (e.g., [5a, 2, 5b] → [2, 5b, 5a])."
- },
- {
- question: "When might Selection Sort be preferred over other simple sorts?",
- options: [
- "When the input is already sorted",
- "When memory writes are expensive",
- "When stability is required",
- "When dealing with very large datasets"
- ],
- correctAnswer: 1,
- explanation: "Selection Sort's O(n) swaps make it useful when memory writes are expensive, even though it still requires O(n²) comparisons."
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = selectedAnswer;
- setAnswers(newAnswers);
-
- const newScore = newAnswers.reduce((acc, ans, idx) => {
- return ans === questions[idx].correctAnswer ? acc + 1 : acc;
- }, 0);
- setScore(newScore);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(newAnswers[currentQuestion + 1]);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Selection Sort Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default SelectionSortQuiz;
\ No newline at end of file
diff --git a/app/visualizer/stack/implementation/usingArray/codeBlock.jsx b/app/visualizer/stack/implementation/usingArray/codeBlock.jsx
deleted file mode 100755
index 27f1e5d38..000000000
--- a/app/visualizer/stack/implementation/usingArray/codeBlock.jsx
+++ /dev/null
@@ -1,530 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Stack Implementation using Array (JavaScript)
-class Stack {
- constructor(size = 10) {
- this.items = new Array(size);
- this.top = -1;
- this.capacity = size;
- }
-
- // Push operation
- push(element) {
- if (this.isFull()) {
- console.log("Stack Overflow");
- return;
- }
- this.items[++this.top] = element;
- }
-
- // Pop operation
- pop() {
- if (this.isEmpty()) {
- console.log("Stack Underflow");
- return undefined;
- }
- return this.items[this.top--];
- }
-
- // Peek operation
- peek() {
- if (this.isEmpty()) {
- console.log("Stack is empty");
- return undefined;
- }
- return this.items[this.top];
- }
-
- // Check if stack is empty
- isEmpty() {
- return this.top === -1;
- }
-
- // Check if stack is full
- isFull() {
- return this.top === this.capacity - 1;
- }
-
- // Get stack size
- size() {
- return this.top + 1;
- }
-
- // Print stack contents
- print() {
- if (this.isEmpty()) {
- console.log("Stack is empty");
- return;
- }
- console.log("Stack contents:");
- for (let i = this.top; i >= 0; i--) {
- console.log(this.items[i]);
- }
- }
-}
-
-// Usage
-const stack = new Stack(5);
-stack.push(10);
-stack.push(20);
-stack.push(30);
-console.log("Top element:", stack.peek()); // 30
-console.log("Stack size:", stack.size()); // 3
-stack.print();
-stack.pop();
-console.log("After pop, top element:", stack.peek()); // 20`,
-
- python: `# Stack Implementation using Array (Python)
-class Stack:
- def __init__(self, size=10):
- self.items = [None] * size
- self.top = -1
- self.capacity = size
-
- def push(self, element):
- if self.is_full():
- print("Stack Overflow")
- return
- self.top += 1
- self.items[self.top] = element
-
- def pop(self):
- if self.is_empty():
- print("Stack Underflow")
- return None
- element = self.items[self.top]
- self.top -= 1
- return element
-
- def peek(self):
- if self.is_empty():
- print("Stack is empty")
- return None
- return self.items[self.top]
-
- def is_empty(self):
- return self.top == -1
-
- def is_full(self):
- return self.top == self.capacity - 1
-
- def size(self):
- return self.top + 1
-
- def print_stack(self):
- if self.is_empty():
- print("Stack is empty")
- return
- print("Stack contents:")
- for i in range(self.top, -1, -1):
- print(self.items[i])
-
-# Usage
-stack = Stack(5)
-stack.push(10)
-stack.push(20)
-stack.push(30)
-print("Top element:", stack.peek()) # 30
-print("Stack size:", stack.size()) # 3
-stack.print_stack()
-stack.pop()
-print("After pop, top element:", stack.peek()) # 20`,
-
- java: `// Stack Implementation using Array (Java)
-public class ArrayStack {
- private int[] items;
- private int top;
- private int capacity;
-
- public ArrayStack(int size) {
- items = new int[size];
- top = -1;
- capacity = size;
- }
-
- public void push(int element) {
- if (isFull()) {
- System.out.println("Stack Overflow");
- return;
- }
- items[++top] = element;
- }
-
- public int pop() {
- if (isEmpty()) {
- System.out.println("Stack Underflow");
- return -1;
- }
- return items[top--];
- }
-
- public int peek() {
- if (isEmpty()) {
- System.out.println("Stack is empty");
- return -1;
- }
- return items[top];
- }
-
- public boolean isEmpty() {
- return top == -1;
- }
-
- public boolean isFull() {
- return top == capacity - 1;
- }
-
- public int size() {
- return top + 1;
- }
-
- public void print() {
- if (isEmpty()) {
- System.out.println("Stack is empty");
- return;
- }
- System.out.println("Stack contents:");
- for (int i = top; i >= 0; i--) {
- System.out.println(items[i]);
- }
- }
-
- public static void main(String[] args) {
- ArrayStack stack = new ArrayStack(5);
- stack.push(10);
- stack.push(20);
- stack.push(30);
- System.out.println("Top element: " + stack.peek()); // 30
- System.out.println("Stack size: " + stack.size()); // 3
- stack.print();
- stack.pop();
- System.out.println("After pop, top element: " + stack.peek()); // 20
- }
-}`,
-
- c: `// Stack Implementation using Array (C)
-#include
-#include
-#include
-
-#define DEFAULT_SIZE 10
-
-typedef struct {
- int *items;
- int top;
- int capacity;
-} Stack;
-
-void initialize(Stack *s, int size) {
- s->items = (int*)malloc(size * sizeof(int));
- s->top = -1;
- s->capacity = size;
-}
-
-bool isFull(Stack *s) {
- return s->top == s->capacity - 1;
-}
-
-bool isEmpty(Stack *s) {
- return s->top == -1;
-}
-
-void push(Stack *s, int element) {
- if (isFull(s)) {
- printf("Stack Overflow\n");
- return;
- }
- s->items[++s->top] = element;
-}
-
-int pop(Stack *s) {
- if (isEmpty(s)) {
- printf("Stack Underflow\n");
- return -1;
- }
- return s->items[s->top--];
-}
-
-int peek(Stack *s) {
- if (isEmpty(s)) {
- printf("Stack is empty\n");
- return -1;
- }
- return s->items[s->top];
-}
-
-int size(Stack *s) {
- return s->top + 1;
-}
-
-void print(Stack *s) {
- if (isEmpty(s)) {
- printf("Stack is empty\n");
- return;
- }
- printf("Stack contents:\n");
- for (int i = s->top; i >= 0; i--) {
- printf("%d\n", s->items[i]);
- }
-}
-
-void destroy(Stack *s) {
- free(s->items);
-}
-
-int main() {
- Stack stack;
- initialize(&stack, 5);
-
- push(&stack, 10);
- push(&stack, 20);
- push(&stack, 30);
- printf("Top element: %d\n", peek(&stack)); // 30
- printf("Stack size: %d\n", size(&stack)); // 3
- print(&stack);
- pop(&stack);
- printf("After pop, top element: %d\n", peek(&stack)); // 20
-
- destroy(&stack);
- return 0;
-}`,
-
- cpp: `// Stack Implementation using Array (C++)
-#include
-using namespace std;
-
-class ArrayStack {
-private:
- int* items;
- int top;
- int capacity;
-
-public:
- ArrayStack(int size = 10) {
- items = new int[size];
- top = -1;
- capacity = size;
- }
-
- ~ArrayStack() {
- delete[] items;
- }
-
- void push(int element) {
- if (isFull()) {
- cout << "Stack Overflow" << endl;
- return;
- }
- items[++top] = element;
- }
-
- int pop() {
- if (isEmpty()) {
- cout << "Stack Underflow" << endl;
- return -1;
- }
- return items[top--];
- }
-
- int peek() const {
- if (isEmpty()) {
- cout << "Stack is empty" << endl;
- return -1;
- }
- return items[top];
- }
-
- bool isEmpty() const {
- return top == -1;
- }
-
- bool isFull() const {
- return top == capacity - 1;
- }
-
- int size() const {
- return top + 1;
- }
-
- void print() const {
- if (isEmpty()) {
- cout << "Stack is empty" << endl;
- return;
- }
- cout << "Stack contents:" << endl;
- for (int i = top; i >= 0; i--) {
- cout << items[i] << endl;
- }
- }
-};
-
-int main() {
- ArrayStack stack(5);
- stack.push(10);
- stack.push(20);
- stack.push(30);
- cout << "Top element: " << stack.peek() << endl; // 30
- cout << "Stack size: " << stack.size() << endl; // 3
- stack.print();
- stack.pop();
- cout << "After pop, top element: " << stack.peek() << endl; // 20
-
- return 0;
-}`,
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Stack Implementation using Array
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/stack/implementation/usingArray/content.jsx b/app/visualizer/stack/implementation/usingArray/content.jsx
deleted file mode 100755
index c10af7141..000000000
--- a/app/visualizer/stack/implementation/usingArray/content.jsx
+++ /dev/null
@@ -1,274 +0,0 @@
-"use client";
-import React from "react";
-import { motion } from "framer-motion";
-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 push = [
- { points: "Check if stack is full" },
- { points: 'If full, return "Stack Overflow"' },
- { points: "Increment top pointer" },
- { points: "Store element at array[top]" },
- ];
-
- const pop = [
- { points: "Check if stack is empty" },
- { points: 'If empty, return "Stack Underflow"' },
- { points: "Access element at array[top]" },
- { points: "Decrement top pointer" },
- { points: "Return the element" },
- ];
-
- const peek = [
- { points: "Check if stack is empty" },
- { points: "If empty, return null" },
- { points: "Return array[top] without removal" },
- ];
-
- const isEmpty = [
- { points: "Return true if top pointer is -1" },
- { points: "Return false otherwise" },
- ];
-
- const initialize = [
- { points: "Create an empty array to store elements" },
- { points: "Initialize top pointer/index to -1" },
- { points: "Optional: Set maximum size limit" },
- ];
-
- const isFull = [
- { points: "Return true if top equals (max_size - 1)" },
- { points: "Return false otherwise" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* ------- HEADER ------- */}
-
-
-
- What is Stack Implementation Using Array?
-
-
-
- A stack is a linear data structure that follows the LIFO (Last In First Out) principle. Arrays provide a simple way to implement stack operations with constant time complexity.
-
-
-
-
- {/* ------- ALGORITHMIC STEPS – LIFT CARDS ------- */}
-
-
-
- Algorithmic Steps
-
-
-
- {/* Basic Operations */}
-
-
Stack Basic Operations
-
- {[{t:"Initialize Stack", s:initialize}, {t:"push()", s:push}, {t:"pop()", s:pop}].map(
- ({t, s}, idx) => (
-
-
- Step {idx + 1}
-
- {t}
-
- {s.map((p, i) => (
-
- {p.points}
-
- ))}
-
-
- )
- )}
-
-
-
- {/* Helper Operations */}
-
-
Stack Helper Operations
-
- {[{t:"peek()", s:peek}, {t:"isEmpty()", s:isEmpty}, {t:"isFull()", s:isFull}].map(
- ({t, s}, idx) => (
-
-
- Step {idx + 1}
-
- {t}
-
- {s.map((p, i) => (
-
- {p.points}
-
- ))}
-
-
- )
- )}
-
-
-
-
-
-
-
-
- Time Complexity
-
-
-
-
-
- Operation
- Complexity
- Reason
-
-
-
- {[
- ["push()", "O(1)", "Single array access"],
- ["pop()", "O(1)", "Single array access"],
- ["peek()", "O(1)", "Single array access"],
- ["isEmpty()", "O(1)", "Pointer comparison"],
- ].map(([op, comp, reason], index) => (
-
- {op}
- {comp}
- {reason}
-
- ))}
-
-
-
-
-
-
-
-
- Key Characteristics
-
-
-
- {[
- "LIFO Principle: Last element added is first removed",
- "Dynamic Size: Can grow until memory limits",
- "Efficiency: All operations work in constant time",
- "Versatility: Foundation for many algorithms",
- ].map((item) => (
-
- {item}
-
- ))}
-
-
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
\ No newline at end of file
diff --git a/app/visualizer/stack/implementation/usingArray/page.jsx b/app/visualizer/stack/implementation/usingArray/page.jsx
deleted file mode 100755
index c69e80d60..000000000
--- a/app/visualizer/stack/implementation/usingArray/page.jsx
+++ /dev/null
@@ -1,104 +0,0 @@
-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/implementation/usingArray/content";
-import Code from "@/app/visualizer/stack/implementation/usingArray/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:
- "Stack Implementation using Array | Learn Stack in DSA with JS, C, Python, Java Code",
- description:
- "Understand how to implement a Stack using an Array with visual explanations, animations, and complete code examples in JavaScript, C, Python, and Java. Perfect for DSA beginners and interview prep.",
- keywords: [
- "Stack using Array",
- "Stack Implementation",
- "Stack Implementation in JavaScript",
- "Stack Implementation in C",
- "Stack Implementation in Python",
- "Stack Implementation in Java",
- "DSA Stack",
- "Array Stack",
- "Data Structures Stack",
- "Stack Push Pop Array",
- "Learn Stack DSA",
- "Visualize Stack Implementation",
- "Stack Code Examples",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/stack/stackArray.png",
- width: 1200,
- height: 630,
- alt: "Stack Implementation using Array",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Stack : Implementation Using Array", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
- Implementation Using Array
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/stack/implementation/usingLinkedList/codeBlock.jsx b/app/visualizer/stack/implementation/usingLinkedList/codeBlock.jsx
deleted file mode 100755
index 2f095c28a..000000000
--- a/app/visualizer/stack/implementation/usingLinkedList/codeBlock.jsx
+++ /dev/null
@@ -1,562 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Stack Implementation using Linked List (JavaScript)
-class Node {
- constructor(value) {
- this.value = value;
- this.next = null;
- }
-}
-
-class LinkedListStack {
- constructor() {
- this.top = null;
- this.size = 0;
- }
-
- // Push operation
- push(value) {
- const newNode = new Node(value);
- newNode.next = this.top;
- this.top = newNode;
- this.size++;
- }
-
- // Pop operation
- pop() {
- if (this.isEmpty()) {
- console.log("Stack Underflow");
- return null;
- }
- const value = this.top.value;
- this.top = this.top.next;
- this.size--;
- return value;
- }
-
- // Peek operation
- peek() {
- if (this.isEmpty()) {
- console.log("Stack is empty");
- return null;
- }
- return this.top.value;
- }
-
- // Check if stack is empty
- isEmpty() {
- return this.size === 0;
- }
-
- // Get stack size
- getSize() {
- return this.size;
- }
-
- // Print stack contents
- print() {
- if (this.isEmpty()) {
- console.log("Stack is empty");
- return;
- }
- let current = this.top;
- console.log("Stack contents (top to bottom):");
- while (current) {
- console.log(current.value);
- current = current.next;
- }
- }
-}
-
-// Usage
-const stack = new LinkedListStack();
-stack.push(10);
-stack.push(20);
-stack.push(30);
-console.log("Top element:", stack.peek()); // 30
-console.log("Stack size:", stack.getSize()); // 3
-stack.print();
-stack.pop();
-console.log("After pop, top element:", stack.peek()); // 20`,
-
- python: `# Stack Implementation using Linked List (Python)
-class Node:
- def __init__(self, value):
- self.value = value
- self.next = None
-
-class LinkedListStack:
- def __init__(self):
- self.top = None
- self.size = 0
-
- def push(self, value):
- new_node = Node(value)
- new_node.next = self.top
- self.top = new_node
- self.size += 1
-
- def pop(self):
- if self.is_empty():
- print("Stack Underflow")
- return None
- value = self.top.value
- self.top = self.top.next
- self.size -= 1
- return value
-
- def peek(self):
- if self.is_empty():
- print("Stack is empty")
- return None
- return self.top.value
-
- def is_empty(self):
- return self.size == 0
-
- def get_size(self):
- return self.size
-
- def print_stack(self):
- if self.is_empty():
- print("Stack is empty")
- return
- current = self.top
- print("Stack contents (top to bottom):")
- while current:
- print(current.value)
- current = current.next
-
-# Usage
-stack = LinkedListStack()
-stack.push(10)
-stack.push(20)
-stack.push(30)
-print("Top element:", stack.peek()) # 30
-print("Stack size:", stack.get_size()) # 3
-stack.print_stack()
-stack.pop()
-print("After pop, top element:", stack.peek()) # 20`,
-
- java: `// Stack Implementation using Linked List (Java)
-class Node {
- int value;
- Node next;
-
- public Node(int value) {
- this.value = value;
- this.next = null;
- }
-}
-
-public class LinkedListStack {
- private Node top;
- private int size;
-
- public LinkedListStack() {
- top = null;
- size = 0;
- }
-
- public void push(int value) {
- Node newNode = new Node(value);
- newNode.next = top;
- top = newNode;
- size++;
- }
-
- public int pop() {
- if (isEmpty()) {
- System.out.println("Stack Underflow");
- return -1;
- }
- int value = top.value;
- top = top.next;
- size--;
- return value;
- }
-
- public int peek() {
- if (isEmpty()) {
- System.out.println("Stack is empty");
- return -1;
- }
- return top.value;
- }
-
- public boolean isEmpty() {
- return size == 0;
- }
-
- public int getSize() {
- return size;
- }
-
- public void print() {
- if (isEmpty()) {
- System.out.println("Stack is empty");
- return;
- }
- Node current = top;
- System.out.println("Stack contents (top to bottom):");
- while (current != null) {
- System.out.println(current.value);
- current = current.next;
- }
- }
-
- public static void main(String[] args) {
- LinkedListStack stack = new LinkedListStack();
- stack.push(10);
- stack.push(20);
- stack.push(30);
- System.out.println("Top element: " + stack.peek()); // 30
- System.out.println("Stack size: " + stack.getSize()); // 3
- stack.print();
- stack.pop();
- System.out.println("After pop, top element: " + stack.peek()); // 20
- }
-}`,
-
- c: `// Stack Implementation using Linked List (C)
-#include
-#include
-#include
-
-typedef struct Node {
- int value;
- struct Node* next;
-} Node;
-
-typedef struct {
- Node* top;
- int size;
-} LinkedListStack;
-
-void initialize(LinkedListStack* s) {
- s->top = NULL;
- s->size = 0;
-}
-
-void push(LinkedListStack* s, int value) {
- Node* newNode = (Node*)malloc(sizeof(Node));
- newNode->value = value;
- newNode->next = s->top;
- s->top = newNode;
- s->size++;
-}
-
-int pop(LinkedListStack* s) {
- if (s->size == 0) {
- printf("Stack Underflow\n");
- return -1;
- }
- Node* temp = s->top;
- int value = temp->value;
- s->top = s->top->next;
- free(temp);
- s->size--;
- return value;
-}
-
-int peek(LinkedListStack* s) {
- if (s->size == 0) {
- printf("Stack is empty\n");
- return -1;
- }
- return s->top->value;
-}
-
-bool isEmpty(LinkedListStack* s) {
- return s->size == 0;
-}
-
-int size(LinkedListStack* s) {
- return s->size;
-}
-
-void print(LinkedListStack* s) {
- if (s->size == 0) {
- printf("Stack is empty\n");
- return;
- }
- Node* current = s->top;
- printf("Stack contents (top to bottom):\n");
- while (current != NULL) {
- printf("%d\n", current->value);
- current = current->next;
- }
-}
-
-void destroy(LinkedListStack* s) {
- while (s->top != NULL) {
- Node* temp = s->top;
- s->top = s->top->next;
- free(temp);
- }
-}
-
-int main() {
- LinkedListStack stack;
- initialize(&stack);
-
- push(&stack, 10);
- push(&stack, 20);
- push(&stack, 30);
- printf("Top element: %d\n", peek(&stack)); // 30
- printf("Stack size: %d\n", size(&stack)); // 3
- print(&stack);
- pop(&stack);
- printf("After pop, top element: %d\n", peek(&stack)); // 20
-
- destroy(&stack);
- return 0;
-}`,
-
- cpp: `// Stack Implementation using Linked List (C++)
-#include
-using namespace std;
-
-class Node {
-public:
- int value;
- Node* next;
-
- Node(int val) : value(val), next(nullptr) {}
-};
-
-class LinkedListStack {
-private:
- Node* top;
- int size;
-
-public:
- LinkedListStack() : top(nullptr), size(0) {}
-
- ~LinkedListStack() {
- while (!isEmpty()) {
- pop();
- }
- }
-
- void push(int value) {
- Node* newNode = new Node(value);
- newNode->next = top;
- top = newNode;
- size++;
- }
-
- int pop() {
- if (isEmpty()) {
- cout << "Stack Underflow" << endl;
- return -1;
- }
- Node* temp = top;
- int value = temp->value;
- top = top->next;
- delete temp;
- size--;
- return value;
- }
-
- int peek() {
- if (isEmpty()) {
- cout << "Stack is empty" << endl;
- return -1;
- }
- return top->value;
- }
-
- bool isEmpty() {
- return size == 0;
- }
-
- int getSize() {
- return size;
- }
-
- void print() {
- if (isEmpty()) {
- cout << "Stack is empty" << endl;
- return;
- }
- Node* current = top;
- cout << "Stack contents (top to bottom):" << endl;
- while (current != nullptr) {
- cout << current->value << endl;
- current = current->next;
- }
- }
-};
-
-int main() {
- LinkedListStack stack;
-
- stack.push(10);
- stack.push(20);
- stack.push(30);
- cout << "Top element: " << stack.peek() << endl; // 30
- cout << "Stack size: " << stack.getSize() << endl; // 3
- stack.print();
- stack.pop();
- cout << "After pop, top element: " << stack.peek() << endl; // 20
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Stack Implementation using Linked-List
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/stack/implementation/usingLinkedList/content.jsx b/app/visualizer/stack/implementation/usingLinkedList/content.jsx
deleted file mode 100755
index 710fa3cb1..000000000
--- a/app/visualizer/stack/implementation/usingLinkedList/content.jsx
+++ /dev/null
@@ -1,306 +0,0 @@
-"use client";
-import React from "react";
-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 = [
- `A stack implemented using a linked list follows the LIFO (Last In First Out) principle. Unlike array implementation, linked list stacks dynamically allocate memory for each element and don't have size limitations (until memory is exhausted).`,
- ];
-
- const opeartions = [
- { points : "Initialize Stack",
- subpoints : [
- "Create a head pointer initialized to null.",
- "Optional: Maintain a size counter initialized to 0.",
- ],
- },
- { points : "push()",
- subpoints : [
- "Create a new node with the given data.",
- "Set new node's next pointer to current head.",
- "Update head to point to the new node.",
- "Increment size counter (if maintained).",
- ],
- },
- { points : "pop()",
- subpoints : [
- "Check if stack is empty (head is null).",
- `If empty, return "Stack Underflow".`,
- "Store current head node in a temporary variabl.",
- "Update head to point to the next node.",
- "Decrement size counter (if maintained).",
- "Return data from the temporary node.",
- ],
- },
- ];
-
- const helper = [
- { points : "peek()",
- subpoints : [
- "Check if stack is empty (head is null).",
- "If empty, return null.",
- "Return data from head node without removal.",
- ],
- },
- { points : "isEmpty()",
- subpoints : [
- "Return true if head is null.",
- "Return false otherwise.",
- ],
- },
- { points : "size()",
- subpoints : [
- "If size counter is maintained, return its value.",
- "Otherwise, traverse the list and count nodes.",
- ],
- },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* Header Section */}
-
-
-
- What is Stack Implementation Using Linked List?
-
-
-
-
- {/* Algorithmic Steps */}
-
-
-
- Algorithmic Steps
-
-
-
- {/* Stack Basic Operations */}
-
-
- Stack Basic Operations
-
-
-
-
-
- {opeartions.map((item, index) => (
-
-
- {item.points}
-
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
-
- {/* Stack Helper Operations */}
-
-
- Stack Helper Operations
-
-
-
-
-
- {helper.map((item, index) => (
-
-
- {item.points}
-
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
-
-
- Operation
- Complexity
-
- Reason
-
-
-
-
- {[
- ["push()", "O(1)", "Only head pointer modification"],
- ["pop()", "O(1)", "Only head pointer modification"],
- ["peek()", "O(1)", "Single node access"],
- ["isEmpty()", "O(1)", "Head pointer check"],
- ["size()", "O(1) or O(n)", "Depends on counter implementation"],
- ].map(([op, comp, reason], index) => (
-
- {op}
-
- {comp}
-
-
- {reason}
-
-
- ))}
-
-
-
-
-
- {/* Key Characteristics */}
-
-
-
- Key Characteristics
-
-
-
- {[
- "Dynamic Size: No fixed capacity (grows as needed)",
- "Memory Efficiency: Uses only needed memory",
- "No Wasted Space: Unlike array implementation",
- "Extra Memory: Requires space for pointers",
- "Flexibility: Can grow until memory exhausted",
- ].map((item) => (
-
- {item}
-
- ))}
-
-
-
-
- {/* Comparison Section */}
-
-
-
- Linked List vs Array Implementation
-
-
-
-
-
- Feature
- Linked List
- Array
-
-
-
- {[
- ["Memory Usage", "Extra for pointers", "Fixed size, may be wasted"],
- ["Dynamic Size", "Yes", "No (unless resized)"],
- ["Memory Allocation", "Dynamic", "Static (usually)"],
- ["Access Time", "O(1) for top", "O(1) for all"],
- ["Implementation Complexity", "Slightly more complex", "Simpler"],
- ].map(([feature, ll, arr], index) => (
-
- {feature}
-
- {ll}
-
-
- {arr}
-
-
- ))}
-
-
-
-
-
-
- );
- };
-
- export default content;
\ No newline at end of file
diff --git a/app/visualizer/stack/implementation/usingLinkedList/page.jsx b/app/visualizer/stack/implementation/usingLinkedList/page.jsx
deleted file mode 100755
index d8cbc2a94..000000000
--- a/app/visualizer/stack/implementation/usingLinkedList/page.jsx
+++ /dev/null
@@ -1,106 +0,0 @@
-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/implementation/usingLinkedList/content";
-import Code from "@/app/visualizer/stack/implementation/usingLinkedList/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:
- "Stack Implementation using Linked List | Learn Stack in DSA with JS, C, Python, Java Code",
- description:
- "Explore how to implement a Stack using a Linked List with step-by-step visual explanations, animations, and complete code in JavaScript, C, Python, and Java. Ideal for DSA learners and coding interview prep.",
- keywords: [
- "Stack using Linked List",
- "Stack Implementation",
- "Stack Implementation in JavaScript",
- "Stack Implementation in C",
- "Stack Implementation in Python",
- "Stack Implementation in Java",
- "Linked List Stack",
- "DSA Stack",
- "Data Structures Stack",
- "Stack Push Pop Linked List",
- "Learn Stack DSA",
- "Visualize Stack Implementation",
- "Stack Code Examples",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/stack/stackLinkedList.png",
- width: 1200,
- height: 630,
- alt: "Stack Implementation using Linked List",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Stack : Implementation Using Linked List", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
- Implementation Using Linked List
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/stack/isempty/animation.jsx b/app/visualizer/stack/isempty/animation.jsx
deleted file mode 100755
index 7728f8f1f..000000000
--- a/app/visualizer/stack/isempty/animation.jsx
+++ /dev/null
@@ -1,274 +0,0 @@
-"use client";
-import React, { useState, useEffect, useRef } from "react";
-import { gsap } from "gsap";
-
-const StackVisualizer = () => {
- /* ---------- state ---------- */
- const [stack, setStack] = useState([]);
- const [inputValue, setInputValue] = useState("");
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("Stack is empty");
- const [isAnimating, setIsAnimating] = useState(false);
- const [peekedItem, setPeekedItem] = useState(null);
- const [isEmptyStatus, setIsEmptyStatus] = useState(null);
-
- const itemRefs = useRef([]);
-
- /* ---------- helpers ---------- */
- const resetRefs = () => (itemRefs.current = []);
-
- /* ---------- push ---------- */
- const push = () => {
- const val = inputValue.trim();
- if (!val) {
- setMessage("Please enter a value to push");
- return;
- }
- setIsAnimating(true);
- setOperation(`Pushing "${val}"…`);
- setMessage("");
- setPeekedItem(null);
- setIsEmptyStatus(null);
-
- setStack((prev) => [val, ...prev]);
-
- setTimeout(() => {
- const el = itemRefs.current[0];
- gsap.set(el, { y: -60, scale: 0.8, opacity: 0 });
- gsap
- .timeline({ onComplete: () => setIsAnimating(false) })
- .to(el, { y: 0, scale: 1, opacity: 1, duration: 0.4, ease: "back.out(1.7)" })
- .to(el, { boxShadow: "0 0 10px #3b82f6", duration: 0.2, yoyo: true, repeat: 1 }, "-=0.2")
- .call(() => setMessage(`"${val}" pushed to stack!`));
- }, 10);
-
- setInputValue("");
- };
-
- /* ---------- pop ---------- */
- const pop = () => {
- if (stack.length === 0) {
- setMessage("Stack is empty!");
- setIsEmptyStatus(true);
- return;
- }
- setIsAnimating(true);
- const val = stack[0];
- setOperation(`Popping "${val}"…`);
- setMessage("");
- setPeekedItem(null);
- setIsEmptyStatus(null);
-
- const el = itemRefs.current[0];
- gsap
- .timeline({ onComplete: () => {
- setStack((prev) => prev.slice(1));
- setIsAnimating(false);
- setMessage(`"${val}" popped from stack!`);
- } })
- .to(el, { scale: 0.5, rotation: 15, y: 80, opacity: 0, duration: 0.5, ease: "power2.in" });
- };
-
- /* ---------- peek ---------- */
- const peek = () => {
- if (stack.length === 0) {
- setMessage("Stack is empty!");
- setIsEmptyStatus(true);
- return;
- }
- setIsAnimating(true);
- setOperation("Peeking at top element…");
- setPeekedItem(stack[0]);
- setIsEmptyStatus(false);
-
- const el = itemRefs.current[0];
- gsap
- .timeline({ onComplete: () => setIsAnimating(false) })
- .to(el, { y: -6, boxShadow: "0 0 15px #a855f7", duration: 0.25 })
- .to(el, { y: 0, boxShadow: "0 0 0px transparent", duration: 0.25 })
- .to(el, { y: -6, duration: 0.25 })
- .to(el, { y: 0, duration: 0.25 })
- .call(() => setMessage(`Top element is "${stack[0]}"`));
- };
-
- /* ---------- isEmpty ---------- */
- const checkEmpty = () => {
- setIsAnimating(true);
- setOperation("Checking if stack is empty…");
- setPeekedItem(null);
- setTimeout(() => {
- const empty = stack.length === 0;
- setIsEmptyStatus(empty);
- setOperation(null);
- setMessage(empty ? "Stack is empty!" : "Stack is not empty");
- setIsAnimating(false);
- }, 1000);
- };
-
- /* ---------- reset ---------- */
- const reset = () => {
- setIsAnimating(true);
- gsap.to(itemRefs.current.filter(Boolean), {
- scale: 0,
- y: -60,
- opacity: 0,
- stagger: 0.06,
- duration: 0.3,
- onComplete: () => {
- setStack([]);
- setInputValue("");
- setOperation(null);
- setMessage("Stack is empty");
- setPeekedItem(null);
- setIsEmptyStatus(null);
- setIsAnimating(false);
- resetRefs();
- },
- });
- };
-
- return (
-
-
- Visualize Push, Pop, Peek, and IsEmpty operations
-
-
-
- {/* Controls */}
-
-
- setInputValue(e.target.value)}
- placeholder="Enter a value"
- className="flex-1 p-2 rounded dark:bg-neutral-900 border"
- disabled={isAnimating}
- />
-
- Push
-
-
-
-
- IsEmpty
-
-
- Reset
-
-
-
-
- {/* Stack Visualization */}
-
-
Stack Visualization
-
- {/* Operation Status */}
- {operation && (
-
- {operation}
-
- )}
-
- {/* Message Display */}
- {message && (
-
- {message}
-
- )}
-
- {/* Vertical Stack */}
-
- {/* Top indicator */}
-
- {stack.length > 0 ? "↑ Top" : ""}
-
-
-
- {stack.length === 0 ? (
-
- ) : (
-
- {stack.map((item, index) => (
-
(itemRefs.current[index] = el)}
- className={`p-3 border-2 rounded text-center font-medium transition-all ${
- index === 0 && peekedItem !== null
- ? "bg-purple-200 dark:bg-purple-800 border-purple-400 dark:border-purple-600"
- : index === 0
- ? "bg-blue-100 dark:bg-blue-900 border-blue-300 dark:border-blue-700"
- : "bg-white dark:bg-gray-700 border-gray-200 dark:border-gray-600"
- }`}
- >
- {item}
-
- ))}
-
- )}
-
-
- {/* Bottom indicator */}
-
- {stack.length > 0 ? "↓ Bottom" : ""}
-
-
-
-
-
- );
-};
-
-/* ---------- cute floating cloud (empty) ---------- */
-const EmptyCloud = () => {
- const cloudRef = useRef(null);
- useEffect(() => {
- gsap.to(cloudRef.current, { y: -6, duration: 2, repeat: -1, yoyo: true, ease: "power1.inOut" });
- }, []);
- return (
-
- );
-};
-
-export default StackVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/stack/isempty/codeBlock.jsx b/app/visualizer/stack/isempty/codeBlock.jsx
deleted file mode 100755
index 3d0df8fca..000000000
--- a/app/visualizer/stack/isempty/codeBlock.jsx
+++ /dev/null
@@ -1,451 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Stack Implementation with isEmpty Operation in JavaScript
-class Stack {
- constructor() {
- this.items = [];
- this.top = -1;
- }
-
- // Push operation
- push(element) {
- this.items[++this.top] = element;
- console.log(\`Pushed: \${element}\`);
- }
-
- // Pop operation
- pop() {
- if (this.isEmpty()) {
- console.log("Stack Underflow - Cannot pop from empty stack");
- return -1;
- }
- return this.items[this.top--];
- }
-
- // Check if stack is empty
- isEmpty() {
- const empty = this.top === -1;
- console.log(\`Stack is \${empty ? "empty" : "not empty"}\`);
- return empty;
- }
-
- // Display stack
- display() {
- console.log("Current Stack:", this.items.slice(0, this.top + 1));
- }
-}
-
-// Usage
-const stack = new Stack();
-console.log("Initial stack check:");
-stack.isEmpty(); // true
-
-stack.push(10);
-stack.push(20);
-stack.display();
-stack.isEmpty(); // false
-
-stack.pop();
-stack.pop();
-stack.isEmpty(); // true`,
-
- python: `# Stack Implementation with isEmpty Operation in Python
-class Stack:
- def __init__(self):
- self.items = []
- self.top = -1
-
- # Push operation
- def push(self, element):
- self.top += 1
- self.items.append(element)
- print(f"Pushed: {element}")
-
- # Pop operation
- def pop(self):
- if self.is_empty():
- print("Stack Underflow - Cannot pop from empty stack")
- return -1
- return self.items.pop()
-
- # Check if stack is empty
- def is_empty(self):
- empty = self.top == -1
- print(f"Stack is {'empty' if empty else 'not empty'}")
- return empty
-
- # Display stack
- def display(self):
- print("Current Stack:", self.items)
-
-# Usage
-stack = Stack()
-print("Initial stack check:")
-stack.is_empty() # True
-
-stack.push(10)
-stack.push(20)
-stack.display()
-stack.is_empty() # False
-
-stack.pop()
-stack.pop()
-stack.is_empty() # True`,
-
- java: `// Stack Implementation with isEmpty Operation in Java
-import java.util.ArrayList;
-
-class Stack {
- private ArrayList items;
- private int top;
-
- public Stack() {
- items = new ArrayList<>();
- top = -1;
- }
-
- // Push operation
- public void push(int element) {
- items.add(++top, element);
- System.out.println("Pushed: " + element);
- }
-
- // Pop operation
- public int pop() {
- if (isEmpty()) {
- System.out.println("Stack Underflow - Cannot pop from empty stack");
- return -1;
- }
- return items.remove(top--);
- }
-
- // Check if stack is empty
- public boolean isEmpty() {
- boolean empty = top == -1;
- System.out.println("Stack is " + (empty ? "empty" : "not empty"));
- return empty;
- }
-
- // Display stack
- public void display() {
- System.out.print("Current Stack: ");
- for (int i = 0; i <= top; i++) {
- System.out.print(items.get(i) + " ");
- }
- System.out.println();
- }
-}
-
-public class Main {
- public static void main(String[] args) {
- Stack stack = new Stack();
- System.out.println("Initial stack check:");
- stack.isEmpty(); // true
-
- stack.push(10);
- stack.push(20);
- stack.display();
- stack.isEmpty(); // false
-
- stack.pop();
- stack.pop();
- stack.isEmpty(); // true
- }
-}`,
-
- c: `// Stack Implementation with isEmpty Operation in C
-#include
-#include
-#define MAX_SIZE 100
-
-typedef struct {
- int items[MAX_SIZE];
- int top;
-} Stack;
-
-void initialize(Stack *s) {
- s->top = -1;
-}
-
-// Push operation
-void push(Stack *s, int element) {
- if (s->top == MAX_SIZE - 1) {
- printf("Stack Overflow\n");
- return;
- }
- s->items[++s->top] = element;
- printf("Pushed: %d\n", element);
-}
-
-// Pop operation
-int pop(Stack *s) {
- if (isEmpty(s)) {
- printf("Stack Underflow - Cannot pop from empty stack\n");
- return -1;
- }
- return s->items[s->top--];
-}
-
-// Check if stack is empty
-bool isEmpty(Stack *s) {
- bool empty = s->top == -1;
- printf("Stack is %s\n", empty ? "empty" : "not empty");
- return empty;
-}
-
-// Display stack
-void display(Stack *s) {
- printf("Current Stack: ");
- for (int i = 0; i <= s->top; i++) {
- printf("%d ", s->items[i]);
- }
- printf("\n");
-}
-
-int main() {
- Stack stack;
- initialize(&stack);
-
- printf("Initial stack check:\n");
- isEmpty(&stack); // true
-
- push(&stack, 10);
- push(&stack, 20);
- display(&stack);
- isEmpty(&stack); // false
-
- pop(&stack);
- pop(&stack);
- isEmpty(&stack); // true
-
- return 0;
-}`,
-
- cpp: `// Stack Implementation with isEmpty Operation in C++
-#include
-#include
-using namespace std;
-
-class Stack {
-private:
- vector items;
- int top;
- const int MAX_SIZE = 100;
-
-public:
- Stack() : top(-1) {}
-
- // Push operation
- void push(int element) {
- if (top == MAX_SIZE - 1) {
- cout << "Stack Overflow" << endl;
- return;
- }
- items.push_back(element);
- top++;
- cout << "Pushed: " << element << endl;
- }
-
- // Pop operation
- int pop() {
- if (isEmpty()) {
- cout << "Stack Underflow - Cannot pop from empty stack" << endl;
- return -1;
- }
- int element = items.back();
- items.pop_back();
- top--;
- return element;
- }
-
- // Check if stack is empty
- bool isEmpty() const {
- bool empty = top == -1;
- cout << "Stack is " << (empty ? "empty" : "not empty") << endl;
- return empty;
- }
-
- // Display stack
- void display() const {
- cout << "Current Stack: ";
- for (int i = 0; i <= top; i++) {
- cout << items[i] << " ";
- }
- cout << endl;
- }
-};
-
-int main() {
- Stack stack;
-
- cout << "Initial stack check:" << endl;
- stack.isEmpty(); // true
-
- stack.push(10);
- stack.push(20);
- stack.display();
- stack.isEmpty(); // false
-
- stack.pop();
- stack.pop();
- stack.isEmpty(); // true
-
- return 0;
-}`,
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Stack Push & Pop Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/stack/isempty/content.jsx b/app/visualizer/stack/isempty/content.jsx
deleted file mode 100755
index 62ade3063..000000000
--- a/app/visualizer/stack/isempty/content.jsx
+++ /dev/null
@@ -1,261 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 paragraphs = [
- `The isEmpty operation checks whether a stack contains any elements or not. It's a fundamental operation that helps prevent errors when trying to perform operations like pop() or peek() on an empty stack.`,
- `The isEmpty operation is a simple but crucial part of stack implementation, ensuring safe stack manipulation and preventing runtime errors.`,
- ];
-
- const usage = [
- { points : "Prevent stack underflow errors before pop() operations." },
- { points : "Check if there are elements to process." },
- { points : "Validate stack state in algorithms." },
- { points : "Terminate processing loops when stack becomes empty." },
- ];
-
- const working = [
- { points : "For an empty stack [ ],isEmpty() returns true." },
- { points : "For a non-empty stack [5, 3, 8],isEmpty() returns false." },
- ];
-
- const implementation = [
- { points : "Check the current size/length of the stack" },
- { points : "Return the result :",
- subpoints : [
- "true if size equals 0.",
- "false otherwise.",
- ],
- },
- ];
-
- const complexity = [
- { points : "O(1) constant time complexity." },
- { points : "The operation only needs to check one value (size/length) regardless of stack size." },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is the isEmpty Operation in Stack? */}
-
-
-
- What is the isEmpty Operation in Stack?
-
-
-
-
- {/* How Does It Work? */}
-
-
-
- How Does It Work?
-
-
-
- Consider a stack represented as an array: [ ] (empty) or [5, 3,
- 8] (with elements).
-
-
-
- {working.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
- The operation simply checks if the stack's size/length is zero.
-
-
-
-
- {/* Algorithm Implementation */}
-
-
-
- Algorithm Implementation
-
-
-
- {implementation.map((item, index) => (
-
- {item.points}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
-
- {/* Time Complexity */}
-
-
-
- Time Complexity
-
-
-
- {complexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
-
- 1}
- averageCase={(n) => 1}
- worstCase={(n) => 1}
- maxN={25}
- />
-
-
-
-
- {/* Practical Usage */}
-
-
-
- Practical Usage
-
-
-
- {usage.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
- };
-
- export default content;
\ No newline at end of file
diff --git a/app/visualizer/stack/isempty/page.jsx b/app/visualizer/stack/isempty/page.jsx
deleted file mode 100755
index 135e134f7..000000000
--- a/app/visualizer/stack/isempty/page.jsx
+++ /dev/null
@@ -1,119 +0,0 @@
-import Animation from "@/app/visualizer/stack/isempty/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/isempty/content";
-import Quiz from "@/app/visualizer/stack/isempty/quiz";
-import Code from "@/app/visualizer/stack/isempty/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import Footer from "@/app/components/footer";
-import BackToTopButton from "@/app/components/ui/backtotop";
-
-export const metadata = {
- title:
- "Stack is empty Visualizer | Learn Stack IsEmpty Operation in JS, C, Python, Java",
- description:
- "Visualize how Stack isEmpty operation works in DSA using interactive animations. Great for beginners and interview prep. Includes code examples in JavaScript, C, Python, and Java.",
- keywords: [
- "Stack DSA",
- "Stack Visualizer",
- "Learn Stack",
- "DSA Animation",
- "Stack isEmpty Operation",
- "Check if Stack is Empty",
- "Stack Implementation in JavaScript",
- "Stack Implementation in C",
- "Stack in Python",
- "Stack in Java",
- "Stack Code Examples",
- "Interactive Stack Tool",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/stack/isEmpty.png",
- width: 1200,
- height: 630,
- alt: "Stack isEmpty Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Stack : IsEmpty", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- IsEmpty Operation
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/stack/isempty/quiz.jsx b/app/visualizer/stack/isempty/quiz.jsx
deleted file mode 100755
index 5cde2bf7e..000000000
--- a/app/visualizer/stack/isempty/quiz.jsx
+++ /dev/null
@@ -1,411 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const StackQuiz = () => {
- const questions = [
- {
- question: "What does the isEmpty operation in a stack determine?",
- options: [
- "The total capacity of the stack",
- "Whether the stack contains any elements",
- "The position of the top element",
- "The time complexity of other operations"
- ],
- correctAnswer: 1,
- explanation:
- "isEmpty checks if the stack has zero elements (true if empty, false otherwise).",
- },
- {
- question: "What does isEmpty() return for a stack with elements [10, 20]?",
- options: ["true", "false", "null", "10"],
- correctAnswer: 1,
- explanation:
- "The stack contains elements, so isEmpty returns false.",
- },
- {
- question: "Why is isEmpty crucial before calling pop() or peek()?",
- options: [
- "To improve time complexity",
- "To prevent stack underflow errors",
- "To resize the stack",
- "To count the elements"
- ],
- correctAnswer: 1,
- explanation:
- "Checking isEmpty first avoids errors when attempting to pop/peek an empty stack.",
- },
- {
- question: "What is the time complexity of isEmpty?",
- options: ["O(n)", "O(1)", "O(log n)", "O(n²)"],
- correctAnswer: 1,
- explanation:
- "isEmpty runs in O(1) time as it only checks if size/length equals zero.",
- },
- {
- question: "How would you implement isEmpty for a stack stored in an array?",
- options: [
- "Check if array[0] === null",
- "Return array.length === 0",
- "Compare top and bottom indices",
- "Count all non-zero elements"
- ],
- correctAnswer: 1,
- explanation:
- "For array-based stacks, isEmpty simply verifies if the length is zero.",
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = selectedAnswer;
- setAnswers(newAnswers);
-
- const newScore = newAnswers.reduce((acc, ans, idx) => {
- return ans === questions[idx].correctAnswer ? acc + 1 : acc;
- }, 0);
- setScore(newScore);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(newAnswers[currentQuestion + 1]);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Stack Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default StackQuiz;
\ No newline at end of file
diff --git a/app/visualizer/stack/isfull/animation.jsx b/app/visualizer/stack/isfull/animation.jsx
deleted file mode 100755
index 8b85d3e79..000000000
--- a/app/visualizer/stack/isfull/animation.jsx
+++ /dev/null
@@ -1,161 +0,0 @@
-"use client";
-import React, { useState, useEffect } from "react";
-import PushPop from "@/app/components/ui/PushPop";
-
-const StackVisualizer = () => {
- const [stack, setStack] = useState([]);
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("Stack is empty");
- const [isAnimating, setIsAnimating] = useState(false);
- const [stackLimit] = useState(5); // Set stack capacity
- const [isFull, setIsFull] = useState(false);
-
- // Check if stack is full
- const checkIfFull = () => {
- setIsAnimating(true);
- setOperation("Checking if stack is full...");
-
- setTimeout(() => {
- const fullStatus = stack.length >= stackLimit;
- setIsFull(fullStatus);
- setOperation(null);
- setMessage(fullStatus ? "Stack is FULL!" : "Stack is NOT full");
- setIsAnimating(false);
- }, 1000);
- };
-
- // Reset stack
- const reset = () => {
- setStack([]);
- setMessage("Stack is empty");
- setOperation(null);
- setIsFull(false);
- };
-
- // Effect to update isFull status when stack changes
- useEffect(() => {
- setIsFull(stack.length >= stackLimit);
- }, [stack, stackLimit]);
-
- return (
-
-
- Visualize the LIFO (Last In, First Out) principle
-
-
-
- {/* Use the PushPop component */}
-
-
- {/* Is Full Check Button */}
-
- Check If Full
-
-
- {/* Stack Visualization */}
-
-
Stack Visualization
-
- {/* Operation Status */}
- {operation && (
-
- {operation}
-
- )}
-
- {/* Message Display */}
- {message && (
-
- {message}
-
- )}
-
- {/* Stack capacity indicator */}
-
- Capacity: {stack.length}/{stackLimit}
-
-
- {/* Vertical Stack */}
-
- {/* Top indicator */}
-
- {stack.length > 0 ? "↑ Top" : ""}
-
-
- {/* Stack elements with full state animation */}
-
- {stack.length === 0 ? (
-
- Stack is empty
-
- ) : (
-
- {stack.map((item, index) => (
-
- {item}
- {index === 0 && (
-
- (Top)
-
- )}
-
- ))}
-
- )}
-
-
- {/* Bottom indicator */}
-
- {stack.length > 0 ? "↓ Bottom" : ""}
-
-
-
-
-
- );
-};
-
-export default StackVisualizer;
diff --git a/app/visualizer/stack/isfull/codeBlock.jsx b/app/visualizer/stack/isfull/codeBlock.jsx
deleted file mode 100755
index 72c4dc5b9..000000000
--- a/app/visualizer/stack/isfull/codeBlock.jsx
+++ /dev/null
@@ -1,500 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Stack Implementation with isFull Operation in JavaScript
-class Stack {
- constructor(maxSize = 5) {
- this.items = [];
- this.top = -1;
- this.MAX_SIZE = maxSize;
- }
-
- // Push operation with isFull check
- push(element) {
- if (this.isFull()) {
- console.log("Stack Overflow - Cannot push to full stack");
- return;
- }
- this.items[++this.top] = element;
- console.log(\`Pushed: \${element}\`);
- }
-
- // Pop operation
- pop() {
- if (this.isEmpty()) {
- console.log("Stack Underflow - Cannot pop from empty stack");
- return -1;
- }
- return this.items[this.top--];
- }
-
- // Check if stack is full
- isFull() {
- const full = this.top === this.MAX_SIZE - 1;
- console.log(\`Stack is \${full ? "full" : "not full"}\`);
- return full;
- }
-
- // Check if stack is empty
- isEmpty() {
- return this.top === -1;
- }
-
- // Display stack
- display() {
- console.log("Current Stack:", this.items.slice(0, this.top + 1));
- }
-}
-
-// Usage
-const stack = new Stack(3); // Small stack for demonstration
-
-console.log("Initial checks:");
-stack.isFull(); // false
-stack.isEmpty(); // true
-
-stack.push(10);
-stack.push(20);
-stack.push(30);
-stack.display();
-stack.isFull(); // true
-
-// Try to push to full stack
-stack.push(40); // Will show overflow message`,
-
- python: `# Stack Implementation with isFull Operation in Python
-class Stack:
- def __init__(self, max_size=5):
- self.items = []
- self.top = -1
- self.MAX_SIZE = max_size
-
- # Push operation with is_full check
- def push(self, element):
- if self.is_full():
- print("Stack Overflow - Cannot push to full stack")
- return
- self.top += 1
- self.items.append(element)
- print(f"Pushed: {element}")
-
- # Pop operation
- def pop(self):
- if self.is_empty():
- print("Stack Underflow - Cannot pop from empty stack")
- return -1
- return self.items.pop()
-
- # Check if stack is full
- def is_full(self):
- full = self.top == self.MAX_SIZE - 1
- print(f"Stack is {'full' if full else 'not full'}")
- return full
-
- # Check if stack is empty
- def is_empty(self):
- return self.top == -1
-
- # Display stack
- def display(self):
- print("Current Stack:", self.items)
-
-# Usage
-stack = Stack(3) # Small stack for demonstration
-
-print("Initial checks:")
-stack.is_full() # False
-stack.is_empty() # True
-
-stack.push(10)
-stack.push(20)
-stack.push(30)
-stack.display()
-stack.is_full() # True
-
-# Try to push to full stack
-stack.push(40) # Will show overflow message`,
-
- java: `// Stack Implementation with isFull Operation in Java
-import java.util.ArrayList;
-
-class Stack {
- private ArrayList items;
- private int top;
- private final int MAX_SIZE;
-
- public Stack(int maxSize) {
- items = new ArrayList<>();
- top = -1;
- MAX_SIZE = maxSize;
- }
-
- // Push operation with isFull check
- public void push(int element) {
- if (isFull()) {
- System.out.println("Stack Overflow - Cannot push to full stack");
- return;
- }
- items.add(++top, element);
- System.out.println("Pushed: " + element);
- }
-
- // Pop operation
- public int pop() {
- if (isEmpty()) {
- System.out.println("Stack Underflow - Cannot pop from empty stack");
- return -1;
- }
- return items.remove(top--);
- }
-
- // Check if stack is full
- public boolean isFull() {
- boolean full = top == MAX_SIZE - 1;
- System.out.println("Stack is " + (full ? "full" : "not full"));
- return full;
- }
-
- // Check if stack is empty
- public boolean isEmpty() {
- return top == -1;
- }
-
- // Display stack
- public void display() {
- System.out.print("Current Stack: ");
- for (int i = 0; i <= top; i++) {
- System.out.print(items.get(i) + " ");
- }
- System.out.println();
- }
-}
-
-public class Main {
- public static void main(String[] args) {
- Stack stack = new Stack(3); // Small stack for demonstration
-
- System.out.println("Initial checks:");
- stack.isFull(); // false
- stack.isEmpty(); // true
-
- stack.push(10);
- stack.push(20);
- stack.push(30);
- stack.display();
- stack.isFull(); // true
-
- // Try to push to full stack
- stack.push(40); // Will show overflow message
- }
-}`,
-
- c: `// Stack Implementation with isFull Operation in C
-#include
-#include
-#define MAX_SIZE 5
-
-typedef struct {
- int items[MAX_SIZE];
- int top;
-} Stack;
-
-void initialize(Stack *s) {
- s->top = -1;
-}
-
-// Push operation with isFull check
-void push(Stack *s, int element) {
- if (isFull(s)) {
- printf("Stack Overflow - Cannot push to full stack\n");
- return;
- }
- s->items[++s->top] = element;
- printf("Pushed: %d\n", element);
-}
-
-// Pop operation
-int pop(Stack *s) {
- if (isEmpty(s)) {
- printf("Stack Underflow - Cannot pop from empty stack\n");
- return -1;
- }
- return s->items[s->top--];
-}
-
-// Check if stack is full
-bool isFull(Stack *s) {
- bool full = s->top == MAX_SIZE - 1;
- printf("Stack is %s\n", full ? "full" : "not full");
- return full;
-}
-
-// Check if stack is empty
-bool isEmpty(Stack *s) {
- return s->top == -1;
-}
-
-// Display stack
-void display(Stack *s) {
- printf("Current Stack: ");
- for (int i = 0; i <= s->top; i++) {
- printf("%d ", s->items[i]);
- }
- printf("\n");
-}
-
-int main() {
- Stack stack;
- initialize(&stack);
-
- printf("Initial checks:\n");
- isFull(&stack); // false
- isEmpty(&stack); // true
-
- push(&stack, 10);
- push(&stack, 20);
- push(&stack, 30);
- push(&stack, 40);
- push(&stack, 50);
- display(&stack);
- isFull(&stack); // true
-
- // Try to push to full stack
- push(&stack, 60); // Will show overflow message
-
- return 0;
-}`,
-
- cpp: `// Stack Implementation with isFull Operation in C++
-#include
-#include
-using namespace std;
-
-class Stack {
-private:
- vector items;
- int top;
- const int MAX_SIZE;
-
-public:
- Stack(int maxSize = 5) : top(-1), MAX_SIZE(maxSize) {}
-
- // Push operation with isFull check
- void push(int element) {
- if (isFull()) {
- cout << "Stack Overflow - Cannot push to full stack" << endl;
- return;
- }
- items.push_back(element);
- top++;
- cout << "Pushed: " << element << endl;
- }
-
- // Pop operation
- int pop() {
- if (isEmpty()) {
- cout << "Stack Underflow - Cannot pop from empty stack" << endl;
- return -1;
- }
- int element = items.back();
- items.pop_back();
- top--;
- return element;
- }
-
- // Check if stack is full
- bool isFull() const {
- bool full = top == MAX_SIZE - 1;
- cout << "Stack is " << (full ? "full" : "not full") << endl;
- return full;
- }
-
- // Check if stack is empty
- bool isEmpty() const {
- return top == -1;
- }
-
- // Display stack
- void display() const {
- cout << "Current Stack: ";
- for (int i = 0; i <= top; i++) {
- cout << items[i] << " ";
- }
- cout << endl;
- }
-};
-
-int main() {
- Stack stack(3); // Small stack for demonstration
-
- cout << "Initial checks:" << endl;
- stack.isFull(); // false
- stack.isEmpty(); // true
-
- stack.push(10);
- stack.push(20);
- stack.push(30);
- stack.display();
- stack.isFull(); // true
-
- // Try to push to full stack
- stack.push(40); // Will show overflow message
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Stack Push & Pop Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/stack/isfull/content.jsx b/app/visualizer/stack/isfull/content.jsx
deleted file mode 100755
index bd3f0a77c..000000000
--- a/app/visualizer/stack/isfull/content.jsx
+++ /dev/null
@@ -1,275 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 paragraphs = [
- `The Is Full operation checks whether a stack has reached its maximum capacity. This is particularly relevant for fixed-size stack implementations (arrays) rather than dynamic implementations (linked lists).`,
- `The Is Full operation is crucial when working with fixed-size stacks to prevent overflow errors. While not needed for dynamically-sized stacks, it's an essential safety check in many system-level implementations.`,
- ];
-
- const working = [
- { points: "Returns true if the stack cannot accept more elements." },
- { points: "Returns false if the stack can accept more elements." },
- {
- points:
- "For dynamic stacks (no fixed size), this operation typically always returns false.",
- },
- { points: "Often used with Push operations to prevent stack overflow." },
- ];
-
- const complexity = [
- {
- points: "Fixed-size Stack:",
- subpoints: ["Time Complexity: O(1)", "Space Complexity: O(1)"],
- },
- {
- points: "Dynamic Stack:",
- subpoints: ["Time Complexity: O(1)", "Space Complexity: O(1)"],
- },
- ];
-
- const useCase = [
- { points: "Preventing stack overflow in memory-constrained systems." },
- { points: "Implementing bounded buffers or fixed-size caches." },
- { points: "Memory management in embedded systems." },
- { points: "Validating stack capacity before push operations" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is the "Is Full" Operation? */}
-
-
-
- What is the "Is Full" Operation?
-
-
-
-
- {/* How It Works */}
-
-
-
- How It Works
-
-
-
- {working.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Time and Space Complexity */}
-
-
-
- Time and Space Complexity
-
-
-
- Here's the time and space complexity analysis for stack
- operations:
-
-
- {complexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
- {item.subpoints && (
-
- {item.subpoints.map((subitem, subindex) => (
-
- {subitem}
-
- ))}
-
- )}
-
- ))}
-
-
-
- 1}
- averageCase={(n) => 1}
- worstCase={(n) => 1}
- maxN={25}
- />
-
-
-
-
- {/* Practical Example */}
-
-
-
- Practical Example
-
-
-
- Consider a stack with maximum capacity of 3 elements:
-
-
-
-
Stack: [ ]
-
- isFull() →{" "}
- false
-
-
-
-
Stack: [5, 3]
-
- isFull() →{" "}
- false
-
-
-
-
Stack: [7, 3, 5]
-
- isFull() →{" "}
-
- true
-
-
-
-
-
-
-
- {/* Common Use Cases */}
-
-
-
- Common Use Cases
-
-
-
- {useCase.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/stack/isfull/page.jsx b/app/visualizer/stack/isfull/page.jsx
deleted file mode 100755
index bf023715b..000000000
--- a/app/visualizer/stack/isfull/page.jsx
+++ /dev/null
@@ -1,119 +0,0 @@
-import Animation from "@/app/visualizer/stack/isfull/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/isfull/content";
-import Quiz from "@/app/visualizer/stack/isfull/quiz";
-import Code from "@/app/visualizer/stack/isfull/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Footer from "@/app/components/footer";
-import BackToTopButton from "@/app/components/ui/backtotop";
-
-export const metadata = {
- title:
- "Stack Is Full Visualizer | Check Full Condition in Stack with Code in JS, C, Python, Java",
- description:
- "Understand how to check if a Stack is full using interactive animations and code examples in JavaScript, C, Python, and Java. A simple guide for beginners and DSA interview preparation.",
- keywords: [
- "Stack Is Full",
- "Is Full Operation Stack",
- "Stack Full Condition",
- "Stack Capacity Check",
- "DSA Stack Animation",
- "Learn Stack Operations",
- "Stack in JavaScript",
- "Stack in C",
- "Stack in Python",
- "Stack in Java",
- "Stack Code Examples",
- "Stack Overflow Condition",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/stack/isFull.png",
- width: 1200,
- height: 630,
- alt: "Stack isFull Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Stack : IsFull", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- IsFull Operation
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/stack/isfull/quiz.jsx b/app/visualizer/stack/isfull/quiz.jsx
deleted file mode 100755
index 92133b570..000000000
--- a/app/visualizer/stack/isfull/quiz.jsx
+++ /dev/null
@@ -1,449 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const StackQuiz = () => {
- const questions = [
- {
- question: "What is the primary purpose of the 'isFull' operation in a stack?",
- options: [
- "To count the number of elements in the stack",
- "To check if the stack has reached its maximum capacity",
- "To remove the top element when the stack is full",
- "To dynamically resize the stack"
- ],
- correctAnswer: 1,
- explanation:
- "The 'isFull' operation checks whether a fixed-size stack can accept more elements (returns true if full).",
- },
- {
- question: "For which type of stack implementation is 'isFull' most relevant?",
- options: [
- "Dynamic stacks (e.g., linked lists)",
- "Fixed-size stacks (e.g., arrays)",
- "Both equally",
- "Stacks with unlimited capacity"
- ],
- correctAnswer: 1,
- explanation:
- "'isFull' is critical for fixed-size implementations (like arrays) to prevent overflow. Dynamic stacks rarely need it.",
- },
- {
- question: "What does isFull() return for a dynamic stack (no fixed size)?",
- options: [
- "Always true",
- "Always false",
- "Depends on current elements",
- "Throws an error"
- ],
- correctAnswer: 1,
- explanation:
- "Dynamic stacks (e.g., linked lists) can theoretically grow indefinitely, so isFull() typically returns false.",
- },
- {
- question: "Given a stack with max capacity 3: [8, 5], what does isFull() return?",
- options: ["true", "false", "null", "Throws overflow error"],
- correctAnswer: 1,
- explanation:
- "The stack has 2/3 elements, so isFull() returns false (not yet full).",
- },
- {
- question: "Why is 'isFull' crucial before push operations in fixed-size stacks?",
- options: [
- "To improve time complexity",
- "To prevent stack overflow errors",
- "To count elements efficiently",
- "To convert the stack to dynamic"
- ],
- correctAnswer: 1,
- explanation:
- "Checking isFull() before push() avoids overflow errors in fixed-capacity stacks.",
- }
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the purpose of 'isFull'");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("knowing which stack implementations use 'isFull'");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("behavior of isFull in dynamic stacks");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("practical scenarios of stack capacity checks");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("importance of preventing overflow before push");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(", ")}. Review the corresponding sections above.`
- : "Perfect! You've mastered all 'isFull' stack concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Stack Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default StackQuiz;
\ No newline at end of file
diff --git a/app/visualizer/stack/peek/animation.jsx b/app/visualizer/stack/peek/animation.jsx
deleted file mode 100755
index 1a399e497..000000000
--- a/app/visualizer/stack/peek/animation.jsx
+++ /dev/null
@@ -1,150 +0,0 @@
-"use client";
-import React, { useState, useEffect, useRef } from "react";
-import { gsap } from "gsap";
-import PushPop from "@/app/components/ui/PushPop";
-
-const StackVisualizer = () => {
- const [stack, setStack] = useState([]);
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("");
- const [isAnimating, setIsAnimating] = useState(false);
-
- const stackRef = useRef(null);
- const itemRefs = useRef([]);
- const peekRef = useRef(null);
-
- /* ---------- random numbers ---------- */
- const addRandomStack = () => {
- if (stack.length > 0) return;
- setIsAnimating(true);
- setOperation("create");
- const nums = Array.from(
- { length: 3 + Math.floor(Math.random() * 3) },
- () => Math.floor(Math.random() * 999) + 1
- );
- setTimeout(() => {
- setStack(nums);
- setOperation(null);
- setIsAnimating(false);
- }, 600);
- };
-
- /* ---------- gsap animations (safe) ---------- */
- useEffect(() => {
- itemRefs.current.length = 0;
- if (!stackRef.current) return;
-
- /* push */
- if (operation?.includes("push") && itemRefs.current[0]) {
- setIsAnimating(true);
- const el = itemRefs.current[0];
- gsap.set(el, { scale: 0, y: -60, opacity: 0 });
- gsap
- .timeline({ onComplete: () => setIsAnimating(false) })
- .to(el, { scale: 1, y: 0, opacity: 1, duration: 0.4, ease: "back.out(1.2)" });
- }
-
- /* pop */
- if (operation?.includes("pop") && itemRefs.current[0]) {
- setIsAnimating(true);
- const el = itemRefs.current[0];
- gsap.to(el, {
- scale: 0,
- y: -60,
- opacity: 0,
- duration: 0.35,
- ease: "power2.in",
- onComplete: () => setIsAnimating(false),
- });
- }
-
- /* peek */
- if (operation?.includes("Peek") && itemRefs.current[0]) {
- setMessage(`Top value is ${stack[0]}`); // ONLY message shown
- setIsAnimating(true);
- const el = itemRefs.current[0];
- peekRef.current = el;
- gsap.to(el, {
- scale: 1.15,
- boxShadow: "0 0 20px #a855f7",
- duration: 0.3,
- yoyo: true,
- repeat: 3,
- ease: "power1.inOut",
- onComplete: () => setIsAnimating(false),
- });
- }
-
- /* reorder */
- gsap.fromTo(
- itemRefs.current.filter(Boolean),
- { y: 20, opacity: 0 },
- { y: 0, opacity: 1, stagger: 0.06, duration: 0.25, ease: "power2.out" }
- );
-
- return () => { peekRef.current = null; };
- }, [stack, operation]);
-
- return (
-
-
- Visualize Push, Pop, and Peek operations
-
-
-
-
-
-
- Add Random Stack
-
-
-
- {/* peek-only message */}
- {message && (
-
- {message}
-
- )}
-
- {/* vertical stack */}
-
-
- {stack.length === 0 ? (
-
- Stack is empty
-
- ) : (
-
- {stack.map((num, idx) => (
-
(itemRefs.current[idx] = el)}
- className={`p-4 rounded-lg border-2 text-center font-medium transition-all ${
- idx === 0 ? "bg-blue-100 dark:bg-blue-900 border-blue-300 dark:border-blue-700" : "bg-white dark:bg-gray-700 border-gray-200 dark:border-gray-600"
- }`}
- >
- {num}
-
- ))}
-
- )}
-
-
-
-
-
- );
-};
-
-export default StackVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/stack/peek/codeBlock.jsx b/app/visualizer/stack/peek/codeBlock.jsx
deleted file mode 100755
index 34b9b1390..000000000
--- a/app/visualizer/stack/peek/codeBlock.jsx
+++ /dev/null
@@ -1,468 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Stack Implementation with Peek Operation in JavaScript
-class Stack {
- constructor() {
- this.items = [];
- this.top = -1;
- }
-
- // Push operation
- push(element) {
- this.items[++this.top] = element;
- console.log(\`Pushed: \${element}\`);
- }
-
- // Pop operation
- pop() {
- if (this.isEmpty()) {
- console.log("Stack Underflow");
- return -1;
- }
- return this.items[this.top--];
- }
-
- // Peek operation
- peek() {
- if (this.isEmpty()) {
- console.log("Stack is empty");
- return -1;
- }
- console.log(\`Top element: \${this.items[this.top]}\`);
- return this.items[this.top];
- }
-
- // Check if stack is empty
- isEmpty() {
- return this.top === -1;
- }
-
- // Display stack
- display() {
- console.log("Current Stack:", this.items.slice(0, this.top + 1));
- }
-}
-
-// Usage
-const stack = new Stack();
-stack.push(10);
-stack.push(20);
-stack.push(30);
-stack.display();
-stack.peek();
-stack.pop();
-stack.peek();`,
-
- python: `# Stack Implementation with Peek Operation in Python
-class Stack:
- def __init__(self):
- self.items = []
- self.top = -1
-
- # Push operation
- def push(self, element):
- self.top += 1
- self.items.append(element)
- print(f"Pushed: {element}")
-
- # Pop operation
- def pop(self):
- if self.is_empty():
- print("Stack Underflow")
- return -1
- return self.items.pop()
-
- # Peek operation
- def peek(self):
- if self.is_empty():
- print("Stack is empty")
- return -1
- print(f"Top element: {self.items[-1]}")
- return self.items[-1]
-
- # Check if stack is empty
- def is_empty(self):
- return self.top == -1
-
- # Display stack
- def display(self):
- print("Current Stack:", self.items)
-
-# Usage
-stack = Stack()
-stack.push(10)
-stack.push(20)
-stack.push(30)
-stack.display()
-stack.peek()
-stack.pop()
-stack.peek()`,
-
- java: `// Stack Implementation with Peek Operation in Java
-import java.util.ArrayList;
-
-class Stack {
- private ArrayList items;
- private int top;
-
- public Stack() {
- items = new ArrayList<>();
- top = -1;
- }
-
- // Push operation
- public void push(int element) {
- items.add(++top, element);
- System.out.println("Pushed: " + element);
- }
-
- // Pop operation
- public int pop() {
- if (isEmpty()) {
- System.out.println("Stack Underflow");
- return -1;
- }
- return items.remove(top--);
- }
-
- // Peek operation
- public int peek() {
- if (isEmpty()) {
- System.out.println("Stack is empty");
- return -1;
- }
- System.out.println("Top element: " + items.get(top));
- return items.get(top);
- }
-
- // Check if stack is empty
- public boolean isEmpty() {
- return top == -1;
- }
-
- // Display stack
- public void display() {
- System.out.print("Current Stack: ");
- for (int i = 0; i <= top; i++) {
- System.out.print(items.get(i) + " ");
- }
- System.out.println();
- }
-}
-
-public class Main {
- public static void main(String[] args) {
- Stack stack = new Stack();
- stack.push(10);
- stack.push(20);
- stack.push(30);
- stack.display();
- stack.peek();
- stack.pop();
- stack.peek();
- }
-}`,
-
- c: `// Stack Implementation with Peek Operation in C
-#include
-#include
-#define MAX_SIZE 100
-
-typedef struct {
- int items[MAX_SIZE];
- int top;
-} Stack;
-
-void initialize(Stack *s) {
- s->top = -1;
-}
-
-// Push operation
-void push(Stack *s, int element) {
- if (s->top == MAX_SIZE - 1) {
- printf("Stack Overflow\n");
- return;
- }
- s->items[++s->top] = element;
- printf("Pushed: %d\n", element);
-}
-
-// Pop operation
-int pop(Stack *s) {
- if (s->top == -1) {
- printf("Stack Underflow\n");
- return -1;
- }
- return s->items[s->top--];
-}
-
-// Peek operation
-int peek(Stack *s) {
- if (s->top == -1) {
- printf("Stack is empty\n");
- return -1;
- }
- printf("Top element: %d\n", s->items[s->top]);
- return s->items[s->top];
-}
-
-// Check if stack is empty
-int isEmpty(Stack *s) {
- return s->top == -1;
-}
-
-// Display stack
-void display(Stack *s) {
- printf("Current Stack: ");
- for (int i = 0; i <= s->top; i++) {
- printf("%d ", s->items[i]);
- }
- printf("\n");
-}
-
-int main() {
- Stack stack;
- initialize(&stack);
-
- push(&stack, 10);
- push(&stack, 20);
- push(&stack, 30);
- display(&stack);
- peek(&stack);
- pop(&stack);
- peek(&stack);
-
- return 0;
-}`,
-
- cpp: `// Stack Implementation with Peek Operation in C++
-#include
-#include
-using namespace std;
-
-class Stack {
-private:
- vector items;
- int top;
- const int MAX_SIZE = 100;
-
-public:
- Stack() : top(-1) {}
-
- // Push operation
- void push(int element) {
- if (top == MAX_SIZE - 1) {
- cout << "Stack Overflow" << endl;
- return;
- }
- items.push_back(element);
- top++;
- cout << "Pushed: " << element << endl;
- }
-
- // Pop operation
- int pop() {
- if (isEmpty()) {
- cout << "Stack Underflow" << endl;
- return -1;
- }
- int element = items.back();
- items.pop_back();
- top--;
- return element;
- }
-
- // Peek operation
- int peek() {
- if (isEmpty()) {
- cout << "Stack is empty" << endl;
- return -1;
- }
- cout << "Top element: " << items.back() << endl;
- return items.back();
- }
-
- // Check if stack is empty
- bool isEmpty() {
- return top == -1;
- }
-
- // Display stack
- void display() {
- cout << "Current Stack: ";
- for (int i = 0; i <= top; i++) {
- cout << items[i] << " ";
- }
- cout << endl;
- }
-};
-
-int main() {
- Stack stack;
- stack.push(10);
- stack.push(20);
- stack.push(30);
- stack.display();
- stack.peek();
- stack.pop();
- stack.peek();
-
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Stack Push & Pop Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/stack/peek/content.jsx b/app/visualizer/stack/peek/content.jsx
deleted file mode 100755
index 259ab213d..000000000
--- a/app/visualizer/stack/peek/content.jsx
+++ /dev/null
@@ -1,164 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 paragraphs = [
- `Returns the topmost element from the stack without removing it.`,
- `The peek operation is useful when you need to inspect the top element before deciding whether to pop it or push another element onto the stack.`,
- ];
-
- const example = [
- { points : "Current stack: [7, 3, 5]" },
- { points : "Peek → returns 7: [7, 3, 5] (stack remains unchanged)" },
- { points : "After pop: [3, 5]" },
- { points : "Peek → returns 3: [3, 5]" },
- ];
-
- const complexity = [
- { points : "Time Complexity: O(1)" },
- { points : "Space Complexity: O(1)" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* Peek Operation */}
-
-
-
- Peek Operation
-
-
-
- {paragraphs[0]}
-
-
-
- Example: Peeking at a stack
-
-
-
- {example.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
- {complexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
-
- 1}
- averageCase={(n) => 1}
- worstCase={(n) => 1}
- maxN={25}
- />
-
-
-
- {paragraphs[1]}
-
-
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/stack/peek/page.jsx b/app/visualizer/stack/peek/page.jsx
deleted file mode 100755
index 54ebabe3b..000000000
--- a/app/visualizer/stack/peek/page.jsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import Animation from "@/app/visualizer/stack/peek/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/peek/content";
-import Quiz from "@/app/visualizer/stack/peek/quiz";
-import Code from "@/app/visualizer/stack/peek/codeBlock";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import ExploreOther from '@/app/components/ui/exploreOther';
-import Footer from '@/app/components/footer';
-import BackToTopButton from '@/app/components/ui/backtotop';
-
-export const metadata = {
- title:
- "Stack Peek Visualizer | Understand Peek Operation in Stack with Code in JS, C, Python, Java",
- description:
- "Learn how the Peek operation works in a Stack using interactive animations and code examples in JavaScript, C, Python, and Java. Perfect for beginners and DSA interview preparation.",
- keywords: [
- "Stack Peek",
- "Peek Operation Stack",
- "Stack Top Element",
- "Peek in DSA",
- "DSA Stack Animation",
- "Learn Stack Operations",
- "Stack in JavaScript",
- "Stack in C",
- "Stack in Python",
- "Stack in Java",
- "Peek Operation Example",
- "Stack Code Examples",
- "Top of Stack",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/stack/peek.png",
- width: 1200,
- height: 630,
- alt: "Stack Peek Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Stack : Peek", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- Peek Operation
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/stack/peek/quiz.jsx b/app/visualizer/stack/peek/quiz.jsx
deleted file mode 100755
index 7a00f638e..000000000
--- a/app/visualizer/stack/peek/quiz.jsx
+++ /dev/null
@@ -1,466 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const StackQuiz = () => {
- const questions = [
- {
- question: "What does the peek operation in a stack do?",
- options: [
- "Removes and returns the top element",
- "Returns the top element without removing it",
- "Adds a new element to the top",
- "Returns the bottom element of the stack"
- ],
- correctAnswer: 1,
- explanation:
- "Peek only inspects the top element without modifying the stack, unlike pop which removes it.",
- },
- {
- question: "What is the time complexity of the peek operation?",
- options: ["O(n)", "O(log n)", "O(1)", "O(n²)"],
- correctAnswer: 2,
- explanation:
- "Peek operates in O(1) time since it directly accesses the top element (constant time).",
- },
- {
- question: "After pushing 10, 20, and 30 onto a stack, what does peek() return?",
- options: ["10", "20", "30", "Error"],
- correctAnswer: 2,
- explanation:
- "The stack becomes [30, 20, 10], so peek returns 30 (the top element).",
- },
- {
- question: "What happens if you peek at an empty stack?",
- options: [
- "Returns null",
- "Returns undefined",
- "Causes stack underflow",
- "Depends on implementation"
- ],
- correctAnswer: 3,
- explanation:
- "Most implementations throw a stack underflow exception (or similar error) when peeking an empty stack.",
- },
- {
- question: "How does peek differ from pop?",
- options: [
- "Peek removes the element, pop doesn't",
- "Peek doesn't modify the stack, pop does",
- "Peek works at the bottom of the stack",
- "Peek has O(n) time complexity"
- ],
- correctAnswer: 1,
- explanation:
- "Peek is non-destructive (only reads data), while pop modifies the stack by removing the top element.",
- },
- {
- question: "In which scenario would peek be particularly useful?",
- options: [
- "When you need to remove all elements",
- "When you need to check the top element before deciding to pop/push",
- "When you need to reverse the stack",
- "When you need to count all elements"
- ],
- correctAnswer: 1,
- explanation:
- "Peek is ideal for inspection before operations (e.g., checking if a parenthesis matches before popping).",
- },
- {
- question: "Given stack = [5, 2, 9], what's the state after peek()?",
- options: [
- "[5, 2, 9]",
- "[2, 9]",
- "[5, 2]",
- "[9, 5, 2]"
- ],
- correctAnswer: 0,
- explanation:
- "Peek only reads the top element (9), leaving the stack unchanged as [5, 2, 9].",
- },
- {
- question: "Which real-world analogy best describes peek?",
- options: [
- "Taking the top plate from a stack of plates",
- "Looking at the top plate without taking it",
- "Adding a new plate to the stack",
- "Counting all plates in the stack"
- ],
- correctAnswer: 1,
- explanation:
- "Peek is like looking at the top plate to see if it's dirty before deciding to remove it.",
- },
- {
- question: "What does peek() return after: push(8), push(4), pop(), peek()?",
- options: ["8", "4", "Error", "Null"],
- correctAnswer: 0,
- explanation:
- "Operations: push(8) → [8], push(4) → [4, 8], pop() → returns 4: [8], peek() → returns 8.",
- },
- {
- question: "Why is peek considered a 'safe' operation?",
- options: [
- "It never throws errors",
- "It doesn't modify stack data",
- "It works on full stacks",
- "It has O(1) space complexity"
- ],
- correctAnswer: 1,
- explanation:
- "Peek is 'safe' in terms of data integrity since it’s read-only (though it may throw errors on empty stacks).",
- },
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = selectedAnswer;
- setAnswers(newAnswers);
-
- const newScore = newAnswers.reduce((acc, ans, idx) => {
- return ans === questions[idx].correctAnswer ? acc + 1 : acc;
- }, 0);
- setScore(newScore);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(newAnswers[currentQuestion + 1]);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Stack Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default StackQuiz;
\ No newline at end of file
diff --git a/app/visualizer/stack/polish/postfix/animation.jsx b/app/visualizer/stack/polish/postfix/animation.jsx
deleted file mode 100755
index 5878a81e5..000000000
--- a/app/visualizer/stack/polish/postfix/animation.jsx
+++ /dev/null
@@ -1,228 +0,0 @@
-"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 = () => {
- /* ======= 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);
- const [steps, setSteps] = useState([]);
- 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 [isPlaying, setIsPlaying] = useState(false);
- const [speed, setSpeed] = useState(1000);
-
- 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);
- };
-
- const convertInfixToPostfix = () => {
- 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 (/[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` });
- } else if (char === "(") {
- tempStack.push(char);
- 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();
- 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` });
- }
- }
- 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 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); };
-
- 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]);
-
- /* ======= NEW: tiny GSAP flash on step change ======= */
- const statusRef = useRef();
- useEffect(() => {
- if (statusRef.current) gsap.fromTo(statusRef.current, { scale: 0.95, opacity: 0.7 }, { scale: 1, opacity: 1, duration: 0.3 });
- }, [message]);
-
- 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 (
-
- 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"/>
- {isProcessing ? "Converting..." : "Convert"}
- Reset
-
-
- {steps.length > 0 && (
-
-
- Previous
- {isPlaying ? "Pause" : "Play"}
- = steps.length - 1 || isAnimating} className="px-4 py-2 bg-gray-200 dark:bg-neutral-900 rounded-md disabled:opacity-50">Next
-
-
-
Speed:
-
setSpeed(Number(e.target.value))} className="px-2 py-1 border border-gray-300 dark:border-gray-600 rounded-md dark:bg-neutral-900">
- Slow Normal Fast Very Fast
-
-
Step {currentStep + 1} of {steps.length}
-
-
-
-
-
- )}
-
-
- {/* Status panel with GSAP flash */}
-
-
Conversion Status
- {operation &&
{operation}
}
- {message &&
{message}
}
- {postfix && currentStep === steps.length - 1 && (
-
- Postfix Result:
{postfix}
-
- )}
-
-
- {/* Visualisations – now with motion */}
-
- {/* Stack */}
-
-
Stack
-
-
{stack.length > 0 ? "↑ Top" : ""}
-
-
- {stack.length === 0 ? (
- Stack is empty
- ) : (
-
- {stack.map((item, i) => (
-
- ))}
-
- )}
-
-
-
{stack.length > 0 ? "↓ Bottom" : ""}
-
-
-
- {/* Output */}
-
-
Output
-
-
-
- {output.length === 0 ? (
- Output will appear here
- ) : (
- output.map((c, i) => )
- )}
-
-
-
-
-
-
- {/* Step table – same as before, just with framer hover */}
- {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}
-
- ))}
-
-
-
-
- )}
-
-
- );
-};
-
-export default InfixToPostfixVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/stack/polish/postfix/codeBlock.jsx b/app/visualizer/stack/polish/postfix/codeBlock.jsx
deleted file mode 100755
index b36697868..000000000
--- a/app/visualizer/stack/polish/postfix/codeBlock.jsx
+++ /dev/null
@@ -1,316 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Postfix Evaluation using Stack (JavaScript)
-function evaluatePostfix(expression) {
- let stack = [];
-
- for (let char of expression) {
- if (!isNaN(char)) {
- stack.push(parseInt(char));
- } else {
- const b = stack.pop();
- const a = stack.pop();
-
- switch(char) {
- case '+': stack.push(a + b); break;
- case '-': stack.push(a - b); break;
- case '*': stack.push(a * b); break;
- case '/': stack.push(Math.floor(a / b)); break;
- }
- }
- }
- return stack.pop();
-}
-
-// Example: "23*5+" becomes (2*3)+5 = 11
-console.log(evaluatePostfix("23*5+")); // Output: 11`,
-
- python: `# Postfix Evaluation using Stack (Python)
-def evaluate_postfix(expression):
- stack = []
-
- for char in expression:
- if char.isdigit():
- stack.append(int(char))
- else:
- b = stack.pop()
- a = stack.pop()
-
- if char == '+': stack.append(a + b)
- elif char == '-': stack.append(a - b)
- elif char == '*': stack.append(a * b)
- elif char == '/': stack.append(a // b)
-
- return stack.pop()
-
-# Example: "23*5+" becomes (2*3)+5 = 11
-print(evaluate_postfix("23*5+")) # Output: 11`,
-
- java: `// Postfix Evaluation using Stack (Java)
-import java.util.Stack;
-
-public class PostfixEvaluator {
- public static int evaluatePostfix(String expression) {
- Stack stack = new Stack<>();
-
- for (char c : expression.toCharArray()) {
- if (Character.isDigit(c)) {
- stack.push(c - '0');
- } else {
- int b = stack.pop();
- int a = stack.pop();
-
- switch (c) {
- case '+': stack.push(a + b); break;
- case '-': stack.push(a - b); break;
- case '*': stack.push(a * b); break;
- case '/': stack.push(a / b); break;
- }
- }
- }
- return stack.pop();
- }
-
- public static void main(String[] args) {
- // Example: "23*5+" becomes (2*3)+5 = 11
- System.out.println(evaluatePostfix("23*5+")); // Output: 11
- }
-}`,
-
- c: `// Postfix Evaluation using Stack (C)
-#include
-#include
-#include
-
-#define MAX_SIZE 100
-
-typedef struct {
- int data[MAX_SIZE];
- int top;
-} Stack;
-
-void push(Stack *s, int val) {
- s->data[++s->top] = val;
-}
-
-int pop(Stack *s) {
- return s->data[s->top--];
-}
-
-int evaluatePostfix(char* expression) {
- Stack s = { .top = -1 };
-
- for (int i = 0; expression[i]; i++) {
- if (isdigit(expression[i])) {
- push(&s, expression[i] - '0');
- } else {
- int b = pop(&s);
- int a = pop(&s);
-
- switch (expression[i]) {
- case '+': push(&s, a + b); break;
- case '-': push(&s, a - b); break;
- case '*': push(&s, a * b); break;
- case '/': push(&s, a / b); break;
- }
- }
- }
- return pop(&s);
-}
-
-int main() {
- // Example: "23*5+" becomes (2*3)+5 = 11
- printf("%d\\n", evaluatePostfix("23*5+")); // Output: 11
- return 0;
-}`,
-
- cpp: `// Postfix Evaluation using Stack (C++)
-#include
-#include
-#include
-#include
-using namespace std;
-
-int evaluatePostfix(const string& expression) {
- stack st;
-
- for (char c : expression) {
- if (isdigit(c)) {
- st.push(c - '0');
- } else {
- int b = st.top(); st.pop();
- int a = st.top(); st.pop();
-
- switch (c) {
- case '+': st.push(a + b); break;
- case '-': st.push(a - b); break;
- case '*': st.push(a * b); break;
- case '/': st.push(a / b); break;
- }
- }
- }
- return st.top();
-}
-
-int main() {
- // Example: "23*5+" becomes (2*3)+5 = 11
- cout << evaluatePostfix("23*5+") << endl; // Output: 11
- return 0;
-}`
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- PostFix implementation using Stack
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
- };
-
- export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/stack/polish/postfix/content.jsx b/app/visualizer/stack/polish/postfix/content.jsx
deleted file mode 100755
index 62cd7d696..000000000
--- a/app/visualizer/stack/polish/postfix/content.jsx
+++ /dev/null
@@ -1,239 +0,0 @@
-"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.`,
- `Note: Higher precedence means the operation will happen first. When operators have equal precedence, they are evaluated left-to-right (except for exponentiation which is right-to-left).`,
- ];
-
- const steps = [
- { points : "Initialize an empty stack and an empty output string." },
- { points : "Scan the infix expression from left to right." },
- { points : "If the element is an operand, add it to the output." },
- { points : "If the element is a '(', push it onto the stack." },
- { points : `If the element is a ')', pop from the stack and add to output until '(' is encountered.` },
- { points : "If the element is an operator, pop from the stack all operators with higher or equal precedence, then push the current operator." },
- { points : "After scanning, pop all remaining operators from the stack." },
- ];
-
- const example = [
- { points : "Infix: (A + B) * (C - D)" },
- { points : `Step 1: Push '(' → Stack: [ '(' ], Output: ''` },
- { points : "Step 2: Add 'A' → Output: 'A'" },
- { points : "Step 3: Push '+' → Stack: [ '(', '+' ]" },
- { points : "Step 4: Add 'B' → Output: 'A B'" },
- { points : "Step 5: Pop until '(' → Stack: [ ], Output: 'A B +'" },
- { points : "Step 6: Continue similarly for the rest → Final Postfix: A B + C D - *" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is Postfix Notation? */}
-
-
-
- What is Postfix Notation?
-
-
- {paragraph.map((text, idx) => (
-
- {text}
-
- ))}
-
-
-
- {/* Infix to Postfix Conversion Steps */}
-
-
-
- Infix to Postfix Conversion Steps
-
-
-
- {steps.map((item, idx) => (
-
- {item.points}
-
- ))}
-
-
-
-
- Example:
-
-
- {example.map((item, idx) => (
-
- {item.points}
-
- ))}
-
-
-
-
-
- {/* Operator Precedence Table */}
-
-
-
- Operator Precedence Table
-
-
-
-
-
-
- Operator
-
-
- Meaning
-
-
- Precedence
-
-
-
-
-
-
- ( )
-
-
- Parentheses
-
-
- Highest
-
-
-
-
- ^ %
-
-
- Exponentiation / Modulus
-
-
- 2
-
-
-
-
- * /
-
-
- Multiplication / Division
-
-
- 3
-
-
-
-
- + -
-
-
- Addition / Subtraction
-
-
- 4 (Lowest)
-
-
-
-
-
- {paragraph[2]}
-
-
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
- };
-
- 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
deleted file mode 100755
index ef051aca3..000000000
--- a/app/visualizer/stack/polish/postfix/page.jsx
+++ /dev/null
@@ -1,117 +0,0 @@
-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",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/stack/postfix.png",
- width: 1200,
- height: 630,
- alt: "Stack infix to postfix",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Stack : Infix to postfix", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
- Infix to Postfix
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/stack/polish/postfix/quiz.jsx b/app/visualizer/stack/polish/postfix/quiz.jsx
deleted file mode 100755
index 28c4c6996..000000000
--- a/app/visualizer/stack/polish/postfix/quiz.jsx
+++ /dev/null
@@ -1,504 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const StackQuiz = () => {
- const questions = [
- {
- question: "What is the key characteristic of postfix notation?",
- options: [
- "Operators appear before their operands",
- "Operators appear between their operands",
- "Operators appear after their operands",
- "Parentheses dictate evaluation order"
- ],
- correctAnswer: 2,
- explanation: "Postfix notation places operators **after** their operands (e.g., `3 4 +` instead of `3 + 4`)."
- },
- {
- question: "How would the infix expression `(A * B) + C` convert to postfix?",
- options: [
- "A B * C +",
- "A B C * +",
- "A * B + C",
- "+ * A B C"
- ],
- correctAnswer: 0,
- explanation: "Parentheses force `A * B` first → `A B *`, then `+ C` → `A B * C +`."
- },
- {
- question: "Which operator has the **highest precedence** in infix-to-postfix conversion?",
- options: ["+", "*", "^ (exponentiation)", "("],
- correctAnswer: 3,
- explanation: "Parentheses `(` have the highest precedence and are handled separately in the stack."
- },
- {
- question: "What is the postfix form of `2 ^ 3 ^ 2`? (Note: `^` = exponentiation)",
- options: [
- "2 3 2 ^ ^",
- "2 3 ^ 2 ^",
- "2 3 2 ^",
- "2 3 ^ 2"
- ],
- correctAnswer: 1,
- explanation: "Exponentiation is **right-associative**, so `2 ^ (3 ^ 2)` → `2 3 2 ^ ^`."
- },
- {
- question: "Which data structure is used to convert infix to postfix?",
- options: ["Queue", "Stack", "Heap", "Linked List"],
- correctAnswer: 1,
- explanation: "A **stack** temporarily holds operators and parentheses during conversion."
- },
- {
- question: "What is the postfix equivalent of `A + B * C - D / E`?",
- options: [
- "A B C * + D E / -",
- "A B + C * D E - /",
- "A B C + * D E / -",
- "A B * C + D E / -"
- ],
- correctAnswer: 0,
- explanation: "`*` and `/` have higher precedence than `+` and `-`. Steps: `B * C` → `A + (result)` → `D / E` → subtract."
- },
- {
- question: "When converting infix to postfix, what happens when a closing `)` is encountered?",
- options: [
- "Push it to the stack",
- "Pop operators from the stack until `(` is found",
- "Ignore it",
- "Add it to the output"
- ],
- correctAnswer: 1,
- explanation: "Pop all operators until `(` is reached (discarding both `(` and `)`)."
- },
- {
- question: "What is the postfix form of `3 + 4 * 5 / 6`?",
- options: [
- "3 4 5 * 6 / +",
- "3 4 5 6 / * +",
- "3 4 * 5 6 / +",
- "3 4 + 5 6 / *"
- ],
- correctAnswer: 0,
- explanation: "`*` and `/` have equal precedence (left-to-right): `4 * 5` → `result / 6` → `3 + (result)`."
- },
- {
- question: "Why does postfix notation not need parentheses?",
- options: [
- "It uses a stack for evaluation",
- "Operator position implicitly defines precedence",
- "It only supports single operations",
- "It reverses the operands"
- ],
- correctAnswer: 1,
- explanation: "Postfix order ensures operations are evaluated correctly without parentheses (e.g., `A B + C *` vs. `A B C * +`)."
- },
- {
- question: "What is the result of evaluating the postfix expression `5 1 2 + 4 * + 3 -`?",
- options: ["14", "10", "18", "20"],
- correctAnswer: 0,
- explanation: "Steps: `1 2 +` → 3; `3 4 *` → 12; `5 12 +` → 17; `17 3 -` → **14**."
- }
-];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the key characteristic of postfix notation");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("converting infix to postfix with parentheses");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("operator precedence in conversion");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("right-associativity of exponentiation");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("using a stack for conversion");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("handling mixed operator precedence");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("handling closing parentheses");
- }
- if (answers[7] !== questions[7].correctAnswer) {
- weakAreas.push("evaluating precedence in arithmetic expressions");
- }
- if (answers[8] !== questions[8].correctAnswer) {
- weakAreas.push("why postfix does not need parentheses");
- }
- if (answers[9] !== questions[9].correctAnswer) {
- weakAreas.push("evaluating complex postfix expressions");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Postfix and Stack concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Stack Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default StackQuiz;
\ No newline at end of file
diff --git a/app/visualizer/stack/polish/prefix/animation.jsx b/app/visualizer/stack/polish/prefix/animation.jsx
deleted file mode 100755
index a97725b67..000000000
--- a/app/visualizer/stack/polish/prefix/animation.jsx
+++ /dev/null
@@ -1,436 +0,0 @@
-"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 = () => {
- /* ======= 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);
- const [steps, setSteps] = useState([]);
- 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 [isPlaying, setIsPlaying] = useState(false);
- const [speed, setSpeed] = useState(1000);
-
- const precedence = { "^": 4, "*": 3, "/": 3, "+": 2, "-": 2 };
-
- /* ---------- helpers ---------- */
- const reset = () => {
- setStack([]);
- setOutput([]);
- setPrefix("");
- setCurrentStep(0);
- setSteps([]);
- setMessage("Enter an infix expression and click Convert");
- setOperation(null);
- setIsPlaying(false);
- };
-
- const convertInfixToPrefix = () => {
- if (!infix.trim()) {
- setMessage("Please enter an infix expression");
- return;
- }
- setIsProcessing(true);
- reset();
-
- const conversionSteps = [];
- let tempStack = [];
- let tempOutput = [];
-
- /* 1. reverse */
- const reversed = infix.split("").reverse().join("");
- conversionSteps.push({
- stack: [],
- output: [],
- char: "",
- action: "Reverse infix",
- description: `Reversed: ${reversed}`,
- });
-
- /* 2. swap parentheses */
- const swapped = reversed.replace(/[()]/g, (c) => (c === "(" ? ")" : "("));
- conversionSteps.push({
- stack: [],
- output: [],
- char: "",
- action: "Swap parentheses",
- description: `Swapped: ${swapped}`,
- });
-
- /* 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: ch,
- action: "Add operand",
- description: `Added operand "${ch}"`,
- });
- } else if (ch === "(") {
- tempStack.push(ch);
- conversionSteps.push({
- stack: [...tempStack],
- output: [...tempOutput],
- char: ch,
- action: "Push to stack",
- description: `Pushed "("`,
- });
- } 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 "${popped}"`,
- });
- }
- tempStack.pop(); // remove '('
- conversionSteps.push({
- stack: [...tempStack],
- output: [...tempOutput],
- char: "(",
- action: "Remove from stack",
- description: `Removed "("`,
- });
- } else {
- while (
- tempStack.length &&
- tempStack[tempStack.length - 1] !== "(" &&
- precedence[ch] <= 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 "${popped}"`,
- });
- }
- tempStack.push(ch);
- conversionSteps.push({
- stack: [...tempStack],
- output: [...tempOutput],
- char: ch,
- action: "Push operator",
- description: `Pushed "${ch}"`,
- });
- }
- }
-
- while (tempStack.length) {
- const popped = tempStack.pop();
- tempOutput.push(popped);
- conversionSteps.push({
- stack: [...tempStack],
- output: [...tempOutput],
- char: popped,
- action: "Pop remaining",
- description: `Popped remaining "${popped}"`,
- });
- }
-
- /* 4. reverse to get prefix */
- const prefixResult = tempOutput.reverse().join(" ");
- conversionSteps.push({
- stack: [],
- output: [...tempOutput],
- char: "",
- action: "Reverse postfix",
- description: `Reversed to get prefix: ${prefixResult}`,
- });
-
- setSteps(conversionSteps);
- setPrefix(prefixResult);
- setIsProcessing(false);
- setIsPlaying(true);
- };
-
- /* ---------- playback ---------- */
- 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);
- };
-
- 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]);
-
- /* ---------- GSAP flash on message change ---------- */
- const statusRef = useRef();
- useEffect(() => {
- if (statusRef.current)
- gsap.fromTo(statusRef.current, { scale: 0.95, opacity: 0.7 }, { scale: 1, opacity: 1, duration: 0.3 });
- }, [message]);
-
- 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 (
-
-
- 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"
- />
-
- {isProcessing ? "Converting..." : "Convert"}
-
-
- Reset
-
-
-
- {steps.length > 0 && (
-
-
-
- Previous
-
-
- {isPlaying ? "Pause" : "Play"}
-
- = steps.length - 1 || isAnimating}
- className="px-4 py-2 bg-gray-200 dark:bg-neutral-900 rounded-md disabled:opacity-50"
- >
- Next
-
-
-
-
Speed:
-
setSpeed(Number(e.target.value))}
- className="px-2 py-1 border border-gray-300 dark:border-gray-600 rounded-md dark:bg-neutral-900"
- >
- Slow
- Normal
- Fast
- Very Fast
-
-
- Step {currentStep + 1} of {steps.length}
-
-
-
-
-
-
- )}
-
-
- {/* 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.map((item, i) => (
-
- ))}
-
- )}
-
-
-
{stack.length > 0 ? "↓ Bottom" : ""}
-
-
-
- {/* Output */}
-
-
Output
-
-
-
- {output.length === 0 ? (
- Output will appear here
- ) : (
- output.map((c, i) => )
- )}
-
-
-
-
-
-
- {/* 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}
-
- ))}
-
-
-
-
- )}
-
-
- );
-};
-
-export default InfixToPrefixVisualizer;
\ No newline at end of file
diff --git a/app/visualizer/stack/polish/prefix/codeBlock.jsx b/app/visualizer/stack/polish/prefix/codeBlock.jsx
deleted file mode 100755
index 0c03e4644..000000000
--- a/app/visualizer/stack/polish/prefix/codeBlock.jsx
+++ /dev/null
@@ -1,323 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Prefix Evaluation using Stack (JavaScript)
-function evaluatePrefix(expression) {
- let stack = [];
- // Process expression in reverse order
- for (let i = expression.length - 1; i >= 0; i--) {
- const char = expression[i];
- if (!isNaN(char)) {
- stack.push(parseInt(char));
- } else {
- const a = stack.pop();
- const b = stack.pop();
-
- switch(char) {
- case '+': stack.push(a + b); break;
- case '-': stack.push(a - b); break;
- case '*': stack.push(a * b); break;
- case '/': stack.push(Math.floor(a / b)); break;
- }
- }
- }
- return stack.pop();
-}
-
-// Example: "+*235" becomes (2*3)+5 = 11
-console.log(evaluatePrefix("+*235")); // Output: 11`,
-
- python: `# Prefix Evaluation using Stack (Python)
-def evaluate_prefix(expression):
- stack = []
- # Process expression in reverse order
- for char in reversed(expression):
- if char.isdigit():
- stack.append(int(char))
- else:
- a = stack.pop()
- b = stack.pop()
-
- if char == '+': stack.append(a + b)
- elif char == '-': stack.append(a - b)
- elif char == '*': stack.append(a * b)
- elif char == '/': stack.append(a // b)
-
- return stack.pop()
-
-# Example: "+*235" becomes (2*3)+5 = 11
-print(evaluate_prefix("+*235")) # Output: 11`,
-
- java: `// Prefix Evaluation using Stack (Java)
-import java.util.Stack;
-
-public class PrefixEvaluator {
- public static int evaluatePrefix(String expression) {
- Stack stack = new Stack<>();
- // Process expression in reverse order
- for (int i = expression.length() - 1; i >= 0; i--) {
- char c = expression.charAt(i);
- if (Character.isDigit(c)) {
- stack.push(c - '0');
- } else {
- int a = stack.pop();
- int b = stack.pop();
-
- switch (c) {
- case '+': stack.push(a + b); break;
- case '-': stack.push(a - b); break;
- case '*': stack.push(a * b); break;
- case '/': stack.push(a / b); break;
- }
- }
- }
- return stack.pop();
- }
-
- public static void main(String[] args) {
- // Example: "+*235" becomes (2*3)+5 = 11
- System.out.println(evaluatePrefix("+*235")); // Output: 11
- }
-}`,
-
- c: `// Prefix Evaluation using Stack (C)
-#include
-#include
-#include
-#include
-
-#define MAX_SIZE 100
-
-typedef struct {
- int data[MAX_SIZE];
- int top;
-} Stack;
-
-void push(Stack *s, int val) {
- s->data[++s->top] = val;
-}
-
-int pop(Stack *s) {
- return s->data[s->top--];
-}
-
-int evaluatePrefix(char* expression) {
- Stack s = { .top = -1 };
- int length = strlen(expression);
-
- // Process expression in reverse order
- for (int i = length - 1; i >= 0; i--) {
- if (isdigit(expression[i])) {
- push(&s, expression[i] - '0');
- } else {
- int a = pop(&s);
- int b = pop(&s);
-
- switch (expression[i]) {
- case '+': push(&s, a + b); break;
- case '-': push(&s, a - b); break;
- case '*': push(&s, a * b); break;
- case '/': push(&s, a / b); break;
- }
- }
- }
- return pop(&s);
-}
-
-int main() {
- // Example: "+*235" becomes (2*3)+5 = 11
- printf("%d\n", evaluatePrefix("+*235")); // Output: 11
- return 0;
-}`,
-
- cpp: `// Prefix Evaluation using Stack (C++)
-#include
-#include
-#include
-#include
-using namespace std;
-
-int evaluatePrefix(const string& expression) {
- stack st;
-
- // Process expression in reverse order
- for (auto it = expression.rbegin(); it != expression.rend(); ++it) {
- char c = *it;
- if (isdigit(c)) {
- st.push(c - '0');
- } else {
- int a = st.top(); st.pop();
- int b = st.top(); st.pop();
-
- switch (c) {
- case '+': st.push(a + b); break;
- case '-': st.push(a - b); break;
- case '*': st.push(a * b); break;
- case '/': st.push(a / b); break;
- }
- }
- }
- return st.top();
-}
-
-int main() {
- // Example: "+*235" becomes (2*3)+5 = 11
- cout << evaluatePrefix("+*235") << endl; // Output: 11
- return 0;
-}`,
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- PreFix implementation using Stack
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/stack/polish/prefix/content.jsx b/app/visualizer/stack/polish/prefix/content.jsx
deleted file mode 100755
index a306241e7..000000000
--- a/app/visualizer/stack/polish/prefix/content.jsx
+++ /dev/null
@@ -1,234 +0,0 @@
-"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.`,
- `Note: Higher precedence means the operation will happen first. Exponentiation (^) is evaluated right-to-left, while others are left-to-right.`,
- ];
-
- const steps = [
- { points : "Reverse the infix expression, while keeping the positions of parentheses correct." },
- { points : "Replace ( with ) and vice-versa." },
- { points : "Convert the reversed expression to postfix using a stack." },
- { points : "Finally, reverse the postfix expression to get the prefix expression." },
- ];
-
- const example = [
- { points : "Infix: (A + B) * (C - D)" },
- { points : "Step 1: Reverse → (D - C) * (B + A)" },
- { points : "Step 2: Convert to postfix → D C - B A + *" },
- { points : "Step 3: Reverse → * + A B - C D" },
- ];
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is Prefix Notation? */}
-
-
-
- What is Prefix Notation?
-
-
-
- {paragraph[0]}
-
-
- {paragraph[1]}
-
-
-
-
- {/* Infix to Prefix Conversion Steps */}
-
-
-
- Infix to Prefix Conversion Steps
-
-
-
- {steps.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
- Example:
-
-
- {example.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
-
-
-
- {/* Operator Precedence Table */}
-
-
-
- Operator Precedence Table
-
-
-
-
-
-
- Operator
-
-
- Meaning
-
-
- Precedence
-
-
-
-
-
-
- ( )
-
-
- Parentheses
-
-
- Highest
-
-
-
-
- ^ %
-
-
- Exponentiation / Modulus
-
-
- 2
-
-
-
-
- * /
-
-
- Multiplication / Division
-
-
- 3
-
-
-
-
- + -
-
-
- Addition / Subtraction
-
-
- 4 (Lowest)
-
-
-
-
-
- {paragraph[2]}
-
-
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-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
deleted file mode 100755
index 87dd2f95a..000000000
--- a/app/visualizer/stack/polish/prefix/page.jsx
+++ /dev/null
@@ -1,119 +0,0 @@
-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 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:
- "Prefix Notation using Stack | Learn Prefix Evaluation in DSA with Code in JS, C, Python, Java",
- description:
- "Understand how to evaluate Prefix expressions using a Stack with interactive animations and code examples in JavaScript, C, Python, and Java. Essential for mastering DSA concepts and preparing for interviews.",
- keywords: [
- "Prefix Notation",
- "Prefix Evaluation Stack",
- "Stack DSA",
- "Prefix Expression",
- "DSA Prefix",
- "Evaluate Prefix using Stack",
- "Learn Prefix Notation",
- "Prefix Evaluation in JavaScript",
- "Prefix Evaluation in C",
- "Prefix Evaluation in Python",
- "Prefix Evaluation in Java",
- "Stack Code Examples",
- "DSA Expression Evaluation",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/stack/prefix.png",
- width: 1200,
- height: 630,
- alt: "Stack infix to prefix",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Stack : Infix to prefix", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
- Infix to Prefix
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/stack/polish/prefix/quiz.jsx b/app/visualizer/stack/polish/prefix/quiz.jsx
deleted file mode 100755
index 654bd3ae5..000000000
--- a/app/visualizer/stack/polish/prefix/quiz.jsx
+++ /dev/null
@@ -1,509 +0,0 @@
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const StackQuiz = () => {
- const questions = [
- {
- question: "What is the defining characteristic of prefix notation?",
- options: [
- "Operators appear between operands",
- "Operators appear after operands",
- "Operators appear before operands",
- "Operators are omitted entirely"
- ],
- correctAnswer: 2,
- explanation: "Prefix notation places operators **before** their operands (e.g., `+ 3 4` instead of `3 + 4`)."
- },
- {
- question: "How is the infix expression `A * (B + C)` converted to prefix?",
- options: [
- "* A + B C",
- "A * B + C",
- "+ * A B C",
- "* + A B C"
- ],
- correctAnswer: 0,
- explanation: "Parentheses force `B + C` first → `+ B C`, then `* A` → `* A + B C`."
- },
- {
- question: "Which step is unique to infix-to-prefix conversion (compared to postfix)?",
- options: [
- "Using a stack for operators",
- "Reversing the infix expression",
- "Handling operator precedence",
- "Processing left to right"
- ],
- correctAnswer: 1,
- explanation: "Prefix conversion requires **reversing the infix expression** first (while handling parentheses swaps)."
- },
- {
- question: "What is the prefix form of `2 ^ 3 ^ 2`? (^ = exponentiation)",
- options: [
- "^ 2 ^ 3 2",
- "^ ^ 2 3 2",
- "2 ^ 3 ^ 2",
- "^ 2 3 ^ 2"
- ],
- correctAnswer: 0,
- explanation: "Exponentiation is right-associative: `2 ^ (3 ^ 2)` → `^ 2 ^ 3 2`."
- },
- {
- question: "Why does prefix notation eliminate the need for parentheses?",
- options: [
- "Operators are evaluated in reverse order",
- "Operator position implicitly defines precedence",
- "It only supports two operands",
- "It uses postfix internally"
- ],
- correctAnswer: 1,
- explanation: "Operator order in prefix ensures correct evaluation (e.g., `* + A B - C D` = `(A+B) * (C-D)`)."
- },
- {
- question: "What is the prefix equivalent of `A - B / C + D`?",
- options: [
- "+ - A / B C D",
- "- A / B + C D",
- "+ / - A B C D",
- "- + A / B C D"
- ],
- correctAnswer: 0,
- explanation: "`/` has higher precedence: `B / C` → `- A (result)` → `+ (result) D` → `+ - A / B C D`."
- },
- {
- question: "Which data structure is used during infix-to-prefix conversion?",
- options: [
- "Queue",
- "Stack",
- "Binary Tree",
- "Hash Table"
- ],
- correctAnswer: 1,
- explanation: "A **stack** manages operators and parentheses during conversion."
- },
- {
- question: "What is the prefix form of `(A + B) * C - D`?",
- options: [
- "- * + A B C D",
- "* + A B - C D",
- "- + * A B C D",
- "* - + A B C D"
- ],
- correctAnswer: 0,
- explanation: "Parentheses first: `+ A B` → `* (result) C` → `- (result) D` → `- * + A B C D`."
- },
- {
- question: "How are parentheses handled during infix reversal for prefix conversion?",
- options: [
- "They are deleted",
- "They are kept in the same order",
- "`(` becomes `)` and vice versa",
- "They are converted to brackets"
- ],
- correctAnswer: 2,
- explanation: "During reversal, `(` and `)` are swapped to maintain correctness (e.g., `(A+B)` → `)B+A(`)."
- },
- {
- question: "What is the result of evaluating the prefix expression `- * + 2 3 4 5`?",
- options: [
- "15",
- "9",
- "17",
- "20"
- ],
- correctAnswer: 0,
- explanation: "Steps: `+ 2 3` → 5; `* 5 4` → 20; `- 20 5` → **15**."
- }
-];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showExplanation, setShowExplanation] = useState(false);
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
- const [penaltyApplied, setPenaltyApplied] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- if (selectedAnswer !== null) return;
- setSelectedAnswer(optionIndex);
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = optionIndex;
- setAnswers(newAnswers);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- if (showExplanation && !penaltyApplied) {
- setScore(prevScore => Math.max(0, prevScore - 0.5));
- setPenaltyApplied(true);
- }
-
- if (selectedAnswer === questions[currentQuestion].correctAnswer) {
- setScore(score + 1);
- }
-
- setShowExplanation(false);
- setPenaltyApplied(false);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(null);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setShowExplanation(false);
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowExplanation(false);
- setShowIntro(true);
- setPenaltyApplied(false);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Stack Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- -0.5 point penalty for viewing explanations
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
- {selectedAnswer !== null && (
-
-
setShowExplanation(!showExplanation)}
- className="text-sm flex items-center text-blue-600 dark:text-blue-400 hover:underline mb-2"
- >
-
- {showExplanation ? "Hide Explanation" : "Show Explanation"}
-
-
- {showExplanation && (
-
- {questions[currentQuestion].explanation}
-
- )}
-
-
- )}
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default StackQuiz;
\ No newline at end of file
diff --git a/app/visualizer/stack/push-pop/animation.jsx b/app/visualizer/stack/push-pop/animation.jsx
deleted file mode 100755
index ab6e116c9..000000000
--- a/app/visualizer/stack/push-pop/animation.jsx
+++ /dev/null
@@ -1,117 +0,0 @@
-"use client";
-import React, { useState, useEffect, useLayoutEffect, useRef } from "react";
-import { gsap } from "gsap";
-import PushPop from "@/app/components/ui/PushPop";
-
-const StackVisualizer = () => {
- const [stack, setStack] = useState([]);
- const [operation, setOperation] = useState(null);
- const [message, setMessage] = useState("Stack is empty");
- const [isAnimating, setIsAnimating] = useState(false);
- const stackRefs = useRef([]);
-
- // Reset stack
- const reset = () => {
- setStack([]);
- setMessage("Stack is empty");
- setOperation(null);
- };
-
- useEffect(() => {
- if (isAnimating && stackRefs.current.length > 0) {
- const el = stackRefs.current[0];
- if (operation?.includes("pushed")) {
- gsap.fromTo(
- el,
- { y: -50, opacity: 0 },
- { y: 0, opacity: 1, duration: 0.5, ease: "power3.out" }
- );
- } else if (operation?.includes("popped")) {
- gsap.to(el, { y: 50, opacity: 0, duration: 0.3, ease: "power1.in" });
- } else if (operation?.includes("Peek")) {
- gsap.fromTo(
- el,
- { scale: 1 },
- { scale: 1.2, yoyo: true, repeat: 1, duration: 0.2 }
- );
- }
- }
- }, [stack, operation, isAnimating]);
-
- return (
-
-
- Visualize the LIFO (Last In, First Out) principle
-
-
-
- {/* Use the PushPop component */}
-
-
- {/* Stack Visualization */}
-
-
Stack Visualization
-
- {/* Operation Status */}
- {operation && (
-
- {operation}
-
- )}
-
- {/* Vertical Stack */}
-
- {/* Top indicator */}
-
- {stack.length > 0 ? "↑ Top" : ""}
-
-
- {/* Stack elements */}
-
- {stack.length === 0 ? (
-
- Stack is empty
-
- ) : (
-
- {stack.map((item, index) => (
-
(stackRefs.current[index] = el)}
- className={`p-3 border-2 rounded text-center font-medium transition-all duration-300 ${
- index === 0
- ? "bg-blue-100 dark:bg-blue-900 border-blue-300 dark:border-blue-700"
- : "bg-white dark:bg-gray-700 border-gray-200 dark:border-gray-600"
- }`}
- >
-
{item}
- {index === 0 && (
-
- (Top)
-
- )}
-
- ))}
-
- )}
-
-
- {/* Bottom indicator */}
-
- {stack.length > 0 ? "↓ Bottom" : ""}
-
-
-
-
-
- );
-};
-
-export default StackVisualizer;
diff --git a/app/visualizer/stack/push-pop/codeBlock.jsx b/app/visualizer/stack/push-pop/codeBlock.jsx
deleted file mode 100755
index 135138afa..000000000
--- a/app/visualizer/stack/push-pop/codeBlock.jsx
+++ /dev/null
@@ -1,415 +0,0 @@
-'use client';
-import { useState, useRef } from 'react';
-import { FaCopy, FaCheck, FaCode } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/github.css';
-import 'highlight.js/styles/github-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = () => {
- const [selectedLanguage, setSelectedLanguage] = useState("javascript");
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
- const topRef = useRef(null);
-
- const languages = [
- { id: "javascript", name: "JavaScript" },
- { id: "python", name: "Python" },
- { id: "java", name: "Java" },
- { id: "c", name: "C" },
- { id: "cpp", name: "C++" },
- ];
-
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- } catch (err) {
- console.error("Failed to copy text: ", err);
- }
- };
-
- const codeExamples = {
- javascript: `// Stack Implementation with Push/Pop in JavaScript
-class Stack {
- constructor() {
- this.items = [];
- this.top = -1;
- this.MAX_SIZE = 10;
- }
-
- // Push operation
- push(element) {
- if (this.top >= this.MAX_SIZE - 1) {
- console.log("Stack Overflow");
- return;
- }
- this.items[++this.top] = element;
- console.log(\`Pushed: \${element}\`);
- }
-
- // Pop operation
- pop() {
- if (this.top < 0) {
- console.log("Stack Underflow");
- return -1;
- }
- const element = this.items[this.top--];
- console.log(\`Popped: \${element}\`);
- return element;
- }
-
- // Display stack
- display() {
- console.log("Current Stack:", this.items.slice(0, this.top + 1));
- }
-}
-
-// Usage
-const stack = new Stack();
-stack.push(10);
-stack.push(20);
-stack.push(30);
-stack.display();
-stack.pop();
-stack.display();`,
-
- python: `# Stack Implementation with Push/Pop in Python
-class Stack:
- def __init__(self):
- self.items = []
- self.top = -1
- self.MAX_SIZE = 10
-
- # Push operation
- def push(self, element):
- if self.top >= self.MAX_SIZE - 1:
- print("Stack Overflow")
- return
- self.top += 1
- self.items.append(element)
- print(f"Pushed: {element}")
-
- # Pop operation
- def pop(self):
- if self.top < 0:
- print("Stack Underflow")
- return -1
- element = self.items.pop()
- self.top -= 1
- print(f"Popped: {element}")
- return element
-
- # Display stack
- def display(self):
- print("Current Stack:", self.items)
-
-# Usage
-stack = Stack()
-stack.push(10)
-stack.push(20)
-stack.push(30)
-stack.display()
-stack.pop()
-stack.display()`,
-
- java: `// Stack Implementation with Push/Pop in Java
-import java.util.ArrayList;
-
-class Stack {
- private ArrayList items;
- private int top;
- private final int MAX_SIZE = 10;
-
- public Stack() {
- items = new ArrayList<>();
- top = -1;
- }
-
- // Push operation
- public void push(int element) {
- if (top >= MAX_SIZE - 1) {
- System.out.println("Stack Overflow");
- return;
- }
- items.add(++top, element);
- System.out.println("Pushed: " + element);
- }
-
- // Pop operation
- public int pop() {
- if (top < 0) {
- System.out.println("Stack Underflow");
- return -1;
- }
- int element = items.remove(top--);
- System.out.println("Popped: " + element);
- return element;
- }
-
- // Display stack
- public void display() {
- System.out.print("Current Stack: ");
- for (int i = 0; i <= top; i++) {
- System.out.print(items.get(i) + " ");
- }
- System.out.println();
- }
-}
-
-public class Main {
- public static void main(String[] args) {
- Stack stack = new Stack();
- stack.push(10);
- stack.push(20);
- stack.push(30);
- stack.display();
- stack.pop();
- stack.display();
- }
-}`,
-
- c: `// Stack Implementation with Push/Pop in C
-#include
-#include
-#define MAX_SIZE 10
-
-typedef struct {
- int items[MAX_SIZE];
- int top;
-} Stack;
-
-void initialize(Stack *s) {
- s->top = -1;
-}
-
-// Push operation
-void push(Stack *s, int element) {
- if (s->top >= MAX_SIZE - 1) {
- printf("Stack Overflow\\n");
- return;
- }
- s->items[++s->top] = element;
- printf("Pushed: %d\\n", element);
-}
-
-// Pop operation
-int pop(Stack *s) {
- if (s->top < 0) {
- printf("Stack Underflow\\n");
- return -1;
- }
- int element = s->items[s->top--];
- printf("Popped: %d\\n", element);
- return element;
-}
-
-// Display stack
-void display(Stack *s) {
- printf("Current Stack: ");
- for (int i = 0; i <= s->top; i++) {
- printf("%d ", s->items[i]);
- }
- printf("\\n");
-}
-
-int main() {
- Stack stack;
- initialize(&stack);
-
- push(&stack, 10);
- push(&stack, 20);
- push(&stack, 30);
- display(&stack);
- pop(&stack);
- display(&stack);
-
- return 0;
-}`,
-
- cpp: `// Stack Implementation with Push/Pop in C++
-#include
-#include
-using namespace std;
-
-class Stack {
-private:
- vector items;
- int top;
- const int MAX_SIZE = 10;
-
-public:
- Stack() : top(-1) {}
-
- // Push operation
- void push(int element) {
- if (top >= MAX_SIZE - 1) {
- cout << "Stack Overflow" << endl;
- return;
- }
- items.push_back(element);
- top++;
- cout << "Pushed: " << element << endl;
- }
-
- // Pop operation
- int pop() {
- if (top < 0) {
- cout << "Stack Underflow" << endl;
- return -1;
- }
- int element = items.back();
- items.pop_back();
- top--;
- cout << "Popped: " << element << endl;
- return element;
- }
-
- // Display stack
- void display() {
- cout << "Current Stack: ";
- for (int i = 0; i <= top; i++) {
- cout << items[i] << " ";
- }
- cout << endl;
- }
-};
-
-int main() {
- Stack stack;
- stack.push(10);
- stack.push(20);
- stack.push(30);
- stack.display();
- stack.pop();
- stack.display();
-
- return 0;
-}`,
- };
-
- return (
- setIsHovered(true)}
- onMouseLeave={() => setIsHovered(false)}
- >
-
- {/* Header */}
-
-
-
-
- Stack Push & Pop Implementation
-
-
-
-
copyToClipboard(codeExamples[selectedLanguage])}
- className="flex items-center gap-2 px-3 py-1.5 bg-gray-100 dark:bg-gray-600 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-500 transition-colors text-gray-800 dark:text-gray-100 text-sm font-medium"
- aria-label="Copy code"
- >
-
- {copied ? (
-
- Copied
-
- ) : (
-
- Copy Code
-
- )}
-
-
-
-
- {/* Language Selector */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang.id)}
- className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
- selectedLanguage === lang.id
- ? "bg-blue-500 text-white shadow-md"
- : "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"
- }`}
- >
- {lang.name}
-
- ))}
-
-
- {/* Code Block */}
-
-
-
-
-
-
-
-
-
- {/* Language indicator (shown on hover) */}
-
- {isHovered && (
-
- {selectedLanguage.toUpperCase()}
-
- )}
-
-
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/stack/push-pop/content.jsx b/app/visualizer/stack/push-pop/content.jsx
deleted file mode 100755
index f4d90ddc0..000000000
--- a/app/visualizer/stack/push-pop/content.jsx
+++ /dev/null
@@ -1,303 +0,0 @@
-"use client";
-import ComplexityGraph from "@/app/components/ui/graph";
-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 paragraphs = [
- `Push and Pop are the two fundamental operations in stack data structure. Stack follows LIFO (Last In First Out) principle - the last element added is the first one to be removed.`,
- `Push and Pop operations are fundamental to stack functionality. While simple to implement, stacks are powerful data structures used in many algorithms and system designs.`,
- ];
-
- const examplePush = [
- { points: "Start with empty stack: [ ]" },
- { points: "Push 5: [5]" },
- { points: "Push 3: [3, 5]" },
- { points: "Push 7: [7, 3, 5]" },
- ];
-
- const pushComplexity = [
- { points: "Time Complexity: O(1)" },
- { points: "Space Complexity: O(1)" },
- ];
-
- const examplePop = [
- { points: "Current stack: [7, 3, 5]" },
- { points: "Pop → returns 7: [3, 5]" },
- { points: "Pop → returns 3: [5]" },
- { points: "Pop → returns 5: [ ]" },
- ];
-
- const popComplexity = [
- { points: "Time Complexity: O(1)" },
- { points: "Space Complexity: O(1)" },
- ];
-
- {
- /* applications */
- }
- const applications = [
- {
- points: "Function call management in programming languages (call stack)",
- },
- { points: "Undo/Redo operations in text editors" },
- { points: "Back/Forward navigation in web browsers" },
- { points: "Expression evaluation and syntax parsing" },
- { points: "Memory management" },
- ];
-
- {
- /* underflow and overflow */
- }
- const flows = [{ title: "Stack Underflow" }, { title: "Stack Overflow" }];
-
- const flowsDetails = [
- { detail: "Trying to pop from an empty stack" },
- {
- detail: "Trying to push to a full stack (in fixed-size implementations)",
- },
- ];
-
- const combineData = flows.map((item, index) => ({
- title: item.title,
- detail: flowsDetails[index].detail,
- }));
-
- return (
-
-
-
- {mounted && (
-
- )}
-
-
-
-
- {/* What is Stack Push & Pop */}
-
-
-
- What is Stack Push & Pop?
-
-
-
-
- {/* Push Operation */}
-
-
-
- Push Operation
-
-
-
- Adds an element to the top of the stack.
-
-
- Example: Pushing elements onto a stack
-
-
- {examplePush.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
- {pushComplexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
-
-
- {/* Pop Operation */}
-
-
-
- Pop Operation
-
-
-
- Removes and returns the topmost element from the stack.
-
-
- Example: Popping elements from a stack
-
-
- {examplePop.map((item, index) => (
-
- {item.points}
-
- ))}
-
-
- {popComplexity.map((item, index) => (
-
-
- {item.points.split(":")[0]}:
-
- {item.points.split(":")[1]}
-
- ))}
-
-
-
- 1}
- averageCase={(n) => 1}
- worstCase={(n) => 1}
- maxN={25}
- />
-
-
-
-
- {/* Stack Underflow & Overflow */}
-
-
-
- Stack Underflow & Overflow
-
-
-
- {combineData.map((item, index) => (
-
- {item.title}: {" "}
- {item.detail}
-
- ))}
-
-
-
-
- {/* Real-world Applications */}
-
-
-
- Real-world Applications
-
-
-
- {applications.map((items, index) => (
-
- {items.points}
-
- ))}
-
-
-
-
- {/* Additional Info */}
-
-
-
- {/* Mobile iframe at bottom */}
-
- {mounted && (
-
- )}
-
-
-
- );
-};
-
-export default content;
diff --git a/app/visualizer/stack/push-pop/page.jsx b/app/visualizer/stack/push-pop/page.jsx
deleted file mode 100755
index 760edf5e2..000000000
--- a/app/visualizer/stack/push-pop/page.jsx
+++ /dev/null
@@ -1,124 +0,0 @@
-import Animation from "@/app/visualizer/stack/push-pop/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/push-pop/content";
-import Quiz from "@/app/visualizer/stack/push-pop/quiz";
-import Code from "@/app/visualizer/stack/push-pop/codeBlock";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import ModuleCard from "@/app/components/ui/ModuleCard";
-import { MODULE_MAPS } from "@/lib/modulesMap";
-import Footer from '@/app/components/footer';
-import BackToTopButton from '@/app/components/ui/backtotop';
-
-export const metadata = {
- title:
- "Stack Push & Pop Visualizer & Quiz | Learn Stack Operations with Code in JS, C, Python, Java",
- description:
- "Understand Stack Push and Pop operations through step-by-step animations and test your knowledge with an interactive quiz. Includes code examples in JavaScript, C, Python, and Java. Ideal for beginners and interview preparation to master stack-based data structures visually and through hands-on coding.",
- keywords: [
- "Stack Push Visualizer",
- "Stack Pop Visualizer",
- "Push and Pop Animation",
- "Stack Operations",
- "Stack Algorithm",
- "Stack Quiz",
- "Data Structure Visualization",
- "Learn Stack Push",
- "Learn Stack Pop",
- "Interactive Stack Tool",
- "Practice Stack Operations",
- "Test Stack Knowledge",
- "Stack in JavaScript",
- "Stack in C",
- "Stack in Python",
- "Stack in Java",
- "Stack Code Examples",
- ],
- robots: "index, follow",
- openGraph: {
- images: [
- {
- url: "/og/stack/pushPop.png",
- width: 1200,
- height: 630,
- alt: "Stack Push and Pop Visualization",
- },
- ],
- },
-};
-
-export default function Page() {
- const paths = [
- { name: "Home", href: "/" },
- { name: "Visualizer", href: "/visualizer" },
- { name: "Stack : Push & Pop", href: "" },
- ];
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
- Test Your Knowledge before moving forward!
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/app/visualizer/stack/push-pop/quiz.jsx b/app/visualizer/stack/push-pop/quiz.jsx
deleted file mode 100755
index eaefc3f9a..000000000
--- a/app/visualizer/stack/push-pop/quiz.jsx
+++ /dev/null
@@ -1,472 +0,0 @@
-"use client";
-import React, { useState } from 'react';
-import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa';
-import { motion, AnimatePresence } from 'framer-motion';
-
-const StackQuiz = () => {
- const questions = [
- {
- question: "What principle does the stack data structure follow?",
- options: [
- "FIFO (First In First Out)",
- "LIFO (Last In First Out)",
- "Random Access",
- "Priority Ordering"
- ],
- correctAnswer: 1,
- explanation:
- "Stack follows LIFO (Last In First Out) principle - the last element added is the first one to be removed.",
- },
- {
- question: "What is the time complexity of push and pop operations in a stack?",
- options: ["O(n)", "O(log n)", "O(1)", "O(n²)"],
- correctAnswer: 2,
- explanation:
- "Both push and pop operations in a stack have O(1) time complexity as they only involve operations at the top of the stack.",
- },
- {
- question: "What happens when you try to pop from an empty stack?",
- options: [
- "Stack Overflow",
- "Stack Underflow",
- "Null Pointer Exception",
- "The stack resizes itself"
- ],
- correctAnswer: 1,
- explanation:
- "Attempting to pop from an empty stack results in stack underflow, which is an error condition.",
- },
- {
- question: "After pushing 10, 20, and 30 onto an empty stack, what will be the result of two consecutive pop operations?",
- options: [
- "10 then 20",
- "20 then 10",
- "30 then 20",
- "30 then 10"
- ],
- correctAnswer: 2,
- explanation:
- "The stack will be [30, 20, 10] after pushes. First pop returns 30, second pop returns 20.",
- },
- {
- question: "What is the space complexity of stack operations?",
- options: ["O(n)", "O(1)", "O(log n)", "Depends on implementation"],
- correctAnswer: 1,
- explanation:
- "Each push/pop operation itself uses constant space (O(1)), though the overall stack may use O(n) space.",
- },
- {
- question: "Which of the following is NOT a typical application of stacks?",
- options: [
- "Function call management",
- "Undo operations in text editors",
- "CPU scheduling",
- "Expression evaluation"
- ],
- correctAnswer: 2,
- explanation:
- "CPU scheduling typically uses queues rather than stacks. Stacks are used in function calls, undo operations, and expression evaluation.",
- },
- {
- question: "What happens when you push to a full stack (in fixed-size implementation)?",
- options: [
- "The stack automatically resizes",
- "Stack Overflow",
- "The oldest element is removed",
- "The operation is queued"
- ],
- correctAnswer: 1,
- explanation:
- "Attempting to push to a full stack in fixed-size implementations results in stack overflow.",
- },
- {
- question: "In a stack implementation, which end is used for both push and pop operations?",
- options: [
- "The front end",
- "The rear end",
- "The top end",
- "Any random end"
- ],
- correctAnswer: 2,
- explanation:
- "All stack operations (push and pop) happen at the top end of the stack.",
- },
- {
- question: "Which data structure would be most appropriate to implement an undo feature?",
- options: [
- "Queue",
- "Stack",
- "Linked List",
- "Tree"
- ],
- correctAnswer: 1,
- explanation:
- "A stack is ideal for undo operations as it naturally follows the LIFO principle - the last action should be the first one undone.",
- },
- {
- question: "What would be the result of pushing 'A', then 'B', then popping, then pushing 'C' to an empty stack?",
- options: [
- "[A, B, C]",
- "[C, A]",
- "[A, C]",
- "[B, C]"
- ],
- correctAnswer: 1,
- explanation:
- "Operations: push A → [A], push B → [B, A], pop → returns B: [A], push C → [C, A].",
- },
- ];
-
- const [currentQuestion, setCurrentQuestion] = useState(0);
- const [selectedAnswer, setSelectedAnswer] = useState(null);
- const [score, setScore] = useState(0);
- const [showResult, setShowResult] = useState(false);
- const [quizCompleted, setQuizCompleted] = useState(false);
- const [answers, setAnswers] = useState(Array(questions.length).fill(null));
- const [showIntro, setShowIntro] = useState(true);
- const [showSuccessAnimation, setShowSuccessAnimation] = useState(false);
-
- const handleAnswerSelect = (optionIndex) => {
- setSelectedAnswer(optionIndex);
- };
-
- const handleNextQuestion = () => {
- if (selectedAnswer === null) return;
-
- const newAnswers = [...answers];
- newAnswers[currentQuestion] = selectedAnswer;
- setAnswers(newAnswers);
-
- const newScore = newAnswers.reduce((acc, ans, idx) => {
- return ans === questions[idx].correctAnswer ? acc + 1 : acc;
- }, 0);
- setScore(newScore);
-
- if (currentQuestion < questions.length - 1) {
- setCurrentQuestion(currentQuestion + 1);
- setSelectedAnswer(newAnswers[currentQuestion + 1]);
- } else {
- setShowSuccessAnimation(true);
- setTimeout(() => {
- setShowSuccessAnimation(false);
- setQuizCompleted(true);
- setShowResult(true);
- }, 2000);
- }
- };
-
- const handlePreviousQuestion = () => {
- setCurrentQuestion(currentQuestion - 1);
- setSelectedAnswer(answers[currentQuestion - 1]);
- };
-
- const resetQuiz = () => {
- setCurrentQuestion(0);
- setSelectedAnswer(null);
- setScore(0);
- setShowResult(false);
- setQuizCompleted(false);
- setAnswers(Array(questions.length).fill(null));
- setShowIntro(true);
- };
-
- const calculateWeakAreas = () => {
- const weakAreas = [];
- if (answers[0] !== questions[0].correctAnswer) {
- weakAreas.push("understanding the basic principle of Selection Sort");
- }
- if (answers[1] !== questions[1].correctAnswer) {
- weakAreas.push("time complexity analysis");
- }
- if (answers[2] !== questions[2].correctAnswer) {
- weakAreas.push("counting swaps in Selection Sort");
- }
- if (answers[3] !== questions[3].correctAnswer) {
- weakAreas.push("comparison with other simple sorts");
- }
- if (answers[4] !== questions[4].correctAnswer) {
- weakAreas.push("space complexity");
- }
- if (answers[5] !== questions[5].correctAnswer) {
- weakAreas.push("stability characteristics");
- }
- if (answers[6] !== questions[6].correctAnswer) {
- weakAreas.push("practical applications");
- }
-
- return weakAreas.length > 0
- ? `Focus on improving: ${weakAreas.join(', ')}. Review the corresponding sections above.`
- : "Perfect! You've mastered all Selection Sort concepts!";
- };
-
- const startQuiz = () => {
- setShowIntro(false);
- };
-
- const getStarRating = () => {
- const percentage = (score / questions.length) * 100;
- if (percentage >= 90) return 5;
- if (percentage >= 70) return 4;
- if (percentage >= 50) return 3;
- if (percentage >= 30) return 2;
- return 1;
- };
-
- return (
-
- {showIntro ? (
-
-
-
- Stack Quiz Challenge
-
-
-
- How it works:
-
-
-
-
- +1 point for each correct answer
-
-
-
- 0 points for wrong answers
-
-
-
- Earn stars based on your final score (max 5 stars)
-
-
-
-
- Start Quiz
-
-
- ) : showSuccessAnimation ? (
-
-
-
-
-
- Quiz Completed!
-
-
- ) : !showResult ? (
-
-
-
-
- Question {currentQuestion + 1} of {questions.length}
-
-
- Score: {score.toFixed(1)}
-
-
-
-
-
-
-
- {questions[currentQuestion].question}
-
-
-
- {questions[currentQuestion].options.map((option, index) => (
-
handleAnswerSelect(index)}
- >
-
-
- {String.fromCharCode(65 + index)}
-
- {option}
-
-
- ))}
-
-
-
-
-
-
-
- Previous
-
-
-
- {currentQuestion === questions.length - 1 ? "Finish" : "Next"}{" "}
-
-
-
-
- ) : (
-
-
-
-
-
- {score.toFixed(1)}/{questions.length}
-
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
-
-
-
-
- {score === questions.length
- ? "Perfect Score!"
- : score >= questions.length * 0.8
- ? "Excellent Work!"
- : score >= questions.length * 0.6
- ? "Good Job!"
- : score >= questions.length * 0.4
- ? "Keep Practicing!"
- : "Let's Review Again!"}
-
-
- You scored {((score / questions.length) * 100).toFixed(0)}%
- correct
-
-
-
-
-
- Performance Analysis
-
-
{calculateWeakAreas()}
-
-
-
-
- Question Breakdown:
-
- {questions.map((q, index) => (
-
-
- {q.question}
-
-
- {answers[index] === q.correctAnswer ? (
-
- ) : (
-
- )}
-
-
- Your answer:{" "}
- {answers[index] !== null
- ? q.options[answers[index]]
- : "Not answered"}
-
- {answers[index] !== q.correctAnswer && (
-
- Correct answer: {q.options[q.correctAnswer]}
-
- )}
-
-
-
- ))}
-
-
-
- Take Quiz Again
-
-
- )}
-
- );
-};
-
-export default StackQuiz;
\ No newline at end of file
diff --git a/app/visualizer/trees/binaryTree/types/animation.jsx b/app/visualizer/trees/binaryTree/types/animation.jsx
deleted file mode 100755
index a0b8fc8f9..000000000
--- a/app/visualizer/trees/binaryTree/types/animation.jsx
+++ /dev/null
@@ -1,39 +0,0 @@
-"use client";
-import Footer from "@/app/components/footer";
-import ExploreOther from "@/app/components/ui/exploreOther";
-import Content from "@/app/visualizer/trees/binaryTree/types/content";
-import CodeBlock from "@/app/visualizer/trees/binaryTree/types/codeBlock";
-import GoBackButton from "@/app/components/ui/goback";
-import BackToTop from "@/app/components/ui/backtotop";
-
-const InfixToPostfixVisualizer = () => {
- return (
-
-
-
- { /* go back block here */}
-
-
-
-
- { /* main logic here */}
-
- Types of Binary Trees
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default InfixToPostfixVisualizer;
diff --git a/app/visualizer/trees/binaryTree/types/codeBlock.jsx b/app/visualizer/trees/binaryTree/types/codeBlock.jsx
deleted file mode 100755
index 2021a3276..000000000
--- a/app/visualizer/trees/binaryTree/types/codeBlock.jsx
+++ /dev/null
@@ -1,81 +0,0 @@
-'use client';
-
-import { useState } from 'react';
-import hljs from 'highlight.js';
-import 'highlight.js/styles/atom-one-dark.css';
-
-export const highlightCode = (code, language) => {
- const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
- return hljs.highlight(code, { language: validLanguage }).value;
-};
-
-const CodeBlock = ({ code = '', language = 'javascript', title = 'Code' }) => {
- const [selectedLanguage, setSelectedLanguage] = useState(language);
- const [copied, setCopied] = useState(false);
- const [isHovered, setIsHovered] = useState(false);
-
- const languages = ['javascript', 'python', 'java', 'c', 'cpp'];
-
- const handleCopy = () => {
- navigator.clipboard.writeText(code);
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- };
-
- const highlightedCode = highlightCode(code, selectedLanguage);
-
- return (
-
- {/* Mac Window Chrome */}
-
-
- {/* Traffic Light Dots */}
-
- {/* Title */}
-
{title}
-
- {/* Copy Button */}
-
- {copied ? '✓ Copied' : '📋 Copy'}
-
-
-
- {/* Language Tabs */}
-
- {languages.map((lang) => (
- setSelectedLanguage(lang)}
- className={`px-4 py-2 rounded-full text-sm font-medium transition-all duration-200 capitalize whitespace-nowrap ${
- selectedLanguage === lang
- ? 'bg-[#a435f0] text-white'
- : 'bg-[#1a1a1a] text-[#999] hover:bg-[#2a2a2a] border border-[#333]'
- }`}
- >
- {lang}
-
- ))}
-
-
- {/* Code Block */}
-
-
- );
-};
-
-export default CodeBlock;
\ No newline at end of file
diff --git a/app/visualizer/trees/binaryTree/types/content.jsx b/app/visualizer/trees/binaryTree/types/content.jsx
deleted file mode 100755
index e24da0d04..000000000
--- a/app/visualizer/trees/binaryTree/types/content.jsx
+++ /dev/null
@@ -1,298 +0,0 @@
-/* content.jsx */
-import React, { useEffect, useRef } from 'react';
-import { gsap } from 'gsap';
-
-/* ------------- tiny helper to draw a tree ------------- */
-function drawTree(
- svg, // element
- nodes, // flat list [ {value, x, y}, ... ]
- edges, // [ {from, to}, ... ] (indices)
- radius = 18
-) {
- // clear previous drawings
- svg.innerHTML = '';
-
- // edges (lines)
- edges.forEach(({ from, to }) => {
- const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
- line.setAttribute('x1', nodes[from].x);
- line.setAttribute('y1', nodes[from].y);
- line.setAttribute('x2', nodes[to].x);
- line.setAttribute('y2', nodes[to].y);
- line.setAttribute('stroke', '#3b82f6'); // blue-500
- line.setAttribute('stroke-width', '2');
- svg.appendChild(line);
- });
-
- // nodes (circles + text)
- nodes.forEach(({ value, x, y }, i) => {
- const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
- const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
- const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
-
- circle.setAttribute('cx', x);
- circle.setAttribute('cy', y);
- circle.setAttribute('r', radius);
- circle.setAttribute('fill', '#3b82f6'); // blue-500
- circle.setAttribute('stroke', '#1e40af'); // blue-800
- circle.setAttribute('stroke-width', '2');
-
- text.setAttribute('x', x);
- text.setAttribute('y', y + 5);
- text.setAttribute('text-anchor', 'middle');
- text.setAttribute('fill', '#fff');
- text.setAttribute('font-size', '14');
- text.textContent = value;
-
- g.appendChild(circle);
- g.appendChild(text);
- svg.appendChild(g);
-
- // animate in
- gsap.from(g, { scale: 0, duration: 0.6, ease: 'back.out(1.7)', delay: i * 0.15 });
- });
-}
-
-export default function content() {
- /* refs for the three svgs */
- const fullSvg = useRef(null);
- const degenSvg = useRef(null);
- const completeSvg = useRef(null);
-
- /* ------------- GSAP trees ------------- */
- useEffect(() => {
- /* Full tree (height 2) */
- drawTree(
- fullSvg.current,
- [
- { value: 'A', x: 60, y: 30 },
- { value: 'B', x: 30, y: 80 },
- { value: 'C', x: 90, y: 80 },
- { value: 'D', x: 15, y: 130 },
- { value: 'E', x: 45, y: 130 },
- { value: 'F', x: 75, y: 130 },
- { value: 'G', x: 105, y: 130 },
- ],
- [
- { from: 0, to: 1 },
- { from: 0, to: 2 },
- { from: 1, to: 3 },
- { from: 1, to: 4 },
- { from: 2, to: 5 },
- { from: 2, to: 6 },
- ]
- );
-
- /* Degenerate / right-skewed */
- drawTree(
- degenSvg.current,
- [
- { value: '1', x: 30, y: 30 },
- { value: '2', x: 30, y: 80 },
- { value: '3', x: 30, y: 130 },
- { value: '4', x: 30, y: 180 },
- ],
- [
- { from: 0, to: 1 },
- { from: 1, to: 2 },
- { from: 2, to: 3 },
- ]
- );
-
- /* Complete tree (7 nodes) */
- drawTree(
- completeSvg.current,
- [
- { value: '1', x: 60, y: 30 },
- { value: '2', x: 30, y: 80 },
- { value: '3', x: 90, y: 80 },
- { value: '4', x: 15, y: 130 },
- { value: '5', x: 45, y: 130 },
- { value: '6', x: 75, y: 130 },
- { value: '7', x: 105, y: 130 },
- ],
- [
- { from: 0, to: 1 },
- { from: 0, to: 2 },
- { from: 1, to: 3 },
- { from: 1, to: 4 },
- { from: 2, to: 5 },
- { from: 2, to: 6 },
- ]
- );
- }, []);
-
- /* ------------- textual content ------------- */
- const defFull = [
- { points: 'Every internal node has exactly two children' },
- { points: 'All leaves are on the same or adjacent levels' },
- { points: 'Maximum nodes for height h = 2^(h+1) – 1' },
- ];
- const defDegenerate = [
- { points: 'Each parent has only one child (left or right)' },
- { points: 'Effectively a linked list → Θ(n) height' },
- { points: 'Worst-case BST shape when data is sorted' },
- ];
- const defComplete = [
- { points: 'All levels fully filled except possibly the last' },
- { points: 'Last-level nodes are packed from the left' },
- { points: 'Array-based heap relies on this structure' },
- ];
- const identify = [
- { points: 'Count children for every node' },
- { points: 'If any node has exactly one child → not full' },
- { points: 'If height = n – 1 → degenerate / skewed' },
- { points: 'If level-order scan finds a gap before last node → not complete' },
- ];
-
- return (
-
-
- {/* Quick tags */}
-
-
-
- Three Types
-
-
- {['Full Binary Tree', 'Degenerate / Skewed', 'Complete Binary Tree'].map(
- (t) => (
-
- {t}
-
- )
- )}
-
-
-
- {/* GSAP trees */}
-
-
-
- Visual Comparison
-
-
-
- {[
- {
- title: 'Full Binary Tree',
- svgRef: fullSvg,
- description: 'A Full Binary Tree is a type of binary tree in which every node has either 0 or 2 children. It is perfectly structured, and all internal nodes have exactly two children while leaves are aligned at the same or adjacent levels, making it balanced for operations and ideal for understanding fundamental tree structures.'
- },
- {
- title: 'Degenerate (Skewed) Tree',
- svgRef: degenSvg,
- description: 'A Degenerate or Skewed Tree is a tree where each parent has only one child, making it essentially a linked list. It has the worst-case height of Θ(n), which can occur in unbalanced binary search trees when inserting sorted data without balancing, leading to inefficient operations.'
- },
- {
- title: 'Complete Binary Tree',
- svgRef: completeSvg,
- description: 'A Complete Binary Tree is a binary tree in which all levels are fully filled except possibly the last, which is filled from left to right. It is the structure used by heaps, ensuring operations can be performed efficiently with predictable height and balanced shape.'
- },
- ].map(({ title, svgRef, description }, i) => (
-
-
-
-
-
-
{title}
-
{description}
-
-
- ))}
-
-
-
- {/* Structural Rules */}
-
-
-
- Structural Rules
-
-
- {[defFull, defDegenerate, defComplete].map((rules, idx) => (
-
-
- {['Full', 'Degenerate', 'Complete'][idx]}
-
-
- {rules.map((r, i) => (
-
- {r.points}
-
- ))}
-
-
- ))}
-
-
-
- {/* Identification */}
-
-
-
- How to Identify a Type
-
-
-
- {identify.map((r, i) => (
-
- {r.points}
-
- ))}
-
-
-
-
- {/* Complexity */}
-
-
-
- Height & Complexity
-
-
-
-
-
- Tree Type
- Height
-
- Search/Insert/Delete
-
-
-
-
- {[
- ['Full (balanced)', 'Θ(log n)', 'Θ(log n)'],
- ['Complete', 'Θ(log n)', 'Θ(log n)'],
- ['Degenerate / Skewed', 'Θ(n)', 'Θ(n)'],
- ].map(([t, h, op], i) => (
-
- {t}
- {h}
-
- {op}
-
-
- ))}
-
-
-
-
-
-
- );
-}
\ No newline at end of file
diff --git a/app/visualizer/trees/binaryTree/types/page.jsx b/app/visualizer/trees/binaryTree/types/page.jsx
deleted file mode 100755
index a12c7cdb4..000000000
--- a/app/visualizer/trees/binaryTree/types/page.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import Animation from "@/app/visualizer/trees/binaryTree/types/animation";
-import Navbar from "@/app/components/navbarinner";
-
-export const metadata = {
- title: 'Binary Tree Types | Learn Full, Complete, and Degenerate Binary Trees in DSA',
- description: 'Learn about Binary Tree types in Data Structures and Algorithms, including Full Binary Tree, Complete Binary Tree, and Degenerate Tree with clear visual explanations, animations, and code examples in JavaScript, C, Python, and Java.',
- keywords: [
- 'Binary Tree',
- 'Binary Tree Types',
- 'Full Binary Tree',
- 'Complete Binary Tree',
- 'Degenerate Tree',
- 'Binary Tree Visualization',
- 'DSA Binary Trees',
- 'Binary Tree Animation',
- 'Binary Tree Implementation',
- 'Binary Tree in JavaScript',
- 'Binary Tree in C',
- 'Binary Tree in Python',
- 'Binary Tree in Java',
- 'Learn Binary Trees DSA',
- ],
- robots: 'index, follow',
-};
-
-export default function Page(){
- return(
- <>
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/app/visualizer/trees/traversing/in-order/animation.jsx b/app/visualizer/trees/traversing/in-order/animation.jsx
deleted file mode 100755
index 67629a79e..000000000
--- a/app/visualizer/trees/traversing/in-order/animation.jsx
+++ /dev/null
@@ -1,405 +0,0 @@
-'use client';
-import React, { useState, useRef, useEffect } from 'react';
-import Navbar from '@/app/components/navbarinner';
-import Footer from '@/app/components/footer';
-
-class TreeNode {
- constructor(value) {
- this.value = value;
- this.left = null;
- this.right = null;
- }
-}
-
-export default function InOrderVisualizer() {
- const [root, setRoot] = useState(null);
- const [inputValue, setInputValue] = useState('');
- const [message, setMessage] = useState('Tree is empty');
- const [isAnimating, setIsAnimating] = useState(false);
- const [highlightedNodes, setHighlightedNodes] = useState([]);
- const [traversalResult, setTraversalResult] = useState([]);
- const [speed, setSpeed] = useState(1);
- const [steps, setSteps] = useState(0);
- const animationRef = useRef(null);
-
- // Insert node into BST
- const insertNode = (node, value) => {
- if (!node) return new TreeNode(value);
- if (value < node.value) {
- node.left = insertNode(node.left, value);
- } else if (value > node.value) {
- node.right = insertNode(node.right, value);
- }
- return node;
- };
-
- const handleInsert = () => {
- const value = parseInt(inputValue);
- if (isNaN(value)) {
- setMessage('Please enter a valid number');
- return;
- }
-
- setRoot(prev => {
- const newRoot = insertNode(prev ? {...prev} : null, value);
- setMessage(`Inserted ${value}`);
- return newRoot;
- });
- setInputValue('');
- setTraversalResult([]);
- setHighlightedNodes([]);
- setSteps(0);
- };
-
- // Generate random tree
- const generateRandomTree = () => {
- const size = Math.floor(Math.random() * 5) + 5; // 5-9 nodes
- const values = Array.from({length: size}, () => Math.floor(Math.random() * 100) + 1);
-
- let newRoot = null;
- values.forEach(val => {
- newRoot = insertNode(newRoot, val);
- });
-
- setRoot(newRoot);
- setMessage(`Generated tree with ${size} nodes`);
- setTraversalResult([]);
- setHighlightedNodes([]);
- setSteps(0);
- };
-
- // Reset everything
- const reset = () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- setRoot(null);
- setInputValue('');
- setIsAnimating(false);
- setMessage('Tree is empty');
- setTraversalResult([]);
- setHighlightedNodes([]);
- setSteps(0);
- };
-
- // In-order traversal with animation tracking
- const inOrderTraversal = (node, path = []) => {
- if (!node) return path;
-
- const leftPath = inOrderTraversal(node.left, path);
- leftPath.push({
- value: node.value,
- action: 'visit',
- highlighted: true
- });
- return inOrderTraversal(node.right, leftPath);
- };
-
- const visualizeInOrder = () => {
- if (!root) {
- setMessage('Tree is empty!');
- return;
- }
-
- setIsAnimating(true);
- setMessage('Performing in-order traversal...');
- setTraversalResult([]);
- setHighlightedNodes([]);
- setSteps(0);
-
- const traversalPath = inOrderTraversal(root);
- let step = 0;
-
- const animateStep = () => {
- if (step < traversalPath.length) {
- const current = traversalPath[step];
- setHighlightedNodes([current.value]);
- setTraversalResult(prev => [...prev, current.value]);
- setSteps(step + 1);
- step++;
- animationRef.current = setTimeout(animateStep, 1000 / speed);
- } else {
- setMessage(`In-order traversal complete: [${traversalPath.map(n => n.value).join(', ')}]`);
- setIsAnimating(false);
- setHighlightedNodes([]);
- }
- };
-
- animateStep();
- };
-
- // Render tree as SVG with centered layout
- const renderTree = (node, x = 400, y = 50, level = 0, nodes = [], edges = []) => {
- if (!node) return { nodes, edges };
-
- const nodeRadius = 25;
- const xOffset = Math.max(50, 200 / (level + 1)); // Dynamic spacing
- const yOffset = 80;
-
- nodes.push({
- value: node.value,
- x,
- y,
- highlighted: highlightedNodes.includes(node.value),
- });
-
- if (node.left) {
- const leftX = x - xOffset;
- const leftY = y + yOffset;
- edges.push({
- x1: x,
- y1: y + nodeRadius,
- x2: leftX,
- y2: leftY - nodeRadius,
- });
- renderTree(node.left, leftX, leftY, level + 1, nodes, edges);
- }
-
- if (node.right) {
- const rightX = x + xOffset;
- const rightY = y + yOffset;
- edges.push({
- x1: x,
- y1: y + nodeRadius,
- x2: rightX,
- y2: rightY - nodeRadius,
- });
- renderTree(node.right, rightX, rightY, level + 1, nodes, edges);
- }
-
- return { nodes, edges };
- };
-
- const { nodes, edges } = root ? renderTree(root) : { nodes: [], edges: [] };
-
- // Calculate SVG dimensions based on tree size
- const getSvgDimensions = () => {
- if (nodes.length === 0) return { width: 800, height: 400 };
-
- const xValues = nodes.map(node => node.x);
- const yValues = nodes.map(node => node.y);
- const padding = 50;
-
- return {
- width: Math.max(800, Math.max(...xValues) - Math.min(...xValues) + 2 * padding),
- height: Math.max(400, Math.max(...yValues) + 2 * padding)
- };
- };
-
- const svgDimensions = getSvgDimensions();
-
- // Clean up on unmount
- useEffect(() => {
- return () => {
- if (animationRef.current) {
- clearTimeout(animationRef.current);
- }
- };
- }, []);
-
- return (
-
-
-
-
-
- In-Order Traversal Visualizer
-
-
- Visualize how in-order traversal visits nodes in a binary search tree
-
-
-
- {/* Controls */}
-
-
-
-
- Generate Random Tree
-
-
- setInputValue(e.target.value)}
- placeholder="Enter number"
- className="flex-1 p-2 border rounded-lg dark:bg-gray-700 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
- disabled={isAnimating}
- onKeyPress={(e) => e.key === 'Enter' && handleInsert()}
- />
-
- Insert
-
-
-
-
-
- {isAnimating ? "Traversing..." : "Start Traversal"}
-
-
- Reset All
-
-
-
-
-
-
- Speed:
- setSpeed(parseFloat(e.target.value))}
- className="flex-1"
- disabled={isAnimating}
- />
- {speed}x
-
-
-
-
Nodes
-
{nodes.length}
-
-
-
-
-
-
- {/* Status Message */}
-
- {message}
-
-
- {/* Tree Visualization */}
-
-
Tree Visualization
-
- {nodes.length > 0 ? (
-
-
- {edges.map((edge, i) => (
-
- ))}
- {nodes.map((node, i) => (
-
-
-
- {node.value}
-
-
- ))}
-
-
- ) : (
-
- {isAnimating ? "Traversing..." : "No tree generated yet"}
-
- )}
-
-
- {traversalResult.length > 0 && (
-
- Path:
- [{traversalResult.join(', ')}]
-
- )}
-
-
- {/* Explanation Panel - Now below the tree */}
-
-
About In-Order Traversal
-
-
-
Visits nodes in the order:
-
- Left subtree
- Root node
- Right subtree
-
-
For BSTs, this produces nodes in sorted order.
-
-
-
-
Algorithm:
-
-{`function inOrder(node) {
- if (node !== null) {
- inOrder(node.left);
- visit(node);
- inOrder(node.right);
- }
-}`}
-
-
-
-
-
-
-
-
-
-
- );
-}
\ No newline at end of file
diff --git a/app/visualizer/trees/traversing/in-order/page.jsx b/app/visualizer/trees/traversing/in-order/page.jsx
deleted file mode 100755
index 2c87be6e4..000000000
--- a/app/visualizer/trees/traversing/in-order/page.jsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import Animation from "@/app/visualizer/trees/traversing/in-order/animation";
-
-export const metadata = {
- title: 'Tree Visualizer | Learn Tree Data Structures with Animation',
- description: 'Visualize how Tree Data Structures work in DSA with interactive animations. Perfect for beginners and interview prep.',
- keywords: ['Tree DSA', 'Tree Visualizer', 'Learn Tree', 'Binary Tree', 'DSA Animation'],
- robots: "index, follow",
-};
-
-const TreeVisualizer = () => {
- return (
-
- );
-};
-
-export default TreeVisualizer;
\ No newline at end of file
diff --git a/arena-socket-server/.gitignore b/arena-socket-server/.gitignore
new file mode 100644
index 000000000..c2658d7d1
--- /dev/null
+++ b/arena-socket-server/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/arena-socket-server/cors.test.js b/arena-socket-server/cors.test.js
new file mode 100644
index 000000000..f0f04e80a
--- /dev/null
+++ b/arena-socket-server/cors.test.js
@@ -0,0 +1,113 @@
+const { describe, it } = require("node:test");
+const assert = require("node:assert");
+const http = require("http");
+const express = require("express");
+const cors = require("cors");
+
+const ALLOWED_ORIGINS = [
+ "http://localhost:3000",
+ "http://127.0.0.1:3000",
+ "https://algobuddy.vercel.app",
+ "https://www.algobuddy.me",
+ "https://algobuddy.me",
+];
+
+function isAllowedVercelOrigin(origin) {
+ try {
+ const url = new URL(origin);
+ const hostname = url.hostname.toLowerCase();
+ return hostname === 'algobuddy.vercel.app' ||
+ hostname.endsWith('.algobuddy.vercel.app');
+ } catch {
+ return false;
+ }
+}
+
+function createTestApp() {
+ const app = express();
+ app.use(cors({
+ origin: (origin, callback) => {
+ if (!origin) {
+ return callback(new Error("Not allowed by CORS"));
+ }
+ if (ALLOWED_ORIGINS.includes(origin) || isAllowedVercelOrigin(origin)) {
+ callback(null, true);
+ } else {
+ callback(new Error("Not allowed by CORS"));
+ }
+ },
+ methods: ["GET", "POST"],
+ }));
+ app.get("/health", (_req, res) => res.json({ status: "ok" }));
+ return app;
+}
+
+function makeRequest(origin) {
+ return new Promise((resolve, reject) => {
+ const app = createTestApp();
+ const server = app.listen(0, () => {
+ const { port } = server.address();
+ const req = http.request({
+ hostname: "127.0.0.1",
+ port,
+ path: "/health",
+ method: "GET",
+ headers: origin ? { origin } : {},
+ }, (res) => {
+ let body = "";
+ res.on("data", (c) => body += c);
+ res.on("end", () => {
+ server.close();
+ resolve({ status: res.statusCode, headers: res.headers, body });
+ });
+ });
+ req.on("error", (err) => {
+ server.close();
+ reject(err);
+ });
+ req.end();
+ });
+ });
+}
+
+describe("CORS origin validation", () => {
+ for (const origin of ALLOWED_ORIGINS) {
+ it(`allows requests from ${origin}`, async () => {
+ const result = await makeRequest(origin);
+ assert.strictEqual(result.status, 200);
+ assert.strictEqual(result.headers["access-control-allow-origin"], origin);
+ });
+ }
+
+ it("rejects requests with no Origin header", async () => {
+ const result = await makeRequest(null);
+ assert.strictEqual(result.status, 500);
+ });
+
+ it("rejects requests from disallowed origins", async () => {
+ const result = await makeRequest("https://evil.com");
+ assert.strictEqual(result.status, 500);
+ });
+
+ it("allows requests from algobuddy.vercel.app subdomains", async () => {
+ const result = await makeRequest("https://my-branch.algobuddy.vercel.app");
+ assert.strictEqual(result.status, 200);
+ assert.strictEqual(result.headers["access-control-allow-origin"], "https://my-branch.algobuddy.vercel.app");
+ });
+
+ it("allows requests from nested algobuddy.vercel.app subdomains", async () => {
+ const result = await makeRequest("https://preview.my-branch.algobuddy.vercel.app");
+ assert.strictEqual(result.status, 200);
+ assert.strictEqual(result.headers["access-control-allow-origin"], "https://preview.my-branch.algobuddy.vercel.app");
+ });
+
+ it("rejects requests from arbitrary vercel.app subdomains", async () => {
+ const result = await makeRequest("https://evil.vercel.app");
+ assert.strictEqual(result.status, 500);
+ });
+
+ it("rejects requests from unrelated vercel.app subdomains", async () => {
+ const result = await makeRequest("https://attacker-deployment.vercel.app");
+ assert.strictEqual(result.status, 500);
+ });
+});
diff --git a/arena-socket-server/index.js b/arena-socket-server/index.js
new file mode 100644
index 000000000..bb1704a41
--- /dev/null
+++ b/arena-socket-server/index.js
@@ -0,0 +1,1147 @@
+require("dotenv").config({ path: '../.env.local' });
+const express = require("express");
+const http = require("http");
+const crypto = require("crypto");
+const { Server } = require("socket.io");
+const cors = require("cors");
+const jwt = require("jsonwebtoken");
+const jwksClient = require('jwks-rsa');
+const redisUrl = process.env.REDIS_URL;
+const Redis = redisUrl ? require("ioredis") : require("ioredis-mock");
+const { createAdapter } = require("@socket.io/redis-adapter");
+
+class BoundedMap {
+ constructor(maxSize = 10000) {
+ this.maxSize = maxSize;
+ this._map = new Map();
+ }
+ get(key) {
+ const value = this._map.get(key);
+ if (value !== undefined) {
+ this._map.delete(key);
+ this._map.set(key, value);
+ }
+ return value;
+ }
+ set(key, value) {
+ if (this._map.has(key)) {
+ this._map.delete(key);
+ } else if (this._map.size >= this.maxSize) {
+ const oldest = this._map.keys().next().value;
+ if (oldest !== undefined) this._map.delete(oldest);
+ }
+ this._map.set(key, value);
+ }
+ delete(key) {
+ return this._map.delete(key);
+ }
+ entries() {
+ return this._map.entries();
+ }
+ get size() {
+ return this._map.size;
+ }
+}
+
+const app = express();
+const ALLOWED_ORIGINS = [
+ "http://localhost:3000",
+ "http://127.0.0.1:3000",
+ "https://algobuddy.vercel.app",
+ "https://www.algobuddy.me",
+ "https://algobuddy.me"
+];
+
+function isAllowedVercelOrigin(origin) {
+ try {
+ const url = new URL(origin);
+ const hostname = url.hostname.toLowerCase();
+ return hostname === 'algobuddy.vercel.app' ||
+ hostname.endsWith('.algobuddy.vercel.app');
+ } catch {
+ return false;
+ }
+}
+
+// Only used outside production, and only for an exact host:port a
+// developer opts into via LAN_DEV_ORIGIN — never a whole /16 CIDR range.
+const LAN_DEV_ORIGIN = process.env.LAN_DEV_ORIGIN || null;
+const isProduction = process.env.NODE_ENV === "production";
+
+function isOriginAllowed(origin, callback) {
+ // Allow requests with no origin (Render health checks, server-to-server)
+ if (!origin) return callback(null, true);
+
+ if (
+ ALLOWED_ORIGINS.includes(origin) ||
+ isAllowedVercelOrigin(origin) ||
+ origin.startsWith("http://localhost:") ||
+ origin.startsWith("http://127.0.0.1:")
+ ) {
+ return callback(null, true);
+ }
+
+ // SECURITY: the previous `origin.startsWith("http://192.168.")` check
+ // trusted the ENTIRE private 192.168.0.0/16 range (65k+ hosts) as a
+ // valid Socket.IO origin in production — any page hosted by another
+ // device on a shared network (coffee shop, campus, office Wi-Fi) would
+ // be treated as trusted, enabling cross-site WebSocket hijacking. LAN
+ // testing is now opt-in, non-production only, and pinned to one exact
+ // origin via LAN_DEV_ORIGIN instead of a whole CIDR block.
+ if (!isProduction && LAN_DEV_ORIGIN && origin === LAN_DEV_ORIGIN) {
+ return callback(null, true);
+ }
+
+ callback(new Error("Not allowed by CORS"));
+}
+
+app.use(cors({
+ origin: isOriginAllowed,
+ methods: ["GET", "POST"],
+}));
+
+const server = http.createServer(app);
+
+// Redis setup
+const pubClient = redisUrl ? new Redis(redisUrl) : new Redis();
+const subClient = pubClient.duplicate();
+const redisClient = pubClient.duplicate();
+
+// Phase 1: Atomically pop an opponent from the queue WITHOUT creating match state
+const ATOMIC_POP_OPPONENT_SCRIPT = `
+ local cjson = require("cjson")
+ local queueKey = KEYS[1]
+ local socketKey = KEYS[2]
+ local entry = ARGV[1]
+ local userId = ARGV[2]
+ local socketId = ARGV[3]
+ local maxAttempts = tonumber(ARGV[4]) or 5
+
+ local existingQueueKey = redis.call('HGET', socketKey, 'queueKey')
+ if existingQueueKey then
+ local elements = redis.call('LRANGE', existingQueueKey, 0, -1)
+ if elements and #elements > 0 then
+ for i = 1, #elements do
+ local el = cjson.decode(elements[i])
+ if el.socketId == socketId or el.userId == userId then
+ redis.call('LREM', existingQueueKey, 0, elements[i])
+ end
+ end
+ end
+ end
+
+ local skipList = {}
+ for attempt = 1, maxAttempts do
+ local opponentStr = redis.call('LPOP', queueKey)
+ if not opponentStr then
+ break
+ end
+
+ local opp = cjson.decode(opponentStr)
+ if opp.userId == userId then
+ table.insert(skipList, opponentStr)
+ else
+ for i = #skipList, 1, -1 do
+ redis.call('RPUSH', queueKey, skipList[i])
+ end
+ redis.call('HSET', socketKey, 'queueKey', queueKey)
+ return cjson.encode({
+ status = "MATCH_FOUND",
+ opponent = {
+ userId = opp.userId,
+ socketId = opp.socketId,
+ name = opp.name or "Player",
+ rating = tonumber(opp.rating) or 1200,
+ level = tonumber(opp.level) or 1
+ }
+ })
+ end
+ end
+
+ for i = #skipList, 1, -1 do
+ redis.call('RPUSH', queueKey, skipList[i])
+ end
+
+ local elements = redis.call('LRANGE', queueKey, 0, -1)
+ if elements and #elements > 0 then
+ for i = 1, #elements do
+ local el = cjson.decode(elements[i])
+ if el.socketId == socketId or el.userId == userId then
+ redis.call('LREM', queueKey, 0, elements[i])
+ end
+ end
+ end
+ redis.call('RPUSH', queueKey, entry)
+ redis.call('HSET', socketKey, 'queueKey', queueKey)
+ return cjson.encode({ status = "QUEUED" })
+`;
+
+ // Phase 2: Atomically create match state (only called after JS confirms liveness)
+ const ATOMIC_CREATE_MATCH_SCRIPT = `
+ local matchKey = KEYS[1]
+ local socketKey = KEYS[2]
+ local oppKey = KEYS[3]
+ local matchDetails = ARGV[1]
+
+ local created = redis.call('SET', matchKey, matchDetails, 'NX', 'EX', 3600)
+ if created then
+ redis.call('HSET', socketKey, 'matchId', matchKey)
+ redis.call('HSET', oppKey, 'matchId', matchKey)
+ redis.call('HDEL', socketKey, 'queueKey')
+ redis.call('HDEL', oppKey, 'queueKey')
+ return '{"status":"CREATED"}'
+ end
+ return '{"status":"FAILED"}'
+`;
+
+const ATOMIC_LEAVE_MATCHMAKING_SCRIPT = `
+ local cjson = require("cjson")
+ local socketKey = KEYS[1]
+ local userId = ARGV[1]
+ local socketId = ARGV[2]
+
+ local existingQueueKey = redis.call('HGET', socketKey, 'queueKey')
+ if existingQueueKey then
+ local elements = redis.call('LRANGE', existingQueueKey, 0, -1)
+ if elements and #elements > 0 then
+ for i = 1, #elements do
+ local el = cjson.decode(elements[i])
+ if el.socketId == socketId or el.userId == userId then
+ redis.call('LREM', existingQueueKey, 0, elements[i])
+ end
+ end
+ end
+ redis.call('HDEL', socketKey, 'queueKey')
+ end
+ return 1
+`;
+
+// Unified atomic match update script — handles both "complete" and "disconnect"
+// without race conditions. Using a single script eliminates the TOCTOU gap
+// between separate disconnect and complete scripts.
+const ATOMIC_MATCH_UPDATE_SCRIPT = `
+ local cjson = require("cjson")
+ local matchKey = KEYS[1]
+ local action = ARGV[1]
+ local actorUserId = ARGV[2]
+
+ local matchStr = redis.call('GET', matchKey)
+ if not matchStr then return cjson.encode({ status = "not_found" }) end
+
+ local match = cjson.decode(matchStr)
+
+ -- Check if the match is already finalized
+ if match.status == "completed" then
+ return cjson.encode({ status = "already_completed" })
+ end
+ if action == "disconnect" and match.status == "disconnected" then
+ return cjson.encode({ status = "already_disconnected" })
+ end
+
+ if action == "complete" then
+ match.status = "completed"
+ match.winnerId = actorUserId
+ redis.call('SET', matchKey, cjson.encode(match), 'EX', 3600)
+ -- Extract opponent socketId for notification
+ local opponentSocketId = ''
+ if match.players then
+ for _, p in ipairs(match.players) do
+ if p.userId ~= actorUserId then
+ opponentSocketId = p.socketId
+ end
+ end
+ end
+ return cjson.encode({ status = "completed", winnerId = actorUserId, opponentSocketId = opponentSocketId })
+
+ elseif action == "disconnect" then
+ match.status = "disconnected"
+ -- Award win to the remaining player
+ if match.players then
+ for _, p in ipairs(match.players) do
+ if p.userId ~= actorUserId then
+ match.winnerId = p.userId
+ end
+ end
+ end
+ redis.call('SET', matchKey, cjson.encode(match), 'EX', 3600)
+ -- Extract opponent info
+ local opponentSocketId = ''
+ local opponentUserId = ''
+ if match.players then
+ for _, p in ipairs(match.players) do
+ if p.userId ~= actorUserId then
+ opponentUserId = p.userId
+ opponentSocketId = p.socketId
+ end
+ end
+ end
+ return cjson.encode({ status = "disconnected", opponentSocketId = opponentSocketId, opponentUserId = opponentUserId })
+ end
+ return cjson.encode({ status = "unknown_action" })
+`;
+
+const io = new Server(server, {
+ cors: {
+ origin: isOriginAllowed,
+ methods: ["GET", "POST"],
+ },
+ adapter: createAdapter(pubClient, subClient)
+});
+
+io.use((socket, next) => {
+ const headers = socket.handshake.headers || {};
+ const realIp = headers["x-real-ip"];
+ const ip = (realIp && typeof realIp === "string") ? realIp.trim() : socket.handshake.address;
+ if (isConnectionRateLimited(ip)) {
+ return next(new Error("Rate limited"));
+ }
+ next();
+});
+
+const PORT = process.env.PORT || 4000;
+
+// JWT Authentication
+const SUPABASE_URL = process.env.SUPABASE_URL || process.env.NEXT_PUBLIC_SUPABASE_URL;
+
+const client = jwksClient({
+ jwksUri: `${SUPABASE_URL}/auth/v1/.well-known/jwks.json`
+});
+
+function getKey(header, callback) {
+ client.getSigningKey(header.kid, function (err, key) {
+ if (err) {
+ callback(err, null);
+ return;
+ }
+ const signingKey = key.publicKey || key.rsaPublicKey;
+ callback(null, signingKey);
+ });
+}
+
+function verifyAuthToken(token) {
+ return new Promise((resolve) => {
+ if (!token || !SUPABASE_URL) {
+ resolve(null);
+ return;
+ }
+ jwt.verify(token, getKey, { algorithms: ["ES256", "RS256"] }, function (err, decoded) {
+ if (err) {
+ resolve(null);
+ } else {
+ resolve(decoded);
+ }
+ });
+ });
+}
+
+// Connection rate limiting to prevent JWT brute-forcing
+const connectionAttempts = new BoundedMap(10000);
+const MAX_CONNECTION_ATTEMPTS = 5;
+const CONNECTION_ATTEMPT_WINDOW_MS = 60000;
+
+function isConnectionRateLimited(ip) {
+ const now = Date.now();
+ const entry = connectionAttempts.get(ip);
+ if (!entry || now > entry.resetTime) {
+ connectionAttempts.set(ip, { count: 1, resetTime: now + CONNECTION_ATTEMPT_WINDOW_MS });
+ return false;
+ }
+ entry.count++;
+ return entry.count > MAX_CONNECTION_ATTEMPTS;
+}
+
+// Periodic queue health checker to remove stale entries from matchmaking queues
+setInterval(async () => {
+ try {
+ const queueKeys = [];
+ let cursor = '0';
+ do {
+ const result = await redisClient.scan(cursor, 'MATCH', '{arena}:queue:*', 'COUNT', 100);
+ cursor = result[0];
+ for (const key of result[1]) {
+ const elements = await redisClient.lrange(key, 0, -1);
+ let changed = false;
+ let remainingCount = elements.length;
+ for (const el of elements) {
+ let parsed;
+ try {
+ parsed = JSON.parse(el);
+ } catch (parseErr) {
+ console.error('[queue-health] Corrupted queue entry, removing:', el.slice(0, 100));
+ await redisClient.lrem(key, 0, el);
+ changed = true;
+ remainingCount--;
+ continue;
+ }
+ if (parsed.expiresAt && Date.now() > parsed.expiresAt) {
+ await redisClient.lrem(key, 0, el);
+ changed = true;
+ remainingCount--;
+ continue;
+ }
+ const socket = io.sockets.sockets.get(parsed.socketId);
+ if (!socket || !socket.connected) {
+ await redisClient.lrem(key, 0, el);
+ changed = true;
+ remainingCount--;
+ }
+ }
+ if (changed && remainingCount === 0) {
+ await redisClient.expire(key, 60);
+ }
+ }
+ } while (cursor !== '0');
+ } catch (err) {
+ console.error('[queue-health] Error cleaning stale entries:', err.message);
+ }
+}, 30000);
+
+// Rate Limiting Config (Redis-backed token bucket)
+const MAX_TOKENS = 10;
+const REFILL_RATE_MS = 200;
+
+async function isRateLimited(userId) {
+ const key = `{arena}:ratelimit:${userId}`;
+ const now = Date.now();
+
+ const script = `
+ local key = KEYS[1]
+ local now = tonumber(ARGV[1])
+ local max_tokens = tonumber(ARGV[2])
+ local refill_rate = tonumber(ARGV[3])
+
+ local data = redis.call('HMGET', key, 'tokens', 'lastRequestTime')
+ local tokens = tonumber(data[1])
+ local lastRequestTime = tonumber(data[2])
+
+ if not tokens then
+ redis.call('HMSET', key, 'tokens', max_tokens - 1, 'lastRequestTime', now)
+ redis.call('EXPIRE', key, 60)
+ return 0
+ end
+
+ local timePassed = now - lastRequestTime
+ local tokensToAdd = math.floor(timePassed / refill_rate)
+
+ if tokensToAdd > 0 then
+ tokens = math.min(max_tokens, tokens + tokensToAdd)
+ lastRequestTime = now
+ end
+
+ if tokens > 0 then
+ redis.call('HMSET', key, 'tokens', tokens - 1, 'lastRequestTime', lastRequestTime)
+ redis.call('EXPIRE', key, 60)
+ return 0
+ end
+ return 1
+ `;
+
+ const result = await redisClient.eval(script, 1, key, now, MAX_TOKENS, REFILL_RATE_MS);
+ return result === 1;
+}
+
+// Spectator rate limiting to prevent chat spam
+const spectatorRateLimit = new BoundedMap(5000);
+
+function isSpectatorRateLimited(userId) {
+ const key = `chat:${userId}`;
+ const entry = spectatorRateLimit.get(key);
+ if (!entry || Date.now() > entry.resetTime) {
+ spectatorRateLimit.set(key, { count: 1, resetTime: Date.now() + 10000 });
+ return false;
+ }
+ entry.count++;
+ return entry.count > 5;
+}
+
+io.on("connection", async (socket) => {
+ // Verify Supabase JWT from handshake auth using JWKS
+ const token = socket.handshake.auth?.token;
+ const authPayload = await verifyAuthToken(token);
+
+ if (!authPayload) {
+ socket.data.userId = `spectator_${crypto.randomUUID()}`;
+ socket.data.isSpectator = true;
+ console.log(`Spectator connected: ${socket.id}`);
+ } else {
+ // Store verified userId from the JWT payload
+ socket.data.userId = authPayload.sub || authPayload.id;
+ socket.data.token = token;
+ console.log(`Authenticated user connected: ${socket.id}, userId: ${socket.data.userId}`);
+ }
+
+ await redisClient.hset(`{arena}:socket:${socket.id}`, 'connected', '1');
+
+ socket.on("join_matchmaking", async (data) => {
+ if (socket.data.isSpectator) return;
+ let opponent = null;
+ try {
+ if (await isRateLimited(socket.data.userId)) return;
+
+ console.log(`User joined matchmaking: userId=${socket.data.userId}`);
+ const targetTopic = data.topic || "Arrays";
+ const targetDifficulty = data.difficulty || "Easy";
+ const queueKey = `{arena}:queue:${targetTopic}:${targetDifficulty}`;
+ const matchId = `match-${Date.now()}-${crypto.randomUUID().split('-')[0]}`;
+ const matchKey = `{arena}:match:${matchId}`;
+
+ const queueEntry = JSON.stringify({
+ ...data,
+ userId: socket.data.userId,
+ topic: targetTopic,
+ difficulty: targetDifficulty,
+ socketId: socket.id,
+ });
+
+ // Phase 1: Atomically pop opponent from queue (no match state created yet)
+ const resultStr = await redisClient.eval(
+ ATOMIC_POP_OPPONENT_SCRIPT,
+ 2,
+ queueKey,
+ `{arena}:socket:${socket.id}`,
+ queueEntry,
+ socket.data.userId,
+ socket.id,
+ 5,
+ );
+
+ const result = JSON.parse(resultStr);
+
+ if (result.status === 'MATCH_FOUND') {
+ opponent = result.opponent;
+
+ // Phase 2: Cross-instance liveness check via Redis
+ const opponentAlive = await redisClient.exists(`{arena}:socket:${opponent.socketId}`);
+ if (!opponentAlive) {
+ const opponentEntry = JSON.stringify({
+ userId: opponent.userId,
+ socketId: opponent.socketId,
+ name: opponent.name || "Player",
+ rating: opponent.rating || 1200,
+ level: opponent.level || 1,
+ topic: targetTopic,
+ difficulty: targetDifficulty,
+ });
+ await redisClient.rpush(queueKey, opponentEntry);
+ console.log(`Opponent disconnected, re-queued opponent: ${opponent.userId}`);
+
+ // Re-queue the requesting player so they can be matched next cycle
+ const reQueueEntry = JSON.stringify({
+ userId: socket.data.userId,
+ socketId: socket.id,
+ name: socket.data.name || "Player",
+ rating: socket.data.rating || 1200,
+ level: socket.data.level || 1,
+ topic: targetTopic,
+ difficulty: targetDifficulty,
+ });
+ await redisClient.rpush(queueKey, reQueueEntry);
+ await redisClient.hset(`{arena}:socket:${socket.id}`, 'queueKey', queueKey);
+
+ socket.emit("matchmaking_retry", { message: "Opponent unavailable, searching for another..." });
+ return;
+ }
+
+ // Phase 3: Create match atomically (only if opponent is alive)
+ const fullMatchDetails = JSON.stringify({
+ matchId,
+ topic: targetTopic,
+ difficulty: targetDifficulty,
+ status: "in-progress",
+ players: [
+ { userId: opponent.userId, name: opponent.name, socketId: opponent.socketId },
+ { userId: socket.data.userId, name: data.name || "Player", socketId: socket.id },
+ ],
+ });
+
+ const createResult = await redisClient.eval(
+ ATOMIC_CREATE_MATCH_SCRIPT,
+ 3,
+ matchKey,
+ `{arena}:socket:${socket.id}`,
+ `{arena}:socket:${opponent.socketId}`,
+ fullMatchDetails,
+ );
+
+ const createParsed = JSON.parse(createResult);
+
+ if (createParsed.status === 'CREATED') {
+ const fullMatch = JSON.parse(fullMatchDetails);
+ io.to(opponent.socketId).emit("match_found", fullMatch);
+ io.to(socket.id).emit("match_found", fullMatch);
+
+ socket.join(matchId);
+ io.in(opponent.socketId).socketsJoin(matchId);
+
+ console.log(`Match found: ${opponent.userId} vs ${socket.data.userId}`);
+ } else {
+ const opponentEntry = JSON.stringify({
+ userId: opponent.userId,
+ socketId: opponent.socketId,
+ name: opponent.name || "Player",
+ rating: opponent.rating || 1200,
+ level: opponent.level || 1,
+ topic: targetTopic,
+ difficulty: targetDifficulty,
+ });
+ await redisClient.rpush(queueKey, opponentEntry);
+ console.log(`Match creation failed (status: ${createParsed.status}), re-queued opponent: ${opponent.userId}`);
+ socket.emit("matchmaking_error", { message: "Could not create match. Please try again." });
+ }
+ } else {
+ console.log(`Added to queue ${queueKey}`);
+ }
+ } catch (error) {
+ console.error(`[join_matchmaking] Error for user ${socket.data.userId}:`, error);
+ if (opponent) {
+ const opponentEntry = JSON.stringify({
+ userId: opponent.userId,
+ socketId: opponent.socketId,
+ name: opponent.name || "Player",
+ rating: opponent.rating || 1200,
+ level: opponent.level || 1,
+ topic: targetTopic,
+ difficulty: targetDifficulty,
+ });
+ await redisClient.rpush(queueKey, opponentEntry);
+ console.log(`Error during matchmaking, re-queued opponent: ${opponent.userId}`);
+ }
+ socket.emit("error", { message: "Matchmaking error. Please try again." });
+ }
+ });
+
+ socket.on("leave_matchmaking", async () => {
+ if (socket.data.isSpectator) return;
+ try {
+ if (await isRateLimited(socket.data.userId)) return;
+ await redisClient.eval(
+ ATOMIC_LEAVE_MATCHMAKING_SCRIPT,
+ 1,
+ `{arena}:socket:${socket.id}`,
+ socket.data.userId,
+ socket.id,
+ );
+ } catch (error) {
+ console.error(`[leave_matchmaking] Error for user ${socket.data.userId}:`, error);
+ socket.emit("error", { message: "Error leaving matchmaking. Please try again." });
+ }
+ });
+
+ socket.on("join_match", async (data) => {
+ if (socket.data.isSpectator) return;
+ try {
+ if (!data.matchId) return;
+ const userMatchId = await redisClient.hget(`{arena}:socket:${socket.id}`, "matchId");
+ if (!userMatchId || userMatchId !== data.matchId) return;
+ const matchStr = await redisClient.get(`{arena}:match:${data.matchId}`);
+ if (!matchStr) return;
+ const match = JSON.parse(matchStr);
+ const isParticipant = match.players && match.players.some(p => p.userId === socket.data.userId);
+ if (!isParticipant) return;
+
+ socket.join(data.matchId);
+ await redisClient.hset(`{arena}:socket:${socket.id}`, "matchId", data.matchId);
+ console.log(`Player ${socket.data.userId} re-joined match ${data.matchId}`);
+ } catch (error) {
+ console.error(`[join_match] Error for user ${socket.data.userId}:`, error);
+ }
+ });
+
+ socket.on("join_spectator", async (data) => {
+ try {
+ if (!data.matchId) return;
+ const matchStr = await redisClient.get(`{arena}:match:${data.matchId}`);
+ if (!matchStr) return;
+
+ const room = `${data.matchId}-spectators`;
+ socket.join(room);
+ const sockets = await io.in(room).fetchSockets();
+ io.in(room).emit("spectator_count", { count: sockets.length });
+ console.log(`Spectator ${socket.data.userId} joined match ${data.matchId}`);
+ } catch (error) {
+ console.error(`[join_spectator] Error for user ${socket.data.userId}:`, error);
+ }
+ });
+
+ socket.on("leave_spectator", async (data) => {
+ if (!data.matchId) return;
+ const room = `${data.matchId}-spectators`;
+ socket.leave(room);
+ const sockets = await io.in(room).fetchSockets();
+ io.in(room).emit("spectator_count", { count: sockets.length });
+ });
+
+ // Duel Room Events
+ socket.on("typing_status", async (data) => {
+ if (socket.data.isSpectator) return;
+ try {
+ if (await isRateLimited(socket.data.userId)) return;
+ const matchId = await redisClient.hget(`{arena}:socket:${socket.id}`, "matchId");
+ if (!matchId || matchId !== data.matchId) {
+ console.log(`Player ${socket.data.userId} failed typing_status because matchId doesn't match: expected ${data.matchId}, got ${matchId}`);
+ return;
+ }
+
+ console.log(`Player ${socket.data.userId} emitted typing_status to room ${data.matchId}`);
+ socket.to(data.matchId).emit("opponent_typing_status", {
+ isTyping: data.isTyping,
+ userId: socket.data.userId,
+ linesCoded: data.linesCoded,
+ cpm: data.cpm || 0,
+ language: data.language
+ });
+ } catch (error) {
+ console.error(`[typing_status] Error for user ${socket.data.userId}:`, error);
+ }
+ });
+
+ socket.on("test_submit", async (data) => {
+ if (socket.data.isSpectator) return;
+ try {
+ if (await isRateLimited(socket.data.userId)) return;
+ const matchId = await redisClient.hget(`{arena}:socket:${socket.id}`, "matchId");
+ if (!matchId || matchId !== data.matchId) return;
+
+ socket.to(data.matchId).emit("opponent_test_submit", {
+ userId: socket.data.userId,
+ failedAttempts: data.failedAttempts
+ });
+ } catch (error) {
+ console.error(`[test_submit] Error for user ${socket.data.userId}:`, error);
+ }
+ });
+
+ socket.on("test_result", async (data) => {
+ if (socket.data.isSpectator) return;
+ try {
+ if (await isRateLimited(socket.data.userId)) return;
+
+ const matchId = await redisClient.hget(`{arena}:socket:${socket.id}`, "matchId");
+ if (!matchId || matchId !== data.matchId) return;
+
+ await redisClient.hset(
+ `{arena}:match:${matchId}:testResults`,
+ socket.data.userId,
+ JSON.stringify({ passed: data.passed, total: data.total, status: data.status, failedAttempts: data.failedAttempts, timestamp: Date.now() })
+ );
+
+ socket.to(data.matchId).emit("opponent_test_result", {
+ userId: socket.data.userId,
+ passed: data.passed,
+ total: data.total,
+ status: data.status,
+ failedAttempts: data.failedAttempts
+ });
+ } catch (error) {
+ console.error(`[test_result] Error for user ${socket.data.userId}:`, error);
+ }
+ });
+
+ socket.on("disconnecting", () => {
+ for (const room of socket.rooms) {
+ if (room.endsWith("-spectators")) {
+ const roomAdapter = io.sockets.adapter.rooms.get(room);
+ if (roomAdapter) {
+ const count = Math.max(0, roomAdapter.size - 1);
+ io.in(room).emit("spectator_count", { count });
+ }
+ }
+ }
+ });
+
+ socket.on("spectator_chat", (data) => {
+ if (!data.matchId || !data.message) return;
+ if (isSpectatorRateLimited(socket.data.userId)) return;
+ if (/<[^>]*>/.test(data.message)) return;
+ if (data.message.length > 500) return;
+ const safeUsername = `Spectator_${socket.id.slice(0, 6)}`;
+ socket.to(data.matchId).emit("spectator_chat", {
+ userId: socket.data.userId,
+ username: safeUsername,
+ message: data.message.slice(0, 500),
+ timestamp: Date.now()
+ });
+ });
+
+ const ALLOWED_EMOTES = new Set(['clap', 'laugh', 'cheer', 'boo', 'wave', 'popcorn', 'cry', 'heart', 'fire', 'thumbsup']);
+
+ socket.on("spectator_emote", (data) => {
+ if (!data.matchId || !data.emote) return;
+ if (isSpectatorRateLimited(socket.data.userId)) return;
+ if (typeof data.emote !== 'string') return;
+ if (data.emote.length > 50) return;
+ if (/<[^>]*>/.test(data.emote)) return;
+ const normalized = data.emote.toLowerCase().trim();
+ if (!ALLOWED_EMOTES.has(normalized)) return;
+ socket.to(data.matchId).emit("spectator_emote", {
+ userId: socket.data.userId,
+ emote: data.emote.slice(0, 50),
+ timestamp: Date.now()
+ });
+ });
+
+ socket.on("match_complete", async (data) => {
+ if (socket.data.isSpectator) return;
+ try {
+ if (await isRateLimited(socket.data.userId)) return;
+
+ const matchId = await redisClient.hget(`{arena}:socket:${socket.id}`, "matchId");
+ if (!matchId || matchId !== data.matchId) return;
+
+ try {
+ const testResultsStr = await redisClient.hget(
+ `{arena}:match:${matchId}:testResults`,
+ socket.data.userId
+ );
+
+ if (!testResultsStr) {
+ return socket.emit("error", { message: "Cannot complete match: no test results recorded" });
+ }
+
+ const testResults = JSON.parse(testResultsStr);
+ if (!testResults.passed || testResults.passed < 1) {
+ return socket.emit("error", { message: "Cannot complete match: insufficient test results" });
+ }
+
+ // Server-side verification to prevent client spoofing
+ const initialMatchStr = await redisClient.get(`{arena}:match:${matchId}`);
+ if (!initialMatchStr) {
+ return socket.emit("error", { message: "Cannot complete match: match not found" });
+ }
+ const match = JSON.parse(initialMatchStr);
+ const topic = match.topic || "Arrays";
+ const VERIFIED_TOPICS = new Set(["Arrays", "Strings"]);
+
+ let verificationCode = data.code || "";
+ const lang = (data.language || "javascript").toLowerCase();
+
+ if (!VERIFIED_TOPICS.has(topic)) {
+ return socket.emit("error", { message: `Match topic "${topic}" does not support server-side verification yet.` });
+ }
+
+ if (lang === "javascript" || lang === "js") {
+ if (topic === "Arrays") {
+ verificationCode += `\n;
+if (typeof twoSum !== 'function' || JSON.stringify(twoSum([2,7,11,15], 9)) !== '[0,1]' || JSON.stringify(twoSum([3,2,4], 6)) !== '[1,2]') {
+ throw new Error("Validation test cases failed!");
+}`;
+ } else if (topic === "Strings") {
+ verificationCode += `\n;
+if (typeof isAnagram !== 'function' || isAnagram("anagram", "nagaram") !== true || isAnagram("rat", "car") !== false) {
+ throw new Error("Validation test cases failed!");
+}`;
+ }
+ }
+
+ if (lang === "javascript" || lang === "js") {
+ const origin = socket.handshake.headers.origin || "http://localhost:3000";
+ try {
+ const res = await fetch(`${origin}/api/code-lab`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Bearer ${socket.data.token}`
+ },
+ body: JSON.stringify({ code: verificationCode })
+ });
+
+ if (!res.ok) {
+ return socket.emit("error", { message: "Server-side code verification failed" });
+ }
+
+ const resData = await res.json();
+ const isSuccess = resData.status === 3 || resData.status === "SUCCESS";
+ if (!isSuccess) {
+ return socket.emit("error", { message: "Your code failed verification test cases!" });
+ }
+ } catch (verErr) {
+ console.error("[match_complete] Code verification request failed:", verErr);
+ return socket.emit("error", { message: "Verification service unavailable" });
+ }
+ }
+
+ const resultStr = await redisClient.eval(
+ ATOMIC_MATCH_UPDATE_SCRIPT,
+ 1,
+ `{arena}:match:${matchId}`,
+ "complete",
+ socket.data.userId
+ );
+
+ const result = JSON.parse(resultStr);
+ if (result.status === "already_completed") return;
+ if (result.status === "not_found") return;
+
+ io.in(matchId).emit("match_ended", { winnerId: socket.data.userId });
+
+ // Clean up socket matchId references
+ const matchStr = await redisClient.get(`{arena}:match:${matchId}`);
+ if (matchStr) {
+ const match = JSON.parse(matchStr);
+ for (const p of match.players) {
+ await redisClient.hdel(`{arena}:socket:${p.socketId}`, "matchId");
+ }
+ }
+ await redisClient.expire(`{arena}:match:${matchId}`, 60 * 60);
+ await redisClient.del(`{arena}:match:${matchId}:testResults`);
+ } catch (err) {
+ console.error(`[match_complete] Error for user ${socket.data.userId}:`, err);
+ }
+ } catch (error) {
+ console.error(`[match_complete] Error for user ${socket.data.userId}:`, error);
+ }
+ });
+
+ socket.on("disconnect", async () => {
+ try {
+ // First, clean up queue entries and socket key
+ const existingQueueKey = await redisClient.hget(`{arena}:socket:${socket.id}`, 'queueKey');
+ if (existingQueueKey) {
+ const elements = await redisClient.lrange(existingQueueKey, 0, -1);
+ if (elements && elements.length > 0) {
+ for (const el of elements) {
+ const parsed = JSON.parse(el);
+ if (parsed.socketId === socket.id || parsed.userId === socket.data.userId) {
+ await redisClient.lrem(existingQueueKey, 0, el);
+ }
+ }
+ }
+ await redisClient.hdel(`{arena}:socket:${socket.id}`, 'queueKey');
+ }
+
+ // Update match state atomically via unified script
+ const matchId = await redisClient.hget(`{arena}:socket:${socket.id}`, "matchId");
+ if (matchId) {
+ const resultStr = await redisClient.eval(
+ ATOMIC_MATCH_UPDATE_SCRIPT,
+ 1,
+ `{arena}:match:${matchId}`,
+ "disconnect",
+ socket.data.userId
+ );
+
+ const result = JSON.parse(resultStr);
+
+ // Only emit opponent_disconnected if the match was actually set to disconnected
+ // (i.e., not if it was already completed)
+ if (result.status === "disconnected" && result.opponentSocketId && result.opponentUserId) {
+ io.to(result.opponentSocketId).emit("opponent_disconnected", { winnerId: result.opponentUserId });
+ }
+
+ // Clean up socket matchId references
+ for (const sId of [socket.id, result.opponentSocketId].filter(Boolean)) {
+ await redisClient.hdel(`{arena}:socket:${sId}`, 'matchId');
+ }
+ }
+
+ // Clean up socket key (rate limit key expires naturally via TTL)
+ await redisClient.del(`{arena}:socket:${socket.id}`);
+
+ console.log(`User disconnected: ${socket.id}`);
+ } catch (error) {
+ console.error(`[disconnect] Error for user ${socket.id}:`, error);
+ }
+ });
+});
+
+async function scanRedisKeys(pattern) {
+ let cursor = '0';
+ const keys = [];
+ do {
+ const result = await redisClient.scan(cursor, 'MATCH', pattern, 'COUNT', 100);
+ cursor = result[0];
+ keys.push(...result[1]);
+ } while (cursor !== '0');
+ return keys;
+}
+
+async function getRedisAggregateStats() {
+ let totalKeys = 0;
+ let stringCount = 0;
+ let listCount = 0;
+ let hashCount = 0;
+ let otherCount = 0;
+
+ let cursor = '0';
+ do {
+ const result = await redisClient.scan(cursor, 'MATCH', '*', 'COUNT', 100);
+ cursor = result[0];
+ for (const key of result[1]) {
+ totalKeys++;
+ const type = await redisClient.type(key);
+ if (type === 'string') stringCount++;
+ else if (type === 'list') listCount++;
+ else if (type === 'hash') hashCount++;
+ else otherCount++;
+ }
+ } while (cursor !== '0');
+
+ return { totalKeys, stringCount, listCount, hashCount, otherCount };
+}
+
+// Rate limiter for debug endpoint to prevent brute-force discovery of debug key
+const debugRequestCounts = new BoundedMap(10000);
+
+function isDebugRateLimited(ip) {
+ const now = Date.now();
+ const windowMs = 60000;
+ const maxRequests = 5;
+ const entry = debugRequestCounts.get(ip);
+ if (!entry || now > entry.resetTime) {
+ debugRequestCounts.set(ip, { count: 1, resetTime: now + windowMs });
+ return false;
+ }
+ entry.count++;
+ return entry.count > maxRequests;
+}
+
+app.get("/debug", async (req, res) => {
+ try {
+ const debugEnabled = process.env.DEBUG_ENABLED === 'true';
+ if (!debugEnabled) {
+ return res.status(404).json({ error: "Not found" });
+ }
+
+ const debugKey = process.env.DEBUG_KEY;
+ const providedKey = req.headers['x-debug-key'];
+ if (!debugKey || providedKey !== debugKey) {
+ return res.status(403).json({ error: "Forbidden" });
+ }
+
+ const headers = req.headers || {};
+ const realIp = headers["x-real-ip"];
+ const clientIp = (realIp && typeof realIp === "string") ? realIp.trim() : (req.ip || req.connection.remoteAddress);
+ if (isDebugRateLimited(clientIp)) {
+ return res.status(429).json({ error: "Too many requests" });
+ }
+
+ const stats = await getRedisAggregateStats();
+
+ res.json({
+ status: "debug info",
+ redis: stats,
+ activeConnections: io.engine.clientsCount,
+ uptime: process.uptime(),
+ });
+ } catch (err) {
+ res.status(500).json({ error: err.message });
+ }
+});
+
+app.get("/api/verify-match/:matchId/:userId", async (req, res) => {
+ try {
+ const authHeader = req.headers.authorization;
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
+ return res.status(401).json({ error: "Authentication required" });
+ }
+ const token = authHeader.split(' ')[1];
+ const decoded = await verifyAuthToken(token);
+ if (!decoded || !decoded.sub) {
+ return res.status(401).json({ error: "Invalid authentication token" });
+ }
+
+ const { matchId, userId } = req.params;
+ if (decoded.sub !== userId) {
+ return res.status(403).json({ error: "userId does not match authenticated user" });
+ }
+ const matchKey = `{arena}:match:${matchId}`;
+ const matchStr = await redisClient.get(matchKey);
+ if (!matchStr) {
+ return res.json({ verified: false });
+ }
+ const match = JSON.parse(matchStr);
+ const players = match.players || [];
+ const isPlayer = players.some(p => p.userId === userId);
+ if (!isPlayer) {
+ return res.json({ verified: false });
+ }
+ const opponent = players.find(p => p.userId !== userId);
+ res.json({
+ verified: true,
+ opponentId: opponent ? opponent.userId : null
+ });
+ } catch (err) {
+ console.error("[verify-match] Error:", err.message);
+ res.status(500).json({ verified: false, error: err.message });
+ }
+});
+
+app.get("/api/verify-match-result/:matchId/:userId", async (req, res) => {
+ try {
+ const authHeader = req.headers.authorization;
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
+ return res.status(401).json({ error: "Authentication required" });
+ }
+ const token = authHeader.split(' ')[1];
+ const decoded = await verifyAuthToken(token);
+ if (!decoded || !decoded.sub) {
+ return res.status(401).json({ error: "Invalid authentication token" });
+ }
+
+ const { matchId, userId } = req.params;
+ if (decoded.sub !== userId) {
+ return res.status(403).json({ error: "userId does not match authenticated user" });
+ }
+ const matchKey = `{arena}:match:${matchId}`;
+
+ const matchStr = await redisClient.get(matchKey);
+ if (!matchStr) {
+ return res.status(404).json({ error: "Match not found" });
+ }
+
+ const match = JSON.parse(matchStr);
+ const players = match.players || [];
+ const isPlayer = players.some(p => p.userId === userId);
+ if (!isPlayer) {
+ return res.status(403).json({ error: "Not a participant" });
+ }
+
+ // Return actual winner from match state — idempotent, no claim race
+ return res.json({
+ verified: true,
+ winnerId: match.winnerId || null,
+ isWinner: match.winnerId === userId
+ });
+ } catch (err) {
+ console.error("[verify-match-result] Error:", err.message);
+ res.status(500).json({ verified: false, error: err.message });
+ }
+});
+
+app.get("/health", (req, res) => {
+ res.json({ status: "Arena Socket Server is running with Redis!" });
+});
+
+app.get("/api/matches/active", async (req, res) => {
+ try {
+ const authHeader = req.headers.authorization;
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
+ return res.status(401).json({ error: "Authentication required" });
+ }
+ const token = authHeader.split(' ')[1];
+ const decoded = await verifyAuthToken(token);
+ if (!decoded || !decoded.sub) {
+ return res.status(401).json({ error: "Invalid authentication token" });
+ }
+
+ const matchKeys = await scanRedisKeys("{arena}:match:*");
+ const activeMatches = [];
+ for (const key of matchKeys) {
+ if (key.endsWith(":completed")) continue;
+ const matchStr = await redisClient.get(key);
+ if (matchStr) {
+ const match = JSON.parse(matchStr);
+ if (match.status === "in-progress") {
+ activeMatches.push(match);
+ }
+ }
+ }
+ res.json({ matches: activeMatches });
+ } catch (err) {
+ res.status(500).json({ error: err.message });
+ }
+});
+
+server.listen(PORT, () => {
+ console.log(`Arena Socket Server running on port ${PORT}`);
+});
diff --git a/arena-socket-server/package-lock.json b/arena-socket-server/package-lock.json
new file mode 100644
index 000000000..bb253c6f2
--- /dev/null
+++ b/arena-socket-server/package-lock.json
@@ -0,0 +1,1406 @@
+{
+ "name": "arena-socket-server",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "arena-socket-server",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "@socket.io/redis-adapter": "^8.3.0",
+ "cors": "^2.8.6",
+ "dotenv": "^17.4.2",
+ "express": "^5.2.1",
+ "ioredis": "^5.11.1",
+ "ioredis-mock": "^8.13.1",
+ "jsonwebtoken": "^9.0.3",
+ "jwks-rsa": "^4.0.1",
+ "socket.io": "^4.8.3"
+ }
+ },
+ "node_modules/@ioredis/as-callback": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@ioredis/as-callback/-/as-callback-3.0.0.tgz",
+ "integrity": "sha512-Kqv1rZ3WbgOrS+hgzJ5xG5WQuhvzzSTRYvNeyPMLOAM78MHSnuKI20JeJGbpuAt//LCuP0vsexZcorqW7kWhJg=="
+ },
+ "node_modules/@ioredis/commands": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.10.0.tgz",
+ "integrity": "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q=="
+ },
+ "node_modules/@socket.io/component-emitter": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
+ "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="
+ },
+ "node_modules/@socket.io/redis-adapter": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/@socket.io/redis-adapter/-/redis-adapter-8.3.0.tgz",
+ "integrity": "sha512-ly0cra+48hDmChxmIpnESKrc94LjRL80TEmZVscuQ/WWkRP81nNj8W8cCGMqbI4L6NCuAaPRSzZF1a9GlAxxnA==",
+ "dependencies": {
+ "debug": "~4.3.1",
+ "notepack.io": "~3.0.1",
+ "uid2": "1.0.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "socket.io-adapter": "^2.5.4"
+ }
+ },
+ "node_modules/@socket.io/redis-adapter/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@types/cors": {
+ "version": "2.8.19",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
+ "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/ioredis-mock": {
+ "version": "8.2.7",
+ "resolved": "https://registry.npmjs.org/@types/ioredis-mock/-/ioredis-mock-8.2.7.tgz",
+ "integrity": "sha512-YsGiaOIYBKeVvu/7GYziAD8qX3LJem5LK00d5PKykzsQJMLysAqXA61AkNuYWCekYl64tbMTqVOMF4SYoCPbQg==",
+ "peer": true,
+ "peerDependencies": {
+ "ioredis": ">=5"
+ }
+ },
+ "node_modules/@types/jsonwebtoken": {
+ "version": "9.0.10",
+ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz",
+ "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==",
+ "dependencies": {
+ "@types/ms": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/ms": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
+ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="
+ },
+ "node_modules/@types/node": {
+ "version": "25.9.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.3.tgz",
+ "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==",
+ "dependencies": {
+ "undici-types": ">=7.24.0 <7.24.7"
+ }
+ },
+ "node_modules/@types/ws": {
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
+ "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "dependencies": {
+ "mime-types": "^3.0.0",
+ "negotiator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/base64id": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
+ "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
+ "engines": {
+ "node": "^4.5.0 || >= 5.9"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
+ "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
+ "dependencies": {
+ "bytes": "^3.1.2",
+ "content-type": "^1.0.5",
+ "debug": "^4.4.3",
+ "http-errors": "^2.0.0",
+ "iconv-lite": "^0.7.0",
+ "on-finished": "^2.4.1",
+ "qs": "^6.14.1",
+ "raw-body": "^3.0.1",
+ "type-is": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/cluster-key-slot": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz",
+ "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
+ "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
+ "engines": {
+ "node": ">=6.6.0"
+ }
+ },
+ "node_modules/cors": {
+ "version": "2.8.6",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
+ "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/denque": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
+ "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "17.4.2",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz",
+ "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/engine.io": {
+ "version": "6.6.8",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.8.tgz",
+ "integrity": "sha512-2agL3ueZhqxoVrfmntO8yuVj+uNSlIOnhykYHk3Cq0ShYPdUjjUiSJrQvXjq01I9jAuI0Zl2YO8Evv5Mqytm5g==",
+ "dependencies": {
+ "@types/cors": "^2.8.12",
+ "@types/node": ">=10.0.0",
+ "@types/ws": "^8.5.12",
+ "accepts": "~1.3.4",
+ "base64id": "2.0.0",
+ "cookie": "~0.7.2",
+ "cors": "~2.8.5",
+ "debug": "~4.4.1",
+ "engine.io-parser": "~5.2.1",
+ "ws": "~8.20.1"
+ },
+ "engines": {
+ "node": ">=10.2.0"
+ }
+ },
+ "node_modules/engine.io-parser": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
+ "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/engine.io/node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/engine.io/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/engine.io/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/engine.io/node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
+ "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
+ "dependencies": {
+ "accepts": "^2.0.0",
+ "body-parser": "^2.2.1",
+ "content-disposition": "^1.0.0",
+ "content-type": "^1.0.5",
+ "cookie": "^0.7.1",
+ "cookie-signature": "^1.2.1",
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "finalhandler": "^2.1.0",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.0",
+ "merge-descriptors": "^2.0.0",
+ "mime-types": "^3.0.0",
+ "on-finished": "^2.4.1",
+ "once": "^1.4.0",
+ "parseurl": "^1.3.3",
+ "proxy-addr": "^2.0.7",
+ "qs": "^6.14.0",
+ "range-parser": "^1.2.1",
+ "router": "^2.2.0",
+ "send": "^1.1.0",
+ "serve-static": "^2.2.0",
+ "statuses": "^2.0.1",
+ "type-is": "^2.0.1",
+ "vary": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/fengari": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/fengari/-/fengari-0.1.5.tgz",
+ "integrity": "sha512-0DS4Nn4rV8qyFlQCpKK8brT61EUtswynrpfFTcgLErcilBIBskSMQ86fO2WVuybr14ywyKdRjv91FiRZwnEuvQ==",
+ "dependencies": {
+ "readline-sync": "^1.4.10",
+ "sprintf-js": "^1.1.3",
+ "tmp": "^0.2.5"
+ }
+ },
+ "node_modules/fengari-interop": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/fengari-interop/-/fengari-interop-0.1.4.tgz",
+ "integrity": "sha512-4/CW/3PJUo3ebD4ACgE1g/3NGEYSq7OQAyETyypsAl/WeySDBbxExikkayNkZzbpgyC9GyJp8v1DU2VOXxNq7Q==",
+ "peerDependencies": {
+ "fengari": "^0.1.0"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
+ "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "on-finished": "^2.4.1",
+ "parseurl": "^1.3.3",
+ "statuses": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
+ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
+ "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/ioredis": {
+ "version": "5.11.1",
+ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.11.1.tgz",
+ "integrity": "sha512-ehuGcf94bQXhfagULNXrJdfnWO38v070jxSx/qE87Kjzmu2fU7ro5EFAb+OPituLqgfyuQaym5DlrNydW2sJ9A==",
+ "dependencies": {
+ "@ioredis/commands": "1.10.0",
+ "cluster-key-slot": "1.1.1",
+ "debug": "4.4.3",
+ "denque": "2.1.0",
+ "redis-errors": "1.2.0",
+ "redis-parser": "3.0.0",
+ "standard-as-callback": "2.1.0"
+ },
+ "engines": {
+ "node": ">=12.22.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/ioredis"
+ }
+ },
+ "node_modules/ioredis-mock": {
+ "version": "8.13.1",
+ "resolved": "https://registry.npmjs.org/ioredis-mock/-/ioredis-mock-8.13.1.tgz",
+ "integrity": "sha512-Wsi50AU+cMiI32nAgfwpUaJVBtb4iQdVsOHl9M6R3tePCO/8vGsToCVIG82XWAxN4Se55TZoOzVseu+QngFLyw==",
+ "dependencies": {
+ "@ioredis/as-callback": "^3.0.0",
+ "@ioredis/commands": "^1.4.0",
+ "fengari": "^0.1.4",
+ "fengari-interop": "^0.1.3",
+ "semver": "^7.7.2"
+ },
+ "engines": {
+ "node": ">=12.22"
+ },
+ "peerDependencies": {
+ "@types/ioredis-mock": "^8",
+ "ioredis": "^5"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-promise": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
+ },
+ "node_modules/jose": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.3.tgz",
+ "integrity": "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/jsonwebtoken": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
+ "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==",
+ "license": "MIT",
+ "dependencies": {
+ "jws": "^4.0.1",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/jwa": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
+ "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-equal-constant-time": "^1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jwks-rsa": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-4.0.1.tgz",
+ "integrity": "sha512-poXwUA8S4cP9P5N8tZS3xnUDJH8WmwSGfKK9gIaRPdjLHyJtd9iX/cngX9CUIe0Caof5JhK2EbN7N5lnnaf9NA==",
+ "dependencies": {
+ "@types/jsonwebtoken": "^9.0.4",
+ "debug": "^4.3.4",
+ "jose": "^6.1.3",
+ "limiter": "^1.1.5",
+ "lru-memoizer": "^3.0.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || >= 23.0.0"
+ }
+ },
+ "node_modules/jws": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
+ "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
+ "license": "MIT",
+ "dependencies": {
+ "jwa": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/limiter": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz",
+ "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA=="
+ },
+ "node_modules/lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
+ },
+ "node_modules/lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "11.5.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz",
+ "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/lru-memoizer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-3.0.0.tgz",
+ "integrity": "sha512-m83w/cYXLdUIboKSPxzPAGfYnk+vqeDYXuoSrQRw1q+yVEd8IXhvMufN8Q5TIPe7e2jyX4SRNrDJI2Skw1yznQ==",
+ "dependencies": {
+ "lodash.clonedeep": "^4.5.0",
+ "lru-cache": "^11.0.1"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
+ "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
+ "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/negotiator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
+ "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/notepack.io": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/notepack.io/-/notepack.io-3.0.1.tgz",
+ "integrity": "sha512-TKC/8zH5pXIAMVQio2TvVDTtPRX+DJPHDqjRbxogtFiByHyzKmy96RA0JtCQJ+WouyyL4A10xomQzgbUT+1jCg=="
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
+ "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.15.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
+ "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
+ "dependencies": {
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
+ "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.7.0",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/readline-sync": {
+ "version": "1.4.10",
+ "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz",
+ "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/redis-errors": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
+ "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/redis-parser": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
+ "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
+ "dependencies": {
+ "redis-errors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/router": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "is-promise": "^4.0.0",
+ "parseurl": "^1.3.3",
+ "path-to-regexp": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/semver": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
+ "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.1",
+ "mime-types": "^3.0.2",
+ "ms": "^2.1.3",
+ "on-finished": "^2.4.1",
+ "range-parser": "^1.2.1",
+ "statuses": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
+ "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
+ "dependencies": {
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "parseurl": "^1.3.3",
+ "send": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
+ "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4",
+ "side-channel-list": "^1.0.1",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/socket.io": {
+ "version": "4.8.3",
+ "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz",
+ "integrity": "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==",
+ "dependencies": {
+ "accepts": "~1.3.4",
+ "base64id": "~2.0.0",
+ "cors": "~2.8.5",
+ "debug": "~4.4.1",
+ "engine.io": "~6.6.0",
+ "socket.io-adapter": "~2.5.2",
+ "socket.io-parser": "~4.2.4"
+ },
+ "engines": {
+ "node": ">=10.2.0"
+ }
+ },
+ "node_modules/socket.io-adapter": {
+ "version": "2.5.7",
+ "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.7.tgz",
+ "integrity": "sha512-e0LyK91f3cUxTmv95/KzoLg47+zF+s/sbxRGDNsyG4dmIP8ZSX8ax6byOxfJXeNNtS/8AZlfD+uP7gBeR7DLlg==",
+ "dependencies": {
+ "debug": "~4.4.1",
+ "ws": "~8.20.1"
+ }
+ },
+ "node_modules/socket.io-parser": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz",
+ "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==",
+ "dependencies": {
+ "@socket.io/component-emitter": "~3.1.0",
+ "debug": "~4.4.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/socket.io/node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/socket.io/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/socket.io/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/socket.io/node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
+ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
+ },
+ "node_modules/standard-as-callback": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
+ "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
+ },
+ "node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/tmp": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz",
+ "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==",
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz",
+ "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==",
+ "dependencies": {
+ "content-type": "^2.0.0",
+ "media-typer": "^1.1.0",
+ "mime-types": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/type-is/node_modules/content-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz",
+ "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/uid2": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/uid2/-/uid2-1.0.0.tgz",
+ "integrity": "sha512-+I6aJUv63YAcY9n4mQreLUt0d4lvwkkopDNmpomkAUz0fAkEMV9pRWxN0EjhW1YfRhcuyHg2v3mwddCDW1+LFQ==",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
+ "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/ws": {
+ "version": "8.20.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
+ "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ }
+ }
+}
diff --git a/arena-socket-server/package.json b/arena-socket-server/package.json
new file mode 100644
index 000000000..310001385
--- /dev/null
+++ b/arena-socket-server/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "arena-socket-server",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "start": "node index.js",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "@socket.io/redis-adapter": "^8.3.0",
+ "cors": "^2.8.6",
+ "dotenv": "^17.4.2",
+ "express": "^5.2.1",
+ "ioredis": "^5.11.1",
+ "ioredis-mock": "^8.13.1",
+ "jsonwebtoken": "^9.0.3",
+ "jwks-rsa": "^4.0.1",
+ "socket.io": "^4.8.3"
+ }
+}
diff --git a/backend/.gitattributes b/backend/.gitattributes
new file mode 100644
index 000000000..3b41682ac
--- /dev/null
+++ b/backend/.gitattributes
@@ -0,0 +1,2 @@
+/mvnw text eol=lf
+*.cmd text eol=crlf
diff --git a/backend/.gitignore b/backend/.gitignore
new file mode 100644
index 000000000..667aaef0c
--- /dev/null
+++ b/backend/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/backend/.mvn/wrapper/maven-wrapper.properties b/backend/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..216df0589
--- /dev/null
+++ b/backend/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,3 @@
+wrapperVersion=3.3.4
+distributionType=only-script
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.16/apache-maven-3.9.16-bin.zip
diff --git a/backend/Dockerfile b/backend/Dockerfile
new file mode 100644
index 000000000..5801a086a
--- /dev/null
+++ b/backend/Dockerfile
@@ -0,0 +1,17 @@
+FROM maven:3.9.8-eclipse-temurin-21 AS build
+
+WORKDIR /app
+
+COPY . .
+
+RUN mvn clean package -DskipTests
+
+FROM eclipse-temurin:21-jre
+
+WORKDIR /app
+
+COPY --from=build /app/target/*.jar app.jar
+
+EXPOSE 8080
+
+ENTRYPOINT ["java", "-jar", "app.jar"]
diff --git a/backend/README.md b/backend/README.md
new file mode 100644
index 000000000..e317b8b0b
--- /dev/null
+++ b/backend/README.md
@@ -0,0 +1,47 @@
+# AlgoBuddy Backend
+
+This is the Spring Boot-based REST API backend for AlgoBuddy.
+
+## CORS Configuration
+
+The backend features a secure, parsed, and validated CORS allowlist configured through properties and environment variables.
+
+### Configuration Properties
+
+You can customize the CORS settings using the following properties:
+
+| Property | Environment Variable | Default Value | Description |
+|---|---|---|---|
+| `app.allowed-origins` | `ALLOWED_ORIGINS` | *Empty* | A comma-separated list of allowed origins (e.g., `http://localhost:3000,https://algobuddy.me`). |
+| `app.environment` | `APP_ENV` | `dev` | The active application environment (e.g., `dev`, `prod`, `production`). Defaults to `spring.profiles.active` if set. |
+
+### Security & Validation Rules
+
+To protect the API against cross-origin security bypasses, the backend applies the following validation rules to configured origins:
+
+1. **No Wildcards:** Wildcard characters (`*`) are disallowed to prevent open access. If found in the configuration, they are ignored.
+2. **Scheme Enforcement:** Origins must explicitly start with `http://` or `https://`. Other schemes (e.g., `ftp://`) or invalid URLs are skipped.
+3. **Trailing Slashes:** Trailing slashes are automatically trimmed (e.g., `http://localhost:3000/` becomes `http://localhost:3000`) to correctly match standard browser `Origin` headers.
+4. **Environment-Aware Fallbacks:**
+ - **Development/Test (`APP_ENV=dev` or not production):** If no origins are configured, it defaults to allowing `http://localhost:3000` so that local development works out-of-the-box.
+ - **Production (`APP_ENV=production` or `prod`):** If no origins are configured, it will print an error and **block all cross-origin requests** by default for safety.
+
+---
+
+## Building and Testing
+
+### Prerequisites
+- Java 21+
+- Maven (or use the included `./mvnw` wrapper)
+
+### Build the Application
+To build the backend package:
+```bash
+./mvnw clean package -DskipTests
+```
+
+### Run Tests
+To run CORS unit and integration tests:
+```bash
+./mvnw test -Dtest=CorsConfigTest,CorsIntegrationTest
+```
diff --git a/backend/mvnw b/backend/mvnw
new file mode 100644
index 000000000..bd8896bf2
--- /dev/null
+++ b/backend/mvnw
@@ -0,0 +1,295 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.3.4
+#
+# Optional ENV vars
+# -----------------
+# JAVA_HOME - location of a JDK home dir, required when download maven via java source
+# MVNW_REPOURL - repo url base for downloading maven distribution
+# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
+# ----------------------------------------------------------------------------
+
+set -euf
+[ "${MVNW_VERBOSE-}" != debug ] || set -x
+
+# OS specific support.
+native_path() { printf %s\\n "$1"; }
+case "$(uname)" in
+CYGWIN* | MINGW*)
+ [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
+ native_path() { cygpath --path --windows "$1"; }
+ ;;
+esac
+
+# set JAVACMD and JAVACCMD
+set_java_home() {
+ # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
+ if [ -n "${JAVA_HOME-}" ]; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ]; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACCMD="$JAVA_HOME/jre/sh/javac"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ JAVACCMD="$JAVA_HOME/bin/javac"
+
+ if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
+ echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
+ echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
+ return 1
+ fi
+ fi
+ else
+ JAVACMD="$(
+ 'set' +e
+ 'unset' -f command 2>/dev/null
+ 'command' -v java
+ )" || :
+ JAVACCMD="$(
+ 'set' +e
+ 'unset' -f command 2>/dev/null
+ 'command' -v javac
+ )" || :
+
+ if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
+ echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
+ return 1
+ fi
+ fi
+}
+
+# hash string like Java String::hashCode
+hash_string() {
+ str="${1:-}" h=0
+ while [ -n "$str" ]; do
+ char="${str%"${str#?}"}"
+ h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
+ str="${str#?}"
+ done
+ printf %x\\n $h
+}
+
+verbose() { :; }
+[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
+
+die() {
+ printf %s\\n "$1" >&2
+ exit 1
+}
+
+trim() {
+ # MWRAPPER-139:
+ # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
+ # Needed for removing poorly interpreted newline sequences when running in more
+ # exotic environments such as mingw bash on Windows.
+ printf "%s" "${1}" | tr -d '[:space:]'
+}
+
+scriptDir="$(dirname "$0")"
+scriptName="$(basename "$0")"
+
+# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
+while IFS="=" read -r key value; do
+ case "${key-}" in
+ distributionUrl) distributionUrl=$(trim "${value-}") ;;
+ distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
+ esac
+done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
+[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
+
+case "${distributionUrl##*/}" in
+maven-mvnd-*bin.*)
+ MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
+ case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
+ *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
+ :Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
+ :Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
+ :Linux*x86_64*) distributionPlatform=linux-amd64 ;;
+ *)
+ echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
+ distributionPlatform=linux-amd64
+ ;;
+ esac
+ distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
+ ;;
+maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
+*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
+esac
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
+[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
+distributionUrlName="${distributionUrl##*/}"
+distributionUrlNameMain="${distributionUrlName%.*}"
+distributionUrlNameMain="${distributionUrlNameMain%-bin}"
+MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
+MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
+
+exec_maven() {
+ unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
+ exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
+}
+
+if [ -d "$MAVEN_HOME" ]; then
+ verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+ exec_maven "$@"
+fi
+
+case "${distributionUrl-}" in
+*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
+*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
+esac
+
+# prepare tmp dir
+if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
+ clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
+ trap clean HUP INT TERM EXIT
+else
+ die "cannot create temp dir"
+fi
+
+mkdir -p -- "${MAVEN_HOME%/*}"
+
+# Download and Install Apache Maven
+verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+verbose "Downloading from: $distributionUrl"
+verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+# select .zip or .tar.gz
+if ! command -v unzip >/dev/null; then
+ distributionUrl="${distributionUrl%.zip}.tar.gz"
+ distributionUrlName="${distributionUrl##*/}"
+fi
+
+# verbose opt
+__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
+[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
+
+# normalize http auth
+case "${MVNW_PASSWORD:+has-password}" in
+'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+esac
+
+if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
+ verbose "Found wget ... using wget"
+ wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
+elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
+ verbose "Found curl ... using curl"
+ curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
+elif set_java_home; then
+ verbose "Falling back to use Java to download"
+ javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
+ targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
+ cat >"$javaSource" <<-END
+ public class Downloader extends java.net.Authenticator
+ {
+ protected java.net.PasswordAuthentication getPasswordAuthentication()
+ {
+ return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
+ }
+ public static void main( String[] args ) throws Exception
+ {
+ setDefault( new Downloader() );
+ java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
+ }
+ }
+ END
+ # For Cygwin/MinGW, switch paths to Windows format before running javac and java
+ verbose " - Compiling Downloader.java ..."
+ "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
+ verbose " - Running Downloader.java ..."
+ "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
+fi
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+if [ -n "${distributionSha256Sum-}" ]; then
+ distributionSha256Result=false
+ if [ "$MVN_CMD" = mvnd.sh ]; then
+ echo "Checksum validation is not supported for maven-mvnd." >&2
+ echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+ exit 1
+ elif command -v sha256sum >/dev/null; then
+ if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
+ distributionSha256Result=true
+ fi
+ elif command -v shasum >/dev/null; then
+ if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
+ distributionSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
+ echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+ exit 1
+ fi
+ if [ $distributionSha256Result = false ]; then
+ echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
+ echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+# unzip and move
+if command -v unzip >/dev/null; then
+ unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
+else
+ tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
+fi
+
+# Find the actual extracted directory name (handles snapshots where filename != directory name)
+actualDistributionDir=""
+
+# First try the expected directory name (for regular distributions)
+if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
+ if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
+ actualDistributionDir="$distributionUrlNameMain"
+ fi
+fi
+
+# If not found, search for any directory with the Maven executable (for snapshots)
+if [ -z "$actualDistributionDir" ]; then
+ # enable globbing to iterate over items
+ set +f
+ for dir in "$TMP_DOWNLOAD_DIR"/*; do
+ if [ -d "$dir" ]; then
+ if [ -f "$dir/bin/$MVN_CMD" ]; then
+ actualDistributionDir="$(basename "$dir")"
+ break
+ fi
+ fi
+ done
+ set -f
+fi
+
+if [ -z "$actualDistributionDir" ]; then
+ verbose "Contents of $TMP_DOWNLOAD_DIR:"
+ verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
+ die "Could not find Maven distribution directory in extracted archive"
+fi
+
+verbose "Found extracted Maven distribution directory: $actualDistributionDir"
+printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
+mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
+
+clean || :
+exec_maven "$@"
diff --git a/backend/mvnw.cmd b/backend/mvnw.cmd
new file mode 100644
index 000000000..92450f932
--- /dev/null
+++ b/backend/mvnw.cmd
@@ -0,0 +1,189 @@
+<# : batch portion
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.3.4
+@REM
+@REM Optional ENV vars
+@REM MVNW_REPOURL - repo url base for downloading maven distribution
+@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
+@REM ----------------------------------------------------------------------------
+
+@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
+@SET __MVNW_CMD__=
+@SET __MVNW_ERROR__=
+@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
+@SET PSModulePath=
+@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
+ IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
+)
+@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
+@SET __MVNW_PSMODULEP_SAVE=
+@SET __MVNW_ARG0_NAME__=
+@SET MVNW_USERNAME=
+@SET MVNW_PASSWORD=
+@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
+@echo Cannot start maven from wrapper >&2 && exit /b 1
+@GOTO :EOF
+: end batch / begin powershell #>
+
+$ErrorActionPreference = "Stop"
+if ($env:MVNW_VERBOSE -eq "true") {
+ $VerbosePreference = "Continue"
+}
+
+# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
+$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
+if (!$distributionUrl) {
+ Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
+}
+
+switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
+ "maven-mvnd-*" {
+ $USE_MVND = $true
+ $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
+ $MVN_CMD = "mvnd.cmd"
+ break
+ }
+ default {
+ $USE_MVND = $false
+ $MVN_CMD = $script -replace '^mvnw','mvn'
+ break
+ }
+}
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
+if ($env:MVNW_REPOURL) {
+ $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
+ $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
+}
+$distributionUrlName = $distributionUrl -replace '^.*/',''
+$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
+
+$MAVEN_M2_PATH = "$HOME/.m2"
+if ($env:MAVEN_USER_HOME) {
+ $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
+}
+
+if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
+ New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
+}
+
+$MAVEN_WRAPPER_DISTS = $null
+if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
+ $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
+} else {
+ $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
+}
+
+$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
+$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
+$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
+
+if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
+ Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+ Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
+ exit $?
+}
+
+if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
+ Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
+}
+
+# prepare tmp dir
+$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
+$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
+$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
+trap {
+ if ($TMP_DOWNLOAD_DIR.Exists) {
+ try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+ catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+ }
+}
+
+New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
+
+# Download and Install Apache Maven
+Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+Write-Verbose "Downloading from: $distributionUrl"
+Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+$webclient = New-Object System.Net.WebClient
+if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
+ $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
+}
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
+if ($distributionSha256Sum) {
+ if ($USE_MVND) {
+ Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
+ }
+ Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
+ if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
+ Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
+ }
+}
+
+# unzip and move
+Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
+
+# Find the actual extracted directory name (handles snapshots where filename != directory name)
+$actualDistributionDir = ""
+
+# First try the expected directory name (for regular distributions)
+$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
+$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
+if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
+ $actualDistributionDir = $distributionUrlNameMain
+}
+
+# If not found, search for any directory with the Maven executable (for snapshots)
+if (!$actualDistributionDir) {
+ Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
+ $testPath = Join-Path $_.FullName "bin/$MVN_CMD"
+ if (Test-Path -Path $testPath -PathType Leaf) {
+ $actualDistributionDir = $_.Name
+ }
+ }
+}
+
+if (!$actualDistributionDir) {
+ Write-Error "Could not find Maven distribution directory in extracted archive"
+}
+
+Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
+Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
+try {
+ Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
+} catch {
+ if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
+ Write-Error "fail to move MAVEN_HOME"
+ }
+} finally {
+ try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+ catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+}
+
+Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
diff --git a/backend/pom.xml b/backend/pom.xml
new file mode 100644
index 000000000..74b8c4ce0
--- /dev/null
+++ b/backend/pom.xml
@@ -0,0 +1,147 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.4.0
+
+
+ com.algobuddy
+ backend
+ 0.0.1-SNAPSHOT
+ backend
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 21
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-oauth2-resource-server
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ org.postgresql
+ postgresql
+ runtime
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.5.0
+
+
+ com.bucket4j
+ bucket4j-core
+ 8.10.1
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ com.github.ben-manes.caffeine
+ caffeine
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ default-compile
+ compile
+
+ compile
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+ default-testCompile
+ test-compile
+
+ testCompile
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
+
+
diff --git a/backend/src/main/java/com/algobuddy/backend/BackendApplication.java b/backend/src/main/java/com/algobuddy/backend/BackendApplication.java
new file mode 100644
index 000000000..ffa44e0b6
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/BackendApplication.java
@@ -0,0 +1,17 @@
+package com.algobuddy.backend;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication
+@EnableCaching
+@EnableScheduling
+public class BackendApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(BackendApplication.class, args);
+ }
+
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/config/CacheConfig.java b/backend/src/main/java/com/algobuddy/backend/config/CacheConfig.java
new file mode 100644
index 000000000..d5a36e1cd
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/config/CacheConfig.java
@@ -0,0 +1,53 @@
+package com.algobuddy.backend.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+
+import java.time.Duration;
+import java.util.Arrays;
+
+@Configuration
+@EnableCaching
+public class CacheConfig {
+
+ @Bean
+ @Primary
+ @ConditionalOnProperty(name = "app.cache.redis.enabled", havingValue = "true")
+ public CacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
+ RedisCacheConfiguration defaults = RedisCacheConfiguration.defaultCacheConfig()
+ .entryTtl(Duration.ofMinutes(30))
+ .disableCachingNullValues();
+
+ return RedisCacheManager.builder(redisConnectionFactory)
+ .cacheDefaults(defaults)
+ .withCacheConfiguration("arenaProfile",
+ RedisCacheConfiguration.defaultCacheConfig()
+ .entryTtl(Duration.ofMinutes(10)))
+ .withCacheConfiguration("arenaLeaderboard",
+ RedisCacheConfiguration.defaultCacheConfig()
+ .entryTtl(Duration.ofMinutes(5)))
+ .withCacheConfiguration("mysheet",
+ RedisCacheConfiguration.defaultCacheConfig()
+ .entryTtl(Duration.ofMinutes(30)))
+ .withCacheConfiguration("bookmarks",
+ RedisCacheConfiguration.defaultCacheConfig()
+ .entryTtl(Duration.ofMinutes(60)))
+ .build();
+ }
+
+ @Bean
+ @ConditionalOnProperty(name = "app.cache.redis.enabled", havingValue = "false", matchIfMissing = true)
+ public CacheManager concurrentMapCacheManager() {
+ ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
+ cacheManager.setCacheNames(Arrays.asList("arenaProfile", "arenaLeaderboard", "mysheet", "bookmarks"));
+ return cacheManager;
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/config/OpenApiConfig.java b/backend/src/main/java/com/algobuddy/backend/config/OpenApiConfig.java
new file mode 100644
index 000000000..aea50fd22
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/config/OpenApiConfig.java
@@ -0,0 +1,33 @@
+package com.algobuddy.backend.config;
+
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.security.SecurityRequirement;
+import io.swagger.v3.oas.models.security.SecurityScheme;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class OpenApiConfig {
+
+ @Bean
+ public OpenAPI customOpenAPI() {
+ final String securitySchemeName = "bearerAuth";
+ return new OpenAPI()
+ .info(new Info().title("AlgoBuddy API")
+ .description("API Documentation for AlgoBuddy Application")
+ .version("v1.0"))
+ .addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
+ .components(
+ new Components()
+ .addSecuritySchemes(securitySchemeName,
+ new SecurityScheme()
+ .name(securitySchemeName)
+ .type(SecurityScheme.Type.HTTP)
+ .scheme("bearer")
+ .bearerFormat("JWT")
+ )
+ );
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/config/RateLimitInterceptor.java b/backend/src/main/java/com/algobuddy/backend/config/RateLimitInterceptor.java
new file mode 100644
index 000000000..0dc545fad
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/config/RateLimitInterceptor.java
@@ -0,0 +1,140 @@
+package com.algobuddy.backend.config;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import io.github.bucket4j.Bandwidth;
+import io.github.bucket4j.Bucket;
+import io.github.bucket4j.ConsumptionProbe;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.lang.NonNull;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@Component
+public class RateLimitInterceptor implements HandlerInterceptor {
+
+ @Value("${app.trusted-proxies:127.0.0.1,::1,10.0.0.1}")
+ private String trustedProxiesConfig;
+
+ private Set trustedProxies;
+
+ private final Cache cache;
+
+ public RateLimitInterceptor() {
+ this.cache = Caffeine.newBuilder()
+ .expireAfterWrite(10, TimeUnit.MINUTES)
+ .maximumSize(10_000)
+ .build();
+ }
+
+ private Bucket newBucket() {
+ Bandwidth limit = Bandwidth.builder()
+ .capacity(100)
+ .refillGreedy(100, Duration.ofMinutes(1))
+ .build();
+ return Bucket.builder().addLimit(limit).build();
+ }
+
+ private Bucket resolveBucket(String key) {
+ return cache.get(key, k -> newBucket());
+ }
+
+ private Set getTrustedProxies() {
+ if (trustedProxies == null) {
+ trustedProxies = Arrays.stream(trustedProxiesConfig.split(","))
+ .map(String::trim)
+ .filter(s -> !s.isEmpty())
+ .collect(Collectors.toSet());
+ }
+ return trustedProxies;
+ }
+
+ private String extractClientIp(HttpServletRequest request) {
+ String xForwardedFor = request.getHeader("X-Forwarded-For");
+ if (xForwardedFor != null && !xForwardedFor.isEmpty() && isFromTrustedProxy(request)) {
+ String[] hops = xForwardedFor.split(",");
+ for (int i = hops.length - 1; i >= 0; i--) {
+ String ip = hops[i].trim();
+ if (isValidIp(ip) && !isPrivateIp(ip)) {
+ return ip;
+ }
+ }
+ }
+ return request.getRemoteAddr();
+ }
+
+ private boolean isFromTrustedProxy(HttpServletRequest request) {
+ return getTrustedProxies().contains(request.getRemoteAddr());
+ }
+
+ private boolean isPrivateIp(String ip) {
+ if (ip.startsWith("10.") || ip.startsWith("192.168.") || ip.startsWith("127.") || ip.equals("::1") || ip.startsWith("fc") || ip.startsWith("fd")) {
+ return true;
+ }
+ if (ip.startsWith("172.")) {
+ try {
+ String[] parts = ip.split("\\.");
+ if (parts.length >= 2) {
+ int secondOctet = Integer.parseInt(parts[1]);
+ return secondOctet >= 16 && secondOctet <= 31;
+ }
+ } catch (Exception e) {}
+ }
+ return false;
+ }
+
+ private boolean isValidIp(String ip) {
+ if (ip == null || ip.isEmpty()) {
+ return false;
+ }
+ try {
+ // InetAddress.getByName accepts both IPv4 and IPv6 literals.
+ // Round-tripping through getHostAddress() rejects hostnames:
+ // a hostname would resolve to a different address string.
+ InetAddress addr = InetAddress.getByName(ip);
+ return addr.getHostAddress().equalsIgnoreCase(ip)
+ || normalizeIpv6(addr.getHostAddress()).equalsIgnoreCase(normalizeIpv6(ip));
+ } catch (UnknownHostException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Strip the zone-ID suffix (e.g. "%eth0") from an IPv6 address string
+ * before comparing, so that scoped addresses compare equal to their
+ * plain counterparts.
+ */
+ private static String normalizeIpv6(String ip) {
+ int zoneIndex = ip.indexOf('%');
+ return zoneIndex >= 0 ? ip.substring(0, zoneIndex) : ip;
+ }
+
+ @Override
+ public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
+ String ip = extractClientIp(request);
+
+ Bucket bucket = resolveBucket(ip);
+ ConsumptionProbe probe = bucket.tryConsumeAndReturnRemaining(1);
+
+ if (probe.isConsumed()) {
+ response.addHeader("X-Rate-Limit-Remaining", String.valueOf(probe.getRemainingTokens()));
+ return true;
+ } else {
+ response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
+ response.getWriter().write("Too many requests. Please try again later.");
+ response.addHeader("X-Rate-Limit-Retry-After-Seconds", String.valueOf(probe.getNanosToWaitForRefill() / 1_000_000_000));
+ return false;
+ }
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/config/SecurityConfig.java b/backend/src/main/java/com/algobuddy/backend/config/SecurityConfig.java
new file mode 100644
index 000000000..b6ddc8693
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/config/SecurityConfig.java
@@ -0,0 +1,120 @@
+package com.algobuddy.backend.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.oauth2.jwt.JwtDecoder;
+import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.ForwardedHeaderFilter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+@Configuration
+@EnableWebSecurity
+public class SecurityConfig {
+
+ private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class);
+
+ @Value("${app.allowed-origins:}")
+ private String allowedOrigins;
+
+ @Value("${app.environment:dev}")
+ private String environment;
+
+ List resolveAllowedOrigins() {
+ List list = new ArrayList<>();
+ if (allowedOrigins != null && !allowedOrigins.trim().isEmpty()) {
+ for (String origin : allowedOrigins.split(",")) {
+ origin = origin.trim();
+ if (!origin.isEmpty()) {
+ if (origin.equals("*")) {
+ log.warn("CORS configuration contains wildcard '*', which is not allowed. Skipping.");
+ continue;
+ }
+ if (origin.endsWith("/")) {
+ origin = origin.substring(0, origin.length() - 1);
+ }
+ if (origin.startsWith("http://") || origin.startsWith("https://")) {
+ list.add(origin);
+ } else {
+ log.warn("Invalid CORS origin format: '{}'. Origins must start with http:// or https://. Skipping.", origin);
+ }
+ }
+ }
+ }
+
+ if (list.isEmpty()) {
+ boolean isProd = environment != null && (environment.toLowerCase().contains("prod") || environment.toLowerCase().contains("production"));
+ if (isProd) {
+ log.error("No valid CORS allowed origins configured for production environment. All cross-origin requests will be blocked.");
+ } else {
+ log.info("No valid CORS allowed origins configured for development/test environment. Defaulting to 'http://localhost:3000'.");
+ list.add("http://localhost:3000");
+ }
+ } else {
+ log.info("CORS allowed origins configured: {}", list);
+ }
+ return list;
+ }
+ @Value("${supabase.url}")
+ private String supabaseUrl;
+
+ @Bean
+ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+ http
+ .cors(cors -> cors.configurationSource(corsConfigurationSource()))
+ .csrf(csrf -> csrf.disable())
+ .sessionManagement(session ->
+ session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+ .authorizeHttpRequests(authz -> authz
+ .requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
+ .requestMatchers(org.springframework.http.HttpMethod.GET, "/api/v1/arena/leaderboard", "/api/v1/arena/daily-challenge").permitAll()
+ .anyRequest().authenticated())
+ .oauth2ResourceServer(oauth2 -> oauth2
+ .jwt(jwt -> jwt.decoder(jwtDecoder())));
+
+ return http.build();
+ }
+
+ @Bean
+ public ForwardedHeaderFilter forwardedHeaderFilter() {
+ return new ForwardedHeaderFilter();
+ }
+
+ @Bean
+ public JwtDecoder jwtDecoder() {
+ String jwkSetUri = supabaseUrl + "/auth/v1/.well-known/jwks.json";
+ return NimbusJwtDecoder.withJwkSetUri(jwkSetUri)
+ .jwsAlgorithm(org.springframework.security.oauth2.jose.jws.SignatureAlgorithm.ES256)
+ .build();
+ }
+
+ @Bean
+ public CorsConfigurationSource corsConfigurationSource() {
+ CorsConfiguration configuration = new CorsConfiguration();
+ List resolvedOrigins = resolveAllowedOrigins();
+ if (resolvedOrigins.isEmpty()) {
+ configuration.setAllowedOrigins(Collections.emptyList());
+ } else {
+ configuration.setAllowedOrigins(resolvedOrigins);
+ }
+ configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
+ configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type", "x-auth-token"));
+ configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", configuration);
+ return source;
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/config/WebMvcConfig.java b/backend/src/main/java/com/algobuddy/backend/config/WebMvcConfig.java
new file mode 100644
index 000000000..e0cf2d44b
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/config/WebMvcConfig.java
@@ -0,0 +1,29 @@
+package com.algobuddy.backend.config;
+
+import com.algobuddy.backend.config.resolver.CurrentUserIdArgumentResolver;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import org.springframework.lang.NonNull;
+import java.util.List;
+
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+ @Autowired
+ private RateLimitInterceptor rateLimitInterceptor;
+
+ @Override
+ public void addInterceptors(@NonNull InterceptorRegistry registry) {
+ registry.addInterceptor(rateLimitInterceptor)
+ .addPathPatterns("/api/**");
+ }
+
+ @Override
+ public void addArgumentResolvers(@NonNull List resolvers) {
+ resolvers.add(new CurrentUserIdArgumentResolver());
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/config/annotation/CurrentUserId.java b/backend/src/main/java/com/algobuddy/backend/config/annotation/CurrentUserId.java
new file mode 100644
index 000000000..09ea6e366
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/config/annotation/CurrentUserId.java
@@ -0,0 +1,15 @@
+package com.algobuddy.backend.config.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to inject the current user's UUID into controller method parameters.
+ * Automatically extracts the UUID from the JWT subject.
+ */
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CurrentUserId {
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/config/resolver/CurrentUserIdArgumentResolver.java b/backend/src/main/java/com/algobuddy/backend/config/resolver/CurrentUserIdArgumentResolver.java
new file mode 100644
index 000000000..aaf97757e
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/config/resolver/CurrentUserIdArgumentResolver.java
@@ -0,0 +1,38 @@
+package com.algobuddy.backend.config.resolver;
+
+import com.algobuddy.backend.config.annotation.CurrentUserId;
+import org.springframework.core.MethodParameter;
+import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.oauth2.jwt.Jwt;
+import org.springframework.web.bind.support.WebDataBinderFactory;
+import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.method.support.ModelAndViewContainer;
+
+import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
+
+import java.util.UUID;
+
+public class CurrentUserIdArgumentResolver implements HandlerMethodArgumentResolver {
+
+ @Override
+ public boolean supportsParameter(@NonNull MethodParameter parameter) {
+ return parameter.getParameterAnnotation(CurrentUserId.class) != null
+ && parameter.getParameterType().equals(UUID.class);
+ }
+
+ @Override
+ public Object resolveArgument(@NonNull MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
+ @NonNull NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+ if (authentication == null || !(authentication.getPrincipal() instanceof Jwt jwt)) {
+ throw new AuthenticationCredentialsNotFoundException("User is not authenticated");
+ }
+
+ return UUID.fromString(jwt.getSubject());
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/controller/ArenaController.java b/backend/src/main/java/com/algobuddy/backend/controller/ArenaController.java
new file mode 100644
index 000000000..ab1555584
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/controller/ArenaController.java
@@ -0,0 +1,73 @@
+package com.algobuddy.backend.controller;
+
+import com.algobuddy.backend.config.annotation.CurrentUserId;
+import com.algobuddy.backend.dto.ArenaProfileResponse;
+import com.algobuddy.backend.dto.InitMatchRequest;
+import com.algobuddy.backend.service.ArenaService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.UUID;
+
+@RestController
+@RequestMapping("/api/v1/arena")
+@RequiredArgsConstructor
+@Tag(name = "Arena", description = "Endpoints for multiplayer coding arena, matchmaking, and leaderboards")
+public class ArenaController {
+
+ private final ArenaService arenaService;
+
+ @GetMapping("/profile")
+ @Operation(summary = "Get user arena profile", description = "Retrieves the arena statistics and rating for the authenticated user.")
+ @ApiResponse(responseCode = "200", description = "Successfully retrieved profile")
+ public ResponseEntity getProfile(@CurrentUserId UUID userId) {
+ return ResponseEntity.ok(arenaService.getProfile(userId));
+ }
+
+ @GetMapping("/leaderboard")
+ @Operation(summary = "Get arena leaderboard", description = "Retrieves the top ranked users in the arena.")
+ @ApiResponse(responseCode = "200", description = "Successfully retrieved leaderboard")
+ public ResponseEntity> getLeaderboard() {
+ return ResponseEntity.ok(arenaService.getLeaderboard());
+ }
+
+ @GetMapping("/history")
+ @Operation(summary = "Get match history", description = "Retrieves the past arena matches for the authenticated user.")
+ @ApiResponse(responseCode = "200", description = "Successfully retrieved match history")
+ public ResponseEntity> getMatchHistory(@CurrentUserId UUID userId) {
+ return ResponseEntity.ok(arenaService.getMatchHistory(userId));
+ }
+
+ @GetMapping("/daily-challenge")
+ @Operation(summary = "Get daily challenge", description = "Retrieves the daily coding challenge for the arena.")
+ @ApiResponse(responseCode = "200", description = "Successfully retrieved daily challenge")
+ public ResponseEntity getDailyChallenge() {
+ return ResponseEntity.ok(arenaService.getDailyChallenge());
+ }
+
+ @PostMapping("/match/init")
+ @Operation(summary = "Initialize match", description = "Creates a match record before the duel begins. Must be called when both players are matched.")
+ @ApiResponse(responseCode = "200", description = "Match initialized successfully")
+ public ResponseEntity initMatch(@CurrentUserId UUID userId, @Valid @RequestBody InitMatchRequest request) {
+ arenaService.initMatch(userId, request);
+ return ResponseEntity.ok("Match initialized successfully");
+ }
+
+ @PostMapping("/match-result")
+ @Operation(summary = "Record match result", description = "Records the outcome of an arena match.")
+ @ApiResponse(responseCode = "200", description = "Match result recorded successfully")
+ public ResponseEntity recordMatchResult(@CurrentUserId UUID userId, @Valid @RequestBody com.algobuddy.backend.dto.RecordMatchRequest request) {
+ arenaService.recordMatchResult(userId, request);
+ return ResponseEntity.ok("Match result recorded successfully");
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/controller/BookmarkController.java b/backend/src/main/java/com/algobuddy/backend/controller/BookmarkController.java
new file mode 100644
index 000000000..da481b774
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/controller/BookmarkController.java
@@ -0,0 +1,60 @@
+package com.algobuddy.backend.controller;
+
+import com.algobuddy.backend.config.annotation.CurrentUserId;
+import com.algobuddy.backend.dto.BookmarkDto;
+import com.algobuddy.backend.dto.BookmarkRequestDto;
+import com.algobuddy.backend.entity.Bookmark;
+import com.algobuddy.backend.mapper.BookmarkMapper;
+import com.algobuddy.backend.service.BookmarkService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.UUID;
+
+@RestController
+@RequestMapping("/api/v1/bookmarks")
+@RequiredArgsConstructor
+@Validated
+@Tag(name = "Bookmarks", description = "Endpoints for managing user bookmarks")
+public class BookmarkController {
+
+ private final BookmarkService bookmarkService;
+ private final BookmarkMapper bookmarkMapper;
+
+ @GetMapping
+ @Operation(summary = "Get bookmarks", description = "Retrieves a list of bookmarks for the authenticated user.")
+ @ApiResponse(responseCode = "200", description = "Successfully retrieved bookmarks")
+ public ResponseEntity> getBookmarks(@CurrentUserId UUID userId) {
+ List bookmarks = bookmarkService.getBookmarks(userId);
+ List dtos = bookmarks.stream()
+ .map(bookmarkMapper::toDto)
+ .toList();
+ return ResponseEntity.ok(dtos);
+ }
+
+ @PostMapping
+ @Operation(summary = "Add bookmark", description = "Adds a new bookmark for the authenticated user.")
+ @ApiResponse(responseCode = "200", description = "Successfully added bookmark")
+ public ResponseEntity addBookmark(@CurrentUserId UUID userId,
+ @Valid @RequestBody BookmarkRequestDto request) {
+ bookmarkService.addBookmark(userId, request.getProblemId(), request.getTopicSlug());
+ return ResponseEntity.ok().build();
+ }
+
+ @DeleteMapping
+ @Operation(summary = "Remove bookmark", description = "Removes a specific bookmark for the authenticated user.")
+ @ApiResponse(responseCode = "200", description = "Successfully removed bookmark")
+ public ResponseEntity removeBookmark(@CurrentUserId UUID userId,
+ @NotBlank(message = "problemId cannot be empty") @RequestParam String problemId) {
+ bookmarkService.removeBookmark(userId, problemId);
+ return ResponseEntity.ok().build();
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/controller/GlobalExceptionHandler.java b/backend/src/main/java/com/algobuddy/backend/controller/GlobalExceptionHandler.java
new file mode 100644
index 000000000..df5572b56
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/controller/GlobalExceptionHandler.java
@@ -0,0 +1,106 @@
+package com.algobuddy.backend.controller;
+
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatusCode;
+import org.springframework.web.context.request.WebRequest;
+import jakarta.validation.ConstraintViolationException;
+import org.springframework.lang.NonNull;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import jakarta.persistence.EntityNotFoundException;
+import org.springframework.orm.ObjectOptimisticLockingFailureException;
+import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@RestControllerAdvice
+public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
+
+ private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+ @Override
+ protected ResponseEntity handleMethodArgumentNotValid(@NonNull MethodArgumentNotValidException ex, @NonNull HttpHeaders headers, @NonNull HttpStatusCode status, @NonNull WebRequest request) {
+ Map errors = new HashMap<>();
+ ex.getBindingResult().getFieldErrors().forEach(error ->
+ errors.put(error.getField(), error.getDefaultMessage()));
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors);
+ }
+
+ @ExceptionHandler(ConstraintViolationException.class)
+ public ResponseEntity> handleConstraintViolationException(ConstraintViolationException ex) {
+ Map response = new HashMap<>();
+ response.put("error", "Validation failed: " + ex.getMessage());
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
+ }
+
+ @ExceptionHandler(DataIntegrityViolationException.class)
+ public ResponseEntity> handleDataIntegrityViolation(DataIntegrityViolationException ex) {
+ Map response = new HashMap<>();
+ response.put("error", "Data integrity violation. A conflict occurred, likely due to a duplicate entry.");
+ return ResponseEntity.status(HttpStatus.CONFLICT).body(response);
+ }
+
+ @ExceptionHandler(AuthenticationCredentialsNotFoundException.class)
+ public ResponseEntity> handleAuthenticationCredentialsNotFound(AuthenticationCredentialsNotFoundException ex) {
+ Map response = new HashMap<>();
+ response.put("error", "Authentication required. Please log in.");
+ return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
+ }
+
+ @ExceptionHandler(EntityNotFoundException.class)
+ public ResponseEntity> handleEntityNotFoundException(EntityNotFoundException ex) {
+ Map response = new HashMap<>();
+ response.put("error", "Resource not found.");
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
+ }
+
+ @ExceptionHandler(ObjectOptimisticLockingFailureException.class)
+ public ResponseEntity> handleOptimisticLockingFailure(ObjectOptimisticLockingFailureException ex) {
+ Map response = new HashMap<>();
+ response.put("error", "Conflict: The resource was updated by another request. Please try again.");
+ return ResponseEntity.status(HttpStatus.CONFLICT).body(response);
+ }
+
+ @ExceptionHandler(IllegalArgumentException.class)
+ public ResponseEntity> handleIllegalArgumentException(IllegalArgumentException ex) {
+ Map response = new HashMap<>();
+ response.put("error", ex.getMessage());
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
+ }
+
+ @ExceptionHandler(IllegalStateException.class)
+ public ResponseEntity> handleIllegalStateException(IllegalStateException ex) {
+ Map response = new HashMap<>();
+ response.put("error", ex.getMessage());
+ HttpStatus status = HttpStatus.BAD_REQUEST;
+ if (ex.getMessage() != null && ex.getMessage().toLowerCase().contains("rate limit")) {
+ status = HttpStatus.TOO_MANY_REQUESTS;
+ }
+ return ResponseEntity.status(status).body(response);
+ }
+
+ @ExceptionHandler(SecurityException.class)
+ public ResponseEntity> handleSecurityException(SecurityException ex) {
+ Map response = new HashMap<>();
+ response.put("error", ex.getMessage());
+ return ResponseEntity.status(HttpStatus.FORBIDDEN).body(response);
+ }
+
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity> handleGenericException(Exception ex) {
+ log.error("Unhandled exception occurred: ", ex);
+ Map response = new HashMap<>();
+ response.put("error", "An internal server error occurred.");
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/controller/LeaderboardController.java b/backend/src/main/java/com/algobuddy/backend/controller/LeaderboardController.java
new file mode 100644
index 000000000..92258b39b
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/controller/LeaderboardController.java
@@ -0,0 +1,32 @@
+package com.algobuddy.backend.controller;
+
+import com.algobuddy.backend.dto.LeaderboardEntryDto;
+import com.algobuddy.backend.service.LeaderboardService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/v1/leaderboard")
+@RequiredArgsConstructor
+@Tag(name = "Leaderboard", description = "Endpoints for fetching global leaderboards")
+public class LeaderboardController {
+
+ private final LeaderboardService leaderboardService;
+
+ @GetMapping("/global/streak")
+ @Operation(summary = "Global streak leaderboard", description = "Top users by streak")
+ public ResponseEntity> getGlobalStreak() {
+ return ResponseEntity.ok(leaderboardService.getGlobalStreakLeaderboard());
+ }
+
+ @GetMapping("/global/arena")
+ @Operation(summary = "Global arena leaderboard", description = "Top users by ELO rating")
+ public ResponseEntity> getGlobalArena() {
+ return ResponseEntity.ok(leaderboardService.getGlobalArenaLeaderboard());
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/controller/MySheetController.java b/backend/src/main/java/com/algobuddy/backend/controller/MySheetController.java
new file mode 100644
index 000000000..1f6d5321d
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/controller/MySheetController.java
@@ -0,0 +1,93 @@
+package com.algobuddy.backend.controller;
+
+import com.algobuddy.backend.config.annotation.CurrentUserId;
+import com.algobuddy.backend.dto.MySheetDto;
+import com.algobuddy.backend.dto.MySheetRequestDto;
+import com.algobuddy.backend.dto.MySheetResponseDto;
+import com.algobuddy.backend.entity.MySheet;
+import com.algobuddy.backend.mapper.MySheetMapper;
+import com.algobuddy.backend.service.MySheetService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/v1/mysheet")
+@RequiredArgsConstructor
+@Validated
+@Tag(name = "My Sheet", description = "Endpoints for managing user's personal coding sheet")
+public class MySheetController {
+
+ private final MySheetService mySheetService;
+ private final MySheetMapper mySheetMapper;
+
+ @GetMapping
+ @Operation(summary = "Get my sheet items", description = "Retrieves a list of items in the user's personal sheet.")
+ @ApiResponse(responseCode = "200", description = "Successfully retrieved sheet items")
+ public ResponseEntity getMySheet(@CurrentUserId UUID userId) {
+ List sheetItems = mySheetService.getMySheet(userId);
+ List dtos = sheetItems.stream()
+ .map(mySheetMapper::toDto)
+ .toList();
+ return ResponseEntity.ok(MySheetResponseDto.builder().items(dtos).build());
+ }
+
+ @PostMapping
+ @Operation(summary = "Add to sheet", description = "Adds a problem to the user's personal sheet.")
+ @ApiResponse(responseCode = "200", description = "Successfully added to sheet")
+ public ResponseEntity addToSheet(@CurrentUserId UUID userId,
+ @Valid @RequestBody MySheetRequestDto request) {
+ mySheetService.addToSheet(userId, request.getProblemId(), request.getNote(), request.getIsPublic(), request.getSharedNotes());
+ return ResponseEntity.ok().build();
+ }
+
+ @PatchMapping("/{problemId}/visibility")
+ @Operation(summary = "Update sheet item visibility", description = "Updates the public visibility and shared-notes flag of a sheet item.")
+ @ApiResponse(responseCode = "200", description = "Successfully updated visibility")
+ public ResponseEntity updateVisibility(@CurrentUserId UUID userId,
+ @PathVariable String problemId,
+ @RequestBody java.util.Map body) {
+ Boolean sharedNotes = body.get("sharedNotes");
+ mySheetService.updateVisibility(userId, problemId, body.getOrDefault("isPublic", false), sharedNotes);
+ return ResponseEntity.ok().build();
+ }
+
+ @DeleteMapping
+ @Operation(summary = "Remove from sheet", description = "Removes a problem from the user's personal sheet.")
+ @ApiResponse(responseCode = "200", description = "Successfully removed from sheet")
+ public ResponseEntity removeFromSheet(@CurrentUserId UUID userId,
+ @NotBlank(message = "problemId cannot be empty") @RequestParam String problemId) {
+ mySheetService.removeFromSheet(userId, problemId);
+ return ResponseEntity.ok().build();
+ }
+
+ @GetMapping("/shared/{userId}")
+ @Operation(summary = "Get shared sheet", description = "Retrieves the public sheet items for a given user ID.")
+ @ApiResponse(responseCode = "200", description = "Successfully retrieved shared sheet items")
+ public ResponseEntity getSharedSheet(@PathVariable UUID userId) {
+ List items = mySheetService.getSharedSheet(userId);
+ List dtos = items.stream()
+ .map(mySheetMapper::toDto)
+ .peek(dto -> { if (!dto.isSharedNotes()) dto.setNote(null); })
+ .collect(Collectors.toList());
+ return ResponseEntity.ok(MySheetResponseDto.builder().items(dtos).build());
+ }
+
+ @PostMapping("/clone/{sharedUserId}")
+ @Operation(summary = "Clone shared sheet", description = "Clones a shared sheet into the authenticated user's sheet.")
+ @ApiResponse(responseCode = "200", description = "Successfully cloned sheet")
+ public ResponseEntity cloneSharedSheet(@CurrentUserId UUID userId, @PathVariable UUID sharedUserId) {
+ mySheetService.cloneSheet(sharedUserId, userId);
+ return ResponseEntity.ok().build();
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/controller/PracticeController.java b/backend/src/main/java/com/algobuddy/backend/controller/PracticeController.java
new file mode 100644
index 000000000..382e0b268
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/controller/PracticeController.java
@@ -0,0 +1,52 @@
+package com.algobuddy.backend.controller;
+
+import com.algobuddy.backend.config.annotation.CurrentUserId;
+import com.algobuddy.backend.dto.BulkProgressRequest;
+import com.algobuddy.backend.dto.ProgressRequest;
+import com.algobuddy.backend.dto.ProgressResponse;
+import com.algobuddy.backend.service.PracticeService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import jakarta.validation.Valid;
+import org.springframework.http.ResponseEntity;
+import org.springframework.lang.NonNull;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.UUID;
+@RestController
+@RequestMapping("/api/v1/practice")
+@RequiredArgsConstructor
+@Tag(name = "Practice", description = "Endpoints for user practice progress and statistics")
+public class PracticeController {
+
+ private final PracticeService practiceService;
+
+ @GetMapping("/progress")
+ @Operation(summary = "Get user progress", description = "Retrieves the practice progress and statistics for the authenticated user.")
+ @ApiResponse(responseCode = "200", description = "Successfully retrieved progress")
+ public ResponseEntity getProgress(@CurrentUserId @NonNull UUID userId) {
+ return ResponseEntity.ok(practiceService.getUserProgress(userId));
+ }
+
+ @PostMapping("/progress")
+ @Operation(summary = "Update progress", description = "Updates the progress status of a single practice problem.")
+ @ApiResponse(responseCode = "200", description = "Successfully updated progress")
+ @ApiResponse(responseCode = "400", description = "Invalid request payload")
+ public ResponseEntity updateProgress(@CurrentUserId @NonNull UUID userId,
+ @Valid @RequestBody ProgressRequest request) {
+ ProgressResponse response = practiceService.updateProgress(userId, request);
+ return ResponseEntity.ok(response);
+ }
+
+ @PostMapping("/progress/bulk")
+ @Operation(summary = "Bulk update progress", description = "Updates the progress status of multiple practice problems at once.")
+ @ApiResponse(responseCode = "200", description = "Successfully updated bulk progress")
+ @ApiResponse(responseCode = "400", description = "Invalid request payload")
+ public ResponseEntity bulkUpdateProgress(@CurrentUserId @NonNull UUID userId,
+ @Valid @RequestBody BulkProgressRequest request) {
+ ProgressResponse response = practiceService.bulkUpdateProgress(userId, request);
+ return ResponseEntity.ok(response);
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/controller/UserProfileController.java b/backend/src/main/java/com/algobuddy/backend/controller/UserProfileController.java
new file mode 100644
index 000000000..494dc3c23
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/controller/UserProfileController.java
@@ -0,0 +1,39 @@
+package com.algobuddy.backend.controller;
+
+import com.algobuddy.backend.config.annotation.CurrentUserId;
+import com.algobuddy.backend.dto.UserProfileDto;
+import com.algobuddy.backend.entity.UserProfile;
+import com.algobuddy.backend.service.UserProfileService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.UUID;
+
+@RestController
+@RequestMapping("/api/v1/users/profile")
+@RequiredArgsConstructor
+@Tag(name = "UserProfile", description = "Endpoints for managing user profile cache")
+public class UserProfileController {
+
+ private final UserProfileService userProfileService;
+
+ @PostMapping
+ @Operation(summary = "Upsert user profile", description = "Updates or creates the cached user profile with username and avatar")
+ public ResponseEntity upsertProfile(@CurrentUserId UUID userId, @Valid @RequestBody UserProfileDto dto) {
+ return ResponseEntity.ok(userProfileService.upsertProfile(userId, dto));
+ }
+
+ @GetMapping
+ @Operation(summary = "Get user profile")
+ public ResponseEntity getProfile(@CurrentUserId UUID userId) {
+ UserProfile profile = userProfileService.getProfile(userId);
+ if (profile == null) {
+ return ResponseEntity.notFound().build();
+ }
+ return ResponseEntity.ok(profile);
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/ArenaLeaderboardProjection.java b/backend/src/main/java/com/algobuddy/backend/dto/ArenaLeaderboardProjection.java
new file mode 100644
index 000000000..78fdc943b
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/ArenaLeaderboardProjection.java
@@ -0,0 +1,15 @@
+package com.algobuddy.backend.dto;
+
+import java.util.UUID;
+
+public interface ArenaLeaderboardProjection {
+ UUID getUserId();
+ Integer getXp();
+ Integer getLevel();
+ Integer getRating();
+ Integer getBattlesWon();
+ Integer getBattlesLost();
+ Integer getTotalProblemsSolved();
+ String getName();
+ String getAvatarUrl();
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/ArenaMatchResponse.java b/backend/src/main/java/com/algobuddy/backend/dto/ArenaMatchResponse.java
new file mode 100644
index 000000000..e3ba77524
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/ArenaMatchResponse.java
@@ -0,0 +1,24 @@
+package com.algobuddy.backend.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class ArenaMatchResponse {
+ private UUID id;
+ private String opponentName; // We might just use "Opponent {uuid}" for now since we don't have a joined users table
+ private String topic;
+ private String difficulty;
+ private LocalDateTime startTime;
+ private String result; // "Victory", "Defeat", "Draw", "In Progress"
+ private Integer ratingChange; // The change specific to the requesting user
+ private Integer xpAwarded; // The XP awarded to the requesting user
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/ArenaProfileResponse.java b/backend/src/main/java/com/algobuddy/backend/dto/ArenaProfileResponse.java
new file mode 100644
index 000000000..1cb1a9cb3
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/ArenaProfileResponse.java
@@ -0,0 +1,29 @@
+package com.algobuddy.backend.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.UUID;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class ArenaProfileResponse implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private UUID userId;
+ private Integer xp;
+ private Integer level;
+ private Integer rating;
+ private Integer battlesWon;
+ private Integer battlesLost;
+ private Integer totalProblemsSolved;
+ private Integer rank; // Calculated rank compared to others
+ private String name;
+ private String avatarUrl;
+}
+
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/BookmarkDto.java b/backend/src/main/java/com/algobuddy/backend/dto/BookmarkDto.java
new file mode 100644
index 000000000..27d45d7f9
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/BookmarkDto.java
@@ -0,0 +1,17 @@
+package com.algobuddy.backend.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.time.OffsetDateTime;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BookmarkDto {
+ private String problemId;
+ private String topicSlug;
+ private OffsetDateTime createdAt;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/BookmarkRequestDto.java b/backend/src/main/java/com/algobuddy/backend/dto/BookmarkRequestDto.java
new file mode 100644
index 000000000..0f7d75c16
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/BookmarkRequestDto.java
@@ -0,0 +1,18 @@
+package com.algobuddy.backend.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import jakarta.validation.constraints.NotBlank;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BookmarkRequestDto {
+ @NotBlank(message = "problemId is required")
+ private String problemId;
+ @NotBlank(message = "topicSlug is required")
+ private String topicSlug;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/BulkProgressRequest.java b/backend/src/main/java/com/algobuddy/backend/dto/BulkProgressRequest.java
new file mode 100644
index 000000000..4c238a47b
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/BulkProgressRequest.java
@@ -0,0 +1,32 @@
+package com.algobuddy.backend.dto;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+import java.util.List;
+import lombok.Data;
+
+@Data
+public class BulkProgressRequest {
+
+ @Valid
+ @NotEmpty(message = "items cannot be empty")
+ @Size(max = 100, message = "Bulk update limited to 100 items per request")
+ private List- items;
+
+ @Pattern(regexp = "^\\d{4}-\\d{2}-\\d{2}$", message = "Invalid date format. Must be YYYY-MM-DD")
+ private String localDate;
+
+ @Data
+ public static class Item {
+ @NotBlank(message = "problemId is required")
+ private String problemId;
+
+ @NotBlank(message = "status is required")
+ @Pattern(regexp = "^(Completed|In Progress|Attempted|Bookmarked)$",
+ message = "Invalid status. Must be one of: Completed, In Progress, Attempted, Bookmarked")
+ private String status;
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/DailyChallengeResponse.java b/backend/src/main/java/com/algobuddy/backend/dto/DailyChallengeResponse.java
new file mode 100644
index 000000000..355e83cdc
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/DailyChallengeResponse.java
@@ -0,0 +1,20 @@
+package com.algobuddy.backend.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DailyChallengeResponse {
+ private String id;
+ private String title;
+ private String description;
+ private String difficulty;
+ private String topic;
+ private int xpAward;
+ private String practiceUrl;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/InitMatchRequest.java b/backend/src/main/java/com/algobuddy/backend/dto/InitMatchRequest.java
new file mode 100644
index 000000000..0d9de92e3
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/InitMatchRequest.java
@@ -0,0 +1,19 @@
+package com.algobuddy.backend.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import jakarta.validation.constraints.NotBlank;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class InitMatchRequest {
+ @NotBlank(message = "matchId is required")
+ private String matchId;
+
+ private String topic;
+ private String difficulty;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/LeaderboardEntryDto.java b/backend/src/main/java/com/algobuddy/backend/dto/LeaderboardEntryDto.java
new file mode 100644
index 000000000..952b85f58
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/LeaderboardEntryDto.java
@@ -0,0 +1,20 @@
+package com.algobuddy.backend.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.UUID;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class LeaderboardEntryDto {
+ private int rank;
+ private UUID userId;
+ private String username;
+ private String avatarUrl;
+ private int score;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/MySheetDto.java b/backend/src/main/java/com/algobuddy/backend/dto/MySheetDto.java
new file mode 100644
index 000000000..35a58e802
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/MySheetDto.java
@@ -0,0 +1,19 @@
+package com.algobuddy.backend.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.time.OffsetDateTime;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MySheetDto {
+ private String problemId;
+ private String note;
+ private boolean isPublic;
+ private boolean sharedNotes;
+ private OffsetDateTime addedAt;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/MySheetRequestDto.java b/backend/src/main/java/com/algobuddy/backend/dto/MySheetRequestDto.java
new file mode 100644
index 000000000..c90bec3a4
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/MySheetRequestDto.java
@@ -0,0 +1,19 @@
+package com.algobuddy.backend.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import jakarta.validation.constraints.NotBlank;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MySheetRequestDto {
+ @NotBlank(message = "problemId is required")
+ private String problemId;
+ private String note;
+ private Boolean isPublic;
+ private Boolean sharedNotes;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/MySheetResponseDto.java b/backend/src/main/java/com/algobuddy/backend/dto/MySheetResponseDto.java
new file mode 100644
index 000000000..37b6adbed
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/MySheetResponseDto.java
@@ -0,0 +1,15 @@
+package com.algobuddy.backend.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.util.List;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MySheetResponseDto {
+ private List
items;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/ProgressRequest.java b/backend/src/main/java/com/algobuddy/backend/dto/ProgressRequest.java
new file mode 100644
index 000000000..2c209d401
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/ProgressRequest.java
@@ -0,0 +1,17 @@
+package com.algobuddy.backend.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Pattern;
+import lombok.Data;
+
+@Data
+public class ProgressRequest {
+ @NotBlank(message = "problemId is required")
+ private String problemId;
+ @NotBlank(message = "status is required")
+ @Pattern(regexp = "^(Completed|In Progress|Attempted|Bookmarked)$",
+ message = "Invalid status. Must be one of: Completed, In Progress, Attempted, Bookmarked")
+ private String status;
+
+ private String localDate;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/ProgressResponse.java b/backend/src/main/java/com/algobuddy/backend/dto/ProgressResponse.java
new file mode 100644
index 000000000..ccf2d8d34
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/ProgressResponse.java
@@ -0,0 +1,30 @@
+package com.algobuddy.backend.dto;
+
+import lombok.Data;
+import lombok.Builder;
+
+import java.util.Map;
+
+@Data
+@Builder
+public class ProgressResponse {
+ private Map progress;
+ private Integer currentStreak;
+ private Integer longestStreak;
+ private Integer visualizedCount;
+ private Integer dailySolved;
+ private Integer weeklySolved;
+ private Integer monthlySolved;
+
+ @Data
+ public static class ProgressDetail {
+ private String status;
+ private java.time.OffsetDateTime updatedAt;
+
+ public ProgressDetail() {}
+ public ProgressDetail(String status, java.time.OffsetDateTime updatedAt) {
+ this.status = status;
+ this.updatedAt = updatedAt;
+ }
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/RecordMatchRequest.java b/backend/src/main/java/com/algobuddy/backend/dto/RecordMatchRequest.java
new file mode 100644
index 000000000..09e36778e
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/RecordMatchRequest.java
@@ -0,0 +1,24 @@
+package com.algobuddy.backend.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RecordMatchRequest {
+
+ @NotBlank(message = "Match ID is required to prevent duplicates")
+ private String matchId;
+ private String topic;
+ private String difficulty;
+
+ @JsonProperty("isWinner")
+ private boolean isWinner;
+}
+
diff --git a/backend/src/main/java/com/algobuddy/backend/dto/UserProfileDto.java b/backend/src/main/java/com/algobuddy/backend/dto/UserProfileDto.java
new file mode 100644
index 000000000..8bb92009e
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/dto/UserProfileDto.java
@@ -0,0 +1,11 @@
+package com.algobuddy.backend.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+@Data
+public class UserProfileDto {
+ @NotBlank
+ private String username;
+ private String avatarUrl;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/entity/ArenaMatch.java b/backend/src/main/java/com/algobuddy/backend/entity/ArenaMatch.java
new file mode 100644
index 000000000..bcb1fde26
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/entity/ArenaMatch.java
@@ -0,0 +1,77 @@
+package com.algobuddy.backend.entity;
+
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+@Entity
+@Table(name = "arena_matches", uniqueConstraints = @UniqueConstraint(columnNames = "match_id"))
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class ArenaMatch {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.UUID)
+ @Column(name = "id", updatable = false, nullable = false)
+ private UUID id;
+
+ @Column(name = "match_id", unique = true)
+ private String matchId;
+
+ @Column(name = "player1_id", nullable = false)
+ private UUID player1Id;
+
+ @Column(name = "player2_id", nullable = false)
+ private UUID player2Id;
+
+ @Column(name = "winner_id")
+ private UUID winnerId; // Null if it was a draw or hasn't finished
+
+ @Column(name = "topic")
+ private String topic;
+
+ @Column(name = "difficulty")
+ private String difficulty;
+
+ @Column(name = "start_time", nullable = false)
+ private LocalDateTime startTime;
+
+ @Column(name = "end_time")
+ private LocalDateTime endTime;
+
+ @Column(name = "rating_change_p1")
+ private Integer ratingChangeP1;
+
+ @Column(name = "rating_change_p2")
+ private Integer ratingChangeP2;
+
+ @Column(name = "xp_awarded_p1")
+ private Integer xpAwardedP1;
+
+ @Column(name = "xp_awarded_p2")
+ private Integer xpAwardedP2;
+
+ @Builder.Default
+ @Enumerated(EnumType.STRING)
+ @Column(name = "status", nullable = false)
+ private MatchStatus status = MatchStatus.PENDING;
+
+ @Version
+ @Builder.Default
+ @Column(name = "version")
+ private Integer version = 0;
+
+ public enum MatchStatus {
+ PENDING,
+ ACTIVE,
+ COMPLETED,
+ EXPIRED
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/entity/Bookmark.java b/backend/src/main/java/com/algobuddy/backend/entity/Bookmark.java
new file mode 100644
index 000000000..44ab92ab1
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/entity/Bookmark.java
@@ -0,0 +1,30 @@
+package com.algobuddy.backend.entity;
+
+import jakarta.persistence.*;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.time.OffsetDateTime;
+import java.util.UUID;
+
+@Entity
+@Table(name = "problem_bookmarks", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "problem_id"})})
+@Data
+@NoArgsConstructor
+public class Bookmark {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.UUID)
+ private UUID id;
+
+ @Column(name = "user_id", nullable = false)
+ private UUID userId;
+
+ @Column(name = "problem_id", nullable = false)
+ private String problemId;
+
+ @Column(name = "topic_slug", nullable = false)
+ private String topicSlug;
+
+ @Column(name = "created_at", insertable = false, updatable = false)
+ private OffsetDateTime createdAt;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/entity/MySheet.java b/backend/src/main/java/com/algobuddy/backend/entity/MySheet.java
new file mode 100644
index 000000000..872765bf0
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/entity/MySheet.java
@@ -0,0 +1,36 @@
+package com.algobuddy.backend.entity;
+
+import jakarta.persistence.*;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.time.OffsetDateTime;
+import java.util.UUID;
+
+@Entity
+@Table(name = "my_sheet", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "problem_id"})})
+@Data
+@NoArgsConstructor
+public class MySheet {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.UUID)
+ private UUID id;
+
+ @Column(name = "user_id", nullable = false)
+ private UUID userId;
+
+ @Column(name = "problem_id", nullable = false)
+ private String problemId;
+
+ @Column(name = "note")
+ private String note;
+
+ @Column(name = "is_public", nullable = false)
+ private boolean isPublic = false;
+
+ @Column(name = "shared_notes", nullable = false)
+ private boolean sharedNotes = false;
+
+ @Column(name = "added_at", insertable = false, updatable = false)
+ private OffsetDateTime addedAt;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/entity/UserArenaProfile.java b/backend/src/main/java/com/algobuddy/backend/entity/UserArenaProfile.java
new file mode 100644
index 000000000..c79a4ba42
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/entity/UserArenaProfile.java
@@ -0,0 +1,65 @@
+package com.algobuddy.backend.entity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import jakarta.persistence.Version;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.UUID;
+
+@Entity
+@Table(name = "user_arena_profiles")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class UserArenaProfile {
+
+ @Id
+ @Column(name = "user_id", columnDefinition = "uuid", updatable = false, nullable = false)
+ private UUID userId;
+
+ @Column(name = "xp", nullable = false)
+ @Builder.Default
+ private Integer xp = 0;
+
+ @Column(name = "level", nullable = false)
+ @Builder.Default
+ private Integer level = 1;
+
+ @Column(name = "rating", nullable = false)
+ @Builder.Default
+ private Integer rating = 1200;
+
+ @Column(name = "battles_won", nullable = false)
+ @Builder.Default
+ private Integer battlesWon = 0;
+
+ @Column(name = "battles_lost", nullable = false)
+ @Builder.Default
+ private Integer battlesLost = 0;
+
+ @Column(name = "total_problems_solved", nullable = false)
+ @Builder.Default
+ private Integer totalProblemsSolved = 0;
+
+ @Version
+ @Column(name = "version")
+ private Integer version;
+
+ public void addXp(int amount) {
+ this.xp += amount;
+ updateLevel();
+ }
+
+ private void updateLevel() {
+ // Simple level logic: Level 1 = 0 XP, Level 2 = 100 XP, Level 3 = 300 XP, etc.
+ // For now, level = (xp / 1000) + 1
+ this.level = (this.xp / 1000) + 1;
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/entity/UserPracticeStats.java b/backend/src/main/java/com/algobuddy/backend/entity/UserPracticeStats.java
new file mode 100644
index 000000000..751603fb3
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/entity/UserPracticeStats.java
@@ -0,0 +1,49 @@
+package com.algobuddy.backend.entity;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import jakarta.persistence.Column;
+import jakarta.persistence.Version;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.AllArgsConstructor;
+import java.util.UUID;
+import java.time.LocalDate;
+
+@Entity
+@Table(name = "user_practice_stats")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class UserPracticeStats {
+
+ @Id
+ @Column(name = "user_id", columnDefinition = "uuid")
+ private UUID userId;
+
+ @Column(name = "current_streak")
+ private Integer currentStreak = 0;
+
+ @Column(name = "longest_streak")
+ private Integer longestStreak = 0;
+
+ @Column(name = "last_active_date")
+ private LocalDate lastActiveDate;
+
+ @Column(name = "visualized_count")
+ private Integer visualizedCount = 0;
+
+ @Version
+ @Column(name = "version")
+ private Integer version = 0;
+
+ public UserPracticeStats(UUID userId, Integer currentStreak, Integer longestStreak, LocalDate lastActiveDate, Integer visualizedCount) {
+ this.userId = userId;
+ this.currentStreak = currentStreak;
+ this.longestStreak = longestStreak;
+ this.lastActiveDate = lastActiveDate;
+ this.visualizedCount = visualizedCount;
+ this.version = 0;
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/entity/UserProfile.java b/backend/src/main/java/com/algobuddy/backend/entity/UserProfile.java
new file mode 100644
index 000000000..c8b26ce2d
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/entity/UserProfile.java
@@ -0,0 +1,34 @@
+package com.algobuddy.backend.entity;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import jakarta.persistence.Column;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import java.util.UUID;
+import java.time.OffsetDateTime;
+
+@Entity
+@Table(name = "user_profiles")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class UserProfile {
+
+ @Id
+ @Column(name = "user_id", columnDefinition = "uuid")
+ private UUID userId;
+
+ @Column(name = "username", nullable = false)
+ private String username;
+
+ @Column(name = "avatar_url")
+ private String avatarUrl;
+
+ @Column(name = "updated_at")
+ private OffsetDateTime updatedAt;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/entity/UserProgress.java b/backend/src/main/java/com/algobuddy/backend/entity/UserProgress.java
new file mode 100644
index 000000000..37f4dcc34
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/entity/UserProgress.java
@@ -0,0 +1,36 @@
+package com.algobuddy.backend.entity;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
+import jakarta.persistence.Column;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.AllArgsConstructor;
+import java.util.UUID;
+import java.time.OffsetDateTime;
+
+@Entity
+@Table(name = "user_progress", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "problem_id"})})
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class UserProgress {
+
+ @Id
+ @Column(columnDefinition = "uuid")
+ private UUID id = UUID.randomUUID();
+
+ @Column(name = "user_id", nullable = false)
+ private UUID userId;
+
+ @Column(name = "problem_id", nullable = false)
+ private String problemId;
+
+ @Column(name = "status", nullable = false)
+ private String status;
+
+ @Column(name = "updated_at")
+ private OffsetDateTime updatedAt;
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/mapper/BookmarkMapper.java b/backend/src/main/java/com/algobuddy/backend/mapper/BookmarkMapper.java
new file mode 100644
index 000000000..9dfd5a280
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/mapper/BookmarkMapper.java
@@ -0,0 +1,20 @@
+package com.algobuddy.backend.mapper;
+
+import com.algobuddy.backend.dto.BookmarkDto;
+import com.algobuddy.backend.entity.Bookmark;
+import org.springframework.stereotype.Component;
+
+@Component
+public class BookmarkMapper {
+
+ public BookmarkDto toDto(Bookmark bookmark) {
+ if (bookmark == null) {
+ return null;
+ }
+ return BookmarkDto.builder()
+ .problemId(bookmark.getProblemId())
+ .topicSlug(bookmark.getTopicSlug())
+ .createdAt(bookmark.getCreatedAt())
+ .build();
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/mapper/MySheetMapper.java b/backend/src/main/java/com/algobuddy/backend/mapper/MySheetMapper.java
new file mode 100644
index 000000000..b4523b15e
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/mapper/MySheetMapper.java
@@ -0,0 +1,22 @@
+package com.algobuddy.backend.mapper;
+
+import com.algobuddy.backend.dto.MySheetDto;
+import com.algobuddy.backend.entity.MySheet;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MySheetMapper {
+
+ public MySheetDto toDto(MySheet mySheet) {
+ if (mySheet == null) {
+ return null;
+ }
+ return MySheetDto.builder()
+ .problemId(mySheet.getProblemId())
+ .note(mySheet.getNote())
+ .isPublic(mySheet.isPublic())
+ .sharedNotes(mySheet.isSharedNotes())
+ .addedAt(mySheet.getAddedAt())
+ .build();
+ }
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/repository/ArenaMatchRepository.java b/backend/src/main/java/com/algobuddy/backend/repository/ArenaMatchRepository.java
new file mode 100644
index 000000000..1e4c5972a
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/repository/ArenaMatchRepository.java
@@ -0,0 +1,35 @@
+package com.algobuddy.backend.repository;
+
+import com.algobuddy.backend.entity.ArenaMatch;
+import com.algobuddy.backend.entity.ArenaMatch.MatchStatus;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.UUID;
+
+@Repository
+public interface ArenaMatchRepository extends JpaRepository {
+
+ @Query("SELECT m FROM ArenaMatch m WHERE m.player1Id = :userId OR m.player2Id = :userId ORDER BY m.startTime DESC")
+ List findRecentMatchesByUserId(@Param("userId") UUID userId, Pageable pageable);
+
+ java.util.Optional findByMatchId(String matchId);
+
+ boolean existsByMatchId(String matchId);
+
+ @Query("SELECT COUNT(m) FROM ArenaMatch m WHERE (m.player1Id = :userId OR m.player2Id = :userId) AND m.endTime IS NOT NULL AND m.endTime >= :since")
+ long countRecentMatchResultsByUserId(@Param("userId") UUID userId, @Param("since") LocalDateTime since);
+
+ @Query("SELECT COUNT(m) FROM ArenaMatch m WHERE (m.player1Id = :userId OR m.player2Id = :userId) AND m.startTime >= :since")
+ long countRecentInitiationsByUserId(@Param("userId") UUID userId, @Param("since") LocalDateTime since);
+
+ @Modifying
+ @Query("UPDATE ArenaMatch m SET m.status = :status, m.endTime = :now WHERE m.status IN ('PENDING', 'ACTIVE') AND m.startTime < :cutoff")
+ int expireStaleMatches(@Param("cutoff") LocalDateTime cutoff, @Param("status") MatchStatus status, @Param("now") LocalDateTime now);
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/repository/BookmarkRepository.java b/backend/src/main/java/com/algobuddy/backend/repository/BookmarkRepository.java
new file mode 100644
index 000000000..28ca7a0d1
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/repository/BookmarkRepository.java
@@ -0,0 +1,18 @@
+package com.algobuddy.backend.repository;
+
+import com.algobuddy.backend.entity.Bookmark;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+@Repository
+public interface BookmarkRepository extends JpaRepository {
+ Page findByUserId(UUID userId, Pageable pageable);
+ List findByUserId(UUID userId); // Keep list method for compatibility if needed elsewhere
+ Optional findByUserIdAndProblemId(UUID userId, String problemId);
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/repository/MySheetRepository.java b/backend/src/main/java/com/algobuddy/backend/repository/MySheetRepository.java
new file mode 100644
index 000000000..e7aed33d7
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/repository/MySheetRepository.java
@@ -0,0 +1,21 @@
+package com.algobuddy.backend.repository;
+
+import com.algobuddy.backend.entity.MySheet;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+@Repository
+public interface MySheetRepository extends JpaRepository {
+ Page findByUserId(UUID userId, Pageable pageable);
+ List findByUserId(UUID userId);
+ Optional findByUserIdAndProblemId(UUID userId, String problemId);
+ List findByUserIdAndIsPublicTrue(UUID userId);
+ List findByUserIdAndIsPublicTrueAndSharedNotesTrue(UUID userId);
+ List findByUserIdAndProblemIdIn(UUID userId, List problemIds);
+}
diff --git a/backend/src/main/java/com/algobuddy/backend/repository/UserArenaProfileRepository.java b/backend/src/main/java/com/algobuddy/backend/repository/UserArenaProfileRepository.java
new file mode 100644
index 000000000..02c15f22e
--- /dev/null
+++ b/backend/src/main/java/com/algobuddy/backend/repository/UserArenaProfileRepository.java
@@ -0,0 +1,98 @@
+package com.algobuddy.backend.repository;
+
+import com.algobuddy.backend.dto.ArenaLeaderboardProjection;
+import com.algobuddy.backend.entity.UserArenaProfile;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+@Repository
+public interface UserArenaProfileRepository extends JpaRepository {
+
+ @Query(value = "SELECT * FROM user_arena_profiles p WHERE p.user_id != '00000000-0000-0000-0000-000000000000' ORDER BY p.rating DESC, p.xp DESC", nativeQuery = true)
+ List findTopPlayers(Pageable pageable);
+
+ @Query(value = """
+ SELECT
+ p.user_id as userId,
+ p.xp as xp,
+ p.level as level,
+ p.rating as rating,
+ p.battles_won as battlesWon,
+ p.battles_lost as battlesLost,
+ (SELECT COALESCE(COUNT(*), 0) FROM public.user_progress up WHERE up.user_id = p.user_id AND up.status = 'Completed') as totalProblemsSolved,
+ COALESCE(u.raw_user_meta_data->>'name', split_part(u.email, '@', 1)) as name,
+ COALESCE(u.raw_user_meta_data->>'avatar_url', u.raw_user_meta_data->>'picture', '') as avatarUrl
+ FROM public.user_arena_profiles p
+ LEFT JOIN auth.users u ON p.user_id = u.id
+ WHERE p.user_id != '00000000-0000-0000-0000-000000000000'
+ ORDER BY p.rating DESC, p.xp DESC
+ """, nativeQuery = true)
+ List findTopPlayersWithUserDetails(Pageable pageable);
+
+ @Query(value = """
+ SELECT
+ p.user_id as userId,
+ p.xp as xp,
+ p.level as level,
+ p.rating as rating,
+ p.battles_won as battlesWon,
+ p.battles_lost as battlesLost,
+ (SELECT COALESCE(COUNT(*), 0) FROM public.user_progress up WHERE up.user_id = p.user_id AND up.status = 'Completed') as totalProblemsSolved,
+ COALESCE(u.raw_user_meta_data->>'name', split_part(u.email, '@', 1)) as name,
+ COALESCE(u.raw_user_meta_data->>'avatar_url', u.raw_user_meta_data->>'picture', '') as avatarUrl
+ FROM public.user_arena_profiles p
+ LEFT JOIN auth.users u ON p.user_id = u.id
+ WHERE p.user_id = :userId
+ """, nativeQuery = true)
+ Optional findProfileWithUserDetails(@Param("userId") UUID userId);
+
+ @Query(value = """
+ SELECT
+ p.user_id as userId,
+ p.xp as xp,
+ p.level as level,
+ p.rating as rating,
+ p.battles_won as battlesWon,
+ p.battles_lost as battlesLost,
+ p.total_problems_solved as totalProblemsSolved,
+ COALESCE(u.raw_user_meta_data->>'name', split_part(u.email, '@', 1)) as name,
+ COALESCE(u.raw_user_meta_data->>'avatar_url', u.raw_user_meta_data->>'picture', '') as avatarUrl
+ FROM public.user_arena_profiles p
+ LEFT JOIN auth.users u ON p.user_id = u.id
+ WHERE p.user_id IN :userIds
+ """, nativeQuery = true)
+ List findProfilesWithUserDetailsIn(@Param("userIds") List