more procs for working on faststacks

This commit is contained in:
Joseph Montanaro 2021-07-16 22:43:45 -07:00
parent cd81150e6c
commit 8d889170df

View File

@ -1,4 +1,4 @@
import bitops, strutils
import bitops, strutils, random
proc show(i: SomeInteger, bitlength = 16) =
@ -67,8 +67,7 @@ proc `[]=`(s: var ColorStack, i: uint8 | BackwardsIndex, c: Color) =
iterator items(s: ColorStack): Color =
# s.len is unsigned so it will wrap around if it's 0
# so we will no-op in that case
# s.len is unsigned so it will wrap around if we do s.len - 1 in that case
if s.len != 0:
for i in countdown(s.len - 1, 0'u8):
yield cast[Color]((s.data shr (i * 3)) and masks[1])
@ -81,6 +80,12 @@ iterator pairs(s: ColorStack): (int, Color) =
inc count
proc find(s: ColorStack, needle: Color): uint8 =
for i in 0'u8 .. s.high:
if s[i] == needle:
return i
proc moveSubstack(src, dst: var ColorStack, nToMove: uint8) =
# Moves a sub-stack from the top of src to the top of dst
# shift the dst stack by the length of the substack to make room
@ -109,22 +114,44 @@ proc moveSubstackPre(src, dst: var ColorStack, nToMove: uint8) =
proc swap(s: var ColorStack, i1, i2: uint8) =
# Swap the values at two indices in the stack
# further explanation to follow
if i1 == i2: return
# i1 and i2 are unsigned, so we have to watch out for underflows
let diff = if i1 > i2:
(i1 - i2) * 3
else:
(i2 - i1) * 3
# take masks[1] from above (rightmost position) and shift to position of i1.
# then do the same for i2, and OR them together.
let mask = (masks[1] shl s.offset(i1)) or (masks[1] shl s.offset(i2))
mask.show
# get rid of everything but the two values we're swapping
let masked = s.data and mask
masked.show
let swapped = ((masked shl diff) and mask) or ((masked shr diff) and mask)
swapped.show
s.data = (s.data and bitnot(mask)) or swapped
s.data.show
# shift by the distance between values in both directions, combine, then mask
let swapped = ((masked shl diff) or (masked shr diff)) and mask
# finally, AND with the inverse of mask so that only the values being
# swapped are erased, and combine that with the swapped values
s.data = (s.data and mask.bitnot) or swapped
proc shuffle(r: var Rand, s: var ColorStack) =
# Fisher-Yates shuffle
for i in countdown(s.high, 1'u8):
let j = cast[uint8](r.rand(i))
if j != i:
s.swap(i, j)
proc reverse(s: var ColorStack, first, last: uint8) =
var x = first
var y = last
while x < y:
s.swap(x, y)
inc x
dec y
proc asInt(s: ColorStack): uint16 = s.data
proc `$`(s: ColorStack): string =
@ -137,11 +164,11 @@ proc `$`(s: ColorStack): string =
var one: ColorStack
one.add(cRed)
one.add(cGreen)
one.add(cBlue)
one.add(cYellow)
one.add(cPurple)
one.add(cRed)
var two: ColorStack
# two.add(cPurple)
@ -149,9 +176,9 @@ two.add(cRed)
# two.add(cYellow)
echo "one: ", one
echo "two: ", two
# echo "two: ", two
one.swap(0, 4)
one.reverse(0, 4)
echo "one: ", one
# one[^2] = cPurple
# echo "one: ", one