Skip to content

Instantly share code, notes, and snippets.

@frectonz
Last active March 13, 2023 17:05
Show Gist options
  • Save frectonz/5c73638d1131dba704252a74195bb0d3 to your computer and use it in GitHub Desktop.
Save frectonz/5c73638d1131dba704252a74195bb0d3 to your computer and use it in GitHub Desktop.
From cassido's March 13, 2023 Newsletter
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