KX Community

Find answers, ask questions, and connect with our KX Community around the world.
KX Community Guidelines

Home Forums kdb+ Challenge 2 – Work out the Angle

  • Challenge 2 – Work out the Angle

    Posted by megan_mcp on February 20, 2023 at 12:00 am

    Thank you to everyone who interacted with my last challenge! The replies were greatly appreciated.

    My next challenge is for the math lovers. The triangle below, ABC is a right-angled triangle.

    M is the mid-point of the hypotenuse AC.

    You are given the lengths AB and BC (which are integers).

    The task is to work out the angle MBC.

     

    This is my solution:

    // reading in 2 sides 
    ab: "I"$read0 0 
    bc: "I"$read0 0 
    
    // finding the distance 
    ac: sqrt((ab*ab)+(bc*bc)) 
    bm: ac % 2.0 
    mc: bm 
    
    // equalizing the sides 
    b: mc 
    c: bm 
    a: bc 
    
    // where b=c 
    // finding the angle in radian 
    angle_b_radian: acos(a % (2*b)) 
    
    // converting the radian to degree 
    round:{"F"$.Q.f[y]x} 
    angle_b_degree: round[((180 * angle_b_radian) % 3.141593);2] 
    answer: "i"$angle_b_degree 
    show angle_b_degree

    I would love to see other approaches to this so if anyone has any comments or suggestions please let me know

    megan_mcp replied 9 months ago 3 Members · 4 Replies
  • 4 Replies
  • SJT

    Member
    March 19, 2024 at 10:55 am

    rak1507s solution above returns radians, while you asked for degrees, so thats a good place to start.

    Degrees are radians נ180/?, and pi is the arc-cosine of -1. So we could extend his solution:

     

    q)ab:4 
    q)bc:5 
    q)atan ab%bc 
    0.6747409 
    q)atan[ab%bc]*180%acos -1 
    38.65981

     

    If this were to solved for different triangles, we would want to define a function . How would we write it?

    It is a function of two quantities, and its math. Default arguments x and y will do fine.

     

    wota:{atan[x%y]*180%acos -1} / work out the angle

     

    Clearly 180/? is a constant we need not calculate repeatedly.

     

    q)wota:{x*atan y%z}[180%acos -1;;] / work out the angle

    q)wota . 4 5

    38.65981

     

    Above, the constant is calculated when wota is defined, and its value bound to the definition. This is a useful technique with constants.

    You might even prefer your function defined as a composition. Below, the three unaries (180%acos -1)*, atan, and .[%] are composed into a function by suffixing them with the general null ::. Again, the constant is calculated only at definition time.

     

    q)wota:(180%acos -1)* atan .[%] :: / work out the angle

    q)wota 4 5

    38.65981

     

    Megan, you named this My Programming Journey, so some travel notes

    Your prior experience has taught you to read in data to work on and, of course, with substantial data sets that is exactly right. But the q REPL offers you a new way to work. A good path is to experiment with q as a calculator on small data structures, and paste into your text editor what works for you. You can also usefully defer formatting output and focus on calculating the value you want.

    Starting in the REPL also helps you explore algorithms more thoroughly than save-load-and-run. Setting aside rjak1507s trigonometrical insight, lets see what that would look like with your algorithm.

     

    q)ab:4; bc:5 
    q)show mc:bm:.5* sqrt sum {x*x}(ab;bc) / lengths BM, MC 
    3.201562 
    q)a:bc; b:mc; c:bm / new triangle 
    q)show air: acos a%2*b / angle in radians 
    0.6747409 
    q)air*180%acos -1 
    38.65981

     

    That could become a lambda:

     

    wota0:{[r2d;ab;bc] /radians>degrees; AB; BC mc:bm:.5* sqrt sum {x*x}(ab;bc); / lengths BM, MC a:bc; b:mc; c:bm; / new triangle r2d * acos a%2*b }[180%acos -1;;]

     

    From which we notice variable c is set but not read, and that mc and bm are synonyms.

     

    wota1:{[r2d;ab;bc] /radians>degrees; AB; BC bm:.5* sqrt sum {x*x}(ab;bc); / lengths BM, MC r2d * acos bc%2*bm }[180%acos -1;;]

     

    Now we notice the definition of bm finishes with .5* but its doubled when read in the result expression. We end up with:

     

    wota2:{[r2d;ab;bc]r2d*acos bc%sqrt sum{x*x}(ab;bc)}[180%acos -1;;]

     

    If you were collecting trig functions you might be happier returning radians and defining conversion functions for re-use.

     

    wota3:{acos x%sqrt(x*x)+y*y} /work out the angle r2d:(180%acos -1)* /radians=>degrees d2r:(acos[-1]%180)* /degrees=>radians

     

    At the 40th anniversary celebration of the British APL Association at the Royal Society in 2004, Arthur Whitney spoke about k, the language in which q is implemented:

    It is theoretically impossible for k to outperform C, because it compiles into C. For every k program there is an equivalent C program that runs exactly as fast.

    Yet k programs routinely outperform hand-coded C. How is this possible? Its because it is a lot easier to find your errors in 4 lines of k than in 400 lines of C.

    Treasure terseness.

  • roryk

    Member
    March 19, 2024 at 11:00 am

    You don’t need any of the midpoint calculation, the answer in radians is atan ab%bc

  • megan_mcp

    Administrator
    March 19, 2024 at 11:00 am

     

    Along with  ‘s help on how to convert to degrees, thanks for showing me a quicker way of solving it!

    q)ab: 10 
    q)bc: 10 
    q)atan ab%bc 
    0.7853982 
    q)atan[ab%bc]*180%acos -1 
    45f

     

  • megan_mcp

    Administrator
    March 19, 2024 at 11:00 am

    thanks so much for all the advice ! Now looking back at my own solution and your examples, I should have took advantage of using a function. I can see how using a lamba is more effective than reading in the values. I will most definitely take this on board in the future as I understand the fewer the lines of code the better debugged.

Log in to reply.