{"id":5316,"date":"2018-09-28T13:50:57","date_gmt":"2018-09-28T13:50:57","guid":{"rendered":"https:\/\/www.dyalog.com\/blog\/?p=5316"},"modified":"2018-09-29T08:13:53","modified_gmt":"2018-09-29T08:13:53","slug":"2018-apl-problem-solving-competition-phase-i-problems-sample-solutions","status":"publish","type":"post","link":"https:\/\/www.dyalog.com\/blog\/2018\/09\/2018-apl-problem-solving-competition-phase-i-problems-sample-solutions\/","title":{"rendered":"2018 APL Problem Solving Competition: Phase I Problems Sample Solutions"},"content":{"rendered":"<p>The following are my attempts at the <a href=\"https:\/\/www.dyalog.com\/uploads\/files\/student_competition\/2018_problems_phase1.pdf\" target=\"_blank\" rel=\"noopener\">Phase I problems<\/a> of the 2018 APL Problem Solving Competition. There are not necessarily &#8220;right answers&#8221; as personal style and taste come into play. More explanation of the code is provided here than common practice. All solutions pass all the tests specified in the official problem description.<\/p>\n<p>The solutions for problems 1 and 3 are due to Brian Becker, judge and supremo of the competition. They are better than the ones I had originally.<\/p>\n<p><strong>1. Oh Say Can You See?<\/strong><\/p>\n<p>Given a vector or scalar of skyscraper heights, compute the number of skyscrapers which can be seen from the left. A skyscraper hides one further to the right of equal or lesser height.<\/p>\n<pre><code class=\"language-apl\">   visible \u2190 {\u2262\u222a\u2308\\\u2375}<\/code><\/pre>\n<p>Proceeding from left to right, each new maximum obscures subsequent equal or lesser values. The answer is the number of unique maxima. A tacit equivalent is <code class=\"language-apl\">\u2262\u2218\u222a\u2218(\u2308\\)<\/code>.<\/p>\n<p><strong>2. Number Splitting<\/strong><\/p>\n<p>Split a non-negative real number into the integer and fractional parts.<\/p>\n<pre><code class=\"language-apl\">   split \u2190 0 1\u2218\u22a4<\/code><\/pre>\n<p>The function <code class=\"language-apl\">\u237a\u22a4\u2375<\/code> encodes the number <code class=\"language-apl\">\u2375<\/code> in the number system specified by numeric vector <code class=\"language-apl\">\u237a<\/code> (the bases). For example, <code class=\"language-apl\">24 60 60\u22a4sec<\/code> expresses <code class=\"language-apl\">sec<\/code> in hours, minutes, and seconds. Such expression obtains by repeated application of the process, starting from the right of <code class=\"language-apl\">\u237a<\/code>: the next &#8220;digit&#8221; is the remainder of the number on division by a base, and the quotient of the division feeds into the division by the next base. Therefore, <code class=\"language-apl\">0 1\u22a4\u2375<\/code> divides <code class=\"language-apl\">\u2375<\/code> by <code class=\"language-apl\">1<\/code>; the remainder of that division is the requisite fractional part and the quotient the integer part. That integer part is further divided by the next base, <code class=\"language-apl\">0<\/code>. In APL, remaindering by <code class=\"language-apl\">0<\/code> is defined to be the identity function.<\/p>\n<p>You can have a good argue about the philosophy (theology?) of division by <code class=\"language-apl\">0<\/code>, but the APL definition in the context of <code class=\"language-apl\">\u237a\u22a4\u2375<\/code> gives practically useful results: A <code class=\"language-apl\">0<\/code> in <code class=\"language-apl\">\u237a<\/code> essentially says, whatever is left. For example, <code class=\"language-apl\">0 24 60 60\u22a4sec<\/code> expresses <code class=\"language-apl\">sec<\/code> as days\/hours\/minutes\/seconds.<\/p>\n<p><strong>3. Rolling Along<\/strong><\/p>\n<p>Given an integer vector or scalar representing a set of dice, produce a histogram of the possible totals that can be rolled.<\/p>\n<pre><code class=\"language-apl\">   roll \u2190 {{\u237a('*'\u2374\u2368\u2262\u2375)}\u2338,+\/\u00a8\u2373\u2375}\r\n\r\n   roll 5 3 4\r\n3  *\r\n4  ***\r\n5  ******\r\n6  *********\r\n7  ***********\r\n8  ***********\r\n9  *********\r\n10 ******\r\n11 ***\r\n12 *<\/code><\/pre>\n<p><code class=\"language-apl\">\u2373\u2375<\/code> produces all possible rolls for the set of dice (the cartesian product of <code class=\"language-apl\">\u2373\u00a8\u2375<\/code>) whence further application of <code class=\"language-apl\">+\/\u00a8<\/code> and then <code class=\"language-apl\">,<\/code> produce a vector of all possible totals. With the vector of possible totals in hand, the required unique totals and corresponding histogram of the number of occurrences obtain readily with the <em>key<\/em> operator <code class=\"language-apl\">\u2338<\/code>. (And rather messy <em>without<\/em> the <em>key<\/em> operator.) For each unique total, the operand function <code class=\"language-apl\">{\u237a('*'\u2374\u2368\u2262\u2375)}<\/code> produces that total and a vector of <code class=\"language-apl\">*<\/code> with the required number of repetitions.<\/p>\n<p>The problem statement does not require it, but it would be nice if the totals are listed in increasing order. At first, I&#8217;d thought that the totals would need to be explicitly sorted to make that happen, but on further reflection realized that the unique elements of <code class=\"language-apl\">,+\/\u00a8\u2373\u2375<\/code> (when produced by taking the first occurrence) are guaranteed to be sorted.<\/p>\n<p><strong>4. What&#8217;s Your Sign?<\/strong><\/p>\n<p>Find the Chinese zodiac sign for a given year.<\/p>\n<pre><code class=\"language-apl\">   zodiac_zh \u2190 {(1+12|\u2375+0&gt;\u2375) \u2283 ' '(\u2260\u2286\u22a2)' Monkey Rooster Dog Pig Rat Ox Tiger Rabbit Dragon Snake Horse Goat'}<\/code><\/pre>\n<p>Since the zodiac signs are assigned in cycles of 12, the phrase <code class=\"language-apl\">12|<\/code> plays a key role in the solution. The <em>residue<\/em> (remainder) function <code class=\"language-apl\">|<\/code> is inherently and necessarily 0-origin; the <code class=\"language-apl\">1+<\/code> accounts for the 1-origin indexing required by the competition. Adding <code class=\"language-apl\">0&gt;\u2375<\/code> overcomes the inconvenient fact that there is no year 0.<\/p>\n<p>Essentials of the computation are brought into sharper relief if each zodiac sign is denoted by a single character:<\/p>\n<pre><code class=\"language-apl\">   zzh \u2190 {(1+12|\u2375+0&gt;\u2375)\u2283'\u7334\u96de\u72d7\u8c6c\u9f20\u725b\u864e\u5154\u9f8d\u86c7\u99ac\u7f8a'}<\/code><\/pre>\n<p>The Chinese Unicode characters were found using <a href=\"https:\/\/translate.google.com\" target=\"_blank\" rel=\"noopener\">https:\/\/translate.google.com<\/a> and then copied and pasted into the Dyalog APL session.<\/p>\n<p><strong>5. What&#8217;s Your Sign? Revisited<\/strong><\/p>\n<p>Find the Western zodiac sign for a given month and day.<\/p>\n<pre><code class=\"language-apl\">   zodiac_en\u2190{\r\n     d\u219012 2\u2374 1 20  2 19  3 21  4 20  5 21  6 21  7 23  8 23  9 23  10 23  11 22  12 22\r\n     s\u219013\u2374' '(\u2260\u2286\u22a2)' Capricorn Aquarius Pisces Aries Taurus Gemini Cancer Leo Virgo Libra Scorpio Sagittarius'\r\n     (1+d\u2378\u2375)\u2283s\r\n   }<\/code><\/pre>\n<p>For working with irregular-sized non-overlapping intervals, the pre-eminent function is <code class=\"language-apl\">\u2378<\/code>, <em>interval index<\/em>. As with the Chinese zodiac, essentials of the computation are brought into sharper relief if each zodiac sign is denoted by a single character:<\/p>\n<pre><code class=\"language-apl\">   zen\u2190{\r\n     d\u219012 2\u2374 1 20  2 19  3 21  4 20  5 21  6 21  7 23  8 23  9 23  10 23  11 22  12 22\r\n     (1+d\u2378\u2375)\u228313\u2374'\u2651\u2652\u2653\u2648\u2649\u264a\u264b\u264c\u264d\u264e\u264f\u2650'\r\n   }<\/code><\/pre>\n<p>The single-character signs, Unicode U+2648 to U+2653, were found by Google search and then confirmed by <a href=\"https:\/\/www.visibone.com\/htmlref\/char\/cer09800.htm\" target=\"_blank\" rel=\"noopener\">https:\/\/www.visibone.com\/htmlref\/char\/cer09800.htm<\/a>. It is possible that the single-character signs do not display correctly in your browser; the line of code can be expressed alternatively as <code class=\"language-apl\">(1+d\u2378\u2375)\u228313\u2374\u2395ucs 9800+12|8+\u237312<\/code>.<\/p>\n<p><strong>6. What\u2019s Your Angle?<\/strong><\/p>\n<p>Check that angle brackets are balanced and not nested.<\/p>\n<pre><code class=\"language-apl\">   balanced \u2190 {(\u2227\/c\u220a0 1)\u22270=\u2283\u233dc\u2190+\\1 \u00af1 0['&lt;&gt;'\u2373\u2375]}<\/code><\/pre>\n<p>In APL, functions take array arguments, and so too <em>indexing<\/em> takes array arguments, including the indices (the &#8220;subscripts&#8221;). This fact is exploited to transform the argument string into a vector <code class=\"language-apl\">c<\/code> of <code class=\"language-apl\">1<\/code> and <code class=\"language-apl\">\u00af1<\/code> and <code class=\"language-apl\">0<\/code>, according to whether a character is <code class=\"language-apl\">&lt;<\/code> or <code class=\"language-apl\">&gt;<\/code> or &#8220;other&#8221;. For the angles to be balanced, the plus scan (the partial sums) of <code class=\"language-apl\">c<\/code> must be a <code class=\"language-apl\">0-1<\/code> vector whose last element is <code class=\"language-apl\">0<\/code>.<\/p>\n<p>The closely related problem where the brackets can be nested (e.g. where the brackets are parentheses), can be solved by checking that <code class=\"language-apl\">c<\/code> is non-negative, that is, <code class=\"language-apl\">\u2227\/(\u00d7c)\u220a0 1<\/code> (and the last element is <code class=\"language-apl\">0<\/code>).<\/p>\n<p><strong>7. Unconditionally Shifty<\/strong><\/p>\n<p>Shift a boolean vector <code class=\"language-apl\">\u2375<\/code> by <code class=\"language-apl\">\u237a<\/code>, where positive means a right shift and negative means a left shift.<\/p>\n<pre><code class=\"language-apl\">   shift \u2190 {(\u2262\u2375)\u2374(-\u237a)\u233d\u2375,(|\u237a)\u23740}<\/code><\/pre>\n<p>The problem solution is facilitated by the <em>rotate<\/em> function <code class=\"language-apl\">\u237a\u233d\u2375<\/code>, where a negative <code class=\"language-apl\">\u237a<\/code> means rotate right and positive means rotate left. Other alternative unguarded code can use <code class=\"language-apl\">\u2191<\/code> or <code class=\"language-apl\">\u2193<\/code> (<em>take<\/em> or <em>drop<\/em>) where a negative <code class=\"language-apl\">\u237a<\/code> means take (drop) from the right and positive means from the left.<\/p>\n<p><strong>8. Making a Good Argument<\/strong><\/p>\n<p>Check whether a numeric left argument to <code class=\"language-apl\">\u237a\u2349\u2375<\/code> is valid.<\/p>\n<pre><code class=\"language-apl\">   dta \u2190 {0::0 \u22c4 1\u22a3\u237a\u2349\u2375}<\/code><\/pre>\n<p>This is probably the shortest possible solution: Return <code class=\"language-apl\">1<\/code> if <code class=\"language-apl\">\u237a\u2349\u2375<\/code> executes successfully, otherwise the error is trapped and a <code class=\"language-apl\">0<\/code> is returned. A longer but more insightful solution is as follows:<\/p>\n<pre><code class=\"language-apl\">   dt \u2190 {((\u2262\u237a)=\u2262\u2374\u2375) \u2227 \u2227\/\u237a\u220a\u2368\u2373(\u2262\u2374\u2375)\u230a(\u00d7\u2262\u237a)\u2308\u2308\u2308\/\u237a}<\/code><\/pre>\n<p>The first part of the conjunction checks that the length of <code class=\"language-apl\">\u237a<\/code> is the same as the rank of <code class=\"language-apl\">\u2375<\/code>. (Many APL authors would write <code class=\"language-apl\">\u2374\u2374\u2375<\/code>; I prefer <code class=\"language-apl\">\u2262\u2374\u2375<\/code> because the result is a scalar.) The second part checks the following properties on <code class=\"language-apl\">\u237a<\/code>:<\/p>\n<ul>\n<li>all elements are positive<\/li>\n<li>the elements (if any) form a dense set of integers (from <code class=\"language-apl\">1<\/code> to <code class=\"language-apl\">\u2308\/\u237a<\/code>)<\/li>\n<li>a (necessarily incorrect) large element would not cause the <code class=\"language-apl\">\u2373<\/code> to error<\/li>\n<\/ul>\n<p>The three consecutive <code class=\"language-apl\">\u2308\u2308\u2308<\/code>, each interpreted differently by the system, are quite the masterstroke, don&#8217;t you think? \u263a<\/p>\n<p><strong>9. Earlier, Later, or the Same<\/strong><\/p>\n<p>Return <code class=\"language-apl\">\u00af1<\/code>, <code class=\"language-apl\">1<\/code>, or <code class=\"language-apl\">0<\/code> according to whether a timestamp is earlier than, later than, or simultaneous with another.<\/p>\n<pre><code class=\"language-apl\">   ts \u2190 {\u22830~\u2368\u00d7\u237a-\u2375}<\/code><\/pre>\n<p>The functions works by returning the first non-zero value in the signum of the difference between the arguments, or <code class=\"language-apl\">0<\/code> if all values are zero. A tacit solution of same: <code class=\"language-apl\">ts1 \u2190 \u2283\u2218(~\u22180)\u2218\u00d7 -<\/code> .<\/p>\n<p><strong>10. Anagrammatically Correct<\/strong><\/p>\n<p>Determine whether two character vectors or scalars are anagrams of each other. Spaces are not significant. The problem statement is silent on this, but I am assuming that upper\/lower case is significant.<\/p>\n<pre><code class=\"language-apl\">   anagram \u2190 {g\u2190{{\u2375[\u234b\u2375]}\u2375~' '} \u22c4 (g \u237a)\u2261(g \u2375)}<\/code><\/pre>\n<p>The function works by first converting each argument to a standard form, sorted and without spaces, using the local function <code class=\"language-apl\">g<\/code>, and then comparing the standard forms. In <code class=\"language-apl\">g<\/code>, the idiom <code class=\"language-apl\">{\u2375[\u234b\u2375]}<\/code> sorts a vector and the phrase <code class=\"language-apl\">\u2375~' '<\/code> removes spaces and finesses the problem of scalars.<\/p>\n<p>A reasonable tacit solution depends on the <em>over<\/em> operator <code class=\"language-apl\">\u2365<\/code>, contemplated but not implemented:<\/p>\n<pre><code class=\"language-apl\">     f\u2365g \u2375  \u2190\u2192  f g \u2375\r\n   \u237a f\u2365g \u2375  \u2190\u2192  (g \u237a) f (g \u2375)<\/code><\/pre>\n<p>A tacit solution written with <em>over<\/em>: <code class=\"language-apl\">\u2261\u2365((\u2282\u2218\u234b \u2337 \u22a2)\u2218(~\u2218' '))<\/code>. I myself would prefer the semi-tacit <code class=\"language-apl\">\u2261\u2365{{\u2375[\u234b\u2375]}\u2375~' '}<\/code>.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The following are my attempts at the Phase I problems of the 2018 APL Problem Solving Competition. There are not necessarily &#8220;right answers&#8221; as personal style and taste come into play. More explanation of the code is provided here than &hellip; <a href=\"https:\/\/www.dyalog.com\/blog\/2018\/09\/2018-apl-problem-solving-competition-phase-i-problems-sample-solutions\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":13,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22],"tags":[],"class_list":["post-5316","post","type-post","status-publish","format-standard","hentry","category-student-competition"],"_links":{"self":[{"href":"https:\/\/www.dyalog.com\/blog\/wp-json\/wp\/v2\/posts\/5316","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dyalog.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dyalog.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dyalog.com\/blog\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dyalog.com\/blog\/wp-json\/wp\/v2\/comments?post=5316"}],"version-history":[{"count":9,"href":"https:\/\/www.dyalog.com\/blog\/wp-json\/wp\/v2\/posts\/5316\/revisions"}],"predecessor-version":[{"id":6139,"href":"https:\/\/www.dyalog.com\/blog\/wp-json\/wp\/v2\/posts\/5316\/revisions\/6139"}],"wp:attachment":[{"href":"https:\/\/www.dyalog.com\/blog\/wp-json\/wp\/v2\/media?parent=5316"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dyalog.com\/blog\/wp-json\/wp\/v2\/categories?post=5316"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dyalog.com\/blog\/wp-json\/wp\/v2\/tags?post=5316"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}