copy-paste problems

This commit is contained in:
jungin.rhee
2023-08-18 16:07:30 +00:00
parent 3ef3cae0cd
commit b1f1f1a5fc
28 changed files with 3276 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
//! Generators
enum Yielded<T> {
Value(T),
Stop,
}
/// Generator
///
/// Reference:
/// - [Python generator](https://python-reference.readthedocs.io/en/latest/docs/generator/)
#[allow(missing_debug_implementations)]
pub struct Generator<T, S> {
state: S,
f: fn(&mut S) -> Yielded<T>,
}
impl<T, S> Iterator for Generator<T, S> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
/// Returns a generator that yields fibonacci numbers.
pub fn fib_generator(first: usize, second: usize) -> Generator<usize, (usize, usize)> {
todo!()
}
/// Returns a generator that yields collatz numbers.
///
/// The generator stops when it reaches to 1.
pub fn collatz_conjecture(start: usize) -> Generator<usize, usize> {
todo!()
}

View File

@@ -0,0 +1,38 @@
#[cfg(test)]
mod test {
use itertools::Itertools;
use ntest::assert_about_eq;
use super::super::generator::*;
#[test]
fn test_generator() {
assert_eq!(
fib_generator(0, 1).take(10).collect::<Vec<_>>(),
vec![0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
);
assert_eq!(
collatz_conjecture(12).collect::<Vec<_>>(),
vec![12, 6, 3, 10, 5, 16, 8, 4, 2, 1]
);
assert_eq!(
collatz_conjecture(19).collect::<Vec<_>>(),
vec![19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
);
assert_eq!(
collatz_conjecture(27).collect::<Vec<_>>(),
vec![
27, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364,
182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790,
395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566,
283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858,
2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308,
1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23,
70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1
]
);
}
}

View File

@@ -0,0 +1,84 @@
//! Hubo is back!
/// Types that represent a direction.
pub trait Direction {
/// Get the direction in the form of a 2-dimensional vector.
/// The resulting value doesn't have to be normalized.
fn get_vector(&self) -> (f32, f32);
}
/// 4-way enum to indicate directions.
#[derive(Debug)]
pub enum Dir4 {
/// +x direction
Right,
/// -x direction
Left,
/// +y direction
Up,
/// -y direction
Down,
}
impl Direction for Dir4 {
fn get_vector(&self) -> (f32, f32) {
todo!()
}
}
impl Direction for (f32, f32) {
fn get_vector(&self) -> (f32, f32) {
todo!()
}
}
/// Hubo.
/// It's direction can be represented by an arbitrary type.
///
/// It can be controlled by [HuboController] only if the direction type implements the [Direction] trait.
#[derive(Debug)]
pub struct Hubo<TDir> {
direction: TDir,
x: f32,
y: f32,
}
/// Controller of the Hubo
#[derive(Debug)]
pub struct HuboController<'s, TDir> {
hubo: &'s mut Hubo<TDir>,
}
impl<TDir> Hubo<TDir> {
/// Create a Hubo.
pub fn new(direction: TDir, x: f32, y: f32) -> Self {
Self { direction, x, y }
}
/// Return the current position of Hubo.
pub fn get_position(&self) -> (f32, f32) {
(self.x, self.y)
}
}
impl<'s, TDir: Direction> HuboController<'s, TDir> {
/// Return the controller of the given Hubo.
/// Note that the lifetime of hubo's mutable reference \['s\] is repeated in the return type.
///
/// This represents that the controller cannot live longer than the mutable reference,
/// since the controller takes and stores the reference.
pub fn new(hubo: &'s mut Hubo<TDir>) -> HuboController<'s, TDir> {
todo!()
}
/// Make Hubo move forward by the given distance. You might need to normalize the vector
/// acquired from `Direction::get_move_vector`.
pub fn move_hubo_forward(&mut self, distance: f32) {
todo!()
}
/// Make Hubo turn to the given direction.
pub fn set_hubo_direction(&mut self, dir: TDir) {
todo!()
}
}

View File

@@ -0,0 +1,40 @@
#[cfg(test)]
mod test {
use itertools::Itertools;
use ntest::assert_about_eq;
use super::super::hubo::*;
#[test]
fn test_hubo_dir4_movement() {
let mut hubo = Hubo::new(Dir4::Right, 0.0, 0.0);
let mut controller = HuboController::new(&mut hubo);
// Test moving forward
controller.move_hubo_forward(5.0);
controller.set_hubo_direction(Dir4::Up);
controller.move_hubo_forward(3.0);
controller.set_hubo_direction(Dir4::Left);
controller.move_hubo_forward(2.0);
assert_eq!(hubo.get_position(), (3.0, 3.0));
}
#[test]
fn test_hubo_tuple_movement() {
let mut hubo = Hubo::new((1., 0.), 0.0, 0.0);
let mut controller = HuboController::new(&mut hubo);
// Test moving forward
controller.move_hubo_forward(5.0);
controller.set_hubo_direction((3., 4.));
controller.move_hubo_forward(5.0);
controller.set_hubo_direction((-8., -6.));
controller.move_hubo_forward(15.0);
assert_eq!(hubo.get_position(), (-4., -5.));
}
}

View File

@@ -0,0 +1,18 @@
//! Assignment 7: Mastering advanced types (2/2).
//!
//! The primary goal of this assignment is to understand generics, traits, and lifetimes.
//!
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-07.sh` works fine.
//! See `assignment07_grade.rs` and `/scripts/grade-07.sh` for the test script.
pub mod generator;
pub mod hubo;
pub mod my_itertools;
pub mod small_exercises;
pub mod transform;
mod generator_grade;
mod hubo_grade;
mod my_itertools_grade;
mod small_exercises_grade;
mod transform_grade;

View File

@@ -0,0 +1,117 @@
//! Implement your own minimal `itertools` crate.
use std::hash::Hash;
/// Iterator that iterates over the given iterator and returns only unique elements.
#[allow(missing_debug_implementations)]
pub struct Unique<I: Iterator> {
// TODO: remove `_marker` and add necessary fields as you want
_marker: std::marker::PhantomData<I>,
}
impl<I: Iterator> Iterator for Unique<I>
where
I::Item: Eq + Hash + Clone,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
/// Iterator that chains two iterators together.
#[allow(missing_debug_implementations)]
pub struct Chain<I1: Iterator, I2: Iterator> {
// TODO: remove `_marker` and add necessary fields as you want
_marker: std::marker::PhantomData<(I1, I2)>,
}
impl<T: Eq + Hash + Clone, I1: Iterator<Item = T>, I2: Iterator<Item = T>> Iterator
for Chain<I1, I2>
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
/// Iterator that iterates over given iterator and enumerates each element.
#[allow(missing_debug_implementations)]
pub struct Enumerate<I: Iterator> {
// TODO: remove `_marker` and add necessary fields as you want
_marker: std::marker::PhantomData<I>,
}
impl<I: Iterator> Iterator for Enumerate<I> {
type Item = (usize, I::Item);
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
/// Iterator that zips two iterators together.
///
/// If one iterator is longer than the other one, the remaining elements for the longer element
/// should be ignored.
#[allow(missing_debug_implementations)]
pub struct Zip<I1: Iterator, I2: Iterator> {
// TODO: remove `_marker` and add necessary fields as you want
_marker: std::marker::PhantomData<(I1, I2)>,
}
impl<I1: Iterator, I2: Iterator> Iterator for Zip<I1, I2> {
type Item = (I1::Item, I2::Item);
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
/// My Itertools trait.
pub trait MyIterTools: Iterator {
/// Returns an iterator that iterates over the `self` and returns only unique elements.
fn my_unique(self) -> Unique<Self>
where
Self: Sized,
{
todo!()
}
/// Returns an iterator that chains `self` and `other` together.
fn my_chain<I: Iterator>(self, other: I) -> Chain<Self, I>
where
Self: Sized,
{
todo!()
}
/// Returns an iterator that iterates over `self` and enumerates each element.
fn my_enumerate(self) -> Enumerate<Self>
where
Self: Sized,
{
todo!()
}
/// Returns an iterator that zips `self` and `other` together.
fn my_zip<I: Iterator>(self, other: I) -> Zip<Self, I>
where
Self: Sized,
{
todo!()
}
/// Foldleft for `MyIterTools`
fn my_fold<T, F>(mut self, init: T, mut f: F) -> T
where
Self: Sized,
F: FnMut(Self::Item, T) -> T,
{
todo!()
}
}
impl<T: ?Sized> MyIterTools for T where T: Iterator {}

View File

@@ -0,0 +1,65 @@
#[cfg(test)]
mod test {
use itertools::Itertools;
use ntest::assert_about_eq;
use super::super::my_itertools::*;
#[test]
fn test_itertools() {
assert_eq!(
[10, 1, 1, 1, 2, 3, 4, 1, 3, 2]
.into_iter()
.my_chain(std::iter::repeat(100))
.my_unique()
.take(4)
.collect::<Vec<_>>(),
vec![10, 1, 2, 3]
);
assert_eq!(
std::iter::repeat(5)
.my_enumerate()
.map(|(i, e)| { i * e })
.take(5)
.collect::<Vec<_>>(),
vec![0, 5, 10, 15, 20]
);
assert_eq!(
vec![0, 1, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,],
[0, 1, 10].into_iter().my_chain(0..10).collect::<Vec<_>>(),
);
let it = || (1..=5).cycle().my_zip((1..=3).cycle()).map(|(x, y)| x * y);
let take15 = vec![
2, // 1 * 1,
4, // 2 * 2,
9, // 3 * 3,
4, // 4 * 1,
10, // 5 * 2,
3, // 1 * 3,
2, // 2 * 1,
6, // 3 * 2,
12, // 4 * 3,
5, // 5 * 1,
2, // 1 * 2,
6, // 2 * 3,
3, // 3 * 1,
8, // 4 * 2,
15, // 5 * 3,
];
assert_eq!(
// 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
// 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
it().take(15).collect::<Vec<_>>(),
take15
);
assert_eq!(
it().take(15).my_fold(0, |elt, acc| elt + acc),
take15.iter().sum()
);
}
}

View File

@@ -0,0 +1,119 @@
//! Implement functions usint `Iterator` trait
struct FindIter<'s, T: Eq> {
query: &'s [T],
base: &'s [T],
curr: usize,
}
impl<T: Eq> Iterator for FindIter<'_, T> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
/// Returns an iterator over substring query indexes in the base.
pub fn find<'s, T: Eq>(query: &'s [T], base: &'s [T]) -> impl 's + Iterator<Item = usize> {
FindIter {
query,
base,
curr: 0,
}
}
/// Implement fibonacci iterator
struct FibIter<T> {
// TODO: remove `_marker` and add necessary fields as you want
_marker: std::marker::PhantomData<T>,
}
impl<T: std::ops::Add<Output = T> + Copy> FibIter<T> {
fn new(first: T, second: T) -> Self {
todo!()
}
}
impl<T> Iterator for FibIter<T>
where
T: std::ops::Add<Output = T> + Copy,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
/// Returns and iterator over the generic fibonacci sequence starting from `first` and `second`.
/// This is a generic version of `fibonacci` function, which works for any types that implements `std::ops::Add` trait.
pub fn fib<T>(first: T, second: T) -> impl Iterator<Item = T>
where
T: std::ops::Add<Output = T> + Copy,
{
todo!("remove below");
std::iter::empty()
}
/// Endpoint of range, inclusive or exclusive.
#[derive(Debug)]
pub enum Endpoint {
/// Inclusive endpoint
Inclusive(isize),
/// Exclusive endpoint
Exclusive(isize),
}
struct RangeIter {
// TODO: add necessary fields as you want
}
impl RangeIter {
fn new(endpoints: (Endpoint, Endpoint), step: isize) -> Self {
todo!()
}
}
impl Iterator for RangeIter {
type Item = isize;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
/// Returns an iterator over the range [left, right) with the given step.
pub fn range(left: Endpoint, right: Endpoint, step: isize) -> impl Iterator<Item = isize> {
todo!("remove below");
std::iter::empty()
}
/// Write an iterator that returns all divisors of n in increasing order.
/// Assume n > 0.
///
/// Hint: trying all candidates from 1 to n will most likely time out!
/// To optimize it, make use of the following fact:
/// if x is a divisor of n that is greater than sqrt(n),
/// then n/x is a divisor of n that is smaller than sqrt(n).
struct Divisors {
n: u64,
// TODO: you may define additional fields here
}
impl Iterator for Divisors {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
/// Returns an iterator over the divisors of n.
pub fn divisors(n: u64) -> impl Iterator<Item = u64> {
Divisors {
n,
// TODO: you may define additional fields here
}
}

View File

@@ -0,0 +1,189 @@
#[cfg(test)]
mod test {
use itertools::Itertools;
use ntest::assert_about_eq;
use super::super::small_exercises::*;
#[test]
fn test_find() {
assert_eq!(
find("abc".as_bytes(), "abcdabcd".as_bytes()).collect::<Vec<usize>>(),
vec![0, 4]
);
assert_eq!(
find("aaba".as_bytes(), "aabaacaadaabaaba".as_bytes()).collect::<Vec<usize>>(),
vec![0, 9, 12]
);
assert_eq!(
find("ababac".as_bytes(), "abababcabababcabababc".as_bytes()).collect::<Vec<usize>>(),
vec![]
);
assert_eq!(
find("ababc".as_bytes(), "abc".as_bytes()).collect::<Vec<usize>>(),
vec![]
);
}
#[test]
fn test_find_usize() {
assert_eq!(
find(&[1, 2, 3], &[1, 2, 3, 4, 1, 2, 3, 4]).collect::<Vec<usize>>(),
vec![0, 4]
);
assert_eq!(
find(
&[5, 5, 7, 5],
&[5, 5, 7, 5, 5, 8, 5, 5, 9, 5, 5, 7, 5, 5, 7, 5]
)
.collect::<Vec<usize>>(),
vec![0, 9, 12]
);
}
#[test]
fn test_fib_iter() {
assert_eq!(
fib(0, 1).take(10).collect::<Vec<_>>(),
vec![0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
);
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Rgb(u8, u8, u8);
impl std::ops::Add for Rgb {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self(
((self.0 as u16 + rhs.0 as u16) / 2) as u8,
((self.1 as u16 + rhs.1 as u16) / 2) as u8,
((self.2 as u16 + rhs.2 as u16) / 2) as u8,
)
}
}
assert_eq!(
fib(Rgb(255, 0, 100), Rgb(1, 128, 0))
.take(20)
.collect::<Vec<_>>(),
vec![
Rgb(255, 0, 100),
Rgb(1, 128, 0),
Rgb(128, 64, 50),
Rgb(64, 96, 25),
Rgb(96, 80, 37),
Rgb(80, 88, 31),
Rgb(88, 84, 34),
Rgb(84, 86, 32),
Rgb(86, 85, 33),
Rgb(85, 85, 32),
Rgb(85, 85, 32),
Rgb(85, 85, 32),
Rgb(85, 85, 32),
Rgb(85, 85, 32),
Rgb(85, 85, 32),
Rgb(85, 85, 32),
Rgb(85, 85, 32),
Rgb(85, 85, 32),
Rgb(85, 85, 32),
Rgb(85, 85, 32)
]
);
}
#[test]
fn test_range_iter() {
let one_to_tens = vec![
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
range(Endpoint::Inclusive(1), Endpoint::Inclusive(10), 1).collect(),
range(Endpoint::Exclusive(0), Endpoint::Inclusive(10), 1).collect(),
range(Endpoint::Inclusive(1), Endpoint::Exclusive(11), 1).collect(),
range(Endpoint::Exclusive(0), Endpoint::Exclusive(11), 1).collect(),
];
assert!(one_to_tens.iter().all_equal());
let ten_to_ones = vec![
vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
range(Endpoint::Inclusive(10), Endpoint::Inclusive(1), -1).collect(),
range(Endpoint::Exclusive(11), Endpoint::Inclusive(1), -1).collect(),
range(Endpoint::Inclusive(10), Endpoint::Exclusive(0), -1).collect(),
range(Endpoint::Exclusive(11), Endpoint::Exclusive(0), -1).collect(),
];
assert!(ten_to_ones.iter().all_equal());
let five_evens = vec![
vec![2, 4, 6, 8, 10],
range(Endpoint::Inclusive(2), Endpoint::Inclusive(10), 2).collect(),
range(Endpoint::Inclusive(2), Endpoint::Inclusive(11), 2).collect(),
range(Endpoint::Exclusive(1), Endpoint::Inclusive(10), 2).collect(),
range(Endpoint::Exclusive(1), Endpoint::Inclusive(11), 2).collect(),
range(Endpoint::Inclusive(2), Endpoint::Exclusive(11), 2).collect(),
range(Endpoint::Inclusive(2), Endpoint::Exclusive(12), 2).collect(),
range(Endpoint::Exclusive(1), Endpoint::Exclusive(11), 2).collect(),
range(Endpoint::Exclusive(1), Endpoint::Exclusive(12), 2).collect(),
];
assert!(five_evens.iter().all_equal());
let emptys = vec![
vec![],
range(Endpoint::Inclusive(2), Endpoint::Inclusive(10), -1).collect(),
range(Endpoint::Inclusive(10), Endpoint::Inclusive(-100), 1).collect(),
range(Endpoint::Inclusive(1), Endpoint::Exclusive(1), 1).collect(),
];
assert!(emptys.iter().all_equal());
}
#[test]
fn test_small() {
assert_eq!(divisors(10).collect::<Vec<u64>>(), vec![1, 2, 5, 10]);
assert_eq!(divisors(17).collect::<Vec<u64>>(), vec![1, 17]);
assert_eq!(divisors(49).collect::<Vec<u64>>(), vec![1, 7, 49]);
assert_eq!(
divisors(120).collect::<Vec<u64>>(),
vec![1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 30, 40, 60, 120]
);
assert_eq!(divisors(1).collect::<Vec<u64>>(), vec![1]);
assert_eq!(divisors(2).collect::<Vec<u64>>(), vec![1, 2]);
assert_eq!(divisors(3).collect::<Vec<u64>>(), vec![1, 3]);
}
#[test]
fn test_large() {
assert_eq!(
divisors(1_000_000_000_000_037).collect::<Vec<u64>>(),
vec![1, 1_000_000_000_000_037]
);
assert_eq!(
divisors(99_999_820_000_081).collect::<Vec<u64>>(),
vec![1, 9_999_991, 99_999_820_000_081]
);
assert_eq!(
divisors(1_234_567_890_123).collect::<Vec<u64>>(),
vec![
1,
3,
3_541,
10_623,
116_216_501,
348_649_503,
411_522_630_041,
1_234_567_890_123
]
);
assert_eq!(divisors(97_821_761_637_600).count(), 17280);
}
}

View File

@@ -0,0 +1,95 @@
//! Tranformer
use std::marker::PhantomData;
use std::ops::Add;
/// Represents transformation of type `T`.
pub trait Transform<T> {
/// Transforms value.
fn transform(&self, value: T) -> T;
}
impl<T1, T2, Tr1: Transform<T1>, Tr2: Transform<T2>> Transform<(T1, T2)> for (Tr1, Tr2) {
fn transform(&self, value: (T1, T2)) -> (T1, T2) {
todo!()
}
}
/// Identity transformation.
#[derive(Debug, Clone, Copy)]
pub struct Identity;
impl<T> Transform<T> for Identity {
fn transform(&self, value: T) -> T {
todo!()
}
}
/// Custom transformation.
#[derive(Debug, Clone, Copy)]
pub struct Custom<T, F: Fn(T) -> T> {
f: F,
_marker: PhantomData<T>,
}
impl<T, F: Fn(T) -> T> From<F> for Custom<T, F> {
fn from(f: F) -> Self {
Self {
f,
_marker: PhantomData,
}
}
}
impl<T, F: Fn(T) -> T> Transform<T> for Custom<T, F> {
fn transform(&self, value: T) -> T {
todo!()
}
}
/// Repeats transformation for `n` times.
#[derive(Debug, Clone, Copy)]
pub struct Repeat<T, Tr: Transform<T>> {
inner: Tr,
n: u32,
_marker: PhantomData<T>,
}
impl<T, Tr: Transform<T>> Repeat<T, Tr> {
/// Creates a new repeat transformation.
pub fn new(inner: Tr, n: u32) -> Self {
Repeat {
inner,
n,
_marker: PhantomData,
}
}
}
impl<T, Tr: Transform<T>> Transform<T> for Repeat<T, Tr> {
fn transform(&self, mut value: T) -> T {
todo!()
}
}
/// Repeats transformation until converges.
#[derive(Debug, Clone, Copy)]
pub struct RepeatUntilConverge<T: Eq, Tr: Transform<T>> {
inner: Tr,
_marker: PhantomData<T>,
}
impl<T: Clone + Eq, Tr: Transform<T>> RepeatUntilConverge<T, Tr> {
/// Creates a new repeat transformation.
pub fn new(inner: Tr) -> Self {
RepeatUntilConverge {
inner,
_marker: PhantomData,
}
}
}
impl<T: Clone + Eq, Tr: Transform<T>> Transform<T> for RepeatUntilConverge<T, Tr> {
fn transform(&self, mut value: T) -> T {
todo!()
}
}

View File

@@ -0,0 +1,62 @@
#[cfg(test)]
mod test {
use itertools::Itertools;
use ntest::assert_about_eq;
use super::super::transform::*;
#[test]
fn test_transform_identity() {
let tr = Identity;
assert_eq!(tr.transform(3), 3);
assert_eq!(tr.transform(3.0), 3.0);
assert_eq!(tr.transform("abc"), "abc");
}
#[test]
fn test_transform_tuple() {
let f1 = |x: u32| x + 1;
let f2 = |x: String| x.clone() + &x;
let tr1: Custom<_, _> = f1.into();
let tr2: Custom<_, _> = f2.into();
let list1 = 0u32..10u32;
let list2 = ["a".to_string(), "bb".to_string(), "ccc".to_string()];
for v1 in list1 {
for v2 in list2.clone() {
let tr = (tr1, tr2.clone());
let input = (v1, v2.clone());
let expected = (f1(v1), f2(v2));
assert_eq!(tr.transform(input), expected);
}
}
}
#[test]
fn test_transform_repeat() {
let inc = Custom::from(|x: i32| x + 1);
let dec = Custom::from(|x: i32| x - 1);
for i in 0..10 {
for j in -10..10 {
assert_eq!(Repeat::new(inc, i as u32).transform(j), j + i);
assert_eq!(Repeat::new(dec, i as u32).transform(j), j - i);
}
}
}
#[test]
fn test_transform_repeat_until_converge() {
let inc = Custom::from(|x: i32| if x < 50 { x + 1 } else { x });
let dec = Custom::from(|x: i32| if x > 50 { x - 1 } else { x });
assert_eq!(RepeatUntilConverge::new(inc).transform(40), 50);
assert_eq!(RepeatUntilConverge::new(inc).transform(60), 60);
assert_eq!(RepeatUntilConverge::new(dec).transform(40), 40);
assert_eq!(RepeatUntilConverge::new(dec).transform(60), 50);
}
}