Last active
March 13, 2023 17:05
-
-
Save frectonz/5c73638d1131dba704252a74195bb0d3 to your computer and use it in GitHub Desktop.
From cassido's March 13, 2023 Newsletter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use anyhow::{anyhow, Error, Result}; | |
use std::{fmt::Display, str::FromStr}; | |
#[derive(Debug, PartialEq, Eq)] | |
struct Fraction { | |
top: isize, | |
bottom: isize, | |
} | |
impl FromStr for Fraction { | |
type Err = Error; | |
fn from_str(s: &str) -> Result<Self> { | |
let mut s = s.split('/'); | |
let top = s | |
.next() | |
.ok_or_else(|| anyhow!("Couldn't find the nominator"))? | |
.parse()?; | |
let bottom = s | |
.next() | |
.ok_or_else(|| anyhow!("Couldn't find the denominator"))? | |
.parse()?; | |
Ok(Self { top, bottom }) | |
} | |
} | |
impl Fraction { | |
fn add(&self, f: &Fraction) -> Fraction { | |
if self.bottom == f.bottom { | |
Fraction { | |
top: self.top + f.top, | |
bottom: self.bottom, | |
} | |
} else { | |
Fraction { | |
top: (self.top * f.bottom) + (self.bottom * f.top), | |
bottom: self.bottom * f.bottom, | |
} | |
} | |
} | |
fn sub(&self, f: &Fraction) -> Fraction { | |
if self.bottom == f.bottom { | |
Fraction { | |
top: self.top - f.top, | |
bottom: self.bottom, | |
} | |
} else { | |
Fraction { | |
top: (self.top * f.bottom) - (self.bottom * f.top), | |
bottom: self.bottom * f.bottom, | |
} | |
} | |
} | |
fn mult(&self, f: &Fraction) -> Fraction { | |
Fraction { | |
top: self.top * f.top, | |
bottom: self.bottom * f.bottom, | |
} | |
} | |
fn div(&self, f: &Fraction) -> Fraction { | |
Fraction { | |
top: self.top * f.bottom, | |
bottom: self.bottom * f.top, | |
} | |
} | |
fn simplify(&mut self) { | |
let gcd = gcd(self.top, self.bottom); | |
self.top /= gcd; | |
self.bottom /= gcd; | |
} | |
} | |
impl Display for Fraction { | |
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
write!(f, "{}/{}", self.top, self.bottom) | |
} | |
} | |
fn gcd(first: isize, second: isize) -> isize { | |
let mut max = first; | |
let mut min = second; | |
if min > max { | |
std::mem::swap(&mut max, &mut min); | |
} | |
loop { | |
let res = max % min; | |
if res == 0 { | |
return min; | |
} | |
max = min; | |
min = res; | |
} | |
} | |
#[derive(Debug)] | |
enum Operation { | |
Add, | |
Substract, | |
Multiply, | |
Divide, | |
} | |
impl FromStr for Operation { | |
type Err = Error; | |
fn from_str(s: &str) -> Result<Self> { | |
use Operation::*; | |
match s { | |
"add" => Ok(Add), | |
"substract" => Ok(Substract), | |
"divide" => Ok(Divide), | |
"multiply" => Ok(Multiply), | |
_ => Err(anyhow!("Unkown Operation")), | |
} | |
} | |
} | |
fn fraction_math(f1: Fraction, operation: Operation, f2: Fraction) -> Fraction { | |
use Operation::*; | |
let mut res = match operation { | |
Add => f1.add(&f2), | |
Substract => f1.sub(&f2), | |
Multiply => f1.mult(&f2), | |
Divide => f1.div(&f2), | |
}; | |
res.simplify(); | |
res | |
} | |
fn main() -> Result<()> { | |
let sum = fraction_math("3/4".parse()?, "add".parse()?, "3/4".parse()?); | |
println!("sum = {sum}"); | |
let product = fraction_math("1/8".parse()?, "multiply".parse()?, "2/2".parse()?); | |
println!("product = {product}"); | |
assert_eq!( | |
fraction_math("2/7".parse()?, "add".parse()?, "29/79".parse()?), | |
"361/553".parse()? | |
); | |
assert_eq!( | |
fraction_math("2/7".parse()?, "substract".parse()?, "29/79".parse()?), | |
"-45/553".parse()? | |
); | |
assert_eq!( | |
fraction_math("2/7".parse()?, "multiply".parse()?, "29/79".parse()?), | |
"58/553".parse()? | |
); | |
assert_eq!( | |
fraction_math("2/7".parse()?, "divide".parse()?, "29/79".parse()?), | |
"158/203".parse()? | |
); | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment