diff --git a/current-calculator/.gitignore b/current-calculator/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/current-calculator/.gitignore @@ -0,0 +1 @@ +/target diff --git a/current-calculator/Cargo.lock b/current-calculator/Cargo.lock new file mode 100644 index 0000000..eee7a8d --- /dev/null +++ b/current-calculator/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "current-calculator" +version = "0.1.0" diff --git a/current-calculator/Cargo.toml b/current-calculator/Cargo.toml new file mode 100644 index 0000000..aaf3644 --- /dev/null +++ b/current-calculator/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "current-calculator" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/current-calculator/challenge.md b/current-calculator/challenge.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/current-calculator/challenge.md @@ -0,0 +1 @@ + diff --git a/current-calculator/src/main.rs b/current-calculator/src/main.rs new file mode 100644 index 0000000..65b6327 --- /dev/null +++ b/current-calculator/src/main.rs @@ -0,0 +1,122 @@ +use std::f32; + +fn main() { + println!("Hello, world!"); +} + +// TODO: maybe don't cast all good data as float?? +#[derive(Clone, Debug)] +enum EntryValue { + NoneType, + Float(f32), + String(String), +} + +// impl Eq for EntryValue { +// fn e +// } + +struct DataEntry { + power: EntryValue, + voltage: EntryValue, +} + +impl DataEntry { + pub fn new(power: EntryValue, voltage: EntryValue) -> Self { + Self { power, voltage } + } + + pub fn compute_current(&self) -> Option { + // check the data types, only return Some(value) if both data entries are valid + match (&self.power, &self.voltage) { + (EntryValue::Float(power), EntryValue::Float(voltage)) => Some(power / voltage), + _ => None, + } + } +} + +struct DataParser { + dataset: Vec, +} + +impl DataParser { + pub fn new(powers: Vec, voltages: Vec) -> Self { + // TODO: generate our vec of DataEntry out of EntryValues + let mut dataset = Vec::new(); + + // TODO: don't use clone here, also just don't create the whole dataset variable (waste memory) + for i in 0..powers.len() { + dataset.push(DataEntry { + power: powers[i].clone(), + voltage: voltages[i].clone(), + }) + } + + Self { dataset } + } + + pub fn get_result(&self) -> Vec> { + let mut res = Vec::new(); + for entry in &self.dataset { + res.push(entry.compute_current()); + } + res + } +} + +#[cfg(test)] +mod test { + use super::DataEntry; + use super::DataParser; + use super::EntryValue; + + #[test] + fn test_current_calc() { + // TODO: maybe have some amount of randomness here + let p = EntryValue::Float(4.0); + let v = EntryValue::Float(2.0); + let exp_i = Some(2.0); + + let de = DataEntry::new(p, v); + + let i = de.compute_current(); + + assert_eq!(i, exp_i); + } + + #[test] + fn bad_data_test() { + let powers = vec![ + EntryValue::Float(37.2), + EntryValue::Float(0.0), + EntryValue::String("X".into()), + EntryValue::Float(-192.0), + EntryValue::NoneType, + ]; + let voltages = vec![ + EntryValue::NoneType, + EntryValue::Float(82.8), + EntryValue::Float(32.0), + EntryValue::Float(-76.0), + EntryValue::String("Y".into()), + ]; + + // one memory opt we could do is to implement a zipped iterator + let data_parser = DataParser::new(powers, voltages); + + let res = data_parser.get_result(); + + let test_result = vec![None, Some(0.0), None, Some(2.5263157), None]; + // let test_result = vec![None, Some(0.0), None, Some(2.52631), None]; + + for i in 0..res.len() { + assert_eq!(res[i], test_result[i]) + } + } +} + +// TEST CONDITION +// powers = [37.2, 0, "X", -192, None] +// voltages = [None, 82.8, 32, -76, "Y"] + +// result = [None, 0.0, None, 2.52631, None]