From 7a71ea67449ef97cbb2416a225aade77bea73477 Mon Sep 17 00:00:00 2001 From: Bryson Zimmerman Date: Tue, 5 Nov 2024 22:49:03 -0500 Subject: [PATCH] Check in WIP on MinHeap and MazeFinderTest --- src/main/kotlin/Main.kt | 11 +++- src/main/kotlin/data/Heap.kt | 60 --------------------- src/main/kotlin/data/MinHeap.kt | 90 +++++++++++++++++++++++++++++++ src/test/kotlin/MazeFinderTest.kt | 3 +- src/test/kotlin/MinHeapTest.kt | 24 +++++++++ 5 files changed, 126 insertions(+), 62 deletions(-) delete mode 100644 src/main/kotlin/data/Heap.kt create mode 100644 src/main/kotlin/data/MinHeap.kt create mode 100644 src/test/kotlin/MinHeapTest.kt diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index 2be77ab..9c57233 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -1,5 +1,8 @@ package technology.zim +import kotlin.times +import kotlin.toString + /* Adjacency matrix for graph representation. 5k x 5k or 10k x 10k are safe goals, for memory Working with a gigantic grid that's mostly full: better to have a up/right/down/left data in each one or a huge adjacency matrix? @@ -14,6 +17,13 @@ class HierarchicalPathfinding { companion object { @JvmStatic fun main(args: Array) { + + buildMaze() + + + } + + fun buildMaze() { val n = 1000 println("Building world") World.setSize(n, n) @@ -26,7 +36,6 @@ class HierarchicalPathfinding { println(e.message) } val endTime = System.currentTimeMillis() - println(World.toString()) println(n*n) println((endTime - startTime).toString() + "ms") diff --git a/src/main/kotlin/data/Heap.kt b/src/main/kotlin/data/Heap.kt deleted file mode 100644 index 33a018e..0000000 --- a/src/main/kotlin/data/Heap.kt +++ /dev/null @@ -1,60 +0,0 @@ -package technology.zim.data - -class Heap { - private val dat = ArrayList() - - fun popMin(): T { - if(dat.isEmpty()) { - throw ArrayIndexOutOfBoundsException() - } - - val ret = dat.first() - - //TODO: Sift and such - return dat.first() - } - - fun popMax(): T { - if(dat.isEmpty()) { - throw ArrayIndexOutOfBoundsException() - } - - val ret = dat.last() - - return ret - } - - fun insert(value: T) { - dat.add(value) - //TODO: siftUp, siftDown - - } - - private fun siftUp() { - - } - - private fun siftDown() { - - } - - private fun delete() { - - } - - fun peekMax(): T { - if(dat.isEmpty()) { - throw ArrayIndexOutOfBoundsException() - } - - return dat.last() - } - - fun peekMin(): T { - if(dat.isEmpty()) { - throw ArrayIndexOutOfBoundsException() - } - return dat[0] - } - -} \ No newline at end of file diff --git a/src/main/kotlin/data/MinHeap.kt b/src/main/kotlin/data/MinHeap.kt new file mode 100644 index 0000000..d4a5884 --- /dev/null +++ b/src/main/kotlin/data/MinHeap.kt @@ -0,0 +1,90 @@ +package technology.zim.data + +//Translated code from CS222 MaxHeap homework +//Cannot use index 0 due to Integer limitations +class MinHeap() { + val dat = ArrayList(2) + + init { + dat.add(Int.MIN_VALUE) + } + + fun popMin(): Int { + if(dat.isEmpty()) { + throw ArrayIndexOutOfBoundsException() + } + + val ret = dat.first() + dat[1] = dat[dat.size - 1] + siftDown(1) + + return ret + } + + fun insert(value: Int) { + dat.add(value) + siftUp(dat.size - 1) + } + + private fun siftUp(index: kotlin.Int) { + if(dat.isEmpty()) + throw ArrayIndexOutOfBoundsException() + + if(dat[index] < dat[parent(index)] && index > 1) { + swap(index, parent(index)) + siftUp(parent(index)) + } + } + + private fun siftDown(index: Int) { + if(!isLeaf(index)) { + var maxIndex = index + + val l = leftChild(index) + if(dat[l] < dat[index] && leftChild(index) <= dat.size) { + maxIndex = l + } + + val r = rightChild(index) + if(dat[r] < dat[index] && rightChild(index) <= dat.size) { + maxIndex = r + } + + if(maxIndex != index) { + swap(index, maxIndex) + siftDown(maxIndex) + } + } + } + + fun peekMax(): Int { + if(dat.isEmpty()) { + throw ArrayIndexOutOfBoundsException() + } + + return dat.last() + } + + fun peekMin(): Int { + if(dat.isEmpty()) { + throw ArrayIndexOutOfBoundsException() + } + return dat[1] + } + + //Helper functions for navigating the heap + private fun parent(index: kotlin.Int): kotlin.Int = index / 2 + private fun leftChild(index: kotlin.Int): kotlin.Int = index * 2 + private fun rightChild(index: kotlin.Int): kotlin.Int = (index * 2) - 1 + + private fun swap(index1: kotlin.Int, index2: kotlin.Int) { + val index1tmp = dat[index1] + dat[index1] = dat[index2] + dat[index2] = index1tmp + } + + private fun isLeaf(index: Int): Boolean { + return index > (dat.size / 2) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/MazeFinderTest.kt b/src/test/kotlin/MazeFinderTest.kt index e464d67..910fe73 100644 --- a/src/test/kotlin/MazeFinderTest.kt +++ b/src/test/kotlin/MazeFinderTest.kt @@ -1,8 +1,9 @@ import kotlin.test.Test +import kotlin.test.BeforeTest import technology.zim.MazeFinder import technology.zim.World import technology.zim.data.Tile -import kotlin.test.BeforeTest + class MazeFinderTest { diff --git a/src/test/kotlin/MinHeapTest.kt b/src/test/kotlin/MinHeapTest.kt new file mode 100644 index 0000000..f72d45a --- /dev/null +++ b/src/test/kotlin/MinHeapTest.kt @@ -0,0 +1,24 @@ +import technology.zim.data.MinHeap +import kotlin.test.Test +import kotlin.test.BeforeTest + +class MinHeapTest { + companion object { + var heap = MinHeap() + } + @BeforeTest + fun setUp() { + heap = MinHeap() + arrayOf(10, 20, 15, 17, 9, 21).forEach { item -> + heap.insert(item) + } + } + + @Test + fun sortTest() { + arrayOf(9, 10, 15, 17, 20, 21 ).forEach { item -> + println(item) + assert(heap.popMin() == item) + } + } +} \ No newline at end of file