Skip to content

Instantly share code, notes, and snippets.

@vyo
Last active October 25, 2017 20:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vyo/4c59c9ed8c6516a4ee0609a3bc801fb6 to your computer and use it in GitHub Desktop.
Save vyo/4c59c9ed8c6516a4ee0609a3bc801fb6 to your computer and use it in GitHub Desktop.
Binary Heap for number values (Moonscript)
logE = math.log(2)
logB = (value) ->
if value == 0 do return 1
return math.floor(math.log(value) / logE)
-- implementation of a binary minimum heap
-- use a function closure for instance creation
-- instead of tables
-- this yields us truly private variables and an
-- overall cleaner package
BinaryHeap = () ->
self = {}
data = {}
swap = (indexA, indexB) ->
tmp = data[indexA]
data[indexA] = data[indexB]
data[indexB] = tmp
lessThan = (a, b) ->
if a != nil and b != nil and a < b
return true
else
return false
heapUp = (index) ->
if index == 1
return
parentIndex = (index - (index %2)) / 2
if data[index] < data[parentIndex]
swap(index, parentIndex)
return heapUp(parentIndex)
heapDown = (index) ->
-- we should swap with the smaller child if and only if we're bigger than them
-- if we're not bigger we should swap with the other child if we're bigger than them
-- if that child is a fatty, too, we can end right here =P
-- also, check left first, so we properly fill up empty buckets
left = index * 2
right = left + 1
biggerThanLeft = if lessThan(data[left], data[right]) and lessThan(data[left], data[index]) then true
biggerThanRight = if lessThan(data[right], data[left]) and lessThan(data[right], data[index]) then true
if biggerThanLeft
swap(index, index * 2)
return heapDown(index * 2)
if biggerThanRight
swap(index, (index * 2) + 1)
return heapDown((index * 2) + 1)
self.store = (value) ->
data[#data + 1] = value
heapUp(#data)
self.retrieve = () ->
result = data[1]
data[1] = data[#data]
data[#data] = nil
heapDown(1)
return result
self.read = () ->
return data[1]
self.iterator = () ->
iterator = coroutine.create(() ->
for step = 1, #data - 1
coroutine.yield(data[step])
return #data)
return iterator
self.print = (width) ->
leafWidth = if width == nil then 4 else width
depth = logB(#data)
if #data == 0
print '| (empty) |'
return
level = 0
spacing = ' '
while not (level > depth)
line = ''
for word = 2^level, 2^(level + 1) - 1
bucketWidth = leafWidth * 2^(depth - level)
bucketString = if data[word] == nil then 'x' else ''..data[word]
for i = 1, (bucketWidth - string.len(bucketString))
if i%2 == 0
bucketString = spacing..bucketString
else
bucketString = bucketString..spacing
bucketString = string.sub(bucketString, 1, bucketWidth)
line ..= bucketString
print '|'..line..'|'
level = level + 1
return self
return BinaryHeap
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment