#![doc = include_str!("../README.md")]
pub struct AlphaCounter {
number: usize,
alphabet: Vec<char>,
length: usize,
}
impl AlphaCounter {
#[must_use]
pub fn lower(number: usize) -> AlphaCounter {
AlphaCounter::custom(number, "abcdefghijklmnopqrstuvwxyz")
}
#[must_use]
pub fn upper(number: usize) -> AlphaCounter {
AlphaCounter::custom(number, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
}
#[must_use]
pub fn custom(number: usize, alphabet: &str) -> AlphaCounter {
let alphabet: Vec<char> = alphabet.chars().collect();
let length = alphabet.len();
AlphaCounter {
number,
alphabet,
length,
}
}
#[must_use]
pub fn recurse(&self, x: usize) -> String {
let d = x / self.length;
let r = x % self.length;
let t = self.alphabet[r];
if d == 0 {
format!("{t}")
} else {
format!("{}{t}", self.recurse(d - 1))
}
}
}
impl core::iter::Iterator for AlphaCounter {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
let r = self.to_string();
self.number += 1;
Some(r)
}
}
impl std::fmt::Display for AlphaCounter {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.recurse(self.number))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn lower() {
assert_eq!(
AlphaCounter::lower(0).take(30).collect::<Vec<String>>(),
vec![
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p",
"q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "aa", "ab", "ac", "ad"
],
);
}
#[test]
fn upper() {
assert_eq!(
AlphaCounter::upper(0).take(30).collect::<Vec<String>>(),
vec![
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P",
"Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD"
],
);
}
#[test]
fn custom() {
assert_eq!(
AlphaCounter::custom(0, "abc")
.take(30)
.collect::<Vec<String>>(),
vec![
"a", "b", "c", "aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc", "aaa", "aab",
"aac", "aba", "abb", "abc", "aca", "acb", "acc", "baa", "bab", "bac", "bba", "bbb",
"bbc", "bca", "bcb", "bcc"
],
);
}
}