Skip to content

Instantly share code, notes, and snippets.

@marinho
Last active June 14, 2017 21:19
Show Gist options
  • Save marinho/42506e1808d64e76a419b2a3a9ae7edf to your computer and use it in GitHub Desktop.
Save marinho/42506e1808d64e76a419b2a3a9ae7edf to your computer and use it in GitHub Desktop.
Playing with implicit conversions and infix in Scala
import scala.language.implicitConversions
import scala.language.postfixOps
// numerator
// ( numerator ÷ denominator ) create a fraction object as -----------
// denominator
object Main extends App {
implicit def intToFraction(i: Int) = new IntWithFraction(i)
// random examples
println(5 ÷ 10)
println(5 ÷ 10 simplify)
println((1 ÷ 2) + (2 ÷ 4) - (3 ÷ 10) simplify)
println((1 ÷ 2) * (2 ÷ 4))
println((8 ÷ 2) / (2 ÷ 1))
// all operations
println((8 ÷ 2) + (2 ÷ 1))
println((8 ÷ 2) - (2 ÷ 1))
println((8 ÷ 2) * (2 ÷ 1))
println((8 ÷ 2) / (2 ÷ 1))
// division by zero
try {
println((8 ÷ 0))
} catch {
case e: Exception => println("8 ÷ 0 => " + e)
}
// recursive operation and string formatting
val result = List(1 ÷ 2, 2 ÷ 4, 3 ÷ 6, 4 ÷ 8).reduceLeft(_ + _)
val simplified = result.simplify
println(s"$result = $simplified")
// operations with integers
println((8 ÷ 2) + 2)
println((8 ÷ 2) - 2)
println((8 ÷ 2) * 2)
println((8 ÷ 2) / 2)
// mixed number
println(10 ÷ 3 mixed)
}
class IntWithFraction(i: Int) {
// http://www.fileformat.info/info/unicode/char/00f7/index.htm
def ÷(denominator: Int) = new Fraction(i, denominator)
}
class Fraction(val numerator: Int, val denominator: Int) {
override def toString = s"$numerator ÷ $denominator"
if (denominator == 0)
throw new Exception("Denominator cannot be zero")
def +(other: Any) = plusOrMinus(this, other, 1)
def -(other: Any) = plusOrMinus(this, other, -1)
def *(other: Any) = other match {
case x: Int => new Fraction(this.numerator * x,
this.denominator)
case x: Fraction => new Fraction(this.numerator * x.numerator,
this.denominator * x.denominator)
}
def /(other: Any) = other match {
case x: Int => new Fraction(this.numerator,
this.denominator * x)
case x: Fraction => new Fraction(this.numerator * x.denominator,
this.denominator * x.numerator)
}
def simplify = {
val minor = math.min(numerator, denominator)
def findMaxDivisor(divisor: Int): Int = {
if (numerator % divisor == 0 && denominator % divisor == 0)
divisor
else
findMaxDivisor(divisor - 1)
}
val maxDivisor = findMaxDivisor(minor)
new Fraction(numerator / maxDivisor, denominator / maxDivisor)
}
def mixed = {
val integer = this.numerator / this.denominator
val rest = new Fraction(this.numerator % this.denominator, this.denominator)
(integer, rest)
}
private def plusOrMinus(a: Fraction, other: Any, operation: Int): Fraction = {
def inner(b: Fraction) = {
val numeratorA = a.numerator * b.denominator
val numeratorB = b.numerator * a.denominator
val denominator = a.denominator * b.denominator
new Fraction(numeratorA + numeratorB * operation, denominator)
}
other match {
case x: Int => inner(new Fraction(x, 1))
case x: Fraction => inner(x)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment