///|
// Length/lexicographic word enumeration without materializing exponential layers.
priv struct WordCursor {
  alphabet : Array[String]
  max_length : Int32
  digits : Array[Int32]
  mut done : Bool
}

///|
fn WordCursor::new(alphabet : Array[String], max_length : Int32) -> WordCursor {
  { alphabet, max_length, digits: [], done: false, }
}

///|
fn WordCursor::next(self : WordCursor) -> Array[String]? {
  if self.done {
    return None
  }
  let word = self.digits.map(index => self.alphabet[index])
  let mut carry = true
  for index = self.digits.length() - 1; index >= 0; index = index - 1 {
    if self.digits[index] + 1 < self.alphabet.length() {
      self.digits[index] += 1
      carry = false
      break
    }
    self.digits[index] = 0
  }
  if carry {
    if self.digits.length() >= self.max_length {
      self.done = true
    } else {
      self.digits.push(0)
    }
  }
  Some(word)
}