Files
valgo/app/page.tsx
T
2024-06-29 13:43:07 +02:00

205 lines
6.1 KiB
TypeScript

"use client"
import { useState, useEffect } from "react"
import { Button } from "@/components/ui/button"
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem } from "@/components/ui/dropdown-menu"
import { Slider } from "@/components/ui/slider"
export default function Component() {
const [array, setArray] = useState<number[]>([])
const [isRunning, setIsRunning] = useState(false)
const [currentAlgorithm, setCurrentAlgorithm] = useState("bubble")
const [arraySize, setArraySize] = useState(20)
useEffect(() => {
generateRandomArray(arraySize)
}, [arraySize])
const generateRandomArray = (size: number) => {
const newArray = Array.from({ length: size }, () => Math.floor(Math.random() * 100))
setArray(newArray)
}
const shuffleArray = () => {
const shuffledArray = [...array].sort(() => Math.random() - 0.5)
setArray(shuffledArray)
}
const startAnimation = () => {
setIsRunning(true)
switch (currentAlgorithm) {
case "bubble":
bubbleSort()
break
case "insertion":
insertionSort()
break
case "merge":
mergeSort(array, 0, array.length - 1)
break
default:
break
}
}
const pauseAnimation = () => {
setIsRunning(false)
}
const resetAnimation = () => {
setIsRunning(false)
generateRandomArray(arraySize)
}
const bubbleSort = async () => {
const newArray = [...array]
for (let i = 0; i < newArray.length; i++) {
for (let j = 0; j < newArray.length - i - 1; j++) {
if (newArray[j] > newArray[j + 1]) {
;[newArray[j], newArray[j + 1]] = [newArray[j + 1], newArray[j]]
setArray([...newArray])
await new Promise((resolve) => setTimeout(resolve, 100))
}
}
}
setIsRunning(false)
}
const insertionSort = async () => {
const newArray = [...array]
for (let i = 1; i < newArray.length; i++) {
const key = newArray[i]
let j = i - 1
while (j >= 0 && newArray[j] > key) {
newArray[j + 1] = newArray[j]
j = j - 1
setArray([...newArray])
await new Promise((resolve) => setTimeout(resolve, 100))
}
newArray[j + 1] = key
setArray([...newArray])
await new Promise((resolve) => setTimeout(resolve, 100))
}
setIsRunning(false)
}
const mergeSort = async (arr: number[], left: number, right: number) => {
if (left < right) {
const mid = Math.floor((left + right) / 2)
await mergeSort(arr, left, mid)
await mergeSort(arr, mid + 1, right)
await merge(arr, left, mid, right)
}
}
const merge = async (arr: number[], left: number, mid: number, right: number) => {
const n1 = mid - left + 1
const n2 = right - mid
const leftArr = new Array(n1)
const rightArr = new Array(n2)
for (let i = 0; i < n1; i++) leftArr[i] = arr[left + i]
for (let j = 0; j < n2; j++) rightArr[j] = arr[mid + 1 + j]
let i = 0, j = 0, k = left
while (i < n1 && j < n2) {
if (leftArr[i] <= rightArr[j]) {
arr[k] = leftArr[i]
i++
} else {
arr[k] = rightArr[j]
j++
}
setArray([...arr])
await new Promise((resolve) => setTimeout(resolve, 100))
k++
}
while (i < n1) {
arr[k] = leftArr[i]
i++
k++
setArray([...arr])
await new Promise((resolve) => setTimeout(resolve, 100))
}
while (j < n2) {
arr[k] = rightArr[j]
j++
k++
setArray([...arr])
await new Promise((resolve) => setTimeout(resolve, 100))
}
}
return (
<div className="flex flex-col items-center h-screen">
<header className="bg-primary text-primary-foreground py-4 px-6 w-full">
<h1 className="text-2xl font-bold text-center">Algorithm Visualizer</h1>
</header>
<div className="flex items-end justify-center min-w-max h-64 mt-10 shadow-2xl p-4">
{array.map((value, index) => (
<div
key={index}
className={`mx-0.5 ${isRunning ? 'bg-red-500' : 'bg-blue-500'}`}
style={{height: `${value * 2}px`, width: '20px'}}
></div>
))}
</div>
<div className="flex mt-10 space-x-4">
<Button onClick={startAnimation}>Start</Button>
<Button onClick={pauseAnimation} variant="outline" a>Pause</Button>
<Button onClick={resetAnimation}>Reset</Button>
<Button onClick={shuffleArray}>Shuffle</Button>
<DropdownMenu>
<DropdownMenuTrigger>
{currentAlgorithm.charAt(0).toUpperCase() + currentAlgorithm.slice(1)} Sort
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuRadioGroup
value={currentAlgorithm}
onValueChange={setCurrentAlgorithm}
>
<DropdownMenuRadioItem value="bubble">Bubble Sort</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="insertion">Insertion Sort</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="merge">Merge Sort</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="flex flex-col items-center mt-10 space-y-4">
<label className="text-xl">Array Size: {arraySize}</label>
<Slider
value={[arraySize]}
onValueChange={(value) => setArraySize(value[0])}
min={5}
max={100}
/>
</div>
</div>
)
}
function ArrowUpDownIcon(props) {
return (
<svg
{...props}
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="m21 16-4 4-4-4" />
<path d="M17 20V4" />
<path d="m3 8 4-4 4 4" />
<path d="M7 4v16" />
</svg>
)
}