cup/combinators.nim

89 lines
1.9 KiB
Nim

import algorithm
import fixedseq, game
proc nextPermutation(x: var FixedSeq): bool =
# copied shamelessly from std/algorithm.nim
if x.len < 2:
return false
var i = x.high
while i > 0 and x[i - 1] >= x[i]:
dec i
if i == 0:
return false
var j = x.high
while j >= i and x[j] <= x[i - 1]:
dec j
swap x[j], x[i - 1]
x.reverse(i, x.high)
result = true
proc prevPermutation(x: var FixedSeq): bool =
# copied shamelessly from std/algorithm.nim
if x.len < 2:
return false
var i = x.high
while i > 0 and x[i - 1] <= x[i]:
dec i
if i == 0:
return false
x.reverse(i, x.high)
var j = x.high
while j >= i and x[j - 1] < x[i - 1]:
dec j
swap x[i - 1], x[j]
result = true
iterator allPermutations*(x: FixedSeq): FixedSeq =
# returns all permutations of a given seq. Order is wonky but we don't care.
var workingCopy = x
yield workingCopy
while workingCopy.nextPermutation: # this mutates workingCopy
yield workingCopy
workingCopy = x
while workingCopy.prevPermutation:
yield workingCopy
iterator allDigits*(lo, hi, size: Natural): auto =
if size > 0: # otherwise we get an infinite loop
var digits: FixedSeq[5, int]
for i in 0 ..< size:
digits.add(lo)
var complete = false
while not complete:
yield digits
for i in countdown(digits.high, 0):
if digits[i] < hi:
inc digits[i]
break
elif i == 0: # since this is the last digit to be incremented, we must be done
complete = true
else:
digits[i] = lo
iterator possibleFutures*(dice: ColorStack): auto =
# iterate over all possible sequences of die rolls. Each outcome
# is returned as a 5-sequence of (color, number) tuples.
for perm in dice.allPermutations:
for digits in allDigits(1, 3, dice.len):
var f: FixedSeq[5, Die]
for i in 0'u8 .. dice.high:
f.add((color: perm[i], value: digits[i]))
yield f