Scala: How to structure code with intermediate results? - scala

I am trying to implement a function that calculates the area of a triangle in the Euclidean space, using the Heron's formula. Unfortunately I have no idea how to outsource partial functions and then pass them as parameters.
That is what I have so far:
import scala.math._
def sqr(a:Double) = a*a
def length(x1:Double,y1:Double,x2:Double,y2:Double)=sqrt(sqr(x2-x1)+sqr(y2-y1))
val a = length(x1,y1,x2,y2)
val b = length(x2,y2,x3,y3)
val c = length(x3,y3,x1,y1)
val u = 0.5*a*b*c
heron(x1:Double,y1:Double,x2:Double,y2:Double,x3:Double,y3:Double) = sqrt(u*(u-a)*(u-b)*(u-c))
That obviously doesn't work, but I hope you get what I am trying to do.

I think you just want to define those intermediate values inside of your function:
// btw, using scala.math.power you can write 'power(a, 2)'
def sqr(a: Double): Double = a * a
def length(
x1: Double, y1: Double,
x2: Double, y2: Double
): Double = sqrt(
sqr(x2 - x1) +
sqr(y2 - y1)
)
def heron(
x1: Double, y1: Double,
x2: Double, y2: Double,
x3: Double, y3: Double
): Double = {
val a = length(x1, y1, x2, y2)
val b = length(x2, y2, x3, y3)
val c = length(x3, y3, x1, y1)
val u = 0.5 * a * b * c
sqrt(u * (u - a) * (u - b) * (u - c))
}
I would also recommend you to make more spaces in the code, it makes it more readable.

Related

Conversion of Looping to Recursive Solution

I have written a method pythagoreanTriplets in scala using nested loops. As a newbie in scala, I am struggling with how can we do the same thing using recursion and use Lazy Evaluation for the returning list(List of tuples). Any help will be highly appreciated.
P.S: The following method is working perfectly fine.
// This method returns the list of all pythagorean triples whose components are
// at most a given limit. Formula a^2 + b^2 = c^2
def pythagoreanTriplets(limit: Int): List[(Int, Int, Int)] = {
// triplet: a^2 + b^2 = c^2
var (a,b,c,m) = (0,0,0,2)
var triplets:List[(Int, Int, Int)] = List()
while (c < limit) {
breakable {
for (n <- 1 until m) {
a = m * m - n * n
b = 2 * m * n
c = m * m + n * n
if (c > limit)
break
triplets = triplets :+ (a, b, c)
}
m += 1
}
}// end of while
triplets
}
I don't see where recursion would offer significant advantages.
def pythagoreanTriplets(limit: Int): List[(Int, Int, Int)] =
for {
m <- (2 to limit/2).toList
n <- 1 until m
c = m*m + n*n if c <= limit
} yield (m*m - n*n, 2*m*n, c)

Scala: Orthogonal projection of a point onto a line

