diff --git a/package-lock.json b/package-lock.json index c952e7e..210d3cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -74,7 +74,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -2454,7 +2453,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "devOptional": true, - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -2464,7 +2462,6 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", "devOptional": true, - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -2500,7 +2497,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2653,7 +2649,6 @@ "url": "https://github.com/sponsors/ai" } ], - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", @@ -2817,8 +2812,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "peer": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/d3-color": { "version": "3.1.0", @@ -2877,7 +2871,6 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -3095,7 +3088,6 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.38.0.tgz", "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", "dev": true, - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4062,7 +4054,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "peer": true, "engines": { "node": ">=12" }, @@ -4088,7 +4079,6 @@ "url": "https://github.com/sponsors/ai" } ], - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -4126,7 +4116,6 @@ "version": "19.2.0", "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4135,7 +4124,6 @@ "version": "19.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -4164,7 +4152,6 @@ "version": "9.2.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", - "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -4315,8 +4302,7 @@ "node_modules/redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", - "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "peer": true + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -4675,7 +4661,6 @@ "version": "7.1.12", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.12.tgz", "integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", diff --git a/src/algorithms/sorting/radixSort.js b/src/algorithms/sorting/radixSort.js new file mode 100644 index 0000000..442cd4a --- /dev/null +++ b/src/algorithms/sorting/radixSort.js @@ -0,0 +1,47 @@ +// src/algorithms/sorting/radixSort.js +export function* radixSort(array) { + const arr = [...array]; + + // Get the maximum number to determine number of digits + const maxNum = Math.max(...arr); + const maxDigits = Math.floor(Math.log10(maxNum)) + 1; + + // Helper function to get digit at a specific place + const getDigit = (num, place) => Math.floor(num / Math.pow(10, place)) % 10; + + // Counting sort for each digit position + for (let place = 0; place < maxDigits; place++) { + const buckets = Array.from({ length: 10 }, () => []); + + // Yield to show current digit pass + yield { type: "digitPassStart", place }; + + // Place each number in corresponding bucket + for (let i = 0; i < arr.length; i++) { + const digit = getDigit(arr[i], place); + buckets[digit].push(arr[i]); + + yield { type: "bucket", digit, value: arr[i], array: [...arr] }; + } + + // Combine buckets back into array + let index = 0; + for (let b = 0; b < 10; b++) { + for (let value of buckets[b]) { + arr[index++] = value; + yield { type: "rebuild", array: [...arr], bucket: b, value }; + } + } + + // Yield after completing sorting by current digit + yield { type: "digitPassEnd", place, array: [...arr] }; + } + + // Mark all elements as sorted + for (let i = 0; i < arr.length; i++) { + yield { type: "sorted", index: i }; + } + + // Final done state + yield { type: "done", array: arr }; +} diff --git a/src/components/sorting/RadixSortVisualizer.jsx b/src/components/sorting/RadixSortVisualizer.jsx new file mode 100644 index 0000000..174e2ff --- /dev/null +++ b/src/components/sorting/RadixSortVisualizer.jsx @@ -0,0 +1,72 @@ +import React from "react"; + +const COLORS = { + default: "bg-blue-500 shadow-[0_0_10px_#3b82f6]", + comparing: "bg-yellow-400 shadow-[0_0_12px_#facc15]", + bucket: "bg-purple-500 shadow-[0_0_12px_#a855f7]", + swap: "bg-red-500 shadow-[0_0_12px_#ef4444]", + sorted: "bg-green-500 shadow-[0_0_12px_#22c55e]", +}; + +export default function RadixSortVisualizer({ array, highlight }) { + const maxValue = Math.max(...array, 1); + const containerHeight = 288; // matches h-72 + + return ( +