cup/colors.nim

140 lines
3.1 KiB
Nim
Raw Normal View History

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.pieces[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"