Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test for Median trait #267

Merged
merged 1 commit into from
Jan 14, 2025
Merged

Add test for Median trait #267

merged 1 commit into from
Jan 14, 2025

Conversation

rustaceanrob
Copy link
Owner

The median time past check is failing over Testnet4 (issue #265). Here I am adding a check to be sure the Median trait defined in the prelude works as expected

cc @nyonson


#[test]
fn test_median() {
let mut empty: Vec<u32> = Vec::new();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these fixtures need to be mutable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, just found the median trait and see that it needs to sort.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, for now there is a sort, but it potentially makes the trait harder to reason about. In a follow-up it might be worthwhile to change this to a copy. Especially if it squashes the testnet4 bug

@nyonson
Copy link
Contributor

nyonson commented Jan 14, 2025

Just spit balling, but I wonder if its worth considering a trait bound implementation (got this set of traits from Claude) to DRY-ify the impl.

use std::ops::Add;
use std::cmp::Ord;

pub trait Median {
    type Output;
    fn median(&mut self) -> Self::Output;
}

impl<T> Median for Vec<T>
where
    T: Copy + Ord + Add<Output = T> + From<u8>,
{
    type Output = T;

    fn median(&mut self) -> T {
        if self.is_empty() {
            return T::from(0);
        }

        self.sort();
        let len = self.len();
        let mid = len / 2;

        if len % 2 == 1 {
            self[mid]
        } else {
            (self[mid - 1] + self[mid]) / T::from(2)
        }
    }
}

Also, I believe there are some potential overflow cases? Haven't actually put the thought in though if the domain cares.

@rustaceanrob
Copy link
Owner Author

rustaceanrob commented Jan 14, 2025

Skeptical of the From<u8> one. i.e. signed integers can't implement the trait. Otherwise, I like that it becomes generic over output. Worthwhile to revisit in another PR.

edit: Nevermind on From<u8>, that requirement is for the T::from(2) I see, which is no problem for signed types. Definitely worth the revisit then.

Copy link
Contributor

@nyonson nyonson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 037e262

Makes sense, sparked a few follow up ideas for later.

@rustaceanrob rustaceanrob merged commit caeb7eb into master Jan 14, 2025
14 checks passed
@rustaceanrob rustaceanrob deleted the median-1-14 branch January 14, 2025 23:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants