import algorithm, random 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 proc `[]`*(s: FixedSeq, i: Natural): FixedSeq.Contents = if i > s.last: raise newException(IndexDefect, "index " & $i & " is out of bounds.") s.data[i] 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 proc shuffle*(s: var FixedSeq, r: var Rand) = r.shuffle(s.data) 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"