[Rustlings] struct3

Im trying to solve this one but im really stuck.

So far I have this :

// structs3.rs

// Structs contain more than simply some data, they can also have logic, in this

// exercise we have defined the Package struct and we want to test some logic attached to it,

// make the code compile and the tests pass! If you have issues execute `rustlings hint structs3`

// I AM NOT DONE

#[derive(Debug)]

struct Package {

   sender_country: String,

   recipient_country: String,

   weight_in_grams: i32,

}

impl Package {

   fn new(sender_country: String, recipient_country: String, weight_in_grams: i32) -> Package {

       if weight_in_grams <= 0 {

           panic!() 

       } else {

           return Package {sender_country, recipient_country, weight_in_grams};

       }

   }

   fn is_international(&self) -> bool {

       &self.sender_country != &self.recipient_country

   }

   fn get_fees(&self, cents_per_kg: i32) -> i32 {

       (&self.weight_in_grams * 1000) * cents_per_kg

   }

}

#[cfg(test)]

mod tests {

   use super::*;

   #[test]

   #[should_panic]

   fn fail_creating_weightless_package() {

       let sender_country = String::from("Spain");

       let recipient_country = String::from("Austria");

       Package::new(sender_country, recipient_country, -2210);

   }

   #[test]

   fn create_international_package() {

       let sender_country = String::from("Spain");

       let recipient_country = String::from("Russia");

       

       let package = Package::new(sender_country, recipient_country, 1200);

       assert!(package.is_international());

   }

   #[test]

   fn calculate_transport_fees() {

       let sender_country = String::from("Spain");

       let recipient_country = String::from("Spain");

       let cents_per_kg = 3;

       

       let package = Package::new(sender_country, recipient_country, 1500);

       

       assert_eq!(package.get_fees(cents_per_kg), 4500);

   }

}

and now the test fail with this :

---- tests::fail_creating_weightless_package stdout ----
thread 'tests::fail_creating_weightless_package' panicked at 'explicit panic', exercises/structs/structs3.rs:18:13


successes:
    tests::create_international_package
    tests::fail_creating_weightless_package

failures:

---- tests::calculate_transport_fees stdout ----
thread 'tests::calculate_transport_fees' panicked at 'assertion failed: `(left == right)`
  left: `4500000`,
 right: `4500`', exercises/structs/structs3.rs:65:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

relevant test :

#[test]

   #[should_panic]

   fn fail_creating_weightless_package() {

       let sender_country = String::from("Spain");

       let recipient_country = String::from("Austria");

       Package::new(sender_country, recipient_country, -2210);

   }
#[test]

    fn calculate_transport_fees() {

        let sender_country = String::from("Spain");

        let recipient_country = String::from("Spain");

        let cents_per_kg = 3;

        

        let package = Package::new(sender_country, recipient_country, 1500);

        

        assert_eq!(package.get_fees(cents_per_kg), 4500);

    }

This will be equal to weight in milligrams, not kilograms.

oke,

Still no luck

 fn get_fees(&self, cents_per_kg: i32) -> i32 {
        (&self.weight_in_grams / 1000) * cents_per_kg
    }
 #[test]
    fn calculate_transport_fees() {
        let sender_country = String::from("Spain");
        let recipient_country = String::from("Spain");

        let cents_per_kg = 3000;
        
        let package = Package::new(sender_country, recipient_country, 1500);
        
        assert_eq!(package.get_fees(cents_per_kg), 4500);
    }
---- tests::calculate_transport_fees stdout ----
thread 'tests::calculate_transport_fees' panicked at 'assertion failed: `(left == right)`
  left: `3000`,
 right: `4500`', exercises/structs/structs3.rs:65:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

This is integer division, i.e. the result is rounded down. Try changing the order of operations, so that the number being rounded will be divided exactly.

bummer and this is also not working :

fn get_fees(&self, cents_per_kg: i32) -> i32 {
        &self.weight_in_grams / 1000 * cents_per_kg
    }

still wierd that in a challenge where you are learning to use structs, this sort of things are in it

As @Cerberuser pointed out, the truncating division needs to occur last. I would also round up rather than truncate, since most sellers want to make money, not lose it. [Some sellers would further bias the rounding in their favor by using a value greater than (1000/2).]

fn get_fees(&self, cents_per_kg: i32) -> i32 {
        (&self.weight_in_grams * cents_per_kg  + (1000 / 2) ) / 1000
    }

Thanks,

Finallt every test is greeen
is this wel written rust code then :

#[derive(Debug)]
struct Package {
    sender_country: String,
    recipient_country: String,
    weight_in_grams: i32,
}

impl Package {
    fn new(sender_country: String, recipient_country: String, weight_in_grams: i32) -> Package {
        if weight_in_grams <= 0 {
            panic!() 
        } else {
            return Package {sender_country, recipient_country, weight_in_grams};
        }
    }

    fn is_international(&self) -> bool {
        &self.sender_country != &self.recipient_country
    }

    fn get_fees(&self, cents_per_kg: i32) -> i32 {
        (&self.weight_in_grams * cents_per_kg  + (1000 / 2) ) / 1000
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    #[should_panic]
    fn fail_creating_weightless_package() {
        let sender_country = String::from("Spain");
        let recipient_country = String::from("Austria");

        Package::new(sender_country, recipient_country, -2210);
    }

    #[test]
    fn create_international_package() {
        let sender_country = String::from("Spain");
        let recipient_country = String::from("Russia");
        
        let package = Package::new(sender_country, recipient_country, 1200);

        assert!(package.is_international());
    }

    #[test]
    fn calculate_transport_fees() {
        let sender_country = String::from("Spain");
        let recipient_country = String::from("Spain");

        let cents_per_kg = 3000;
        
        let package = Package::new(sender_country, recipient_country, 1500);
        
        assert_eq!(package.get_fees(cents_per_kg), 4500);
    }
}

is this not better then :

fn get_fees(&self, cents_per_kg: i32) -> i32 {

       (&self.weight_in_grams * cents_per_kg).div_euclid(1000) 

   }

Mathematically it makes no difference, since both weight_in_grams and cents_per_kg will be non-negative. According to the method definition,

Note: The above statement is also true for an integer dividend of 0.

As I noted in my prior post, if you are the seller then over the long term you will lose money by not rounding the division. However, if you are the buyer, you will save money if the seller is too naïve to round the division.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.