syndicate-nim/src/syndicate/bags.nim

51 lines
1.2 KiB
Nim

# SPDX-FileCopyrightText: 2021 ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
## An unordered association of items to counts.
## An item count may be negative, unlike CountTable.
import std/[assertions, tables]
type
ChangeDescription* = enum
cdPresentToAbsent,
cdAbsentToAbsent,
cdAbsentToPresent,
cdPresentToPresent
Bag*[T] = Table[T, int]
proc change(count: var int; delta: int; clamp: bool): ChangeDescription =
var
oldCount = count
newCount = oldCount + delta
if clamp:
newCount = max(0, newCount)
if newCount == 0:
result =
if oldCount == 0: cdAbsentToAbsent
else: cdPresentToAbsent
else:
result =
if oldCount == 0: cdAbsentToPresent
else: cdPresentToPresent
count = newCount
proc change*[T](bag: var Bag[T]; key: T; delta: int; clamp = false): ChangeDescription =
assert(delta != 0)
result = change(bag.mGetOrPut(key, 0), delta, clamp)
if result in {cdAbsentToAbsent, cdPresentToAbsent}:
bag.del(key)
iterator items*[T](bag: Bag[T]): T =
for x in bag.keys: yield x
proc `$`*(bag: Bag): string =
result.add '{'
for x in bag.keys:
if result.len > 1: result.add ' '
result.add $x
result.add '}'
export tables.contains, tables.del, tables.len