#![allow(unused)]
fn main() {
/*!
lifetimes illustrates the use of [Vec] and the Error Handling with [Option] and [Result].
It also showcases struct enums.
*/
pub mod custom_int;
pub mod io;
mod minimum;
pub mod something_or_nothing;
#[cfg(test)]
mod tests {
use crate::minimum::Minimum;
use crate::something_or_nothing::{SomethingOrNothing, find_min};
#[test]
fn test_creation() {
let n1: SomethingOrNothing<i32> = SomethingOrNothing::default();
assert!(n1 == SomethingOrNothing::default());
let n2: SomethingOrNothing<i32> = SomethingOrNothing::new(1);
assert!(n2 == SomethingOrNothing::new(1));
}
#[test]
#[should_panic]
fn test_failure_creation() {
let n2: SomethingOrNothing<i32> = SomethingOrNothing::new(1);
assert!(n2 == SomethingOrNothing::default());
assert!(n2 == SomethingOrNothing::new(2));
}
#[test]
fn test_min() {
let a = vec![1, 5, -1, 2, 0, 10, 11, 0, 3];
let min = find_min(&a);
assert!(*min.unwrap() == -1);
}
#[test]
fn test_min_empty() {
let a: Vec<i32> = vec![];
let min = find_min(&a);
assert!(min == SomethingOrNothing::default());
}
#[test]
fn test_min_i32() {
let x = 5;
let y = 10;
assert_eq!(*Minimum::min(&x, &y), x);
assert_eq!(*Minimum::min(&y, &x), x);
assert_eq!(*Minimum::min(&x, &x), x);
assert_eq!(*Minimum::min(&y, &y), y);
}
#[test]
fn test_min_something_or_nothing() {
let x = SomethingOrNothing::new(5i32);
let y = SomethingOrNothing::new(10i32);
let z = SomethingOrNothing::default();
assert!(*x.min(&y) == x);
assert!(*y.min(&x) == x);
assert!(*z.min(&y) == y);
assert!(*y.min(&z) == y);
assert!(*z.min(&z) == z);
}
}
}
use lifetimes::custom_int::CustomInt;
use lifetimes::io;
use lifetimes::something_or_nothing::find_min;
// ANCHOR: main
fn main() -> Result<(), String> {
let v1 = vec![1, 3, 6, 9];
let v2 = vec![2, 4, 2, 1];
let v3 = vec![7, 4, 5, 3];
let v4 = vec![4, 1, 1, 1];
let v5 = vec![2, 5, 1, 8];
let v6 = vec![5, 1, 5, 2];
let v7 = vec![7, 6, 6, 7];
let v8 = vec![8, 2, 2, 2];
let lhs = vec![
CustomInt::try_new(&v1, 1)?,
CustomInt::try_new(&v2, -1)?,
CustomInt::try_new(&v3, 1)?,
CustomInt::try_new(&v4, -1)?,
CustomInt::try_new(&v5, 1)?,
CustomInt::try_new(&v6, 1)?,
CustomInt::try_new(&v7, 1)?,
CustomInt::try_new(&v8, 1)?,
];
println!("Among the custom ints in the list:");
io::print_tab_custom_int(&lhs);
let min = find_min(&lhs);
println!("The minimum is {min}");
Ok(())
}
// ANCHOR_END: main
#![allow(unused)]
fn main() {
use std::cmp::Ordering;
use crate::minimum::Minimum;
/// Larger ints based on a [Vec] of [u8] to represent arbitrary lengthy numbers.
/// The number has a sign as well.
// ANCHOR: custom_int
#[derive(Debug)]
pub struct CustomInt<'a> {
/// The data contains the unsigned integers that are read from right to left
/// The number 1337 is stored as vec![7, 3, 3, 1]. Each number must be in the range [0,9]
/// and no trailing 0s are allowed.
data: &'a Vec<u8>,
/// Contains the sign of the number +/-1;
sign: i8,
}
// ANCHOR_END: custom_int
// ANCHOR: custom_int_impl
impl<'a> CustomInt<'a>
// ANCHOR_END: custom_int_impl
{
/// Tries to create a new [CustomInt]. If the number is valid it returns
/// an Ok(CustomInt) an Error otherwise.
///
/// # Examples
///
/// ```
/// use lifetimes::custom_int::CustomInt;
/// let v1 = vec![1, 2, 3, 4];
/// let num = CustomInt::try_new(&v1, 1);
/// assert!(num.is_ok());
/// let num = CustomInt::try_new(&v1, -1);
/// assert!(num.is_ok());
/// let num = CustomInt::try_new(&v1, 10);
/// assert!(num.is_err());
/// let num = CustomInt::try_new(&v1, -10);
/// assert!(num.is_err());
/// let v1 = vec![];
/// let num = CustomInt::try_new(&v1, -1);
/// assert!(num.is_err());
/// ```
///
// ANCHOR: try_new
pub fn try_new(data: &'a Vec<u8>, sign: i8) -> Result<Self, String> {
if data.is_empty() {
Err(String::from("Data is empty."))
} else if sign == 1 || sign == -1 {
Ok(CustomInt { data, sign })
} else {
Err(String::from("Invalid sign."))
}
}
// ANCHOR_END: try_new
}
// ANCHOR: minimum
impl<'a> Minimum<'a> for CustomInt<'a>
// ANCHOR_END: minimum
{
// ANCHOR: min
fn min(&'a self, rhs: &'a Self) -> &'a Self {
match self.sign.cmp(&rhs.sign) {
Ordering::Less => return self,
Ordering::Greater => return rhs,
Ordering::Equal => match self.data.len().cmp(&rhs.data.len()) {
Ordering::Less => {
if self.sign == 1 {
return self;
} else {
return rhs;
}
}
Ordering::Greater => {
if self.sign == 1 {
return rhs;
} else {
return self;
}
}
Ordering::Equal => {
for (l, r) in self.data.iter().rev().zip(rhs.data.iter().rev()) {
let ls = (*l as i8) * self.sign;
let rs = (*r as i8) * self.sign;
match ls.cmp(&rs) {
Ordering::Less => return self,
Ordering::Greater => return rhs,
Ordering::Equal => {}
}
}
}
},
}
self
}
// ANCHOR_END: min
}
// ANCHOR: partialeq
impl<'a> PartialEq for CustomInt<'a>
// ANCHOR_END: partialeq
{
fn eq(&self, other: &Self) -> bool {
if self.sign == other.sign && self.data.len() == other.data.len() {
self.data
.iter()
.zip(other.data.iter())
.try_fold(true, |_, (l, r)| if *l == *r { Some(true) } else { None })
.is_some()
} else {
false
}
}
}
// ANCHOR: display
impl<'a> std::fmt::Display for CustomInt<'a>
// ANCHOR_END: display
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// This could be replaced by an `?`
if self.sign == -1 {
write!(f, "-")?;
}
// This could be replaced by an `?`
let res = self
.data
.iter()
.rev()
.try_fold((), |_, t| write!(f, "{}", t));
res
}
}
#[cfg(test)]
mod tests {
use crate::custom_int::CustomInt;
use crate::minimum::Minimum;
use crate::something_or_nothing::find_min;
#[test]
fn test_creation() {
let v1 = vec![1, 2, 3, 4];
CustomInt::try_new(&v1, 1).unwrap();
CustomInt::try_new(&v1, -1).unwrap();
}
#[test]
#[should_panic]
fn test_failure_creation_sign() {
let v1 = vec![1, 2, 3, 4];
CustomInt::try_new(&v1, 10).unwrap();
}
#[test]
#[should_panic]
fn test_failure_creation_sign2() {
let v1 = vec![1, 2, 3, 4];
CustomInt::try_new(&v1, 0).unwrap();
}
#[test]
#[should_panic]
fn test_failure_creation_data() {
let v1 = vec![];
CustomInt::try_new(&v1, 1).unwrap();
}
#[test]
fn test_min() {
let mut v = Vec::new();
let v1 = vec![1, 2, 3, 4];
let v2 = vec![1, 2, 3];
let lhs = CustomInt::try_new(&v1, 1).unwrap();
let rhs = CustomInt::try_new(&v2, 1).unwrap();
assert!(rhs == *lhs.min(&rhs));
v.push(lhs);
v.push(rhs);
let lhs = CustomInt::try_new(&v1, -1).unwrap();
let rhs = CustomInt::try_new(&v2, -1).unwrap();
assert!(lhs == *lhs.min(&rhs));
v.push(lhs);
v.push(rhs);
let v1 = vec![1, 2, 3, 4];
let v2 = vec![1, 2, 5, 4];
let lhs = CustomInt::try_new(&v1, -1).unwrap();
let rhs = CustomInt::try_new(&v2, -1).unwrap();
assert!(rhs == *lhs.min(&rhs));
v.push(lhs);
v.push(rhs);
let lhs = CustomInt::try_new(&v1, 1).unwrap();
let rhs = CustomInt::try_new(&v2, 1).unwrap();
assert!(lhs == *lhs.min(&rhs));
let min = find_min(&v);
assert_eq!(*min.unwrap(), CustomInt::try_new(&v2, -1).unwrap());
}
}
}
#![allow(unused)]
fn main() {
use crate::custom_int::CustomInt;
/// Prints all the elements of the `tab`.
/// Tab is borrowed here
pub fn print_tab(tab: &Vec<i32>) {
for t in tab {
print!("{} ", t);
}
println!();
}
/// Prints all the elements of the `tab`.
/// Tab is borrowed here
pub fn print_tab_custom_int(tab: &Vec<CustomInt>) {
for i in tab {
println!("{i} ");
}
println!();
}
}
#![allow(unused)]
fn main() {
// ANCHOR: minimum
pub trait Minimum<'a> {
fn min(&'a self, rhs: &'a Self) -> &'a Self;
}
// ANCHOR_END: minimum
// ANCHOR: min
impl<'a> Minimum<'a> for i32 {
fn min(&'a self, rhs: &'a Self) -> &'a Self {
if self < rhs { self } else { rhs }
}
}
// ANCHOR_END: min
}
use std::fmt::Display;
use crate::minimum::Minimum;
/// A generic newtype that wraps an Option<T>.
// ANCHOR: newtype
#[derive(Debug)]
pub struct SomethingOrNothing<T>(Option<T>);
// ANCHOR_END: newtype
impl<T> SomethingOrNothing<T> {
pub fn new(val: T) -> Self {
SomethingOrNothing(Some(val))
}
// ANCHOR: newtype_unwrap
pub fn unwrap(self) -> T {
self.0.unwrap()
}
// ANCHOR_END: newtype_unwrap
}
// ANCHOR: newtype_display
impl<T: Display> std::fmt::Display for SomethingOrNothing<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self {
SomethingOrNothing(None) => write!(f, "Nothing.")?,
SomethingOrNothing(Some(val)) => write!(f, "Something is: {}", val)?,
}
Ok(())
}
}
// ANCHOR_END: newtype_display
// ANCHOR: newtype_default
impl<T> Default for SomethingOrNothing<T> {
/// By Default a [SomethingOrNothing] is a nothing.
fn default() -> Self {
SomethingOrNothing(None)
}
}
// ANCHOR_END: newtype_default
// ANCHOR: newtype_partialeq
impl<T: PartialEq> PartialEq for SomethingOrNothing<T> {
fn eq(&self, other: &Self) -> bool {
match (&self, &other) {
(SomethingOrNothing(None), SomethingOrNothing(None)) => true,
(SomethingOrNothing(Some(lhs)), SomethingOrNothing(Some(rhs))) => lhs == rhs,
_ => false,
}
}
}
// ANCHOR_END: newtype_partialeq
// ANCHOR: min
// ANCHOR: impl_min
impl<'a, T: Minimum<'a> + PartialEq> Minimum<'a> for SomethingOrNothing<T>
// ANCHOR_END: impl_min
{
fn min(&'a self, rhs: &'a Self) -> &'a Self {
match (self, rhs) {
(SomethingOrNothing(None), SomethingOrNothing(None)) => self,
(SomethingOrNothing(Some(l)), SomethingOrNothing(Some(r))) => {
if *l == *l.min(r) {
self
} else {
rhs
}
}
(SomethingOrNothing(None), SomethingOrNothing(Some(_))) => rhs,
(SomethingOrNothing(Some(_)), SomethingOrNothing(None)) => self,
}
}
}
// ANCHOR_END: min
/// Computes the minimum of an Array of a type T which implements the [Minimum] trait.
/// Returns a [Something] containing the minimum value
/// or [Nothing] if no minimum value was found.
///
/// # Examples
///
/// ```
/// # use lifetimes::something_or_nothing::{SomethingOrNothing, find_min};
/// # fn main() {
/// let tab = vec![10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let min = find_min(&tab);
/// assert!(*min.unwrap() == 2);
/// # }
/// ```
///
/// ```
/// # use lifetimes::something_or_nothing::{SomethingOrNothing, find_min};
/// # fn main() {
/// let tab: Vec<i32> = vec![];
/// let min = find_min(&tab);
/// assert!(min == SomethingOrNothing::default());
/// # }
/// ```
// ANCHOR: find_min
pub fn find_min<'a, T: Minimum<'a>>(tab: &'a [T]) -> SomethingOrNothing<&'a T> {
// A very elegant fold applied on an iterator
tab.iter().fold(SomethingOrNothing::default(), |res, x| {
let r = match res {
SomethingOrNothing(None) => x,
SomethingOrNothing(Some(r)) => r.min(x),
};
SomethingOrNothing::new(r)
})
}
// ANCHOR_END: find_min
/// Finds the minimum values contained in two slices and returns the reference
/// towards the slice that contains it.
///
/// # Examples
///
/// ```
/// # use lifetimes::something_or_nothing::{SomethingOrNothing, vec_with_min};
/// # fn main() {
/// let tab1 = vec![10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let tab2 = vec![10, 32, 12, 43, -2, 53, 83, 2, 9];
///
/// let min = vec_with_min(&tab1, &tab2).unwrap();
/// assert!(min == &tab2);
/// # }
/// ```
pub fn vec_with_min<'a, T: Minimum<'a> + PartialEq>(
lhs: &'a [T],
rhs: &'a [T],
) -> SomethingOrNothing<&'a [T]> {
match (find_min(lhs), find_min(rhs)) {
(SomethingOrNothing(None), SomethingOrNothing(None)) => SomethingOrNothing::default(),
(SomethingOrNothing(None), SomethingOrNothing(Some(_))) => SomethingOrNothing::new(rhs),
(SomethingOrNothing(Some(_)), SomethingOrNothing(None)) => SomethingOrNothing::new(lhs),
(SomethingOrNothing(Some(l)), SomethingOrNothing(Some(r))) => {
if *l == *l.min(r) {
SomethingOrNothing::new(lhs)
} else {
SomethingOrNothing::new(rhs)
}
}
}
}