140 lines
3.1 KiB
Nim
140 lines
3.1 KiB
Nim
import strutils
|
|
|
|
|
|
type
|
|
Color* = enum
|
|
cRed, cGreen, cBlue, cYellow, cPurple
|
|
|
|
ColorStack* = object
|
|
pieces: array[5, int8]
|
|
last: int8
|
|
|
|
|
|
proc init*(s: var ColorStack) =
|
|
for i in 0..4:
|
|
s.pieces[i] = -1
|
|
s.last = -1
|
|
|
|
|
|
proc `[]`*(s: ColorStack, i: Natural): Color =
|
|
if i > s.last:
|
|
raise newException(IndexDefect, "index " & $i & " is out of bounds.")
|
|
result = Color(s.pieces[i])
|
|
|
|
|
|
proc `[]`*(s: ColorStack, i: BackwardsIndex): Color =
|
|
if s.last == -1:
|
|
raise newException(IndexDefect, "index out of bounds, the container is empty.") # matching stdlib again
|
|
result = Color(s.pieces[s.last - int8(i) + 1])
|
|
|
|
|
|
proc `[]=`*(s: var ColorStack, i: Natural, v: Color) =
|
|
if i > s.last:
|
|
raise newException(IndexDefect, "index " & $i & " is out of bounds.")
|
|
s.pieces[i] = int8(v)
|
|
|
|
|
|
proc `$`*(s: ColorStack): string =
|
|
result.add("St@[")
|
|
for i in 0 .. s.last:
|
|
let c = Color(s.pieces[i])
|
|
result.add($c)
|
|
if i < s.last:
|
|
result.add(", ")
|
|
result.add("]")
|
|
|
|
|
|
proc high*(s: ColorStack): int8 =
|
|
result = s.last
|
|
|
|
|
|
proc low*(s: ColorStack): int8 =
|
|
result = case s.last
|
|
of -1: 0 # a bit weird but it's how the stdlib seq works
|
|
else: s.last
|
|
|
|
|
|
proc len*(s: ColorStack): int8 =
|
|
result = s.last + 1
|
|
|
|
|
|
iterator items*(s: ColorStack): Color =
|
|
for i in 0 .. s.last:
|
|
yield Color(s[i])
|
|
|
|
|
|
iterator asInt*(s: ColorStack): int8 =
|
|
for i in 0 .. s.last:
|
|
yield s.pieces[i] # no conversion, should speed up hashing? maybe
|
|
|
|
|
|
iterator pairs*(s: ColorStack): auto =
|
|
var count = 0
|
|
for c in s:
|
|
yield (count, c)
|
|
inc count
|
|
|
|
|
|
proc add*(s: var ColorStack, c: Color) =
|
|
let i = s.last + 1
|
|
s.pieces[i] = int8(c) # will raise exception if out of bounds
|
|
s.last = i
|
|
|
|
|
|
proc insert*(s: var ColorStack, c: Color, idx: Natural = 0) =
|
|
for i in countdown(s.last, int8(idx)):
|
|
swap(s.pieces[i], s.pieces[i + 1]) # will also raise exception if out of bounds
|
|
s.pieces[idx] = int8(c)
|
|
inc s.last
|
|
|
|
|
|
proc delete*(s: var ColorStack, idx: Natural) =
|
|
if idx > s.last:
|
|
raise newException(IndexDefect, "index " & $idx & " is out of bounds.")
|
|
s.pieces[idx] = -1
|
|
dec s.last
|
|
for i in int8(idx) .. s.last:
|
|
swap(s.pieces[i], s.pieces[i + 1])
|
|
|
|
|
|
proc find(s: ColorStack, c: Color): int8 =
|
|
let needle = int(c)
|
|
for i, v in s.pieces:
|
|
if v == needle:
|
|
return i
|
|
return -1
|
|
|
|
|
|
proc moveSubstack*(src, dst: var ColorStack; start: Natural) =
|
|
var count = 0 # have to track this separately apparently
|
|
for idx in (int8(start) .. src.last):
|
|
swap(src.pieces[idx], dst.pieces[dst.last + 1 + count])
|
|
inc count
|
|
dst.last += int8(count)
|
|
src.last -= int8(count)
|
|
|
|
|
|
proc moveSubstackPre*(src, dst: var ColorStack; start: Natural) =
|
|
let ssLen = src.last - start + 1 # length of substack
|
|
for i in countdown(dst.last, 0):
|
|
swap(dst.pieces[i], dst.pieces[i + ssLen])
|
|
|
|
var count = 0
|
|
for i in start .. src.last:
|
|
swap(src.pieces[i], dst.pieces[count])
|
|
inc count
|
|
|
|
dst.last += int8(ssLen)
|
|
src.last -= int8(ssLen)
|
|
|
|
|
|
proc display(s: ColorStack) =
|
|
var p: seq[string]
|
|
for i in s.pieces:
|
|
if i == -1:
|
|
p.add("none")
|
|
else:
|
|
p.add($Color(i))
|
|
echo "pieces: @[", p.join(", "), "], last: ", s.last
|
|
echo "len: ", s.len, "\n"
|