I'm trying to make a function that takes 3 points as arguments. The first two of which represent two points on a line. The third one represents another point, outside of that line. Suppose a perpendicular through the third point on the line defined by the first two points. Now what I want to do, is calculate that intersection. I've come up with this procedure so far, but somehow it works only like 50% of the time. Could somebody figure out what I'm doing wrong here?
def calculateIntersection(p1: (Double, Double), p2: (Double, Double), c: (Double, Double)): (Double, Double) = {
var intersection: (Double, Double) = null
// CASE 1: line is vertical
if(p1._1 == p2._1) {
intersection = (p1._1, c._2)
}
// CASE 2: line is horizontal
else if(p1._2 == p2._2) {
intersection = (c._1, p1._2)
}
// CASE 3: line is neither vertical, nor horizontal
else {
val slope1: Double = (p2._2 - p1._2) / (p2._1 - p1._1) // slope of the line
val slope2: Double = pow(slope1, -1) * -1 // slope of the perpendicular
val intercept1: Double = p1._2 - (slope1 * p1._1) // y-intercept of the line
val intercept2: Double = c._2 - (slope2 * c._1) // y-intercept of the perpendicular
intersection = ((intercept2 - intercept1) / (slope1 - slope2),
slope1 * ((intercept2 - intercept1) / (slope1 - slope2)) + intercept1)
}
intersection
}
Given the following definitions:
type Point = (Double, Double)
implicit class PointOps(p: Point) {
def +(other: Point) = (p._1 + other._1, p._2 + other._2)
def -(other: Point) = (p._1 - other._1, p._2 - other._2)
def dot(other: Point) = p._1 * other._1 + p._2 * other._2
def *(scalar: Double) = (p._1 * scalar, p._2 * scalar)
def normSquare: Double = p._1 * p._1 + p._2 * p._2
}
meaning that
a + b // is vector addition
a - b // is vector subtraction
a dot b // is the dot product (scalar product)
a * f // is multiplication of a vector `a` with a scalar factor `f`
a.normSquare // is the squared length of a vector
you obtain the projection of a point p on line going through points line1 and line2 as follows:
/** Projects point `p` on line going through two points `line1` and `line2`. */
def projectPointOnLine(line1: Point, line2: Point, p: Point): Point = {
val v = p - line1
val d = line2 - line1
line1 + d * ((v dot d) / d.normSquare)
}
Example:
println(projectPointOnLine((-1.0, 10.0), (7.0, 4.0), (6.0, 11.0)))
gives
(3.0, 7.0)
This works in 3D (or n-D) in exactly the same way.
Some math behind that (How to derive it from scratch)
(notation as above)
We have three points: l1 and l2 for the line and p for the target point.
We want to project the point p orthogonally onto the line that goes through l1 and l2 (assuming l1 != l2).
Let d = l2 - l1 be the direction from l1 to l2. Then every point on the line can be represented as
l1 + d * t
with some scalar factor t. Now we want to find a t such that the vector connecting p and l1 + d * t is orthogonal to d, that is:
(p - (l1 + d * t)) dot d == 0
Recall that
(v1 + v2) dot v3 = (v1 dot v3) + (v2 dot v3)
for all vectors v1, v2, v3, and that
(v1 * s) dot v2 = (v1 dot v2) * s
for scalar factors s. Using this and the definition v.normSquared = v dot v, we obtain:
(p - l1 - d * t) dot d
= (p - l1) dot d - (d dot d) * t
= (p - l1) dot d - d.normSquare * t
and this should become 0. Resolving for t gives:
t = ((p - l1) dot d) / d.normSquare
and this is exactly the formula that is used in the code.
(Thanks at SergGr for adding an initial sketch of the derivation)

Scala for the Impatient, chapter 2, exercise on recursive pow function

I am reading Scala for the Impatient, Chapter 2 and there is an exercise question I don't understanding what exactly does it want:
Write a function that computes x^n, where n is an integer. Use the
following recursive definition:
X^n = y * y if n is even and positive, where y = x^(n/2)
X^n = x * x^(n-1) if n is odd and positive
x^0 = 1
x^n = 1 / x^-n if n is negative
If the question want x^n, I could just use the pow method defined in scala.math:
def pow(x: Double, y: Double): Double
The question is asking to (re)implement a recursive pow function on integers:
def pow(x: Int, y: Int): Int = ...
You need write a smarter implementation than the naive O(n) algorithm:
def slowPow(x: Int, y: Int): Int =
if (y == 0) 1 else x * slowPow(x, y - 1)
Try to use the given recursive definition instead...
To answer your question directly, I don't think you can dodge the question using the one from scala.math. As you noted it only works on Doubles. Also is neither recursive nor implemented in Scala.
def pow(x: Double, n: Int): Double = {
if (n == 0) 1
else if (n < 0) 1 / (x - n)
else if (n % 2 == 1) x * pow(x, n - 1)
else {
val y = pow(x, n / 2)
y * y
}
}
pow(2, 0) == 1
pow(2, -2) == 0.25
pow(2, 4) == 16
pow(2, 5) == 32

Method inheritance on contravariant type

