2021-03-24 17:54:50 +00:00
|
|
|
import algorithm, random
|
2021-03-24 07:18:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
type
|
|
|
|
FixedSeq*[Idx: static int; Contents; Pointer: SomeSignedInt] = object
|
|
|
|
data: array[Idx, Contents]
|
|
|
|
last: Pointer
|
|
|
|
|
|
|
|
|
|
|
|
proc initFixedSeq*(size: static Natural; cType: typedesc; pType: typedesc[SomeSignedInt]): auto =
|
|
|
|
var s: FixedSeq[size, cType, pType]
|
|
|
|
s.last = -1
|
|
|
|
result = s
|
|
|
|
|
|
|
|
proc initFixedSeq*(s: var FixedSeq) =
|
|
|
|
s.last = -1
|
|
|
|
|
|
|
|
|
2021-03-24 17:54:50 +00:00
|
|
|
proc `[]`*(s: FixedSeq, i: Natural): FixedSeq.Contents =
|
|
|
|
if i > s.last:
|
|
|
|
raise newException(IndexDefect, "index " & $i & " is out of bounds.")
|
|
|
|
s.data[i]
|
|
|
|
|
2021-03-24 07:18:53 +00:00
|
|
|
proc `[]`*(s: var FixedSeq, i: Natural): var FixedSeq.Contents =
|
|
|
|
if i > s.last:
|
|
|
|
raise newException(IndexDefect, "index " & $i & " is out of bounds.")
|
|
|
|
s.data[i]
|
|
|
|
|
|
|
|
|
|
|
|
proc `[]`*(s: FixedSeq, i: BackwardsIndex): auto =
|
|
|
|
if s.last == -1:
|
|
|
|
raise newException(IndexDefect, "index out of bounds, the container is empty.") # matching stdlib again
|
|
|
|
s.data[s.last - typeof(s.last)(i) + 1]
|
|
|
|
|
|
|
|
|
|
|
|
proc `[]=`*(s: var FixedSeq, i: Natural, v: FixedSeq.Contents) =
|
|
|
|
if i > s.last:
|
|
|
|
raise newException(IndexDefect, "index " & $i & " is out of bounds.")
|
|
|
|
s.data[i] = v
|
|
|
|
|
|
|
|
|
|
|
|
proc high*(s: FixedSeq): auto =
|
|
|
|
result = s.last
|
|
|
|
|
|
|
|
|
|
|
|
proc low*(s: FixedSeq): auto =
|
|
|
|
result = case s.last
|
|
|
|
of -1: 0 # a bit weird but it's how the stdlib seq works
|
|
|
|
else: s.last
|
|
|
|
|
|
|
|
|
|
|
|
proc len*(s: FixedSeq): auto =
|
|
|
|
result = s.last + 1
|
|
|
|
|
|
|
|
|
|
|
|
iterator items*(s: FixedSeq): auto =
|
|
|
|
for i in 0 .. s.last:
|
|
|
|
yield s.data[i]
|
|
|
|
|
|
|
|
|
|
|
|
iterator asInt*(s: FixedSeq): int8 =
|
|
|
|
for i in 0 .. s.last:
|
|
|
|
yield int8(s.data[i]) # now we do have to convert
|
|
|
|
|
|
|
|
|
|
|
|
iterator pairs*(s: FixedSeq): auto =
|
|
|
|
var count = 0
|
|
|
|
for c in s:
|
|
|
|
yield (count, c)
|
|
|
|
inc count
|
|
|
|
|
|
|
|
|
|
|
|
proc add*(s: var FixedSeq, v: FixedSeq.Contents) =
|
|
|
|
let i = s.last + 1
|
|
|
|
s.data[i] = v # will raise exception if out of bounds
|
|
|
|
s.last = i
|
|
|
|
|
|
|
|
|
|
|
|
proc insert*(s: var FixedSeq, v: FixedSeq.Contents, idx: Natural = 0) =
|
|
|
|
for i in countdown(s.last, typeof(s.last)(idx)):
|
|
|
|
swap(s.data[i], s.data[i + 1]) # will also raise exception if out of bounds
|
|
|
|
s.data[idx] = v
|
|
|
|
inc s.last
|
|
|
|
|
|
|
|
|
|
|
|
proc delete*(s: var FixedSeq, idx: Natural) =
|
|
|
|
if idx > s.last:
|
|
|
|
raise newException(IndexDefect, "index " & $idx & " is out of bounds.")
|
|
|
|
s.data[idx] = -1
|
|
|
|
dec s.last
|
|
|
|
for i in typeof(s.last)(idx) .. s.last:
|
|
|
|
swap(s.data[i], s.data[i + 1])
|
|
|
|
|
|
|
|
|
|
|
|
proc find*(s: FixedSeq, needle: FixedSeq.Contents): FixedSeq.Pointer =
|
|
|
|
for i, v in s.data:
|
|
|
|
if v == needle:
|
|
|
|
return i
|
|
|
|
return -1
|
|
|
|
|
|
|
|
|
|
|
|
proc nextPermutation*(s: var FixedSeq): bool = s.data.nextPermutation
|
|
|
|
|
|
|
|
proc prevPermutation*(s: var FixedSeq): bool = s.data.prevPermutation
|
|
|
|
|
2021-03-24 17:54:50 +00:00
|
|
|
proc shuffle*(s: var FixedSeq, r: var Rand) =
|
|
|
|
r.shuffle(s.data)
|
2021-03-24 07:18:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
proc moveSubstack*(src, dst: var FixedSeq; start: Natural) =
|
|
|
|
var count: typeof(src.last) = 0 # have to track this separately apparently
|
|
|
|
for idx in start .. src.last:
|
|
|
|
swap(src.data[idx], dst.data[dst.last + 1 + count])
|
|
|
|
inc count
|
|
|
|
dst.last += count
|
|
|
|
src.last -= count
|
|
|
|
|
|
|
|
|
|
|
|
proc moveSubstackPre*(src, dst: var FixedSeq; start: Natural) =
|
|
|
|
let ssLen = typeof(src.last)(src.last - start + 1) # length of substack
|
|
|
|
for i in countdown(dst.last, 0):
|
|
|
|
swap(dst.data[i], dst.data[i + ssLen])
|
|
|
|
|
|
|
|
var count = 0
|
|
|
|
for i in start .. src.last:
|
|
|
|
swap(src.data[i], dst.data[count])
|
|
|
|
inc count
|
|
|
|
|
|
|
|
dst.last += ssLen
|
|
|
|
src.last -= 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"
|