"use client"; import { useState, useCallback } from "react"; import { Card } from "@/components/ui/card"; import { StepControls } from "./step-controls"; type SortDirection = "ascending" | "descending"; interface Step { label: string; values: { value: number; str: string; sorted: boolean; comparing: boolean }[]; comparingPair?: [number, number]; } function padDecimal(s: string, maxInt: number, maxDec: number): string { const parts = s.split("."); const intPart = (parts[0] || "0").padStart(maxInt, "\u00A0"); // nbsp padding const decPart = (parts[1] || "").padEnd(maxDec, "0"); return maxDec > 0 ? `${intPart}.${decPart}` : intPart; } function buildSortSteps(values: number[], direction: SortDirection): Step[] { const steps: Step[] = []; const strs = values.map((v) => v.toString()); // Find max integer and decimal lengths for alignment const maxInt = Math.max(...strs.map((s) => s.split(".")[0].length)); const maxDec = Math.max(...strs.map((s) => (s.split(".")[1] || "").length)); // Step 0: Show unsorted steps.push({ label: `Sort ${values.length} decimals in ${direction} order`, values: values.map((v, i) => ({ value: v, str: padDecimal(strs[i], maxInt, maxDec), sorted: false, comparing: false, })), }); // Step 1: Show aligned place values steps.push({ label: "Align decimal points to compare place values", values: values.map((v, i) => ({ value: v, str: padDecimal(strs[i], maxInt, maxDec), sorted: false, comparing: false, })), }); // Bubble sort with steps const arr = [...values]; const arrStrs = [...strs]; const cmp = direction === "ascending" ? (a: number, b: number) => a > b : (a: number, b: number) => a < b; for (let i = 0; i < arr.length - 1; i++) { for (let j = 0; j < arr.length - 1 - i; j++) { // Show comparison steps.push({ label: `Compare ${arrStrs[j]} and ${arrStrs[j + 1]}`, values: arr.map((v, k) => ({ value: v, str: padDecimal(arrStrs[k], maxInt, maxDec), sorted: k >= arr.length - i, comparing: k === j || k === j + 1, })), comparingPair: [j, j + 1], }); if (cmp(arr[j], arr[j + 1])) { // Swap [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; [arrStrs[j], arrStrs[j + 1]] = [arrStrs[j + 1], arrStrs[j]]; steps.push({ label: `Swap: ${arrStrs[j]} ${direction === "ascending" ? "<" : ">"} ${arrStrs[j + 1]}`, values: arr.map((v, k) => ({ value: v, str: padDecimal(arrStrs[k], maxInt, maxDec), sorted: k >= arr.length - i, comparing: k === j || k === j + 1, })), }); } } } // Final step: Show sorted steps.push({ label: `Sorted (${direction}): ${arrStrs.join(direction === "ascending" ? " < " : " > ")}`, values: arr.map((v, k) => ({ value: v, str: padDecimal(arrStrs[k], maxInt, maxDec), sorted: true, comparing: false, })), }); return steps; } function NumberLine({ values, min, max }: { values: { value: number; sorted: boolean; comparing: boolean }[]; min: number; max: number }) { const range = max - min || 1; return (
Enter 2-6 decimal numbers (comma separated)
{error}
}Enter decimals above and click Sort
) : ( <>{step.label}
{/* Place value columns */}Result will appear here when steps are complete
) : ( <>Sorted ({direction})
{step!.values.map((v) => v.value).join(direction === "ascending" ? " < " : " > ")}
> )}