pub fn unfold<T, F>(func: F, init: T) -> Unfold<T, F>
where
F: Fn(T) -> T,
T: Copy,
{
Unfold::new(func, init)
}
pub fn unfold_vector<T, F>(func: F, init: T, len: usize) -> Vec<T>
where
F: Fn(T) -> T,
T: Copy,
{
unfold(func, init).take(len).collect()
}
pub fn unfold_nth<T, F>(func: F, init: T, index: usize) -> T
where
F: Fn(T) -> T,
T: Copy,
{
unfold(func, init).take(index).last().unwrap()
}
pub fn unfold_count<T, F>(func: F, init: T, count: usize) -> impl Iterator<Item = T>
where
F: Fn(T) -> T,
T: Copy,
{
unfold(func, init).take(count)
}
pub struct Unfold<T, F>
where
F: Fn(T) -> T,
T: Copy,
{
curr: T,
func: F,
}
impl<T, F> Unfold<T, F>
where
F: Fn(T) -> T,
T: Copy,
{
pub fn new(function: F, init: T) -> Self {
Self {
func: function,
curr: init,
}
}
}
impl<T, F> Iterator for Unfold<T, F>
where
F: Fn(T) -> T,
T: Copy,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let tmp = self.curr;
self.curr = (self.func)(self.curr);
Some(tmp)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fibonacci() {
let fib = Unfold::new(|(a, b)| (b, a + b), (0, 1))
.map(|(a, _)| a)
.take(8)
.last()
.unwrap();
assert_eq!(fib, 13);
}
#[test]
fn test_unfold_nth() {
let fib = unfold_nth(|(a, b)| (b, a + b), (0, 1), 8).0;
assert_eq!(fib, 13);
}
#[test]
fn test_unfold_vector() {
let count = unfold_vector(|x| x + 1, 0, 10);
let result: Vec<i32> = (0..10).collect();
assert_eq!(count, result);
}
#[test]
fn test_unfold_count() {
let mut iter = unfold_count(|x| x + 1, 0, 5);
assert_eq!(iter.next(), Some(0));
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next(), Some(4));
assert_eq!(iter.next(), None);
}
}