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
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)
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)
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
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)
}
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)