Forum Replies Created

Page 1 of 2
  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: How long should a name be?

    When I joined the ranks of APL instructors years ago it was well known that students learned APL faster if they had not been exposed to other programming languages. (Iverson always warned against confusing unfamiliar and difficult.)

    Back in the day, we supposed that evidence of the superiority of Iversons notation. Other languages were rubbish; one day all software would be written in APL.

    Nowadays we know better. (I have written an application GUI in APL. I intend it to remain a once-in-a-lifetime experience.) We need to be polyglots. Nothing bad in that: humans have been polyglots since the Old Stone Age. (Only in recent centuries have linguistic communities grown large enough to host monoglots.)

    Which leaves us with the barrier of the unfamiliar. Q widened access to kdb+ by letting users exploit their knowledge of SQL. KX Insights is doing more by providing access through Python and Web UI. But for those who need to write in q there remains the transition from what (in a recent ArrayCast episode) Joel Kaplan called the one-potato-two-potato approach to what shall we call it vector thinking?

    A recent article in the RSA Journal  on lifelong education stresses the challenge of unlearning as part of learning new skills.

    What helped you learn vector thinking?

    Last year I led an online workshop on vector thinking. We explored vector solutions in q to a small but non-trivial problem. Participants found it helped them, and I promised to hold another one. Perhaps its time? (Respond here to encourage me.)

  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Five easy pieces #3: Mark this

    Oh yes.  Now were having fun.

     

    {.h.htc[y;x]}/[.h.text"nn"vs"c"$ read1 `:smile.md;`body`html]

     

  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Challenge 2 – Work out the Angle

    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.

  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Five easy pieces #3: Mark this

    Second stage: smile2.md

     

    # The All-American Smile In a way he was like the land itself. Everything came to him too easily. But at least he knew it, and from time to time he worried about being a phoney.

     

    Output:

     

    <html>
      <body>
        <h1>The All-American Smile</h1>
         <p>In a way he was like the land itself. Everything came to him too easily.</p>
         <p>But at least he knew it, and from time to time he worried about being a phoney.</p>
      </body>
    </html>

     

     

  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Five easy pieces
  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Five easy pieces #4: Little Six

    Nice!

    Interesting that you have used bracket notation for the Do iteration; that is, {x[5 0 4 1 3 2]}[5;i] rather than 5 {x[5 0 4 1 3 2]}i. I dont think it does anything for you here, but it means you could get a unary {x[5 0 4 1 3 2]}[5;] to use in a composition.

    Now

    1. Can you do the shuffle without a lambda?
    2. Try using cut for the envoi
  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Five easy pieces #4: Little Six

    Very nice! Especially the use of Converge. Your expression makes it clear that the permutation returns to the original order and that the envoi has the order of the original.

    Further thoughts: if you use Do with a left argument of 6, you can then use Apply At @ to apply " "sv'2 cut to the last item. This expression emphasises that the permutation returns the envoi to the original order.

     

    sest1:{1_raze” “,/:@[;6;” “sv’2 cut]6 @[;5 0 4 1 3 2]x}

     

    Getting down to a single reference to the argument introduces the possibility of writing the function as a composition, which eliminates the tiny overhead of a lambda. Here we can use the bracket notation you introduced earlier for Do.

     

    sest2:1_ raze ” “,/: @[;6;” “sv’2 cut] @[;5 0 4 1 3 2][6;] @

     

    Above spaces clarify the structure a composition of five unaries:

    1. 1_
    2. raze
    3. " ",/:
    4. @[;6;" "sv'2 cut]
    5. @[;5 0 4 1 3 2][6;]

    If you’ve read this far, test your understanding!

    When projecting a binary function f onto its first argument (e.g. 6) we can elide the semicolon and write either f[6;] or f[6]. Why can we not do that here why does @[;5 0 4 1 3 2][6] not work?

    Lastly, can 5 0 4 1 3 2 become a function of the stanza length assuming an even number of lines? That would support new forms, such as an octrina (I just made that word up) or a quatrina.

  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Five easy pieces #2: getting around
    rnd:{[x;nd;m] string%[;s]((ceiling;floor;floor 0.5+)`up`dn`nr?m)@:x*s:10 xexp nd}

     

    Here the case structure is not a dictionary, just a mapping from the symbols to functions. The primitives all iterate implicitly: the Each Left : is used only to support multiple rounding modes.

    In the list of unary functions the third item floor 0.5+ is an implicit composition of two unaries: floor and the projection 0.5+.

  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Five easy pieces #3: Mark this

    Not tempted yet? Lets make it easier and harder.

    • Easier: file lines have no trailing spaces.
    • Harder: let your expression contain no more than one reference to .h.htc.
  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Challenge 3 The Runner-Up

     

    q)list1:4 7 9 7 2 8 9 
    q)ru:@[;1] desc distinct:: /runner-up 
    q)ru list1 
    8

     

    Using general list notation (items separated by semicolons and embraced by parentheses) suggests a list is general; better to write a vector as a vector literal.

    Composition ru is a sequence of three unaries. In evaluation order: select the distinct items; sort descending; select second item.

  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Challenge 3 The Runner-Up

    Nicely timed question! Im just up to the chapter on composition in the book Im writing, Vector Programming in Q, and I need to settle a few questions about it myself. For example, is there ever a reason to prefer Compose to a train suffixed by @ or ::?

    Nick Psaris commented recently that he favours :: because it composes directly rather than forming a projection. (I doubt the evaluation overhead is significant, but I get the point.)

  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Something for the weekend?

    Hint: there is a faster test than x=" " or null x.

  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Challenge 1 – Triangle Font

     

    q){x#’x}1+til 4

    ,1

    2 2

    3 3 3

    4 4 4 4

    q)tf:{x#’x}1+til ::

     

    Breaking it down

    1. 1+til gives us the natural numbers to whatever
    2. {x#'x} gives us N of each N
    3. Suffixing the three unaries with :: gives us the composition to be known as tf

    Nice challenge! Who would like to come to another Vector Dojo?

  • SJT

    Member
    March 19, 2024 at 10:55 am in reply to: Challenge 1 – Triangle Font

    Or to lose the spaces

    q)-1 "0123456789"{x#'x}1+til 5; 
    1 
    22 
    333 
    4444 
    55555
  • SJT

    Member
    June 3, 2023 at 12:00 am in reply to: Something for the weekend?

    A surprise? Char is a sortable type and Less Than is as fast as Equals and faster than Not Equals.

    q)ts:100000 “quick brown fox”>” ”

    13 752

    q)ts:100000 “quick brown fox”<>” ”

    27 880

    q)ts:100000 “quick brown fox”=” ”

    13 752

    q)ts:100000 not”quick brown fox”=” ”

    23 864

Page 1 of 2