I have defined two typeclasses:
trait WeakOrder[-X] { self =>
def cmp(x: X, y: X): Int
def max[Y <: X](x: Y, y: Y): Y = if (cmp(x, y) >= 0) x else y
def min[Y <: X](x: Y, y: Y): Y = if (cmp(x, y) <= 0) x else y
}
trait Lattice[X] { self =>
def sup(x: X, y: X): X
def inf(x: X, y: X): X
}
I would like to do the following:
trait TotalOrder[-X] extends Lattice[X] with WeakOrder[X] { self =>
def sup(x: X, y: X): X = max(x, y)
def inf(x: X, y: X): X = min(x, y)
}
But this is impossible because contravariant type X appears at a covariant position (the returning value of sup and inf).
However, semantically this is correct: max and min with the type signature max[Y <: X](x: Y, y: Y): Y encodes the fact that the returning value of max / min must be one of the two arguments.
I tried to do the following:
trait TotalOrder[-X] extends Lattice[X] with WeakOrder[X] { self =>
def sup[Y <: X](x: Y, y: Y): Y = max(x, y)
def inf[Y <: X](x: Y, y: Y): Y = min(x, y)
}
However, the method def sup[Y <: X](x: Y, y: Y): Y cannot inherit def sup[X](x: X, y: X): X. The compiler complains that the type signature does not match. But the former one (with the on-site variance annotation) imposes a stronger type restrictions than the latter signature. Why the former one cannot inherit the latter one? How can I bypass the contravariant type restrictions on TotalOrder[-X] (semantically, a total order is contravariant)?
This is not semantically correct. It should be clear from the definition of covariant and contravariant, but I'll try to give an example:
Suppose we have hierarchy of entities:
class Shape(s:Float)
class Circle(r:Float) extends Shape(Math.PI.toFloat * r * r)
And let's assume that it's possible to create contravariant orders, as you tried:
trait CircleOrder extends TotalOrder[Circle] {
// compare by r
}
trait ShapeOrder extends TotalOrder[Shape] {
// compare by s
}
By definition of contravariants, as Shape <: Circle,
CircleOrder <: ShapeOrder
(CircleOrder is supertype of ShapeOrder)
Suppose we have client that takes CircleOrder as the argument
and uses it to compare circles:
def clientMethod(circleOrder:TotalOrder[Circle]) = {
val maxCircle = circleOrder.max(???, ???) // expected to return Circle
maxCircle.r // accessing field that is present only in circle
}
Then, by definition of inheritance, it should be possible to pass
ShapeOrder instead of CircleOrder (remember, ShapeOrder is subtype):
clientMethod(new ShapeOrder {/*...*/})
Obviously it will not work, as client still expects order to return Circles, not Shapes.
I think in your case the most reasonable approach will use regular generics.
Update
This is how you can ensure type safety, but it's a bit ugly.
trait WeakOrder[-X] {
def cmp(x: X, y: X): Int
def max[T](x: X with T, y: X with T): T =
if (cmp(x, y) >= 0) x else y
def min[T](x: X with T, y: X with T): T =
if (cmp(x, y) <= 0) x else y
}
trait Lattice[X] {
def sup[T](x: X with T, y: X with T): T
def inf[T](x: X with T, y: X with T): T
}
trait TotalOrder[-X] extends Lattice[X] with WeakOrder[X] {
def sup[T](x: X with T, y: X with T): T = max(x, y)
def inf[T](x: X with T, y: X with T): T = min(x, y)
}

Python 3 Operator Overloading

I'm trying to define the operator type add when it comes to my class Point. Point is exactly what it seems, (x, y). I can't seem to get the operator to work though because the code keeps printing the <main.Point...>. I'm pretty new to this stuff, so can someone explain what I am doing wrong? Thanks. Here is my code:
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
p1 = Point(3,4)
p2 = Point(5,6)
p3 = p1 + p2
print(p3)
Your add function is working as intended. It's your print that's the problem. You're getting an ugly result like <__main__.Point object at 0x027FA5B0> because you haven't told the class how you want it to display itself. Implement __str__ or __repr__ so that it shows a nice string.
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
def __repr__(self):
return "Point({}, {})".format(self.x, self.y)
p1 = Point(3,4)
p2 = Point(5,6)
p3 = p1 + p2
print(p3)
Result:
Point(8, 10)