I asked Chatgpt to test my skills

Greetings you all,
I am new to rust and decided to prompt chatgpt to test me having learnt from the first chapter of the rust book down to the Struct part.
Here was the test

Define a struct called Rectangle with fields width and height.
Implement a method inside the Rectangle struct that returns the area of the rectangle. The method should return an Option—return None if either width or height is zero, as a rectangle with zero dimensions is invalid.

Then, implement a method to compare two rectangles:

If the first rectangle is larger, return Some("First").
If the second rectangle is larger, return Some("Second").
If they are the same size, return Some("Equal").
If one of the rectangles is invalid, return None.

I made a struct.rs file for my struct and this was my logic

#[derive(Debug)]
pub struct Rectangle{
    pub width: u32,
    pub height: u32
}

impl Rectangle {
    pub fn area(&self) -> Option<u32>{
        if self.width.to_string() == "0" || self.height.to_string() == "0"{
            return  None
        }
        Some(self.width * self.height)
    }
}

impl Rectangle {
    pub fn compare(&self, rec2: Rectangle) -> Option<&str>{
        if self.area() > rec2.area(){
            Some("First")
        }
        else if self.area() == rec2.area() {
            Some("equal")
        }
        else if self.area()<rec2.area() {
            Some("rec2")
        }
        else {
            None
        }
    }
} 

Here is my main.rs

use structs::Rectangle;
mod structs;
fn main(){

        let rec1 = structs::Rectangle{
            width: 55,
            height: 46
        };

        match rec1.area(){
            Some(a) => println!("The area is {}",a),
            None => panic!("Sorry error")
        }

        let rec2: Rectangle = structs::Rectangle{
            ..rec1
        };

        println!("Rec1 is {:?} to Rec2", rec1.compare(rec2));

    }

Haven submitted to chatgpt for check, it brought to my notice a couple issues of which i have studied about but i still need your idea or contribution on this particular part where it said i can't directly compare the Option values using operators.... and the second part where it says i shouldn't compare self.width.to_string() with "0" i literally cracked my brain for an alternative while attempting the question but i found none because 0 itself is an i32 type and self.width is a &u32 type... i tried using into() and deferencing the &u32 but it wouldn't work:(

Your contributions are much appreciated thanks

I've created a playground with minor changes to your code.

I'd recommend having a look at rustlings as a resource for learning Rust. It offers you solutions you can look at to self-validate your code.

6 Likes

Thank you so much for your reply.

I will definitely check the playground out and yeah i make use rustlings too I've solved all exercises down to structs and trying to learn enums to proceed.

Thank you for your reply ones more.

This is more Rust way:

1 Like

If you think about it a bit more, it can't be true can it? Are signed 32 bits the only numeric type allowed to have values of 0? It would be ludicrous if they were.

What you've spotted is that with no other context, rust infers that a 0 is type i32. It's an arbitrary default numeric type.

But

let a: u8 = 0;
let b: i64 = 0;
let c: usize = 0;

Is all fine.

In fact:

fn needs_u8(n: u8) {
    // ...
}

let a = 0;
needs_u8(a);  // a is inferred to be a u8
1 Like

ChatGPT gave some requirements I think are bad:

  • Rectangles with a size of zero in either dimension are, usually, perfectly valid. But...
  • If you really want to maintain that invariant, then make the fields private. Then you can return a failure once, in initialization, rather than many times all over. In fact, you could even use NonZeroU32 (don't worry about it though). In any case, please don't pretend that certain values are acceptable, only to throw errors down the line (again, that's GPT's fault, not yours).
  • Rust specifically has an enum, std::cmp::Ordering, for the result of a comparison. Use the Greater, Lesser, and Equal variants, rather than "First", "Second", and "Equal". If you've addressed my first two points, you can also drop the Option part entirely.

These are issues with ChatGPT's challenge, not your implementation. However, I think it's indicative of how bad LLMs are at Rust: in the future, I'd recommend avoiding them.

7 Likes

Wow much thanks Kyllingene
Got that🙏

Looks scary for a beginner i guess :joy:
Thank you🙏got alot to learn from from your solution

That Ord impl claims Rect::new(55, 46) is equal to Rect::new(46, 55). This has some implications such as the inability to store these two rectangles in a BTreeSet.

Relatedly, the PartialOrd impl violates the requirement:

a == b if and only if partial_cmp(a, b) == Some(Equal).

The second assertion fails:

let rec1 = Rectangle::new(55, 46);
let rec2 = Rectangle::new(46, 55);

assert_eq!(rec1.partial_cmp(&rec2), Some(Ordering::Equal));
assert_eq!(rec1, rec2);
7 Likes

I knew something seemed fishy about ordering by area. This articulates it well!

1 Like

I'd not drop the Option, but use it for a different reason:

2 Likes

There are a couple of ways to order by area that don’t run into this problem:

  • Only implement PartialOrd such that rectangles with the same area and differing dimensions are both unequal and unorderable.
  • Sort by area first, and then break ties by ordering on something else that distinguishes rectangle of equal area. The most obvious choice would be either width or height, but you could also do something more complicated like sorting by aspect ratio instead.
1 Like