From 8d889170dfeaf3029bb4ea4073b3b071e9151736 Mon Sep 17 00:00:00 2001 From: Joseph Montanaro Date: Fri, 16 Jul 2021 22:43:45 -0700 Subject: [PATCH] more procs for working on faststacks --- faststack.nim | 53 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/faststack.nim b/faststack.nim index a5949fc..e6d5c63 100644 --- a/faststack.nim +++ b/faststack.nim @@ -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