9
\$\begingroup\$

Try to write the shortest program or function you can that prints or returns the calculated orthocenter of a triangle.

The orthocenter of a triangle is the intersection point of the three altitudes of a triangle. The altitude of a triangle is a perpendicular segment from the vertex of the triangle to the opposite side.

Input:

  • Three points in 2D space correponding to the triangle's vertices

Output:

  • The calculated orthocenter of the triangle

A sample input would be

A(0,0)
B(3,6)
C(6,0)

and a sample output would be:

Calculated Othocenter (3, 1.5)

One formula for orthocenter can be written as

(x, y) = ((ax*tan(α) + bx*tan(β) + cx*tan(γ))/(tan(α) + tan(β) + tan(γ),
          (ay*tan(α) + by*tan(β) + cy*tan(γ))/(tan(α) + tan(β) + tan(γ))

Shortest program in bytes wins.

\$\endgroup\$
  • \$\begingroup\$ I added a description, and yes, the use of global's as a function was a slip up on my part, I copy and pasted from the wrong notepad file I had open without realizing it. The use of arrays is purely optional, it is just a habit of mine to do so, vs a naming convention like Ax, Ay, Bx... \$\endgroup\$ – Roberto Duran Jun 27 '15 at 5:33
  • \$\begingroup\$ Welcome to PPCG. Language specific challenges are frowned on here, because they limit participation and are frequently homework questions in disguise. I will cast a reopen vote if the language restriction is removed (and I say this despite the fact that most of my answers are in C.) \$\endgroup\$ – Level River St Jun 27 '15 at 9:33
  • 3
    \$\begingroup\$ I cleaned this whole thing up for you, but you need to specify how the points are to be supplied to the function or program and what exactly the points are (angles, coordinates?) \$\endgroup\$ – Beta Decay Jun 27 '15 at 10:00
  • \$\begingroup\$ @BetaDecay it was fairly clear to me that the given points and required orthocentre are x.y coordinates. See 3rd comment from the top. \$\endgroup\$ – Level River St Jun 27 '15 at 10:04
  • 4
    \$\begingroup\$ This question would benefit greatly from a good set of test cases; and, as with all questions involving floating point numbers, the spec isn't complete without a carefully thought out constraint on numerical accuracy. \$\endgroup\$ – Peter Taylor Jun 27 '15 at 11:09
3
\$\begingroup\$

Python, 193 168

Should work for any valid triangle...

def h(a,A,b,B,c,C):
 if A==B:b,B,c,C=c,C,b,B
 m=(a-b)/(B-A)
 return m,C-m*c
def f(a,A,b,B,c,C):
 m,q=h(a,A,b,B,c,C)
 k,z=h(c,C,b,B,a,A)
 x=(q-z)/(k-m)
 return (x,k*x+z)
| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

CJam, 90 bytes

q~:C2$]_2ew::.-:D;;D1=0=D2=0=*D1=1=D2=1=*+D0=1=D2=0=*D0=0=D2=1=*-/_D0=1=*C0=+C1=@D0=0=*-S\

Try it online

CJam isn't really optimized for geometry, so the code isn't doing anything fancy. It uses the parametric representation for two of the lines passing through a corner and being orthogonal to the opposite side, and solves the 2x2 system of equations resulting from intersecting the two lines. Well, it only needs one of the resulting parameters, which is then used for calculating the intersection point.

Note that some of the signs in the intermediate values are wrong. Instead of flipping them with additional code, I kept them the way they are, and corrected for the wrong sign by changing additions to subtractions (or vice versa) when the value is used later. For example, if you see a + where you would normally expect a - when calculating a determinant, that's because one of the terms has the wrong sign. In fact, both determinants have the wrong sign (at least relative to my paper notes), but that doesn't matter because they are divided by each other.

Since the input format was not precisely specified, I made it CJam friendly. The code expects 3 points in CJam array format, where the values have to be floating point. For the given example, the expected input is:

[0. 0.] [3. 6.] [6. 0.]

Explanation:

q~      Get and interpret input.
:C      Store away the last point in variable C. Will be needed at the end
        to calculate the intersection point.
2$]     Repeat the first point, and wrap all points in an array.
_2ew    Generate array with all pairs of points [[A B] [B C] [C A]].
::.-    Calculate the vector difference of all point pairs [A-B B-C C-A].
        These are the vectors for each side of the triangle.
:D;;    Store the side vectors in a variable, and clear the stack.
D1=0=D2=0=*D1=1=D2=1=*+
        Calculate determinant for first unknown in 2x2 system of equations.
D0=1=D2=0=*D0=0=D2=1=*-
        Calculate main determinant of 2x2 system of equations.
/       Divide the two determinants. This gives the parameter of the
        intersection point for the line starting at C and orthogonal to A-B.
_       Copy it because we'll need it twice.
D0=1=*C0=+
        Calculate x-coordinate of intersection point.
C1=@D0=0=*-
        Calculate y-coordinate of intersection point.
S\      Put a space between the two values.
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

R, 102 70 68 bytes

As an unnamed function which implements the formula in the question. The parameter for the function a vector of complex numbers (X+Yi) and it returns a complex number. I'm assuming that complex numbers are okay for input and output.

function(E)sum((F=tan((D=Arg(E-E[c(3,1,2)]))-D[c(2,3,1)]))*E)/sum(F)

Edit Vectorized it a lot

Expanded explanation

f=function(E){
    D=Arg(E-E[c(3,1,2)]); # Angles of sides
    F=tan(D-D[c(2,3,1)]); # Internal triangle angles tangents
    sum(E*F)/sum(F);      # Orthocenter coordinate return
}

Test

> f=function(E)sum((F=tan((D=Arg(E-E[c(3,1,2)]))-D[c(2,3,1)]))*E)/sum(F)
> f(c(0+0i,3+6i,6+0i))
[1] 3+1.5i
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Is the code shorter if you use complex numbers or just required for the calculation? \$\endgroup\$ – Beta Decay Jun 30 '15 at 18:17
  • \$\begingroup\$ @BetaDecay both really. They made the calculation easier and shorter. If it turns out that they aren't allowed as input or output I would probably still us them internally. \$\endgroup\$ – MickyT Jun 30 '15 at 18:46
0
\$\begingroup\$

Cobra - 247

def f(p as System.Drawing.Point[])
    a,b,c=p
    d,e,f=for q in[[b,c],[a,c],[a,b]]get if(z=q[0].x-q[1].x,(q[0].y-q[1].y)/z,0f)
    print (a.x*(g=((e-f)/(1+e*f)).abs)+b.x*(h=((d-f)/(1+d*f)).abs)+c.x*(i=((e-d)/(1+e*d)).abs))/(j=g+h+i),(a.y*g+b.y*h+c.y*i)/j
| improve this answer | |
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.