Solve without implementing Copy trait

use std::cmp::Ordering;

#[macro_use]
extern crate itertools;

#[derive(Debug, Eq)]
pub struct Palindrome {
    factors: (u64, u64)
    
}


// assert_eq!(5.cmp(&10), Ordering::Less);
// assert_eq!(10.cmp(&5), Ordering::Greater);
// assert_eq!(5.cmp(&5), Ordering::Equal);

impl PartialOrd for Palindrome {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Palindrome {
    fn cmp(&self, other: &Self) -> Ordering {
        // self.height.cmp(&other.height)
        (self.value()).cmp(&other.value()) 
        
    }
}


impl PartialEq for Palindrome {
    fn eq(&self, other: &Self) -> bool {
        // self.height == other.height
        self.value() == other.value() 


    }
}

impl Palindrome {
    pub fn new(a: u64, b: u64) -> Palindrome {
        Palindrome{
            factors: (b, a)
        }

        
    }

    pub fn value(&self) ->  u64 {
        self.factors.0*self.factors.1
    }

    pub fn insert(&mut self, a: u64, b: u64) {
            self.factors.0 = a;
            self.factors.1 = b;

    }
}


fn reverse_number(mut n: u64) -> u64{
    let radix = 10;
    let mut reversed = 0;

    while n != 0 {
        reversed = reversed * radix + n % radix;
        n /= radix;
    }

    reversed

}


fn is_palindrome(palindrome: &Palindrome) -> bool{
    if palindrome.value() == reverse_number(palindrome.value()){
        return true;
    }
    false
}

pub fn palindrome_products(min: u64, max: u64)-> Option<(Palindrome, Palindrome)>{

    let products = iproduct!(min..=max, min..=max)
        .map(|(i, j)| Palindrome::new(i, j))
        .filter(|palindrome| is_palindrome(palindrome))
        .collect::<Vec<Palindrome>>();

        let min = products.iter().min().unwrap();
        let max = products.iter().max().unwrap();

    Some((*min, *max))

    }

Error:

  Compiling palindrome-products v1.2.0 (/home/feynman/rust_programs/exercism_programs/rust/palindrome-products)
error[E0507]: cannot move out of `*min` which is behind a shared reference
  --> src/lib.rs:93:11
   |
93 |     Some((*min, *max))
   |           ^^^^ move occurs because `*min` has type `Palindrome`, which does not implement the `Copy` trait

error[E0507]: cannot move out of `*min` which is behind a shared reference
  --> src/lib.rs:93:11
   |
93 |     Some((*min, *max))
   |           ^^^^ move occurs because `*min` has type `Palindrome`, which does not implement the `Copy` trait

error[E0507]: cannot move out of `*max` which is behind a shared reference
  --> src/lib.rs:93:17
   |
93 |     Some((*min, *max))
   |                 ^^^^ move occurs because `*max` has type `Palindrome`, which does not implement the `Copy` trait

error[E0507]: cannot move out of `*max` which is behind a shared reference
  --> src/lib.rs:93:17
   |
93 |     Some((*min, *max))
   |                 ^^^^ move occurs because `*max` has type `Palindrome`, which does not implement the `Copy` trait

error: aborting due to 2 previous errors


Why not implement Copy for Palindrome? It's not that big and should be easy to copy around.

2 Likes

THis is how i did it.

pub fn palindrome_products(min: u64, max: u64)-> Option<(Palindrome, Palindrome)>{
    if max <= min {
        return None;
    }

    let products = iproduct!(min..=max, min..=max)
        .map(|(i, j)| Palindrome::new(i, j))
        .filter(|palindrome| is_palindrome(palindrome));

        Some((products.clone().min()?, products.clone().max()?))


    }

That's in fact cloning every Palindrome twice, which, since it conly contains two u64s, is equivalent with making it Copy and going with your original code. There's no advantage to this over the original.

By the way, your code can be vastly simplified to (playground):

use itertools::iproduct;

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Palindrome {
    factors: (u64, u64),
}

impl Palindrome {
    pub fn new(a: u64, b: u64) -> Palindrome {
        Palindrome { factors: (b, a) }
    }

    pub fn value(&self) -> u64 {
        self.factors.0 * self.factors.1
    }

    pub fn insert(&mut self, a: u64, b: u64) {
        self.factors.0 = a;
        self.factors.1 = b;
    }
}

fn reverse_number(mut n: u64) -> u64 {
    let radix = 10;
    let mut reversed = 0;

    while n != 0 {
        reversed = reversed * radix + n % radix;
        n /= radix;
    }

    reversed
}

fn is_palindrome(palindrome: &Palindrome) -> bool {
    palindrome.value() == reverse_number(palindrome.value())
}

pub fn palindrome_products(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
    let products = iproduct!(min..=max, min..=max)
        .map(|(i, j)| Palindrome::new(i, j))
        .filter(is_palindrome);

    let min = products.clone().min()?;
    let max = products.max()?;

    Some((min, max))
}
3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.