commit 73faa75086422b1d5aa8ef8d509e261526528779 Author: Olivia Brooks <109807080+Cutieguwu@users.noreply.github.com> Date: Mon Jun 16 07:32:32 2025 -0400 Initial commit to repo. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..9aef30e --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "quartile_calculator" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e003a8d --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "quartile_calculator" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/main.py b/main.py new file mode 100644 index 0000000..9bd609e --- /dev/null +++ b/main.py @@ -0,0 +1,40 @@ +from dataclasses import dataclass +from sys import float_info +from typing import TypeAlias; + +@dataclass +class DatasetCalculator: + data_set: list[float] + + def first_quartile(self) -> float: + self.lower_data_set() + + def second_quartile(self) -> float: + ... + + def third_quartile(self) -> float: + ... + + def interquartile_range(self) -> float: + ... + + def semi_interquartile_range(self) -> float: + ... + + def strip_outliers(self) -> DatasetCalculator: + ... + + def lower_data_set(self) -> DatasetCalculator: + ... + + def upper_data_set(self) -> DatasetCalculator: + ... + + def median(self) -> float: + ... + +def main(): + ... + +if __name__ == '__main__': + main() diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..8036039 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,241 @@ +fn main() { + let arizona_state: Vec = vec![11.0, 16.0, 16.0, 16.0, 9.0, 15.0]; + + let colorado: Vec = vec![10.0, 15.0, 12.0, 12.0, 20.0]; + + let iowa: Vec = vec![18.0, 10.0, 13.0, 17.0, 19.0, 16.0, 18.0]; + + let nebraska: Vec = vec![15.0, 28.0, 15.0, 20.0, 10.0, 11.0, 12.0]; + + let south_carolina: Vec = vec![18.0, 15.0, 10.0, 18.0]; + + let syracuse: Vec = vec![14.0, 19.0, 11.0, 15.0, 19.0]; + + let texas: Vec = vec![20.0, 17.0, 9.0, 9.0, 27.0]; + + println!("Arizona Average: {}", average(&arizona_state)); + println!("Colorado Average: {}", average(&colorado)); + println!("Iowa Average: {}", average(&iowa)); + println!("Nebraska Average: {}", average(&nebraska)); + println!("SouthCarolina Average: {}", average(&south_carolina)); + println!("Syracuse Average: {}", average(&syracuse)); + println!("TexasAnM Average: {}", average(&texas)); + + let mut set: Vec = vec![]; + set.extend(arizona_state); + set.extend(colorado); + set.extend(iowa); + set.extend(nebraska); + set.extend(south_carolina); + set.extend(syracuse); + set.extend(texas); + + let mut d = Dataset::from(set); + println!("Pre-outlier Stripping: {:#?}", d.0); + + println!("Q1: {}", d.quartile(Quartile::First)); + println!("Q2: {}", d.quartile(Quartile::Second)); + println!("Q3: {}", d.quartile(Quartile::Third)); + + d.strip_outliers(); + println!("Outliers Stripped: {:#?}", d.0) +} + +fn average(values: &Vec) -> f64 { + values.iter().sum::() / values.len() as f64 +} + +#[derive(Debug, Clone, PartialEq)] +struct Dataset(Vec); + +impl From> for Dataset { + fn from(mut value: Vec) -> Self { + Dataset({ + value.sort_by(|a, b| a.partial_cmp(b).unwrap()); + value + }) + } +} + +impl Dataset { + fn quartile(&self, quartile: Quartile) -> f64 { + let data_set = match quartile { + Quartile::First => self.half_data_set(Half::Lower), + Quartile::Second => self.clone(), + Quartile::Third => self.half_data_set(Half::Upper), + }; + + data_set.median() + } + + /// Returns a half of the data set. + /// This method may get screwy with very small datasets. + fn half_data_set(&self, half: Half) -> Self { + let mut data = self.0.clone(); + let length = data.len(); + let middle_idx = length / 2; + + if (length % 2) != 0 { + data.remove(middle_idx); + } + + let data_set = match half { + Half::Lower => Dataset({ + let _ = data.split_off(middle_idx); + data + }), + Half::Upper => Dataset(data.split_off(middle_idx)), + }; + + data_set + } + + fn median(&self) -> f64 { + let data = self.0.clone(); + let length = data.len(); + + let a = data[length / 2]; + + let median = if (length % 2) == 0 { + let s: [f64; 2] = [a, data[(length / 2) - 1]]; + + s.iter().sum::() / 2_f64 + } else { + a + }; + + median + } + + fn interquartile_range(&self) -> f64 { + self.quartile(Quartile::Third) - self.quartile(Quartile::First) + } + + fn strip_outliers(&mut self) { + let mut data: Vec; + + let first_quartile = self.quartile(Quartile::First); + let third_quartile = self.quartile(Quartile::Third); + let iqr_margin = 1.5 * self.interquartile_range(); + + // Filter low outliers + data = self + .0 + .clone() + .into_iter() + .filter_map(|x| { + if x >= (first_quartile - iqr_margin) { + Some(x) + } else { + None + } + }) + .collect::>(); + + // Filter high outliers. + data = data + .into_iter() + .filter_map(|x| { + if x <= (third_quartile + iqr_margin) { + Some(x) + } else { + None + } + }) + .collect::>(); + + self.0 = data + } +} + +struct Percentile(Vec); + +enum Quartile { + First, + Second, + Third, +} + +enum Half { + Upper, + Lower, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn odd_quartiles() { + let d = Dataset::from(vec![ + 1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64, + ]); + + assert_eq!(d.quartile(Quartile::First), 3_f64); + assert_eq!(d.quartile(Quartile::Second), 6_f64); + assert_eq!(d.quartile(Quartile::Third), 9_f64); + } + + #[test] + fn even_quartiles() { + let d = Dataset::from(vec![ + 1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64, + ]); + + assert_eq!(d.quartile(Quartile::First), 3.5_f64); + assert_eq!(d.quartile(Quartile::Second), 6.5_f64); + assert_eq!(d.quartile(Quartile::Third), 9.5_f64); + } + + #[test] + fn odd_dataset_halves() { + let d = Dataset::from(vec![ + 1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64, + ]); + + assert_eq!( + d.half_data_set(Half::Lower), + Dataset::from(vec![1_f64, 2_f64, 3_f64, 4_f64, 5_f64]) + ); + assert_eq!( + d.half_data_set(Half::Upper), + Dataset::from(vec![7_f64, 8_f64, 9_f64, 10_f64, 11_f64]) + ); + } + + #[test] + fn even_dataset_halves() { + let d = Dataset::from(vec![ + 1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64, + ]); + + assert_eq!( + d.half_data_set(Half::Lower), + Dataset::from(vec![1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64]) + ); + assert_eq!( + d.half_data_set(Half::Upper), + Dataset::from(vec![7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64]) + ); + } + + #[test] + fn interquartile_range() { + let d = Dataset::from(vec![ + 1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64, + ]); + + assert_eq!(d.interquartile_range(), 6_f64) + } + + #[test] + fn strip_outliers() { + let mut d = Dataset::from(vec![ + 1_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64, 98_f64, + ]); + + d.strip_outliers(); + + assert_eq!(d.0, vec![7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64]) + } +}