Last active
April 22, 2017 02:21
-
-
Save myndzi/950207f5d531aec1dae9d3804f75b9b6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// values 0 through 6 represent tetris pieces | |
// heap[1] is always the piece that has been seen the | |
// fewest number of times (or is tied with it) | |
heap = [unused, 0, 1, 2, 3, 4, 5, 6] | |
update(piece_id) { | |
// find the piece to update | |
for (ptr = 1; ptr <= 8; ptr++) { | |
if (heap[ptr] & 0x07 == piece_id) break; | |
} | |
if (ptr == 8) { | |
// piece_id was not valid; do nothing | |
return; | |
} | |
if (heap[ptr] >= 0xF8) { | |
// we're at the max possible value, we need to reduce everything | |
// so we have headroom | |
reduce_heap(); | |
} | |
if (heap[ptr] < 0xF8) { | |
// increment seen-count | |
// it's possible that reduce_heap() had no effect, so we have | |
// to check the bounds once more, here | |
heap[ptr] += 8; | |
} else { | |
// we didn't change anything, no need to update heap | |
// optional early exit | |
return; | |
} | |
// update heap | |
// this could be written as an unrolled loop if you have | |
// more instructions available than cycles, since the size | |
// of the heap is bounded -- max swaps will be 2 | |
while (ptr <= 3) { | |
// positions > 3 have no children and can't move down any farther | |
child = heap[2*ptr]; | |
if (heap[child] > heap[child+1]) { | |
// it's a min-heap, so we swap with the smallest child; | |
// children are located at loc*2 and loc*2+1, so we compare | |
// loc*2 (child) with loc*2+1 (child+1), and if child is | |
// larger, we change it to point to child+1 | |
child++; | |
} | |
if (heap[ptr] <= heap[child]) { | |
// ptr is not larger than its children, heap property | |
// is satisfied | |
return; | |
} | |
// swap children (xor swap); using a temp var | |
// might be faster, depending? | |
heap[ptr] = heap[ptr] ^ heap[child]; | |
heap[child] = heap[ptr] ^ heap[child]; | |
heap[ptr] = heap[ptr] ^ heap[child]; | |
// the value we updated (ptr) is now at index child | |
ptr = child; | |
} | |
} | |
reduce_heap() { | |
// chop off the piece value so we only change the count | |
min = heap[1] & 0xF8; | |
if (min == 0) { | |
// nothing to do; optional early exit | |
return; | |
} | |
for (ptr = 1; ptr <= 7; ptr++) { | |
// the heap property guarantees every value is greater than | |
// or equal to the first index (min-heap), so this subtraction | |
// should always result in a count >= 0 | |
heap[ptr] -= min; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MRU list for fun. may not be particularly optimized? | |
// index = piece id, from 0-6; index 7 points to | |
// the head of the list. list[7] is always the | |
// most-recently-seen piece | |
list = [1, 2, 3, 4, 5, 6, 255, 0] | |
update(piece_id) { | |
if (piece_id > 6) { | |
// invalid piece id | |
return; | |
} | |
// find the item in the list that points to piece_id | |
ptr = list[7]; | |
// a for-loop would be safer here, in case the links | |
// got messed up, but this approach should be fewer | |
// cycles? | |
while (list[ptr] != piece_id) { ptr = list[ptr]; } | |
// A->B->C => A->C | |
list[ptr] = list[piece_id]; | |
// B->C => B->X | |
list[piece_id] = list[7]; | |
// HEAD->X => HEAD->B | |
list[7] = piece_id; | |
} | |
get_oldest() { | |
ptr = list[7]; | |
// move the pointer 6 times to get the 7th value | |
for (i = 0; i <= 5; i++) { | |
ptr = list[ptr]; | |
} | |
return ptr; | |
} | |
// or: | |
get_oldest() { | |
ptr = list[7]; | |
ptr = list[ptr]; | |
ptr = list[ptr]; | |
ptr = list[ptr]; | |
ptr = list[ptr]; | |
ptr = list[ptr]; | |
ptr = list[ptr]; | |
return ptr; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment