Identify If The List Is Empty - list

I am entirely new to F# I have this function that calculates the sum of the two different x and y points like this let vAdd (x1, y1) (x2, y2) : float * float = (x1 + x2, y1 + y2) and then I have another function that takes a list of the points and then uses vAdd to do the calculation. let vSum [(x1, y1); (x2, y2)] = vAdd (x1, y1) (x2, y2)
Now my question would be, how would I check and throw some error if the list given is empty? I tried with if ... then failwith "list is empty" but IsEmpty wasn't working. Another thing that I have looked at was pattern matching, but again, I don't know how it would work with my specific function. F# Check if a list is empty
Any help would be appreciated, and thanks in advance!

The most elegant approach is to use pattern matching, which lets you check that the list has exactly two elements and extract their values:
let vSum list =
match list with
| [(x1, y1); (x2, y2)] -> vAdd (x1, y1) (x2, y2)
| _ -> failwith "The list did not have two elements!"
You can slightly shorten this by using the function keyword, which is a shortcut for a function taking a variable and pattern matching on it:
let vSum = function
| [(x1, y1); (x2, y2)] -> vAdd (x1, y1) (x2, y2)
| _ -> failwith "The list did not have two elements!"
That said, if you always want to pass around two things, you should not be using a list, but use a tuple instead. You can have a tuple of tuples - that is fine - but if you know it is exactly two elements, then using a list is breaking the rule "make invalid states unrepresentable".

Related

Determine Next Point on a Line Between Point A and B From A

I have a 2D Coordinate system where The Origin Starts at the top Left
(Y Is higher as I move downward)
I am Given Two Points in Space, Lets Say Point A, and Point B.
How can I determine that next Point on the line From Point A to Point B?
For example, I have Point A(10, 10) and Point B (1,1)
I know the point I'm looking for is (9,9).
But how do I do this mathematically?
For say a more complicated Set of points
A(731, 911) and B(200, 1298)
I'm trying to move my mouse, one pixel at a time from its current location to a new one.
This doesn't work, but honestly I'm stumped where to begin.
int rise = x2 - 460; //(460 is Point A x)
int run = y2 - 360;//(360 is Point A Y)
float slope = rise / run;
int newx = x1 + ((slope / slope) * 1); //x1 Is my current mouse POS x
int newy = y1 + (slope * -1);//y1 is my current mouse Pos y
It almost works but seems inverted, and wrong.
You already have the slope, so to get the next point on the line (there are infinitely many), you have to choose a step value or just arbitrarily pick one of the points.
Given A(y1, x1), your goal in finding a new point, B(y2, x2) is that it must satisfy the equation: (y2 - y1) / (x2 - x1) = slope.
To simplify, (x2 - x1) * slope = y2 - y1
You already have x1, slope, y1, and you can choose any arbitrary x2, so when you plug all those into the equation, you can simplify it further to:
y2 = (x2 - x1) * slope + y1
To illustrate this with your other points (A(731, 911) and C(200, 1298)) and say you want to find a new point B, we can proceed as follows:
Find the slope first:
float slope = (1298 - 911) / (200 - 731); // -0.728813559322
Choose x and solve for y:
x1 = 731, slope = -0.728813559322, y1 = 911
Choose x2 = 500 and solving for y2, we get:
float y2 = (500 - 731) * -0.728813559322 + 911; // 1079.355932203382
So your new point is:
B(500, 1079.355932203382)
You can verify this new point still has the same slope to point C
With A = (x1,y1) and B = (x2,y2) the line is (expressed in two same equations):
(1) y = (x-x1)*(y2-y1)/(x2-x1) + y1
(2) x = (y-y1)*(x2-x1)/(y2-y1) + x1
To find next point, put x1+1 (or x1-1 you know) in equation (1) and find y and also put y1+1 or y1-1 in equation (2) and find x.
You can decide which one is better choice. Take care of vertical or horizontal lines, where one of the equations won't work.
NOTE: do not cast floating point result to int. Do round instead.

Unit test function returning function in F#

I have written the following function in F# which, given two points, returns a function representing the line which passes throught the two points:
let getFunction (point1:float*float) (point2:float*float) =
let x1 = fst point1
let y1 = snd point1
let x2 = fst point2
let y2 = snd point2
let m = (y2-y1)/(x2-x1)
let n = y1-x1*m
fun x -> m*x+n
I would like to unit test this function, but I haven't find how to do it, since I can't use a function in a equality assertion. I have thought about generating a secuence of random points and testing the application of the function against the expected result for each point, but I was wondering if there is a better way.
I would use a property-based testing approach (see http://fsharpforfunandprofit.com/pbt/ for an excellent introduction).
You presumably want to check that, for any inputs (x1, y1) and (x2, y2), that the resulting function satisfies the following properties:
f(x1) = y1
f(x2) = y2
f is linear
If the function satisifies these, it must be correct.
You can check the first two easily. For the final property, you can pick some random x values to test.
Repeat for a selection of inputs, and you're done. As Carsten mentions, FsCheck can be used to automate testing these properties using a large number of randomly generated test cases.

Return pairs of points from N 2D points where each two points define a line

I have a List of 2D points: (x1, y1), (x2, y2) … (xN, yN) - N 2D points.
Each two points define a 2D line.
Return a list of all unique 2D lines, which you can build using pairs of points from the list.
How can I implement using hash table/map - to keep unique lines (there are infinite lines)
I am trying to find the slope and intercept then point of intersection.
slope = y2 -y1 / x2 - x1
intercept = y1 - slope * x1;
(trying to do this in c++)
you didn't specify language, so I will use python here for the sake of easiness. it will look like a joke to python:
import itertools
def slope(p1, p2):
return (p1[1]-p2[1]) / (p1[0]-p2[0])
def slp_intrcpt(p1, p2):
"""
return the tuple of slope and intercept
"""
slp = slope(p1, p2)
return slp, p1[1] - slp * p1[0]
def uniq_lines(points):
return set(slp_intrcpt(p1, p2) for p1, p2 in itertools.combinations(points, 2))
since (slope, intercept) pair is good enough to determine a line, so i would say that finished your requirement.
if you want to keep track of all pairs that produce the lines, you may
import collections
def uniq_lines(points):
d = collections.defaultdict(lambda: [])
for p1, p2 in itertools.combinations(points, 2):
d[slp_intrcpt(p1, p2)].append((p1, p2))
return d

C++ function calculating the area of a triangle

I have the following function in C++ that is supposed to find the area of a triangle using Heron's formula. I haven't made any mistake in the math but it doesn't produce the right result! I am looking at it for more than 3 hours and I can't find any mistake. What am I missing?
float TriangleArea(float x0, float y0, float x1, float y1, float x2, float y2)
{
float area_triangle;
float a, b, c, s;
a=std::sqrt((x0-x1)*(x0-x1)-(y0-y1)*(y0-y1));
b=std::sqrt((x1-x2)*(x1-x2)-(y1-y2)*(y1-y2));
c=std::sqrt((x0-x2)*(x0-x2)-(y0-y2)*(y0-y2));
s=(a+b+c)/2;
area_triangle=std::sqrt((s*(s-a)*(s-b)*(s-c)));
return area_triangle;
}
I haven't made any mistake in the math but it doesn't produce the right result!
If it's not producing the right result, then I think there's a very high chance you made a mistake in the math.
a=std::sqrt((x0-x1)*(x0-x1)-(y0-y1)*(y0-y1));
That - looks suspicious. I'm assuming you're trying to find the distance between (x0, y0) and (x1, y1). If that's the case, you should be adding the two quantities, not subtracting.
I'm not familiar with Heron's formula, but you can use this simpler formula:
area = std::abs(x0 * (y1 - y2) + x1 * (y2 - y0) + x2 * (y0 - y1)) / 2;
Edit: I forgot to mention the abs function for the simplified formula, which was pointed out by Antonio.
I think you have a sign error. The values a, b, and c are the triangle sides, right?
a=std::sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
^
An alternative formula (with demonstration) can be found here
area = fabs((x0 - x2) * (y1 - y0) - (x0 - x1) * (y2 - y0) ) / 2;
(As a side note, if the formula has to be used to test points collinearity, the absolute value can be removed... But then you might need it anyway, as working with floating points you cannot test equality but against some epsilon value)

Calculate direction vector

HI All,
How can I calculate direction vector of a line segment, defined by start point (x1, y1) and end point (x2, y2)?
Cheers.
(x2 - x1, y2 - y1)
If you want the unit direction vector, divide each component by sqrt((x2 - x1)² + (y2 - y1)²).
The direction vector can be represented as (x2 - x1)i + (y2 - y1)j where i and j are unit vectors along x and y axis respectively.
cheers
If you want the vector from the end of vector (x1,y1) to the end of vector (x2,y2), the answer is
(x2-x1, y2-y1) + (x1,y1)
If you want the (unit-length) direction vector, then the answer is
((x2-x1)/L, (y2-y1)/L)
where L=√((x2-x1)² + (y2-y1)²) (thats $L=\sqrt{(x2-x1)^2 + (y2-y1)^2}$ in LaTeX).