Dyalog APL competition phase 2: Add explanations for problems 1-4
This commit is contained in:
parent
a93dcfbf46
commit
25688997a2
4 changed files with 514 additions and 386 deletions
272
_site/atom.xml
272
_site/atom.xml
|
@ -54,6 +54,8 @@
|
||||||
<a class="sourceLine" id="cb2-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb2-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb2-9" title="9"> score←2(⍎⍕)dd×+/scores</a>
|
<a class="sourceLine" id="cb2-9" title="9"> score←2(⍎⍕)dd×+/scores</a>
|
||||||
<a class="sourceLine" id="cb2-10" title="10">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb2-10" title="10">∇</a></code></pre></div>
|
||||||
|
<p>This is a very straightforward implementation of the algorithm describe in the problem description. I decided to switch explicitly on the size of the input vector because I feel it is more natural. For the cases with 5 or 7 judges, we use Drop (<code>↓</code>) to remove the lowest and highest scores.</p>
|
||||||
|
<p>At the end, we sum up the scores with <code>+/</code> and multiply them by <code>dd</code>. The last operation, <code>2(⍎⍕)</code>, is a train using <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Format%20Dyadic.htm">Format (Dyadic)</a> to round to 2 decimal places, and <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Execute.htm">Execute</a> to get actual numbers and not strings.</p>
|
||||||
<h2 id="problem-2-another-step-in-the-proper-direction">Problem 2 – Another Step in the Proper Direction</h2>
|
<h2 id="problem-2-another-step-in-the-proper-direction">Problem 2 – Another Step in the Proper Direction</h2>
|
||||||
<div class="sourceCode" id="cb3"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb3-1" title="1">∇ steps←{p}Steps fromTo;segments;width</a>
|
<div class="sourceCode" id="cb3"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb3-1" title="1">∇ steps←{p}Steps fromTo;segments;width</a>
|
||||||
<a class="sourceLine" id="cb3-2" title="2"> width←|-/fromTo</a>
|
<a class="sourceLine" id="cb3-2" title="2"> width←|-/fromTo</a>
|
||||||
|
@ -69,147 +71,161 @@
|
||||||
<a class="sourceLine" id="cb3-12" title="12"> ⍝ Take into account the start point and the direction.</a>
|
<a class="sourceLine" id="cb3-12" title="12"> ⍝ Take into account the start point and the direction.</a>
|
||||||
<a class="sourceLine" id="cb3-13" title="13"> steps←fromTo{(⊃⍺)+(-×-/⍺)×⍵}segments</a>
|
<a class="sourceLine" id="cb3-13" title="13"> steps←fromTo{(⊃⍺)+(-×-/⍺)×⍵}segments</a>
|
||||||
<a class="sourceLine" id="cb3-14" title="14">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb3-14" title="14">∇</a></code></pre></div>
|
||||||
|
<p>This is an extension to <a href="./dyalog-apl-competition-2020-phase-1.html#stepping-in-the-proper-direction">Problem 5 of Phase I</a>. In each case, we compute the “segments”, i.e., the steps starting from 0. In a last step, common to all cases, we add the correct starting point and correct the direction if need be.</p>
|
||||||
|
<p>To compute equally-sized steps, we first divide the segment <span class="math inline">\([0, 1]\)</span> in <code>p</code> equal segments with <code>(⍳p)÷p</code>. This subdivision can then be multiplied by the width to obtain the required segments.</p>
|
||||||
|
<p>When <code>p</code> is the step size, we just divide the width by the step size (rounded to the next largest integer) to get the required number of segments. If the last segment is too large, we “crop” it to the width with Minimum (<code>⌊</code>).</p>
|
||||||
<h2 id="problem-3-past-tasks-blast">Problem 3 – Past Tasks Blast</h2>
|
<h2 id="problem-3-past-tasks-blast">Problem 3 – Past Tasks Blast</h2>
|
||||||
<div class="sourceCode" id="cb4"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb4-1" title="1">∇ urls←PastTasks url;r;paths</a>
|
<div class="sourceCode" id="cb4"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb4-1" title="1">∇ urls←PastTasks url;r;paths</a>
|
||||||
<a class="sourceLine" id="cb4-2" title="2"> r←HttpCommand.Get url</a>
|
<a class="sourceLine" id="cb4-2" title="2"> r←HttpCommand.Get url</a>
|
||||||
<a class="sourceLine" id="cb4-3" title="3"> paths←('[a-zA-Z0-9_/]+\.pdf'⎕S'&')r.Data</a>
|
<a class="sourceLine" id="cb4-3" title="3"> paths←('[a-zA-Z0-9_/]+\.pdf'⎕S'&')r.Data</a>
|
||||||
<a class="sourceLine" id="cb4-4" title="4"> urls←('https://www.dyalog.com/'∘,)¨paths</a>
|
<a class="sourceLine" id="cb4-4" title="4"> urls←('https://www.dyalog.com/'∘,)¨paths</a>
|
||||||
<a class="sourceLine" id="cb4-5" title="5">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb4-5" title="5">∇</a></code></pre></div>
|
||||||
|
<p>I decided to use <code>HttpCommand</code> for this task, since it is simply one <code>]load HttpCommand</code> away and should be platform-independent.</p>
|
||||||
|
<p>Parsing XML is not something I consider “fun” in the best of cases, and I feel like APL is not the best language to do this kind of thing. Given how simple the task is, I just decided to find the relevant bits with a regular expression using <a href="https://help.dyalog.com/18.0/index.htm#Language/System%20Functions/r.htm">Replace and Search</a> (<code>⎕S</code>).</p>
|
||||||
|
<p>After finding all the strings vaguely resembling a PDF file name (only alphanumeric characters and underscores, with a <code>.pdf</code> extension), I just concatenate them to the base URL of the Dyalog domain.</p>
|
||||||
<h2 id="problem-4-bioinformatics">Problem 4 – Bioinformatics</h2>
|
<h2 id="problem-4-bioinformatics">Problem 4 – Bioinformatics</h2>
|
||||||
|
<p>The first task can be solved by decomposing it into several functions.</p>
|
||||||
<div class="sourceCode" id="cb5"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb5-1" title="1">⍝ Test if a DNA string is a reverse palindrome.</a>
|
<div class="sourceCode" id="cb5"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb5-1" title="1">⍝ Test if a DNA string is a reverse palindrome.</a>
|
||||||
<a class="sourceLine" id="cb5-2" title="2">isrevp←{⍵≡⌽'TAGC'['ATCG'⍳⍵]}</a>
|
<a class="sourceLine" id="cb5-2" title="2">isrevp←{⍵≡⌽'TAGC'['ATCG'⍳⍵]}</a></code></pre></div>
|
||||||
<a class="sourceLine" id="cb5-3" title="3"></a>
|
<p>First, we compute the complement of a DNA string (using simple indexing) and test if its Reverse (<code>⌽</code>) is equal to the original string.</p>
|
||||||
<a class="sourceLine" id="cb5-4" title="4">⍝ Generate all subarrays (position, length) pairs, for</a>
|
<div class="sourceCode" id="cb6"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb6-1" title="1">⍝ Generate all subarrays (position, length) pairs, for 4 ≤ length ≤ 12.</a>
|
||||||
<a class="sourceLine" id="cb5-5" title="5">⍝ 4 ≤ length ≤ 12.</a>
|
<a class="sourceLine" id="cb6-2" title="2">subarrays←{⊃,/(⍳⍵),¨¨3↓¨⍳¨12⌊1+⍵-⍳⍵}</a></code></pre></div>
|
||||||
<a class="sourceLine" id="cb5-6" title="6">subarrays←{⊃,/(⍳⍵),¨¨3↓¨⍳¨12⌊1+⍵-⍳⍵}</a>
|
<p>We first compute all the possible lengths for each starting point. For instance, the last element cannot have any (position, length) pair associated to it, because there is no three element following it. So we crop the possible lengths to <span class="math inline">\([3, 12]\)</span>. For instance for an array of size 10:</p>
|
||||||
<a class="sourceLine" id="cb5-7" title="7"></a>
|
<div class="sourceCode" id="cb7"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb7-1" title="1"> {3↓¨⍳¨12⌊1+⍵-⍳⍵}10</a>
|
||||||
<a class="sourceLine" id="cb5-8" title="8">∇ r←revp dna;positions</a>
|
<a class="sourceLine" id="cb7-2" title="2">┌──────────────┬───────────┬─────────┬───────┬─────┬───┬─┬┬┬┐</a>
|
||||||
<a class="sourceLine" id="cb5-9" title="9"> positions←subarrays⍴dna</a>
|
<a class="sourceLine" id="cb7-3" title="3">│4 5 6 7 8 9 10│4 5 6 7 8 9│4 5 6 7 8│4 5 6 7│4 5 6│4 5│4││││</a>
|
||||||
<a class="sourceLine" id="cb5-10" title="10"> ⍝ Filter subarrays which are reverse palindromes.</a>
|
<a class="sourceLine" id="cb7-4" title="4">└──────────────┴───────────┴─────────┴───────┴─────┴───┴─┴┴┴┘</a></code></pre></div>
|
||||||
<a class="sourceLine" id="cb5-11" title="11"> r←↑({isrevp dna[¯1+⍵[1]+⍳⍵[2]]}¨positions)/positions</a>
|
<p>Then, we just add the corresponding starting position to each length (1 for the first block, 2 for the second, and so on). Finally, we flatten everything.</p>
|
||||||
<a class="sourceLine" id="cb5-12" title="12">∇</a></code></pre></div>
|
<div class="sourceCode" id="cb8"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb8-1" title="1">∇ r←revp dna;positions</a>
|
||||||
<div class="sourceCode" id="cb6"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb6-1" title="1">sset←{((1E6|2∘×)⍣⍵)1}</a></code></pre></div>
|
<a class="sourceLine" id="cb8-2" title="2"> positions←subarrays⍴dna</a>
|
||||||
|
<a class="sourceLine" id="cb8-3" title="3"> ⍝ Filter subarrays which are reverse palindromes.</a>
|
||||||
|
<a class="sourceLine" id="cb8-4" title="4"> r←↑({isrevp dna[¯1+⍵[1]+⍳⍵[2]]}¨positions)/positions</a>
|
||||||
|
<a class="sourceLine" id="cb8-5" title="5">∇</a></code></pre></div>
|
||||||
|
<p>For each possible (position, length) pair, we get the corresponding DNA substring with <code>dna[¯1+⍵[1]+⍳⍵[2]]</code> (adding <code>¯1</code> is necessary because <code>⎕IO←1</code>). We test if this substring is a reverse palindrome using <code>isrevp</code> above. <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Replicate.htm">Replicate</a> (<code>/</code>) then selects only the (position, length) pairs for which the substring is a reverse palindrome.</p>
|
||||||
|
<p>The second task is just about counting the number of subsets modulo 1,000,000. So we just need to compute <span class="math inline">\(2^n \mod 1000000\)</span> for any positive integer <span class="math inline">\(n\leq1000\)</span>.</p>
|
||||||
|
<div class="sourceCode" id="cb9"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb9-1" title="1">sset←{((1E6|2∘×)⍣⍵)1}</a></code></pre></div>
|
||||||
|
<p>Since we cannot just compute <span class="math inline">\(2^n\)</span> directly and take the remainder, we use modular arithmetic to stay mod 1,000,000 during the whole computation. The dfn <code>(1E6|2∘×)</code> doubles its argument mod 1,000,000. So we just apply this function <span class="math inline">\(n\)</span> times using the <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Operators/Power%20Operator.htm">Power</a> operator (<code>⍣</code>), with an initial value of 1.</p>
|
||||||
<h2 id="problem-5-future-and-present-value">Problem 5 – Future and Present Value</h2>
|
<h2 id="problem-5-future-and-present-value">Problem 5 – Future and Present Value</h2>
|
||||||
<div class="sourceCode" id="cb7"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb7-1" title="1">⍝ First solution: ((1+⊢)⊥⊣) computes the total return</a>
|
<div class="sourceCode" id="cb10"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb10-1" title="1">⍝ First solution: ((1+⊢)⊥⊣) computes the total return</a>
|
||||||
<a class="sourceLine" id="cb7-2" title="2">⍝ for a vector of amounts ⍺ and a vector of rates</a>
|
<a class="sourceLine" id="cb10-2" title="2">⍝ for a vector of amounts ⍺ and a vector of rates</a>
|
||||||
<a class="sourceLine" id="cb7-3" title="3">⍝ ⍵. It is applied to every prefix subarray of amounts</a>
|
<a class="sourceLine" id="cb10-3" title="3">⍝ ⍵. It is applied to every prefix subarray of amounts</a>
|
||||||
<a class="sourceLine" id="cb7-4" title="4">⍝ and rates to get all intermediate values. However,</a>
|
<a class="sourceLine" id="cb10-4" title="4">⍝ and rates to get all intermediate values. However,</a>
|
||||||
<a class="sourceLine" id="cb7-5" title="5">⍝ this has quadratic complexity.</a>
|
<a class="sourceLine" id="cb10-5" title="5">⍝ this has quadratic complexity.</a>
|
||||||
<a class="sourceLine" id="cb7-6" title="6">⍝ rr←(,\⊣)((1+⊢)⊥⊣)¨(,\⊢)</a>
|
<a class="sourceLine" id="cb10-6" title="6">⍝ rr←(,\⊣)((1+⊢)⊥⊣)¨(,\⊢)</a>
|
||||||
<a class="sourceLine" id="cb7-7" title="7"></a>
|
<a class="sourceLine" id="cb10-7" title="7"></a>
|
||||||
<a class="sourceLine" id="cb7-8" title="8">⍝ Second solution: We want to be able to use the</a>
|
<a class="sourceLine" id="cb10-8" title="8">⍝ Second solution: We want to be able to use the</a>
|
||||||
<a class="sourceLine" id="cb7-9" title="9">⍝ recurrence relation (recur) and scan through the</a>
|
<a class="sourceLine" id="cb10-9" title="9">⍝ recurrence relation (recur) and scan through the</a>
|
||||||
<a class="sourceLine" id="cb7-10" title="10">⍝ vectors of amounts and rates, accumulating the total</a>
|
<a class="sourceLine" id="cb10-10" title="10">⍝ vectors of amounts and rates, accumulating the total</a>
|
||||||
<a class="sourceLine" id="cb7-11" title="11">⍝ value at every time step. However, APL evaluation is</a>
|
<a class="sourceLine" id="cb10-11" title="11">⍝ value at every time step. However, APL evaluation is</a>
|
||||||
<a class="sourceLine" id="cb7-12" title="12">⍝ right-associative, so a simple Scan</a>
|
<a class="sourceLine" id="cb10-12" title="12">⍝ right-associative, so a simple Scan</a>
|
||||||
<a class="sourceLine" id="cb7-13" title="13">⍝ (recur\amounts,¨values) would not give the correct</a>
|
<a class="sourceLine" id="cb10-13" title="13">⍝ (recur\amounts,¨values) would not give the correct</a>
|
||||||
<a class="sourceLine" id="cb7-14" title="14">⍝ result, since recur is not associative and we need</a>
|
<a class="sourceLine" id="cb10-14" title="14">⍝ result, since recur is not associative and we need</a>
|
||||||
<a class="sourceLine" id="cb7-15" title="15">⍝ to evaluate it left-to-right. (In any case, in this</a>
|
<a class="sourceLine" id="cb10-15" title="15">⍝ to evaluate it left-to-right. (In any case, in this</a>
|
||||||
<a class="sourceLine" id="cb7-16" title="16">⍝ case, Scan would have quadratic complexity, so would</a>
|
<a class="sourceLine" id="cb10-16" title="16">⍝ case, Scan would have quadratic complexity, so would</a>
|
||||||
<a class="sourceLine" id="cb7-17" title="17">⍝ not bring any benefit over the previous solution.)</a>
|
<a class="sourceLine" id="cb10-17" title="17">⍝ not bring any benefit over the previous solution.)</a>
|
||||||
<a class="sourceLine" id="cb7-18" title="18">⍝ What we need is something akin to Haskell's scanl</a>
|
<a class="sourceLine" id="cb10-18" title="18">⍝ What we need is something akin to Haskell's scanl</a>
|
||||||
<a class="sourceLine" id="cb7-19" title="19">⍝ function, which would evaluate left to right in O(n)</a>
|
<a class="sourceLine" id="cb10-19" title="19">⍝ function, which would evaluate left to right in O(n)</a>
|
||||||
<a class="sourceLine" id="cb7-20" title="20">⍝ time. This is what we do here, accumulating values</a>
|
<a class="sourceLine" id="cb10-20" title="20">⍝ time. This is what we do here, accumulating values</a>
|
||||||
<a class="sourceLine" id="cb7-21" title="21">⍝ from left to right. (This is inspired from</a>
|
<a class="sourceLine" id="cb10-21" title="21">⍝ from left to right. (This is inspired from</a>
|
||||||
<a class="sourceLine" id="cb7-22" title="22">⍝ dfns.ascan, although heavily simplified.)</a>
|
<a class="sourceLine" id="cb10-22" title="22">⍝ dfns.ascan, although heavily simplified.)</a>
|
||||||
<a class="sourceLine" id="cb7-23" title="23">rr←{recur←{⍵[1]+⍺×1+⍵[2]} ⋄ 1↓⌽⊃{(⊂(⊃⍵)recur⍺),⍵}/⌽⍺,¨⍵}</a></code></pre></div>
|
<a class="sourceLine" id="cb10-23" title="23">rr←{recur←{⍵[1]+⍺×1+⍵[2]} ⋄ 1↓⌽⊃{(⊂(⊃⍵)recur⍺),⍵}/⌽⍺,¨⍵}</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb8"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb8-1" title="1">⍝ Simply apply the formula for cashflow calculations.</a>
|
<div class="sourceCode" id="cb11"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb11-1" title="1">⍝ Simply apply the formula for cashflow calculations.</a>
|
||||||
<a class="sourceLine" id="cb8-2" title="2">pv←{+/⍺÷×\1+⍵}</a></code></pre></div>
|
<a class="sourceLine" id="cb11-2" title="2">pv←{+/⍺÷×\1+⍵}</a></code></pre></div>
|
||||||
<h2 id="problem-6-merge">Problem 6 – Merge</h2>
|
<h2 id="problem-6-merge">Problem 6 – Merge</h2>
|
||||||
<div class="sourceCode" id="cb9"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb9-1" title="1">∇ val←ns getval var</a>
|
<div class="sourceCode" id="cb12"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb12-1" title="1">∇ val←ns getval var</a>
|
||||||
<a class="sourceLine" id="cb9-2" title="2"> :If ''≡var ⍝ literal '@'</a>
|
<a class="sourceLine" id="cb12-2" title="2"> :If ''≡var ⍝ literal '@'</a>
|
||||||
<a class="sourceLine" id="cb9-3" title="3"> val←'@'</a>
|
<a class="sourceLine" id="cb12-3" title="3"> val←'@'</a>
|
||||||
<a class="sourceLine" id="cb9-4" title="4"> :ElseIf (⊂var)∊ns.⎕NL ¯2</a>
|
<a class="sourceLine" id="cb12-4" title="4"> :ElseIf (⊂var)∊ns.⎕NL ¯2</a>
|
||||||
<a class="sourceLine" id="cb9-5" title="5"> val←⍕ns⍎var</a>
|
<a class="sourceLine" id="cb12-5" title="5"> val←⍕ns⍎var</a>
|
||||||
<a class="sourceLine" id="cb9-6" title="6"> :Else</a>
|
<a class="sourceLine" id="cb12-6" title="6"> :Else</a>
|
||||||
<a class="sourceLine" id="cb9-7" title="7"> val←'???'</a>
|
<a class="sourceLine" id="cb12-7" title="7"> val←'???'</a>
|
||||||
<a class="sourceLine" id="cb9-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb12-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb9-9" title="9">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb12-9" title="9">∇</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb10"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb10-1" title="1">∇ text←templateFile Merge jsonFile;template;ns</a>
|
<div class="sourceCode" id="cb13"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb13-1" title="1">∇ text←templateFile Merge jsonFile;template;ns</a>
|
||||||
<a class="sourceLine" id="cb10-2" title="2"> template←⊃⎕NGET templateFile 1</a>
|
<a class="sourceLine" id="cb13-2" title="2"> template←⊃⎕NGET templateFile 1</a>
|
||||||
<a class="sourceLine" id="cb10-3" title="3"> ns←⎕JSON⊃⎕NGET jsonFile</a>
|
<a class="sourceLine" id="cb13-3" title="3"> ns←⎕JSON⊃⎕NGET jsonFile</a>
|
||||||
<a class="sourceLine" id="cb10-4" title="4"> ⍝ We use a simple regex search and replace on the</a>
|
<a class="sourceLine" id="cb13-4" title="4"> ⍝ We use a simple regex search and replace on the</a>
|
||||||
<a class="sourceLine" id="cb10-5" title="5"> ⍝ template.</a>
|
<a class="sourceLine" id="cb13-5" title="5"> ⍝ template.</a>
|
||||||
<a class="sourceLine" id="cb10-6" title="6"> text←↑('@[a-zA-Z]*@'⎕R{ns getval ¯1↓1↓⍵.Match})template</a>
|
<a class="sourceLine" id="cb13-6" title="6"> text←↑('@[a-zA-Z]*@'⎕R{ns getval ¯1↓1↓⍵.Match})template</a>
|
||||||
<a class="sourceLine" id="cb10-7" title="7">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb13-7" title="7">∇</a></code></pre></div>
|
||||||
<h2 id="problem-7-upc">Problem 7 – UPC</h2>
|
<h2 id="problem-7-upc">Problem 7 – UPC</h2>
|
||||||
<div class="sourceCode" id="cb11"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb11-1" title="1">CheckDigit←{10|-⍵+.×11⍴3 1}</a></code></pre></div>
|
<div class="sourceCode" id="cb14"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb14-1" title="1">CheckDigit←{10|-⍵+.×11⍴3 1}</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb12"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb12-1" title="1">⍝ Left and right representations of digits. Decoding</a>
|
<div class="sourceCode" id="cb15"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb15-1" title="1">⍝ Left and right representations of digits. Decoding</a>
|
||||||
<a class="sourceLine" id="cb12-2" title="2">⍝ the binary representation from decimal is more</a>
|
<a class="sourceLine" id="cb15-2" title="2">⍝ the binary representation from decimal is more</a>
|
||||||
<a class="sourceLine" id="cb12-3" title="3">⍝ compact than writing everything explicitly.</a>
|
<a class="sourceLine" id="cb15-3" title="3">⍝ compact than writing everything explicitly.</a>
|
||||||
<a class="sourceLine" id="cb12-4" title="4">lrepr←⍉(7⍴2)⊤13 25 19 61 35 49 47 59 55 11</a>
|
<a class="sourceLine" id="cb15-4" title="4">lrepr←⍉(7⍴2)⊤13 25 19 61 35 49 47 59 55 11</a>
|
||||||
<a class="sourceLine" id="cb12-5" title="5">rrepr←~¨lrepr</a></code></pre></div>
|
<a class="sourceLine" id="cb15-5" title="5">rrepr←~¨lrepr</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb13"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb13-1" title="1">∇ bits←WriteUPC digits;left;right</a>
|
<div class="sourceCode" id="cb16"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb16-1" title="1">∇ bits←WriteUPC digits;left;right</a>
|
||||||
<a class="sourceLine" id="cb13-2" title="2"> :If (11=≢digits)∧∧/digits∊0,⍳9</a>
|
<a class="sourceLine" id="cb16-2" title="2"> :If (11=≢digits)∧∧/digits∊0,⍳9</a>
|
||||||
<a class="sourceLine" id="cb13-3" title="3"> left←,lrepr[1+6↑digits;]</a>
|
<a class="sourceLine" id="cb16-3" title="3"> left←,lrepr[1+6↑digits;]</a>
|
||||||
<a class="sourceLine" id="cb13-4" title="4"> right←,rrepr[1+6↓digits,CheckDigit digits;]</a>
|
<a class="sourceLine" id="cb16-4" title="4"> right←,rrepr[1+6↓digits,CheckDigit digits;]</a>
|
||||||
<a class="sourceLine" id="cb13-5" title="5"> bits←1 0 1,left,0 1 0 1 0,right,1 0 1</a>
|
<a class="sourceLine" id="cb16-5" title="5"> bits←1 0 1,left,0 1 0 1 0,right,1 0 1</a>
|
||||||
<a class="sourceLine" id="cb13-6" title="6"> :Else</a>
|
<a class="sourceLine" id="cb16-6" title="6"> :Else</a>
|
||||||
<a class="sourceLine" id="cb13-7" title="7"> bits←¯1</a>
|
<a class="sourceLine" id="cb16-7" title="7"> bits←¯1</a>
|
||||||
<a class="sourceLine" id="cb13-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb16-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb13-9" title="9">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb16-9" title="9">∇</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb14"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb14-1" title="1">∇ digits←ReadUPC bits</a>
|
<div class="sourceCode" id="cb17"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb17-1" title="1">∇ digits←ReadUPC bits</a>
|
||||||
<a class="sourceLine" id="cb14-2" title="2"> :If 95≠⍴bits ⍝ incorrect number of bits</a>
|
<a class="sourceLine" id="cb17-2" title="2"> :If 95≠⍴bits ⍝ incorrect number of bits</a>
|
||||||
<a class="sourceLine" id="cb14-3" title="3"> digits←¯1</a>
|
<a class="sourceLine" id="cb17-3" title="3"> digits←¯1</a>
|
||||||
<a class="sourceLine" id="cb14-4" title="4"> :Else</a>
|
<a class="sourceLine" id="cb17-4" title="4"> :Else</a>
|
||||||
<a class="sourceLine" id="cb14-5" title="5"> ⍝ Test if the barcode was scanned right-to-left.</a>
|
<a class="sourceLine" id="cb17-5" title="5"> ⍝ Test if the barcode was scanned right-to-left.</a>
|
||||||
<a class="sourceLine" id="cb14-6" title="6"> :If 0=2|+/bits[3+⍳7]</a>
|
<a class="sourceLine" id="cb17-6" title="6"> :If 0=2|+/bits[3+⍳7]</a>
|
||||||
<a class="sourceLine" id="cb14-7" title="7"> bits←⌽bits</a>
|
<a class="sourceLine" id="cb17-7" title="7"> bits←⌽bits</a>
|
||||||
<a class="sourceLine" id="cb14-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb17-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb14-9" title="9"> digits←({¯1+lrepr⍳⍵}¨(7/⍳6)⊆42↑3↓bits),{¯1+rrepr⍳⍵}¨(7/⍳6)⊆¯42↑¯3↓bits</a>
|
<a class="sourceLine" id="cb17-9" title="9"> digits←({¯1+lrepr⍳⍵}¨(7/⍳6)⊆42↑3↓bits),{¯1+rrepr⍳⍵}¨(7/⍳6)⊆¯42↑¯3↓bits</a>
|
||||||
<a class="sourceLine" id="cb14-10" title="10"> :If ~∧/digits∊0,⍳9 ⍝ incorrect parity</a>
|
<a class="sourceLine" id="cb17-10" title="10"> :If ~∧/digits∊0,⍳9 ⍝ incorrect parity</a>
|
||||||
<a class="sourceLine" id="cb14-11" title="11"> digits←¯1</a>
|
<a class="sourceLine" id="cb17-11" title="11"> digits←¯1</a>
|
||||||
<a class="sourceLine" id="cb14-12" title="12"> :ElseIf (⊃⌽digits)≠CheckDigit ¯1↓digits ⍝ incorrect check digit</a>
|
<a class="sourceLine" id="cb17-12" title="12"> :ElseIf (⊃⌽digits)≠CheckDigit ¯1↓digits ⍝ incorrect check digit</a>
|
||||||
<a class="sourceLine" id="cb14-13" title="13"> digits←¯1</a>
|
<a class="sourceLine" id="cb17-13" title="13"> digits←¯1</a>
|
||||||
<a class="sourceLine" id="cb14-14" title="14"> :EndIf</a>
|
<a class="sourceLine" id="cb17-14" title="14"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb14-15" title="15"> :EndIf</a>
|
<a class="sourceLine" id="cb17-15" title="15"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb14-16" title="16">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb17-16" title="16">∇</a></code></pre></div>
|
||||||
<h2 id="problem-8-balancing-the-scales">Problem 8 – Balancing the Scales</h2>
|
<h2 id="problem-8-balancing-the-scales">Problem 8 – Balancing the Scales</h2>
|
||||||
<div class="sourceCode" id="cb15"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb15-1" title="1">∇ parts←Balance nums;subsets;partitions</a>
|
<div class="sourceCode" id="cb18"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb18-1" title="1">∇ parts←Balance nums;subsets;partitions</a>
|
||||||
<a class="sourceLine" id="cb15-2" title="2"> ⍝ This is a brute force solution, running in</a>
|
<a class="sourceLine" id="cb18-2" title="2"> ⍝ This is a brute force solution, running in</a>
|
||||||
<a class="sourceLine" id="cb15-3" title="3"> ⍝ exponential time. We generate all the possible</a>
|
<a class="sourceLine" id="cb18-3" title="3"> ⍝ exponential time. We generate all the possible</a>
|
||||||
<a class="sourceLine" id="cb15-4" title="4"> ⍝ partitions, filter out those which are not</a>
|
<a class="sourceLine" id="cb18-4" title="4"> ⍝ partitions, filter out those which are not</a>
|
||||||
<a class="sourceLine" id="cb15-5" title="5"> ⍝ balanced, and return the first matching one. There</a>
|
<a class="sourceLine" id="cb18-5" title="5"> ⍝ balanced, and return the first matching one. There</a>
|
||||||
<a class="sourceLine" id="cb15-6" title="6"> ⍝ are more advanced approach running in</a>
|
<a class="sourceLine" id="cb18-6" title="6"> ⍝ are more advanced approach running in</a>
|
||||||
<a class="sourceLine" id="cb15-7" title="7"> ⍝ pseudo-polynomial time (based on dynamic</a>
|
<a class="sourceLine" id="cb18-7" title="7"> ⍝ pseudo-polynomial time (based on dynamic</a>
|
||||||
<a class="sourceLine" id="cb15-8" title="8"> ⍝ programming, see the "Partition problem" Wikipedia</a>
|
<a class="sourceLine" id="cb18-8" title="8"> ⍝ programming, see the "Partition problem" Wikipedia</a>
|
||||||
<a class="sourceLine" id="cb15-9" title="9"> ⍝ page), but they are not warranted here, as the</a>
|
<a class="sourceLine" id="cb18-9" title="9"> ⍝ page), but they are not warranted here, as the</a>
|
||||||
<a class="sourceLine" id="cb15-10" title="10"> ⍝ input size remains fairly small.</a>
|
<a class="sourceLine" id="cb18-10" title="10"> ⍝ input size remains fairly small.</a>
|
||||||
<a class="sourceLine" id="cb15-11" title="11"></a>
|
<a class="sourceLine" id="cb18-11" title="11"></a>
|
||||||
<a class="sourceLine" id="cb15-12" title="12"> ⍝ Generate all partitions of a vector of a given</a>
|
<a class="sourceLine" id="cb18-12" title="12"> ⍝ Generate all partitions of a vector of a given</a>
|
||||||
<a class="sourceLine" id="cb15-13" title="13"> ⍝ size, as binary mask vectors.</a>
|
<a class="sourceLine" id="cb18-13" title="13"> ⍝ size, as binary mask vectors.</a>
|
||||||
<a class="sourceLine" id="cb15-14" title="14"> subsets←{1↓2⊥⍣¯1⍳2*⍵}</a>
|
<a class="sourceLine" id="cb18-14" title="14"> subsets←{1↓2⊥⍣¯1⍳2*⍵}</a>
|
||||||
<a class="sourceLine" id="cb15-15" title="15"> ⍝ Keep only the subsets whose sum is exactly</a>
|
<a class="sourceLine" id="cb18-15" title="15"> ⍝ Keep only the subsets whose sum is exactly</a>
|
||||||
<a class="sourceLine" id="cb15-16" title="16"> ⍝ (+/nums)÷2.</a>
|
<a class="sourceLine" id="cb18-16" title="16"> ⍝ (+/nums)÷2.</a>
|
||||||
<a class="sourceLine" id="cb15-17" title="17"> partitions←nums{((2÷⍨+/⍺)=⍺+.×⍵)/⍵}subsets⍴nums</a>
|
<a class="sourceLine" id="cb18-17" title="17"> partitions←nums{((2÷⍨+/⍺)=⍺+.×⍵)/⍵}subsets⍴nums</a>
|
||||||
<a class="sourceLine" id="cb15-18" title="18"> :If 0=≢,partitions</a>
|
<a class="sourceLine" id="cb18-18" title="18"> :If 0=≢,partitions</a>
|
||||||
<a class="sourceLine" id="cb15-19" title="19"> ⍝ If no partition satisfy the above</a>
|
<a class="sourceLine" id="cb18-19" title="19"> ⍝ If no partition satisfy the above</a>
|
||||||
<a class="sourceLine" id="cb15-20" title="20"> ⍝ criterion, we return ⍬.</a>
|
<a class="sourceLine" id="cb18-20" title="20"> ⍝ criterion, we return ⍬.</a>
|
||||||
<a class="sourceLine" id="cb15-21" title="21"> parts←⍬</a>
|
<a class="sourceLine" id="cb18-21" title="21"> parts←⍬</a>
|
||||||
<a class="sourceLine" id="cb15-22" title="22"> :Else</a>
|
<a class="sourceLine" id="cb18-22" title="22"> :Else</a>
|
||||||
<a class="sourceLine" id="cb15-23" title="23"> ⍝ Otherwise, we return the first possible</a>
|
<a class="sourceLine" id="cb18-23" title="23"> ⍝ Otherwise, we return the first possible</a>
|
||||||
<a class="sourceLine" id="cb15-24" title="24"> ⍝ partition.</a>
|
<a class="sourceLine" id="cb18-24" title="24"> ⍝ partition.</a>
|
||||||
<a class="sourceLine" id="cb15-25" title="25"> parts←nums{((⊂,(⊂~))⊃↓⍉⍵)/¨2⍴⊂⍺}partitions</a>
|
<a class="sourceLine" id="cb18-25" title="25"> parts←nums{((⊂,(⊂~))⊃↓⍉⍵)/¨2⍴⊂⍺}partitions</a>
|
||||||
<a class="sourceLine" id="cb15-26" title="26"> :EndIf</a>
|
<a class="sourceLine" id="cb18-26" title="26"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb15-27" title="27">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb18-27" title="27">∇</a></code></pre></div>
|
||||||
<h2 id="problem-9-upwardly-mobile">Problem 9 – Upwardly Mobile</h2>
|
<h2 id="problem-9-upwardly-mobile">Problem 9 – Upwardly Mobile</h2>
|
||||||
<div class="sourceCode" id="cb16"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb16-1" title="1">∇ weights←Weights filename;mobile;branches;mat</a>
|
<div class="sourceCode" id="cb19"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb19-1" title="1">∇ weights←Weights filename;mobile;branches;mat</a>
|
||||||
<a class="sourceLine" id="cb16-2" title="2"> ⍝ Put your code and comments below here</a>
|
<a class="sourceLine" id="cb19-2" title="2"> ⍝ Put your code and comments below here</a>
|
||||||
<a class="sourceLine" id="cb16-3" title="3"></a>
|
<a class="sourceLine" id="cb19-3" title="3"></a>
|
||||||
<a class="sourceLine" id="cb16-4" title="4"> ⍝ Parse the mobile input file.</a>
|
<a class="sourceLine" id="cb19-4" title="4"> ⍝ Parse the mobile input file.</a>
|
||||||
<a class="sourceLine" id="cb16-5" title="5"> mobile←↑⊃⎕NGET filename 1</a>
|
<a class="sourceLine" id="cb19-5" title="5"> mobile←↑⊃⎕NGET filename 1</a>
|
||||||
<a class="sourceLine" id="cb16-6" title="6"> branches←⍸mobile∊'┌┴┐'</a>
|
<a class="sourceLine" id="cb19-6" title="6"> branches←⍸mobile∊'┌┴┐'</a>
|
||||||
<a class="sourceLine" id="cb16-7" title="7"> ⍝ TODO: Build the matrix of coefficients mat.</a>
|
<a class="sourceLine" id="cb19-7" title="7"> ⍝ TODO: Build the matrix of coefficients mat.</a>
|
||||||
<a class="sourceLine" id="cb16-8" title="8"></a>
|
<a class="sourceLine" id="cb19-8" title="8"></a>
|
||||||
<a class="sourceLine" id="cb16-9" title="9"> ⍝ Solve the system of equations (arbitrarily setting</a>
|
<a class="sourceLine" id="cb19-9" title="9"> ⍝ Solve the system of equations (arbitrarily setting</a>
|
||||||
<a class="sourceLine" id="cb16-10" title="10"> ⍝ the first variable at 1 because the system is</a>
|
<a class="sourceLine" id="cb19-10" title="10"> ⍝ the first variable at 1 because the system is</a>
|
||||||
<a class="sourceLine" id="cb16-11" title="11"> ⍝ overdetermined), then multiply the coefficients by</a>
|
<a class="sourceLine" id="cb19-11" title="11"> ⍝ overdetermined), then multiply the coefficients by</a>
|
||||||
<a class="sourceLine" id="cb16-12" title="12"> ⍝ their least common multiple to get the smallest</a>
|
<a class="sourceLine" id="cb19-12" title="12"> ⍝ their least common multiple to get the smallest</a>
|
||||||
<a class="sourceLine" id="cb16-13" title="13"> ⍝ integer weights.</a>
|
<a class="sourceLine" id="cb19-13" title="13"> ⍝ integer weights.</a>
|
||||||
<a class="sourceLine" id="cb16-14" title="14"> weights←((1∘,)×(∧/÷))mat[;1]⌹1↓[2]mat</a>
|
<a class="sourceLine" id="cb19-14" title="14"> weights←((1∘,)×(∧/÷))mat[;1]⌹1↓[2]mat</a>
|
||||||
<a class="sourceLine" id="cb16-15" title="15">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb19-15" title="15">∇</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb17"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb17-1" title="1"> :EndNamespace</a>
|
<div class="sourceCode" id="cb20"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb20-1" title="1"> :EndNamespace</a>
|
||||||
<a class="sourceLine" id="cb17-2" title="2">:EndNamespace</a></code></pre></div>
|
<a class="sourceLine" id="cb20-2" title="2">:EndNamespace</a></code></pre></div>
|
||||||
</section>
|
</section>
|
||||||
</article>
|
</article>
|
||||||
]]></summary>
|
]]></summary>
|
||||||
|
|
|
@ -88,6 +88,8 @@
|
||||||
<a class="sourceLine" id="cb2-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb2-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb2-9" title="9"> score←2(⍎⍕)dd×+/scores</a>
|
<a class="sourceLine" id="cb2-9" title="9"> score←2(⍎⍕)dd×+/scores</a>
|
||||||
<a class="sourceLine" id="cb2-10" title="10">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb2-10" title="10">∇</a></code></pre></div>
|
||||||
|
<p>This is a very straightforward implementation of the algorithm describe in the problem description. I decided to switch explicitly on the size of the input vector because I feel it is more natural. For the cases with 5 or 7 judges, we use Drop (<code>↓</code>) to remove the lowest and highest scores.</p>
|
||||||
|
<p>At the end, we sum up the scores with <code>+/</code> and multiply them by <code>dd</code>. The last operation, <code>2(⍎⍕)</code>, is a train using <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Format%20Dyadic.htm">Format (Dyadic)</a> to round to 2 decimal places, and <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Execute.htm">Execute</a> to get actual numbers and not strings.</p>
|
||||||
<h2 id="problem-2-another-step-in-the-proper-direction">Problem 2 – Another Step in the Proper Direction</h2>
|
<h2 id="problem-2-another-step-in-the-proper-direction">Problem 2 – Another Step in the Proper Direction</h2>
|
||||||
<div class="sourceCode" id="cb3"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb3-1" title="1">∇ steps←{p}Steps fromTo;segments;width</a>
|
<div class="sourceCode" id="cb3"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb3-1" title="1">∇ steps←{p}Steps fromTo;segments;width</a>
|
||||||
<a class="sourceLine" id="cb3-2" title="2"> width←|-/fromTo</a>
|
<a class="sourceLine" id="cb3-2" title="2"> width←|-/fromTo</a>
|
||||||
|
@ -103,147 +105,161 @@
|
||||||
<a class="sourceLine" id="cb3-12" title="12"> ⍝ Take into account the start point and the direction.</a>
|
<a class="sourceLine" id="cb3-12" title="12"> ⍝ Take into account the start point and the direction.</a>
|
||||||
<a class="sourceLine" id="cb3-13" title="13"> steps←fromTo{(⊃⍺)+(-×-/⍺)×⍵}segments</a>
|
<a class="sourceLine" id="cb3-13" title="13"> steps←fromTo{(⊃⍺)+(-×-/⍺)×⍵}segments</a>
|
||||||
<a class="sourceLine" id="cb3-14" title="14">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb3-14" title="14">∇</a></code></pre></div>
|
||||||
|
<p>This is an extension to <a href="./dyalog-apl-competition-2020-phase-1.html#stepping-in-the-proper-direction">Problem 5 of Phase I</a>. In each case, we compute the “segments”, i.e., the steps starting from 0. In a last step, common to all cases, we add the correct starting point and correct the direction if need be.</p>
|
||||||
|
<p>To compute equally-sized steps, we first divide the segment <span class="math inline">\([0, 1]\)</span> in <code>p</code> equal segments with <code>(⍳p)÷p</code>. This subdivision can then be multiplied by the width to obtain the required segments.</p>
|
||||||
|
<p>When <code>p</code> is the step size, we just divide the width by the step size (rounded to the next largest integer) to get the required number of segments. If the last segment is too large, we “crop” it to the width with Minimum (<code>⌊</code>).</p>
|
||||||
<h2 id="problem-3-past-tasks-blast">Problem 3 – Past Tasks Blast</h2>
|
<h2 id="problem-3-past-tasks-blast">Problem 3 – Past Tasks Blast</h2>
|
||||||
<div class="sourceCode" id="cb4"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb4-1" title="1">∇ urls←PastTasks url;r;paths</a>
|
<div class="sourceCode" id="cb4"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb4-1" title="1">∇ urls←PastTasks url;r;paths</a>
|
||||||
<a class="sourceLine" id="cb4-2" title="2"> r←HttpCommand.Get url</a>
|
<a class="sourceLine" id="cb4-2" title="2"> r←HttpCommand.Get url</a>
|
||||||
<a class="sourceLine" id="cb4-3" title="3"> paths←('[a-zA-Z0-9_/]+\.pdf'⎕S'&')r.Data</a>
|
<a class="sourceLine" id="cb4-3" title="3"> paths←('[a-zA-Z0-9_/]+\.pdf'⎕S'&')r.Data</a>
|
||||||
<a class="sourceLine" id="cb4-4" title="4"> urls←('https://www.dyalog.com/'∘,)¨paths</a>
|
<a class="sourceLine" id="cb4-4" title="4"> urls←('https://www.dyalog.com/'∘,)¨paths</a>
|
||||||
<a class="sourceLine" id="cb4-5" title="5">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb4-5" title="5">∇</a></code></pre></div>
|
||||||
|
<p>I decided to use <code>HttpCommand</code> for this task, since it is simply one <code>]load HttpCommand</code> away and should be platform-independent.</p>
|
||||||
|
<p>Parsing XML is not something I consider “fun” in the best of cases, and I feel like APL is not the best language to do this kind of thing. Given how simple the task is, I just decided to find the relevant bits with a regular expression using <a href="https://help.dyalog.com/18.0/index.htm#Language/System%20Functions/r.htm">Replace and Search</a> (<code>⎕S</code>).</p>
|
||||||
|
<p>After finding all the strings vaguely resembling a PDF file name (only alphanumeric characters and underscores, with a <code>.pdf</code> extension), I just concatenate them to the base URL of the Dyalog domain.</p>
|
||||||
<h2 id="problem-4-bioinformatics">Problem 4 – Bioinformatics</h2>
|
<h2 id="problem-4-bioinformatics">Problem 4 – Bioinformatics</h2>
|
||||||
|
<p>The first task can be solved by decomposing it into several functions.</p>
|
||||||
<div class="sourceCode" id="cb5"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb5-1" title="1">⍝ Test if a DNA string is a reverse palindrome.</a>
|
<div class="sourceCode" id="cb5"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb5-1" title="1">⍝ Test if a DNA string is a reverse palindrome.</a>
|
||||||
<a class="sourceLine" id="cb5-2" title="2">isrevp←{⍵≡⌽'TAGC'['ATCG'⍳⍵]}</a>
|
<a class="sourceLine" id="cb5-2" title="2">isrevp←{⍵≡⌽'TAGC'['ATCG'⍳⍵]}</a></code></pre></div>
|
||||||
<a class="sourceLine" id="cb5-3" title="3"></a>
|
<p>First, we compute the complement of a DNA string (using simple indexing) and test if its Reverse (<code>⌽</code>) is equal to the original string.</p>
|
||||||
<a class="sourceLine" id="cb5-4" title="4">⍝ Generate all subarrays (position, length) pairs, for</a>
|
<div class="sourceCode" id="cb6"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb6-1" title="1">⍝ Generate all subarrays (position, length) pairs, for 4 ≤ length ≤ 12.</a>
|
||||||
<a class="sourceLine" id="cb5-5" title="5">⍝ 4 ≤ length ≤ 12.</a>
|
<a class="sourceLine" id="cb6-2" title="2">subarrays←{⊃,/(⍳⍵),¨¨3↓¨⍳¨12⌊1+⍵-⍳⍵}</a></code></pre></div>
|
||||||
<a class="sourceLine" id="cb5-6" title="6">subarrays←{⊃,/(⍳⍵),¨¨3↓¨⍳¨12⌊1+⍵-⍳⍵}</a>
|
<p>We first compute all the possible lengths for each starting point. For instance, the last element cannot have any (position, length) pair associated to it, because there is no three element following it. So we crop the possible lengths to <span class="math inline">\([3, 12]\)</span>. For instance for an array of size 10:</p>
|
||||||
<a class="sourceLine" id="cb5-7" title="7"></a>
|
<div class="sourceCode" id="cb7"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb7-1" title="1"> {3↓¨⍳¨12⌊1+⍵-⍳⍵}10</a>
|
||||||
<a class="sourceLine" id="cb5-8" title="8">∇ r←revp dna;positions</a>
|
<a class="sourceLine" id="cb7-2" title="2">┌──────────────┬───────────┬─────────┬───────┬─────┬───┬─┬┬┬┐</a>
|
||||||
<a class="sourceLine" id="cb5-9" title="9"> positions←subarrays⍴dna</a>
|
<a class="sourceLine" id="cb7-3" title="3">│4 5 6 7 8 9 10│4 5 6 7 8 9│4 5 6 7 8│4 5 6 7│4 5 6│4 5│4││││</a>
|
||||||
<a class="sourceLine" id="cb5-10" title="10"> ⍝ Filter subarrays which are reverse palindromes.</a>
|
<a class="sourceLine" id="cb7-4" title="4">└──────────────┴───────────┴─────────┴───────┴─────┴───┴─┴┴┴┘</a></code></pre></div>
|
||||||
<a class="sourceLine" id="cb5-11" title="11"> r←↑({isrevp dna[¯1+⍵[1]+⍳⍵[2]]}¨positions)/positions</a>
|
<p>Then, we just add the corresponding starting position to each length (1 for the first block, 2 for the second, and so on). Finally, we flatten everything.</p>
|
||||||
<a class="sourceLine" id="cb5-12" title="12">∇</a></code></pre></div>
|
<div class="sourceCode" id="cb8"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb8-1" title="1">∇ r←revp dna;positions</a>
|
||||||
<div class="sourceCode" id="cb6"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb6-1" title="1">sset←{((1E6|2∘×)⍣⍵)1}</a></code></pre></div>
|
<a class="sourceLine" id="cb8-2" title="2"> positions←subarrays⍴dna</a>
|
||||||
|
<a class="sourceLine" id="cb8-3" title="3"> ⍝ Filter subarrays which are reverse palindromes.</a>
|
||||||
|
<a class="sourceLine" id="cb8-4" title="4"> r←↑({isrevp dna[¯1+⍵[1]+⍳⍵[2]]}¨positions)/positions</a>
|
||||||
|
<a class="sourceLine" id="cb8-5" title="5">∇</a></code></pre></div>
|
||||||
|
<p>For each possible (position, length) pair, we get the corresponding DNA substring with <code>dna[¯1+⍵[1]+⍳⍵[2]]</code> (adding <code>¯1</code> is necessary because <code>⎕IO←1</code>). We test if this substring is a reverse palindrome using <code>isrevp</code> above. <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Replicate.htm">Replicate</a> (<code>/</code>) then selects only the (position, length) pairs for which the substring is a reverse palindrome.</p>
|
||||||
|
<p>The second task is just about counting the number of subsets modulo 1,000,000. So we just need to compute <span class="math inline">\(2^n \mod 1000000\)</span> for any positive integer <span class="math inline">\(n\leq1000\)</span>.</p>
|
||||||
|
<div class="sourceCode" id="cb9"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb9-1" title="1">sset←{((1E6|2∘×)⍣⍵)1}</a></code></pre></div>
|
||||||
|
<p>Since we cannot just compute <span class="math inline">\(2^n\)</span> directly and take the remainder, we use modular arithmetic to stay mod 1,000,000 during the whole computation. The dfn <code>(1E6|2∘×)</code> doubles its argument mod 1,000,000. So we just apply this function <span class="math inline">\(n\)</span> times using the <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Operators/Power%20Operator.htm">Power</a> operator (<code>⍣</code>), with an initial value of 1.</p>
|
||||||
<h2 id="problem-5-future-and-present-value">Problem 5 – Future and Present Value</h2>
|
<h2 id="problem-5-future-and-present-value">Problem 5 – Future and Present Value</h2>
|
||||||
<div class="sourceCode" id="cb7"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb7-1" title="1">⍝ First solution: ((1+⊢)⊥⊣) computes the total return</a>
|
<div class="sourceCode" id="cb10"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb10-1" title="1">⍝ First solution: ((1+⊢)⊥⊣) computes the total return</a>
|
||||||
<a class="sourceLine" id="cb7-2" title="2">⍝ for a vector of amounts ⍺ and a vector of rates</a>
|
<a class="sourceLine" id="cb10-2" title="2">⍝ for a vector of amounts ⍺ and a vector of rates</a>
|
||||||
<a class="sourceLine" id="cb7-3" title="3">⍝ ⍵. It is applied to every prefix subarray of amounts</a>
|
<a class="sourceLine" id="cb10-3" title="3">⍝ ⍵. It is applied to every prefix subarray of amounts</a>
|
||||||
<a class="sourceLine" id="cb7-4" title="4">⍝ and rates to get all intermediate values. However,</a>
|
<a class="sourceLine" id="cb10-4" title="4">⍝ and rates to get all intermediate values. However,</a>
|
||||||
<a class="sourceLine" id="cb7-5" title="5">⍝ this has quadratic complexity.</a>
|
<a class="sourceLine" id="cb10-5" title="5">⍝ this has quadratic complexity.</a>
|
||||||
<a class="sourceLine" id="cb7-6" title="6">⍝ rr←(,\⊣)((1+⊢)⊥⊣)¨(,\⊢)</a>
|
<a class="sourceLine" id="cb10-6" title="6">⍝ rr←(,\⊣)((1+⊢)⊥⊣)¨(,\⊢)</a>
|
||||||
<a class="sourceLine" id="cb7-7" title="7"></a>
|
<a class="sourceLine" id="cb10-7" title="7"></a>
|
||||||
<a class="sourceLine" id="cb7-8" title="8">⍝ Second solution: We want to be able to use the</a>
|
<a class="sourceLine" id="cb10-8" title="8">⍝ Second solution: We want to be able to use the</a>
|
||||||
<a class="sourceLine" id="cb7-9" title="9">⍝ recurrence relation (recur) and scan through the</a>
|
<a class="sourceLine" id="cb10-9" title="9">⍝ recurrence relation (recur) and scan through the</a>
|
||||||
<a class="sourceLine" id="cb7-10" title="10">⍝ vectors of amounts and rates, accumulating the total</a>
|
<a class="sourceLine" id="cb10-10" title="10">⍝ vectors of amounts and rates, accumulating the total</a>
|
||||||
<a class="sourceLine" id="cb7-11" title="11">⍝ value at every time step. However, APL evaluation is</a>
|
<a class="sourceLine" id="cb10-11" title="11">⍝ value at every time step. However, APL evaluation is</a>
|
||||||
<a class="sourceLine" id="cb7-12" title="12">⍝ right-associative, so a simple Scan</a>
|
<a class="sourceLine" id="cb10-12" title="12">⍝ right-associative, so a simple Scan</a>
|
||||||
<a class="sourceLine" id="cb7-13" title="13">⍝ (recur\amounts,¨values) would not give the correct</a>
|
<a class="sourceLine" id="cb10-13" title="13">⍝ (recur\amounts,¨values) would not give the correct</a>
|
||||||
<a class="sourceLine" id="cb7-14" title="14">⍝ result, since recur is not associative and we need</a>
|
<a class="sourceLine" id="cb10-14" title="14">⍝ result, since recur is not associative and we need</a>
|
||||||
<a class="sourceLine" id="cb7-15" title="15">⍝ to evaluate it left-to-right. (In any case, in this</a>
|
<a class="sourceLine" id="cb10-15" title="15">⍝ to evaluate it left-to-right. (In any case, in this</a>
|
||||||
<a class="sourceLine" id="cb7-16" title="16">⍝ case, Scan would have quadratic complexity, so would</a>
|
<a class="sourceLine" id="cb10-16" title="16">⍝ case, Scan would have quadratic complexity, so would</a>
|
||||||
<a class="sourceLine" id="cb7-17" title="17">⍝ not bring any benefit over the previous solution.)</a>
|
<a class="sourceLine" id="cb10-17" title="17">⍝ not bring any benefit over the previous solution.)</a>
|
||||||
<a class="sourceLine" id="cb7-18" title="18">⍝ What we need is something akin to Haskell's scanl</a>
|
<a class="sourceLine" id="cb10-18" title="18">⍝ What we need is something akin to Haskell's scanl</a>
|
||||||
<a class="sourceLine" id="cb7-19" title="19">⍝ function, which would evaluate left to right in O(n)</a>
|
<a class="sourceLine" id="cb10-19" title="19">⍝ function, which would evaluate left to right in O(n)</a>
|
||||||
<a class="sourceLine" id="cb7-20" title="20">⍝ time. This is what we do here, accumulating values</a>
|
<a class="sourceLine" id="cb10-20" title="20">⍝ time. This is what we do here, accumulating values</a>
|
||||||
<a class="sourceLine" id="cb7-21" title="21">⍝ from left to right. (This is inspired from</a>
|
<a class="sourceLine" id="cb10-21" title="21">⍝ from left to right. (This is inspired from</a>
|
||||||
<a class="sourceLine" id="cb7-22" title="22">⍝ dfns.ascan, although heavily simplified.)</a>
|
<a class="sourceLine" id="cb10-22" title="22">⍝ dfns.ascan, although heavily simplified.)</a>
|
||||||
<a class="sourceLine" id="cb7-23" title="23">rr←{recur←{⍵[1]+⍺×1+⍵[2]} ⋄ 1↓⌽⊃{(⊂(⊃⍵)recur⍺),⍵}/⌽⍺,¨⍵}</a></code></pre></div>
|
<a class="sourceLine" id="cb10-23" title="23">rr←{recur←{⍵[1]+⍺×1+⍵[2]} ⋄ 1↓⌽⊃{(⊂(⊃⍵)recur⍺),⍵}/⌽⍺,¨⍵}</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb8"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb8-1" title="1">⍝ Simply apply the formula for cashflow calculations.</a>
|
<div class="sourceCode" id="cb11"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb11-1" title="1">⍝ Simply apply the formula for cashflow calculations.</a>
|
||||||
<a class="sourceLine" id="cb8-2" title="2">pv←{+/⍺÷×\1+⍵}</a></code></pre></div>
|
<a class="sourceLine" id="cb11-2" title="2">pv←{+/⍺÷×\1+⍵}</a></code></pre></div>
|
||||||
<h2 id="problem-6-merge">Problem 6 – Merge</h2>
|
<h2 id="problem-6-merge">Problem 6 – Merge</h2>
|
||||||
<div class="sourceCode" id="cb9"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb9-1" title="1">∇ val←ns getval var</a>
|
<div class="sourceCode" id="cb12"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb12-1" title="1">∇ val←ns getval var</a>
|
||||||
<a class="sourceLine" id="cb9-2" title="2"> :If ''≡var ⍝ literal '@'</a>
|
<a class="sourceLine" id="cb12-2" title="2"> :If ''≡var ⍝ literal '@'</a>
|
||||||
<a class="sourceLine" id="cb9-3" title="3"> val←'@'</a>
|
<a class="sourceLine" id="cb12-3" title="3"> val←'@'</a>
|
||||||
<a class="sourceLine" id="cb9-4" title="4"> :ElseIf (⊂var)∊ns.⎕NL ¯2</a>
|
<a class="sourceLine" id="cb12-4" title="4"> :ElseIf (⊂var)∊ns.⎕NL ¯2</a>
|
||||||
<a class="sourceLine" id="cb9-5" title="5"> val←⍕ns⍎var</a>
|
<a class="sourceLine" id="cb12-5" title="5"> val←⍕ns⍎var</a>
|
||||||
<a class="sourceLine" id="cb9-6" title="6"> :Else</a>
|
<a class="sourceLine" id="cb12-6" title="6"> :Else</a>
|
||||||
<a class="sourceLine" id="cb9-7" title="7"> val←'???'</a>
|
<a class="sourceLine" id="cb12-7" title="7"> val←'???'</a>
|
||||||
<a class="sourceLine" id="cb9-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb12-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb9-9" title="9">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb12-9" title="9">∇</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb10"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb10-1" title="1">∇ text←templateFile Merge jsonFile;template;ns</a>
|
<div class="sourceCode" id="cb13"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb13-1" title="1">∇ text←templateFile Merge jsonFile;template;ns</a>
|
||||||
<a class="sourceLine" id="cb10-2" title="2"> template←⊃⎕NGET templateFile 1</a>
|
<a class="sourceLine" id="cb13-2" title="2"> template←⊃⎕NGET templateFile 1</a>
|
||||||
<a class="sourceLine" id="cb10-3" title="3"> ns←⎕JSON⊃⎕NGET jsonFile</a>
|
<a class="sourceLine" id="cb13-3" title="3"> ns←⎕JSON⊃⎕NGET jsonFile</a>
|
||||||
<a class="sourceLine" id="cb10-4" title="4"> ⍝ We use a simple regex search and replace on the</a>
|
<a class="sourceLine" id="cb13-4" title="4"> ⍝ We use a simple regex search and replace on the</a>
|
||||||
<a class="sourceLine" id="cb10-5" title="5"> ⍝ template.</a>
|
<a class="sourceLine" id="cb13-5" title="5"> ⍝ template.</a>
|
||||||
<a class="sourceLine" id="cb10-6" title="6"> text←↑('@[a-zA-Z]*@'⎕R{ns getval ¯1↓1↓⍵.Match})template</a>
|
<a class="sourceLine" id="cb13-6" title="6"> text←↑('@[a-zA-Z]*@'⎕R{ns getval ¯1↓1↓⍵.Match})template</a>
|
||||||
<a class="sourceLine" id="cb10-7" title="7">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb13-7" title="7">∇</a></code></pre></div>
|
||||||
<h2 id="problem-7-upc">Problem 7 – UPC</h2>
|
<h2 id="problem-7-upc">Problem 7 – UPC</h2>
|
||||||
<div class="sourceCode" id="cb11"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb11-1" title="1">CheckDigit←{10|-⍵+.×11⍴3 1}</a></code></pre></div>
|
<div class="sourceCode" id="cb14"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb14-1" title="1">CheckDigit←{10|-⍵+.×11⍴3 1}</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb12"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb12-1" title="1">⍝ Left and right representations of digits. Decoding</a>
|
<div class="sourceCode" id="cb15"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb15-1" title="1">⍝ Left and right representations of digits. Decoding</a>
|
||||||
<a class="sourceLine" id="cb12-2" title="2">⍝ the binary representation from decimal is more</a>
|
<a class="sourceLine" id="cb15-2" title="2">⍝ the binary representation from decimal is more</a>
|
||||||
<a class="sourceLine" id="cb12-3" title="3">⍝ compact than writing everything explicitly.</a>
|
<a class="sourceLine" id="cb15-3" title="3">⍝ compact than writing everything explicitly.</a>
|
||||||
<a class="sourceLine" id="cb12-4" title="4">lrepr←⍉(7⍴2)⊤13 25 19 61 35 49 47 59 55 11</a>
|
<a class="sourceLine" id="cb15-4" title="4">lrepr←⍉(7⍴2)⊤13 25 19 61 35 49 47 59 55 11</a>
|
||||||
<a class="sourceLine" id="cb12-5" title="5">rrepr←~¨lrepr</a></code></pre></div>
|
<a class="sourceLine" id="cb15-5" title="5">rrepr←~¨lrepr</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb13"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb13-1" title="1">∇ bits←WriteUPC digits;left;right</a>
|
<div class="sourceCode" id="cb16"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb16-1" title="1">∇ bits←WriteUPC digits;left;right</a>
|
||||||
<a class="sourceLine" id="cb13-2" title="2"> :If (11=≢digits)∧∧/digits∊0,⍳9</a>
|
<a class="sourceLine" id="cb16-2" title="2"> :If (11=≢digits)∧∧/digits∊0,⍳9</a>
|
||||||
<a class="sourceLine" id="cb13-3" title="3"> left←,lrepr[1+6↑digits;]</a>
|
<a class="sourceLine" id="cb16-3" title="3"> left←,lrepr[1+6↑digits;]</a>
|
||||||
<a class="sourceLine" id="cb13-4" title="4"> right←,rrepr[1+6↓digits,CheckDigit digits;]</a>
|
<a class="sourceLine" id="cb16-4" title="4"> right←,rrepr[1+6↓digits,CheckDigit digits;]</a>
|
||||||
<a class="sourceLine" id="cb13-5" title="5"> bits←1 0 1,left,0 1 0 1 0,right,1 0 1</a>
|
<a class="sourceLine" id="cb16-5" title="5"> bits←1 0 1,left,0 1 0 1 0,right,1 0 1</a>
|
||||||
<a class="sourceLine" id="cb13-6" title="6"> :Else</a>
|
<a class="sourceLine" id="cb16-6" title="6"> :Else</a>
|
||||||
<a class="sourceLine" id="cb13-7" title="7"> bits←¯1</a>
|
<a class="sourceLine" id="cb16-7" title="7"> bits←¯1</a>
|
||||||
<a class="sourceLine" id="cb13-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb16-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb13-9" title="9">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb16-9" title="9">∇</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb14"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb14-1" title="1">∇ digits←ReadUPC bits</a>
|
<div class="sourceCode" id="cb17"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb17-1" title="1">∇ digits←ReadUPC bits</a>
|
||||||
<a class="sourceLine" id="cb14-2" title="2"> :If 95≠⍴bits ⍝ incorrect number of bits</a>
|
<a class="sourceLine" id="cb17-2" title="2"> :If 95≠⍴bits ⍝ incorrect number of bits</a>
|
||||||
<a class="sourceLine" id="cb14-3" title="3"> digits←¯1</a>
|
<a class="sourceLine" id="cb17-3" title="3"> digits←¯1</a>
|
||||||
<a class="sourceLine" id="cb14-4" title="4"> :Else</a>
|
<a class="sourceLine" id="cb17-4" title="4"> :Else</a>
|
||||||
<a class="sourceLine" id="cb14-5" title="5"> ⍝ Test if the barcode was scanned right-to-left.</a>
|
<a class="sourceLine" id="cb17-5" title="5"> ⍝ Test if the barcode was scanned right-to-left.</a>
|
||||||
<a class="sourceLine" id="cb14-6" title="6"> :If 0=2|+/bits[3+⍳7]</a>
|
<a class="sourceLine" id="cb17-6" title="6"> :If 0=2|+/bits[3+⍳7]</a>
|
||||||
<a class="sourceLine" id="cb14-7" title="7"> bits←⌽bits</a>
|
<a class="sourceLine" id="cb17-7" title="7"> bits←⌽bits</a>
|
||||||
<a class="sourceLine" id="cb14-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb17-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb14-9" title="9"> digits←({¯1+lrepr⍳⍵}¨(7/⍳6)⊆42↑3↓bits),{¯1+rrepr⍳⍵}¨(7/⍳6)⊆¯42↑¯3↓bits</a>
|
<a class="sourceLine" id="cb17-9" title="9"> digits←({¯1+lrepr⍳⍵}¨(7/⍳6)⊆42↑3↓bits),{¯1+rrepr⍳⍵}¨(7/⍳6)⊆¯42↑¯3↓bits</a>
|
||||||
<a class="sourceLine" id="cb14-10" title="10"> :If ~∧/digits∊0,⍳9 ⍝ incorrect parity</a>
|
<a class="sourceLine" id="cb17-10" title="10"> :If ~∧/digits∊0,⍳9 ⍝ incorrect parity</a>
|
||||||
<a class="sourceLine" id="cb14-11" title="11"> digits←¯1</a>
|
<a class="sourceLine" id="cb17-11" title="11"> digits←¯1</a>
|
||||||
<a class="sourceLine" id="cb14-12" title="12"> :ElseIf (⊃⌽digits)≠CheckDigit ¯1↓digits ⍝ incorrect check digit</a>
|
<a class="sourceLine" id="cb17-12" title="12"> :ElseIf (⊃⌽digits)≠CheckDigit ¯1↓digits ⍝ incorrect check digit</a>
|
||||||
<a class="sourceLine" id="cb14-13" title="13"> digits←¯1</a>
|
<a class="sourceLine" id="cb17-13" title="13"> digits←¯1</a>
|
||||||
<a class="sourceLine" id="cb14-14" title="14"> :EndIf</a>
|
<a class="sourceLine" id="cb17-14" title="14"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb14-15" title="15"> :EndIf</a>
|
<a class="sourceLine" id="cb17-15" title="15"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb14-16" title="16">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb17-16" title="16">∇</a></code></pre></div>
|
||||||
<h2 id="problem-8-balancing-the-scales">Problem 8 – Balancing the Scales</h2>
|
<h2 id="problem-8-balancing-the-scales">Problem 8 – Balancing the Scales</h2>
|
||||||
<div class="sourceCode" id="cb15"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb15-1" title="1">∇ parts←Balance nums;subsets;partitions</a>
|
<div class="sourceCode" id="cb18"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb18-1" title="1">∇ parts←Balance nums;subsets;partitions</a>
|
||||||
<a class="sourceLine" id="cb15-2" title="2"> ⍝ This is a brute force solution, running in</a>
|
<a class="sourceLine" id="cb18-2" title="2"> ⍝ This is a brute force solution, running in</a>
|
||||||
<a class="sourceLine" id="cb15-3" title="3"> ⍝ exponential time. We generate all the possible</a>
|
<a class="sourceLine" id="cb18-3" title="3"> ⍝ exponential time. We generate all the possible</a>
|
||||||
<a class="sourceLine" id="cb15-4" title="4"> ⍝ partitions, filter out those which are not</a>
|
<a class="sourceLine" id="cb18-4" title="4"> ⍝ partitions, filter out those which are not</a>
|
||||||
<a class="sourceLine" id="cb15-5" title="5"> ⍝ balanced, and return the first matching one. There</a>
|
<a class="sourceLine" id="cb18-5" title="5"> ⍝ balanced, and return the first matching one. There</a>
|
||||||
<a class="sourceLine" id="cb15-6" title="6"> ⍝ are more advanced approach running in</a>
|
<a class="sourceLine" id="cb18-6" title="6"> ⍝ are more advanced approach running in</a>
|
||||||
<a class="sourceLine" id="cb15-7" title="7"> ⍝ pseudo-polynomial time (based on dynamic</a>
|
<a class="sourceLine" id="cb18-7" title="7"> ⍝ pseudo-polynomial time (based on dynamic</a>
|
||||||
<a class="sourceLine" id="cb15-8" title="8"> ⍝ programming, see the "Partition problem" Wikipedia</a>
|
<a class="sourceLine" id="cb18-8" title="8"> ⍝ programming, see the "Partition problem" Wikipedia</a>
|
||||||
<a class="sourceLine" id="cb15-9" title="9"> ⍝ page), but they are not warranted here, as the</a>
|
<a class="sourceLine" id="cb18-9" title="9"> ⍝ page), but they are not warranted here, as the</a>
|
||||||
<a class="sourceLine" id="cb15-10" title="10"> ⍝ input size remains fairly small.</a>
|
<a class="sourceLine" id="cb18-10" title="10"> ⍝ input size remains fairly small.</a>
|
||||||
<a class="sourceLine" id="cb15-11" title="11"></a>
|
<a class="sourceLine" id="cb18-11" title="11"></a>
|
||||||
<a class="sourceLine" id="cb15-12" title="12"> ⍝ Generate all partitions of a vector of a given</a>
|
<a class="sourceLine" id="cb18-12" title="12"> ⍝ Generate all partitions of a vector of a given</a>
|
||||||
<a class="sourceLine" id="cb15-13" title="13"> ⍝ size, as binary mask vectors.</a>
|
<a class="sourceLine" id="cb18-13" title="13"> ⍝ size, as binary mask vectors.</a>
|
||||||
<a class="sourceLine" id="cb15-14" title="14"> subsets←{1↓2⊥⍣¯1⍳2*⍵}</a>
|
<a class="sourceLine" id="cb18-14" title="14"> subsets←{1↓2⊥⍣¯1⍳2*⍵}</a>
|
||||||
<a class="sourceLine" id="cb15-15" title="15"> ⍝ Keep only the subsets whose sum is exactly</a>
|
<a class="sourceLine" id="cb18-15" title="15"> ⍝ Keep only the subsets whose sum is exactly</a>
|
||||||
<a class="sourceLine" id="cb15-16" title="16"> ⍝ (+/nums)÷2.</a>
|
<a class="sourceLine" id="cb18-16" title="16"> ⍝ (+/nums)÷2.</a>
|
||||||
<a class="sourceLine" id="cb15-17" title="17"> partitions←nums{((2÷⍨+/⍺)=⍺+.×⍵)/⍵}subsets⍴nums</a>
|
<a class="sourceLine" id="cb18-17" title="17"> partitions←nums{((2÷⍨+/⍺)=⍺+.×⍵)/⍵}subsets⍴nums</a>
|
||||||
<a class="sourceLine" id="cb15-18" title="18"> :If 0=≢,partitions</a>
|
<a class="sourceLine" id="cb18-18" title="18"> :If 0=≢,partitions</a>
|
||||||
<a class="sourceLine" id="cb15-19" title="19"> ⍝ If no partition satisfy the above</a>
|
<a class="sourceLine" id="cb18-19" title="19"> ⍝ If no partition satisfy the above</a>
|
||||||
<a class="sourceLine" id="cb15-20" title="20"> ⍝ criterion, we return ⍬.</a>
|
<a class="sourceLine" id="cb18-20" title="20"> ⍝ criterion, we return ⍬.</a>
|
||||||
<a class="sourceLine" id="cb15-21" title="21"> parts←⍬</a>
|
<a class="sourceLine" id="cb18-21" title="21"> parts←⍬</a>
|
||||||
<a class="sourceLine" id="cb15-22" title="22"> :Else</a>
|
<a class="sourceLine" id="cb18-22" title="22"> :Else</a>
|
||||||
<a class="sourceLine" id="cb15-23" title="23"> ⍝ Otherwise, we return the first possible</a>
|
<a class="sourceLine" id="cb18-23" title="23"> ⍝ Otherwise, we return the first possible</a>
|
||||||
<a class="sourceLine" id="cb15-24" title="24"> ⍝ partition.</a>
|
<a class="sourceLine" id="cb18-24" title="24"> ⍝ partition.</a>
|
||||||
<a class="sourceLine" id="cb15-25" title="25"> parts←nums{((⊂,(⊂~))⊃↓⍉⍵)/¨2⍴⊂⍺}partitions</a>
|
<a class="sourceLine" id="cb18-25" title="25"> parts←nums{((⊂,(⊂~))⊃↓⍉⍵)/¨2⍴⊂⍺}partitions</a>
|
||||||
<a class="sourceLine" id="cb15-26" title="26"> :EndIf</a>
|
<a class="sourceLine" id="cb18-26" title="26"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb15-27" title="27">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb18-27" title="27">∇</a></code></pre></div>
|
||||||
<h2 id="problem-9-upwardly-mobile">Problem 9 – Upwardly Mobile</h2>
|
<h2 id="problem-9-upwardly-mobile">Problem 9 – Upwardly Mobile</h2>
|
||||||
<div class="sourceCode" id="cb16"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb16-1" title="1">∇ weights←Weights filename;mobile;branches;mat</a>
|
<div class="sourceCode" id="cb19"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb19-1" title="1">∇ weights←Weights filename;mobile;branches;mat</a>
|
||||||
<a class="sourceLine" id="cb16-2" title="2"> ⍝ Put your code and comments below here</a>
|
<a class="sourceLine" id="cb19-2" title="2"> ⍝ Put your code and comments below here</a>
|
||||||
<a class="sourceLine" id="cb16-3" title="3"></a>
|
<a class="sourceLine" id="cb19-3" title="3"></a>
|
||||||
<a class="sourceLine" id="cb16-4" title="4"> ⍝ Parse the mobile input file.</a>
|
<a class="sourceLine" id="cb19-4" title="4"> ⍝ Parse the mobile input file.</a>
|
||||||
<a class="sourceLine" id="cb16-5" title="5"> mobile←↑⊃⎕NGET filename 1</a>
|
<a class="sourceLine" id="cb19-5" title="5"> mobile←↑⊃⎕NGET filename 1</a>
|
||||||
<a class="sourceLine" id="cb16-6" title="6"> branches←⍸mobile∊'┌┴┐'</a>
|
<a class="sourceLine" id="cb19-6" title="6"> branches←⍸mobile∊'┌┴┐'</a>
|
||||||
<a class="sourceLine" id="cb16-7" title="7"> ⍝ TODO: Build the matrix of coefficients mat.</a>
|
<a class="sourceLine" id="cb19-7" title="7"> ⍝ TODO: Build the matrix of coefficients mat.</a>
|
||||||
<a class="sourceLine" id="cb16-8" title="8"></a>
|
<a class="sourceLine" id="cb19-8" title="8"></a>
|
||||||
<a class="sourceLine" id="cb16-9" title="9"> ⍝ Solve the system of equations (arbitrarily setting</a>
|
<a class="sourceLine" id="cb19-9" title="9"> ⍝ Solve the system of equations (arbitrarily setting</a>
|
||||||
<a class="sourceLine" id="cb16-10" title="10"> ⍝ the first variable at 1 because the system is</a>
|
<a class="sourceLine" id="cb19-10" title="10"> ⍝ the first variable at 1 because the system is</a>
|
||||||
<a class="sourceLine" id="cb16-11" title="11"> ⍝ overdetermined), then multiply the coefficients by</a>
|
<a class="sourceLine" id="cb19-11" title="11"> ⍝ overdetermined), then multiply the coefficients by</a>
|
||||||
<a class="sourceLine" id="cb16-12" title="12"> ⍝ their least common multiple to get the smallest</a>
|
<a class="sourceLine" id="cb19-12" title="12"> ⍝ their least common multiple to get the smallest</a>
|
||||||
<a class="sourceLine" id="cb16-13" title="13"> ⍝ integer weights.</a>
|
<a class="sourceLine" id="cb19-13" title="13"> ⍝ integer weights.</a>
|
||||||
<a class="sourceLine" id="cb16-14" title="14"> weights←((1∘,)×(∧/÷))mat[;1]⌹1↓[2]mat</a>
|
<a class="sourceLine" id="cb19-14" title="14"> weights←((1∘,)×(∧/÷))mat[;1]⌹1↓[2]mat</a>
|
||||||
<a class="sourceLine" id="cb16-15" title="15">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb19-15" title="15">∇</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb17"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb17-1" title="1"> :EndNamespace</a>
|
<div class="sourceCode" id="cb20"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb20-1" title="1"> :EndNamespace</a>
|
||||||
<a class="sourceLine" id="cb17-2" title="2">:EndNamespace</a></code></pre></div>
|
<a class="sourceLine" id="cb20-2" title="2">:EndNamespace</a></code></pre></div>
|
||||||
</section>
|
</section>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
|
272
_site/rss.xml
272
_site/rss.xml
|
@ -50,6 +50,8 @@
|
||||||
<a class="sourceLine" id="cb2-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb2-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb2-9" title="9"> score←2(⍎⍕)dd×+/scores</a>
|
<a class="sourceLine" id="cb2-9" title="9"> score←2(⍎⍕)dd×+/scores</a>
|
||||||
<a class="sourceLine" id="cb2-10" title="10">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb2-10" title="10">∇</a></code></pre></div>
|
||||||
|
<p>This is a very straightforward implementation of the algorithm describe in the problem description. I decided to switch explicitly on the size of the input vector because I feel it is more natural. For the cases with 5 or 7 judges, we use Drop (<code>↓</code>) to remove the lowest and highest scores.</p>
|
||||||
|
<p>At the end, we sum up the scores with <code>+/</code> and multiply them by <code>dd</code>. The last operation, <code>2(⍎⍕)</code>, is a train using <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Format%20Dyadic.htm">Format (Dyadic)</a> to round to 2 decimal places, and <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Execute.htm">Execute</a> to get actual numbers and not strings.</p>
|
||||||
<h2 id="problem-2-another-step-in-the-proper-direction">Problem 2 – Another Step in the Proper Direction</h2>
|
<h2 id="problem-2-another-step-in-the-proper-direction">Problem 2 – Another Step in the Proper Direction</h2>
|
||||||
<div class="sourceCode" id="cb3"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb3-1" title="1">∇ steps←{p}Steps fromTo;segments;width</a>
|
<div class="sourceCode" id="cb3"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb3-1" title="1">∇ steps←{p}Steps fromTo;segments;width</a>
|
||||||
<a class="sourceLine" id="cb3-2" title="2"> width←|-/fromTo</a>
|
<a class="sourceLine" id="cb3-2" title="2"> width←|-/fromTo</a>
|
||||||
|
@ -65,147 +67,161 @@
|
||||||
<a class="sourceLine" id="cb3-12" title="12"> ⍝ Take into account the start point and the direction.</a>
|
<a class="sourceLine" id="cb3-12" title="12"> ⍝ Take into account the start point and the direction.</a>
|
||||||
<a class="sourceLine" id="cb3-13" title="13"> steps←fromTo{(⊃⍺)+(-×-/⍺)×⍵}segments</a>
|
<a class="sourceLine" id="cb3-13" title="13"> steps←fromTo{(⊃⍺)+(-×-/⍺)×⍵}segments</a>
|
||||||
<a class="sourceLine" id="cb3-14" title="14">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb3-14" title="14">∇</a></code></pre></div>
|
||||||
|
<p>This is an extension to <a href="./dyalog-apl-competition-2020-phase-1.html#stepping-in-the-proper-direction">Problem 5 of Phase I</a>. In each case, we compute the “segments”, i.e., the steps starting from 0. In a last step, common to all cases, we add the correct starting point and correct the direction if need be.</p>
|
||||||
|
<p>To compute equally-sized steps, we first divide the segment <span class="math inline">\([0, 1]\)</span> in <code>p</code> equal segments with <code>(⍳p)÷p</code>. This subdivision can then be multiplied by the width to obtain the required segments.</p>
|
||||||
|
<p>When <code>p</code> is the step size, we just divide the width by the step size (rounded to the next largest integer) to get the required number of segments. If the last segment is too large, we “crop” it to the width with Minimum (<code>⌊</code>).</p>
|
||||||
<h2 id="problem-3-past-tasks-blast">Problem 3 – Past Tasks Blast</h2>
|
<h2 id="problem-3-past-tasks-blast">Problem 3 – Past Tasks Blast</h2>
|
||||||
<div class="sourceCode" id="cb4"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb4-1" title="1">∇ urls←PastTasks url;r;paths</a>
|
<div class="sourceCode" id="cb4"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb4-1" title="1">∇ urls←PastTasks url;r;paths</a>
|
||||||
<a class="sourceLine" id="cb4-2" title="2"> r←HttpCommand.Get url</a>
|
<a class="sourceLine" id="cb4-2" title="2"> r←HttpCommand.Get url</a>
|
||||||
<a class="sourceLine" id="cb4-3" title="3"> paths←('[a-zA-Z0-9_/]+\.pdf'⎕S'&')r.Data</a>
|
<a class="sourceLine" id="cb4-3" title="3"> paths←('[a-zA-Z0-9_/]+\.pdf'⎕S'&')r.Data</a>
|
||||||
<a class="sourceLine" id="cb4-4" title="4"> urls←('https://www.dyalog.com/'∘,)¨paths</a>
|
<a class="sourceLine" id="cb4-4" title="4"> urls←('https://www.dyalog.com/'∘,)¨paths</a>
|
||||||
<a class="sourceLine" id="cb4-5" title="5">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb4-5" title="5">∇</a></code></pre></div>
|
||||||
|
<p>I decided to use <code>HttpCommand</code> for this task, since it is simply one <code>]load HttpCommand</code> away and should be platform-independent.</p>
|
||||||
|
<p>Parsing XML is not something I consider “fun” in the best of cases, and I feel like APL is not the best language to do this kind of thing. Given how simple the task is, I just decided to find the relevant bits with a regular expression using <a href="https://help.dyalog.com/18.0/index.htm#Language/System%20Functions/r.htm">Replace and Search</a> (<code>⎕S</code>).</p>
|
||||||
|
<p>After finding all the strings vaguely resembling a PDF file name (only alphanumeric characters and underscores, with a <code>.pdf</code> extension), I just concatenate them to the base URL of the Dyalog domain.</p>
|
||||||
<h2 id="problem-4-bioinformatics">Problem 4 – Bioinformatics</h2>
|
<h2 id="problem-4-bioinformatics">Problem 4 – Bioinformatics</h2>
|
||||||
|
<p>The first task can be solved by decomposing it into several functions.</p>
|
||||||
<div class="sourceCode" id="cb5"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb5-1" title="1">⍝ Test if a DNA string is a reverse palindrome.</a>
|
<div class="sourceCode" id="cb5"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb5-1" title="1">⍝ Test if a DNA string is a reverse palindrome.</a>
|
||||||
<a class="sourceLine" id="cb5-2" title="2">isrevp←{⍵≡⌽'TAGC'['ATCG'⍳⍵]}</a>
|
<a class="sourceLine" id="cb5-2" title="2">isrevp←{⍵≡⌽'TAGC'['ATCG'⍳⍵]}</a></code></pre></div>
|
||||||
<a class="sourceLine" id="cb5-3" title="3"></a>
|
<p>First, we compute the complement of a DNA string (using simple indexing) and test if its Reverse (<code>⌽</code>) is equal to the original string.</p>
|
||||||
<a class="sourceLine" id="cb5-4" title="4">⍝ Generate all subarrays (position, length) pairs, for</a>
|
<div class="sourceCode" id="cb6"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb6-1" title="1">⍝ Generate all subarrays (position, length) pairs, for 4 ≤ length ≤ 12.</a>
|
||||||
<a class="sourceLine" id="cb5-5" title="5">⍝ 4 ≤ length ≤ 12.</a>
|
<a class="sourceLine" id="cb6-2" title="2">subarrays←{⊃,/(⍳⍵),¨¨3↓¨⍳¨12⌊1+⍵-⍳⍵}</a></code></pre></div>
|
||||||
<a class="sourceLine" id="cb5-6" title="6">subarrays←{⊃,/(⍳⍵),¨¨3↓¨⍳¨12⌊1+⍵-⍳⍵}</a>
|
<p>We first compute all the possible lengths for each starting point. For instance, the last element cannot have any (position, length) pair associated to it, because there is no three element following it. So we crop the possible lengths to <span class="math inline">\([3, 12]\)</span>. For instance for an array of size 10:</p>
|
||||||
<a class="sourceLine" id="cb5-7" title="7"></a>
|
<div class="sourceCode" id="cb7"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb7-1" title="1"> {3↓¨⍳¨12⌊1+⍵-⍳⍵}10</a>
|
||||||
<a class="sourceLine" id="cb5-8" title="8">∇ r←revp dna;positions</a>
|
<a class="sourceLine" id="cb7-2" title="2">┌──────────────┬───────────┬─────────┬───────┬─────┬───┬─┬┬┬┐</a>
|
||||||
<a class="sourceLine" id="cb5-9" title="9"> positions←subarrays⍴dna</a>
|
<a class="sourceLine" id="cb7-3" title="3">│4 5 6 7 8 9 10│4 5 6 7 8 9│4 5 6 7 8│4 5 6 7│4 5 6│4 5│4││││</a>
|
||||||
<a class="sourceLine" id="cb5-10" title="10"> ⍝ Filter subarrays which are reverse palindromes.</a>
|
<a class="sourceLine" id="cb7-4" title="4">└──────────────┴───────────┴─────────┴───────┴─────┴───┴─┴┴┴┘</a></code></pre></div>
|
||||||
<a class="sourceLine" id="cb5-11" title="11"> r←↑({isrevp dna[¯1+⍵[1]+⍳⍵[2]]}¨positions)/positions</a>
|
<p>Then, we just add the corresponding starting position to each length (1 for the first block, 2 for the second, and so on). Finally, we flatten everything.</p>
|
||||||
<a class="sourceLine" id="cb5-12" title="12">∇</a></code></pre></div>
|
<div class="sourceCode" id="cb8"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb8-1" title="1">∇ r←revp dna;positions</a>
|
||||||
<div class="sourceCode" id="cb6"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb6-1" title="1">sset←{((1E6|2∘×)⍣⍵)1}</a></code></pre></div>
|
<a class="sourceLine" id="cb8-2" title="2"> positions←subarrays⍴dna</a>
|
||||||
|
<a class="sourceLine" id="cb8-3" title="3"> ⍝ Filter subarrays which are reverse palindromes.</a>
|
||||||
|
<a class="sourceLine" id="cb8-4" title="4"> r←↑({isrevp dna[¯1+⍵[1]+⍳⍵[2]]}¨positions)/positions</a>
|
||||||
|
<a class="sourceLine" id="cb8-5" title="5">∇</a></code></pre></div>
|
||||||
|
<p>For each possible (position, length) pair, we get the corresponding DNA substring with <code>dna[¯1+⍵[1]+⍳⍵[2]]</code> (adding <code>¯1</code> is necessary because <code>⎕IO←1</code>). We test if this substring is a reverse palindrome using <code>isrevp</code> above. <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Replicate.htm">Replicate</a> (<code>/</code>) then selects only the (position, length) pairs for which the substring is a reverse palindrome.</p>
|
||||||
|
<p>The second task is just about counting the number of subsets modulo 1,000,000. So we just need to compute <span class="math inline">\(2^n \mod 1000000\)</span> for any positive integer <span class="math inline">\(n\leq1000\)</span>.</p>
|
||||||
|
<div class="sourceCode" id="cb9"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb9-1" title="1">sset←{((1E6|2∘×)⍣⍵)1}</a></code></pre></div>
|
||||||
|
<p>Since we cannot just compute <span class="math inline">\(2^n\)</span> directly and take the remainder, we use modular arithmetic to stay mod 1,000,000 during the whole computation. The dfn <code>(1E6|2∘×)</code> doubles its argument mod 1,000,000. So we just apply this function <span class="math inline">\(n\)</span> times using the <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Operators/Power%20Operator.htm">Power</a> operator (<code>⍣</code>), with an initial value of 1.</p>
|
||||||
<h2 id="problem-5-future-and-present-value">Problem 5 – Future and Present Value</h2>
|
<h2 id="problem-5-future-and-present-value">Problem 5 – Future and Present Value</h2>
|
||||||
<div class="sourceCode" id="cb7"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb7-1" title="1">⍝ First solution: ((1+⊢)⊥⊣) computes the total return</a>
|
<div class="sourceCode" id="cb10"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb10-1" title="1">⍝ First solution: ((1+⊢)⊥⊣) computes the total return</a>
|
||||||
<a class="sourceLine" id="cb7-2" title="2">⍝ for a vector of amounts ⍺ and a vector of rates</a>
|
<a class="sourceLine" id="cb10-2" title="2">⍝ for a vector of amounts ⍺ and a vector of rates</a>
|
||||||
<a class="sourceLine" id="cb7-3" title="3">⍝ ⍵. It is applied to every prefix subarray of amounts</a>
|
<a class="sourceLine" id="cb10-3" title="3">⍝ ⍵. It is applied to every prefix subarray of amounts</a>
|
||||||
<a class="sourceLine" id="cb7-4" title="4">⍝ and rates to get all intermediate values. However,</a>
|
<a class="sourceLine" id="cb10-4" title="4">⍝ and rates to get all intermediate values. However,</a>
|
||||||
<a class="sourceLine" id="cb7-5" title="5">⍝ this has quadratic complexity.</a>
|
<a class="sourceLine" id="cb10-5" title="5">⍝ this has quadratic complexity.</a>
|
||||||
<a class="sourceLine" id="cb7-6" title="6">⍝ rr←(,\⊣)((1+⊢)⊥⊣)¨(,\⊢)</a>
|
<a class="sourceLine" id="cb10-6" title="6">⍝ rr←(,\⊣)((1+⊢)⊥⊣)¨(,\⊢)</a>
|
||||||
<a class="sourceLine" id="cb7-7" title="7"></a>
|
<a class="sourceLine" id="cb10-7" title="7"></a>
|
||||||
<a class="sourceLine" id="cb7-8" title="8">⍝ Second solution: We want to be able to use the</a>
|
<a class="sourceLine" id="cb10-8" title="8">⍝ Second solution: We want to be able to use the</a>
|
||||||
<a class="sourceLine" id="cb7-9" title="9">⍝ recurrence relation (recur) and scan through the</a>
|
<a class="sourceLine" id="cb10-9" title="9">⍝ recurrence relation (recur) and scan through the</a>
|
||||||
<a class="sourceLine" id="cb7-10" title="10">⍝ vectors of amounts and rates, accumulating the total</a>
|
<a class="sourceLine" id="cb10-10" title="10">⍝ vectors of amounts and rates, accumulating the total</a>
|
||||||
<a class="sourceLine" id="cb7-11" title="11">⍝ value at every time step. However, APL evaluation is</a>
|
<a class="sourceLine" id="cb10-11" title="11">⍝ value at every time step. However, APL evaluation is</a>
|
||||||
<a class="sourceLine" id="cb7-12" title="12">⍝ right-associative, so a simple Scan</a>
|
<a class="sourceLine" id="cb10-12" title="12">⍝ right-associative, so a simple Scan</a>
|
||||||
<a class="sourceLine" id="cb7-13" title="13">⍝ (recur\amounts,¨values) would not give the correct</a>
|
<a class="sourceLine" id="cb10-13" title="13">⍝ (recur\amounts,¨values) would not give the correct</a>
|
||||||
<a class="sourceLine" id="cb7-14" title="14">⍝ result, since recur is not associative and we need</a>
|
<a class="sourceLine" id="cb10-14" title="14">⍝ result, since recur is not associative and we need</a>
|
||||||
<a class="sourceLine" id="cb7-15" title="15">⍝ to evaluate it left-to-right. (In any case, in this</a>
|
<a class="sourceLine" id="cb10-15" title="15">⍝ to evaluate it left-to-right. (In any case, in this</a>
|
||||||
<a class="sourceLine" id="cb7-16" title="16">⍝ case, Scan would have quadratic complexity, so would</a>
|
<a class="sourceLine" id="cb10-16" title="16">⍝ case, Scan would have quadratic complexity, so would</a>
|
||||||
<a class="sourceLine" id="cb7-17" title="17">⍝ not bring any benefit over the previous solution.)</a>
|
<a class="sourceLine" id="cb10-17" title="17">⍝ not bring any benefit over the previous solution.)</a>
|
||||||
<a class="sourceLine" id="cb7-18" title="18">⍝ What we need is something akin to Haskell's scanl</a>
|
<a class="sourceLine" id="cb10-18" title="18">⍝ What we need is something akin to Haskell's scanl</a>
|
||||||
<a class="sourceLine" id="cb7-19" title="19">⍝ function, which would evaluate left to right in O(n)</a>
|
<a class="sourceLine" id="cb10-19" title="19">⍝ function, which would evaluate left to right in O(n)</a>
|
||||||
<a class="sourceLine" id="cb7-20" title="20">⍝ time. This is what we do here, accumulating values</a>
|
<a class="sourceLine" id="cb10-20" title="20">⍝ time. This is what we do here, accumulating values</a>
|
||||||
<a class="sourceLine" id="cb7-21" title="21">⍝ from left to right. (This is inspired from</a>
|
<a class="sourceLine" id="cb10-21" title="21">⍝ from left to right. (This is inspired from</a>
|
||||||
<a class="sourceLine" id="cb7-22" title="22">⍝ dfns.ascan, although heavily simplified.)</a>
|
<a class="sourceLine" id="cb10-22" title="22">⍝ dfns.ascan, although heavily simplified.)</a>
|
||||||
<a class="sourceLine" id="cb7-23" title="23">rr←{recur←{⍵[1]+⍺×1+⍵[2]} ⋄ 1↓⌽⊃{(⊂(⊃⍵)recur⍺),⍵}/⌽⍺,¨⍵}</a></code></pre></div>
|
<a class="sourceLine" id="cb10-23" title="23">rr←{recur←{⍵[1]+⍺×1+⍵[2]} ⋄ 1↓⌽⊃{(⊂(⊃⍵)recur⍺),⍵}/⌽⍺,¨⍵}</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb8"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb8-1" title="1">⍝ Simply apply the formula for cashflow calculations.</a>
|
<div class="sourceCode" id="cb11"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb11-1" title="1">⍝ Simply apply the formula for cashflow calculations.</a>
|
||||||
<a class="sourceLine" id="cb8-2" title="2">pv←{+/⍺÷×\1+⍵}</a></code></pre></div>
|
<a class="sourceLine" id="cb11-2" title="2">pv←{+/⍺÷×\1+⍵}</a></code></pre></div>
|
||||||
<h2 id="problem-6-merge">Problem 6 – Merge</h2>
|
<h2 id="problem-6-merge">Problem 6 – Merge</h2>
|
||||||
<div class="sourceCode" id="cb9"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb9-1" title="1">∇ val←ns getval var</a>
|
<div class="sourceCode" id="cb12"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb12-1" title="1">∇ val←ns getval var</a>
|
||||||
<a class="sourceLine" id="cb9-2" title="2"> :If ''≡var ⍝ literal '@'</a>
|
<a class="sourceLine" id="cb12-2" title="2"> :If ''≡var ⍝ literal '@'</a>
|
||||||
<a class="sourceLine" id="cb9-3" title="3"> val←'@'</a>
|
<a class="sourceLine" id="cb12-3" title="3"> val←'@'</a>
|
||||||
<a class="sourceLine" id="cb9-4" title="4"> :ElseIf (⊂var)∊ns.⎕NL ¯2</a>
|
<a class="sourceLine" id="cb12-4" title="4"> :ElseIf (⊂var)∊ns.⎕NL ¯2</a>
|
||||||
<a class="sourceLine" id="cb9-5" title="5"> val←⍕ns⍎var</a>
|
<a class="sourceLine" id="cb12-5" title="5"> val←⍕ns⍎var</a>
|
||||||
<a class="sourceLine" id="cb9-6" title="6"> :Else</a>
|
<a class="sourceLine" id="cb12-6" title="6"> :Else</a>
|
||||||
<a class="sourceLine" id="cb9-7" title="7"> val←'???'</a>
|
<a class="sourceLine" id="cb12-7" title="7"> val←'???'</a>
|
||||||
<a class="sourceLine" id="cb9-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb12-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb9-9" title="9">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb12-9" title="9">∇</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb10"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb10-1" title="1">∇ text←templateFile Merge jsonFile;template;ns</a>
|
<div class="sourceCode" id="cb13"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb13-1" title="1">∇ text←templateFile Merge jsonFile;template;ns</a>
|
||||||
<a class="sourceLine" id="cb10-2" title="2"> template←⊃⎕NGET templateFile 1</a>
|
<a class="sourceLine" id="cb13-2" title="2"> template←⊃⎕NGET templateFile 1</a>
|
||||||
<a class="sourceLine" id="cb10-3" title="3"> ns←⎕JSON⊃⎕NGET jsonFile</a>
|
<a class="sourceLine" id="cb13-3" title="3"> ns←⎕JSON⊃⎕NGET jsonFile</a>
|
||||||
<a class="sourceLine" id="cb10-4" title="4"> ⍝ We use a simple regex search and replace on the</a>
|
<a class="sourceLine" id="cb13-4" title="4"> ⍝ We use a simple regex search and replace on the</a>
|
||||||
<a class="sourceLine" id="cb10-5" title="5"> ⍝ template.</a>
|
<a class="sourceLine" id="cb13-5" title="5"> ⍝ template.</a>
|
||||||
<a class="sourceLine" id="cb10-6" title="6"> text←↑('@[a-zA-Z]*@'⎕R{ns getval ¯1↓1↓⍵.Match})template</a>
|
<a class="sourceLine" id="cb13-6" title="6"> text←↑('@[a-zA-Z]*@'⎕R{ns getval ¯1↓1↓⍵.Match})template</a>
|
||||||
<a class="sourceLine" id="cb10-7" title="7">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb13-7" title="7">∇</a></code></pre></div>
|
||||||
<h2 id="problem-7-upc">Problem 7 – UPC</h2>
|
<h2 id="problem-7-upc">Problem 7 – UPC</h2>
|
||||||
<div class="sourceCode" id="cb11"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb11-1" title="1">CheckDigit←{10|-⍵+.×11⍴3 1}</a></code></pre></div>
|
<div class="sourceCode" id="cb14"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb14-1" title="1">CheckDigit←{10|-⍵+.×11⍴3 1}</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb12"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb12-1" title="1">⍝ Left and right representations of digits. Decoding</a>
|
<div class="sourceCode" id="cb15"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb15-1" title="1">⍝ Left and right representations of digits. Decoding</a>
|
||||||
<a class="sourceLine" id="cb12-2" title="2">⍝ the binary representation from decimal is more</a>
|
<a class="sourceLine" id="cb15-2" title="2">⍝ the binary representation from decimal is more</a>
|
||||||
<a class="sourceLine" id="cb12-3" title="3">⍝ compact than writing everything explicitly.</a>
|
<a class="sourceLine" id="cb15-3" title="3">⍝ compact than writing everything explicitly.</a>
|
||||||
<a class="sourceLine" id="cb12-4" title="4">lrepr←⍉(7⍴2)⊤13 25 19 61 35 49 47 59 55 11</a>
|
<a class="sourceLine" id="cb15-4" title="4">lrepr←⍉(7⍴2)⊤13 25 19 61 35 49 47 59 55 11</a>
|
||||||
<a class="sourceLine" id="cb12-5" title="5">rrepr←~¨lrepr</a></code></pre></div>
|
<a class="sourceLine" id="cb15-5" title="5">rrepr←~¨lrepr</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb13"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb13-1" title="1">∇ bits←WriteUPC digits;left;right</a>
|
<div class="sourceCode" id="cb16"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb16-1" title="1">∇ bits←WriteUPC digits;left;right</a>
|
||||||
<a class="sourceLine" id="cb13-2" title="2"> :If (11=≢digits)∧∧/digits∊0,⍳9</a>
|
<a class="sourceLine" id="cb16-2" title="2"> :If (11=≢digits)∧∧/digits∊0,⍳9</a>
|
||||||
<a class="sourceLine" id="cb13-3" title="3"> left←,lrepr[1+6↑digits;]</a>
|
<a class="sourceLine" id="cb16-3" title="3"> left←,lrepr[1+6↑digits;]</a>
|
||||||
<a class="sourceLine" id="cb13-4" title="4"> right←,rrepr[1+6↓digits,CheckDigit digits;]</a>
|
<a class="sourceLine" id="cb16-4" title="4"> right←,rrepr[1+6↓digits,CheckDigit digits;]</a>
|
||||||
<a class="sourceLine" id="cb13-5" title="5"> bits←1 0 1,left,0 1 0 1 0,right,1 0 1</a>
|
<a class="sourceLine" id="cb16-5" title="5"> bits←1 0 1,left,0 1 0 1 0,right,1 0 1</a>
|
||||||
<a class="sourceLine" id="cb13-6" title="6"> :Else</a>
|
<a class="sourceLine" id="cb16-6" title="6"> :Else</a>
|
||||||
<a class="sourceLine" id="cb13-7" title="7"> bits←¯1</a>
|
<a class="sourceLine" id="cb16-7" title="7"> bits←¯1</a>
|
||||||
<a class="sourceLine" id="cb13-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb16-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb13-9" title="9">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb16-9" title="9">∇</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb14"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb14-1" title="1">∇ digits←ReadUPC bits</a>
|
<div class="sourceCode" id="cb17"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb17-1" title="1">∇ digits←ReadUPC bits</a>
|
||||||
<a class="sourceLine" id="cb14-2" title="2"> :If 95≠⍴bits ⍝ incorrect number of bits</a>
|
<a class="sourceLine" id="cb17-2" title="2"> :If 95≠⍴bits ⍝ incorrect number of bits</a>
|
||||||
<a class="sourceLine" id="cb14-3" title="3"> digits←¯1</a>
|
<a class="sourceLine" id="cb17-3" title="3"> digits←¯1</a>
|
||||||
<a class="sourceLine" id="cb14-4" title="4"> :Else</a>
|
<a class="sourceLine" id="cb17-4" title="4"> :Else</a>
|
||||||
<a class="sourceLine" id="cb14-5" title="5"> ⍝ Test if the barcode was scanned right-to-left.</a>
|
<a class="sourceLine" id="cb17-5" title="5"> ⍝ Test if the barcode was scanned right-to-left.</a>
|
||||||
<a class="sourceLine" id="cb14-6" title="6"> :If 0=2|+/bits[3+⍳7]</a>
|
<a class="sourceLine" id="cb17-6" title="6"> :If 0=2|+/bits[3+⍳7]</a>
|
||||||
<a class="sourceLine" id="cb14-7" title="7"> bits←⌽bits</a>
|
<a class="sourceLine" id="cb17-7" title="7"> bits←⌽bits</a>
|
||||||
<a class="sourceLine" id="cb14-8" title="8"> :EndIf</a>
|
<a class="sourceLine" id="cb17-8" title="8"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb14-9" title="9"> digits←({¯1+lrepr⍳⍵}¨(7/⍳6)⊆42↑3↓bits),{¯1+rrepr⍳⍵}¨(7/⍳6)⊆¯42↑¯3↓bits</a>
|
<a class="sourceLine" id="cb17-9" title="9"> digits←({¯1+lrepr⍳⍵}¨(7/⍳6)⊆42↑3↓bits),{¯1+rrepr⍳⍵}¨(7/⍳6)⊆¯42↑¯3↓bits</a>
|
||||||
<a class="sourceLine" id="cb14-10" title="10"> :If ~∧/digits∊0,⍳9 ⍝ incorrect parity</a>
|
<a class="sourceLine" id="cb17-10" title="10"> :If ~∧/digits∊0,⍳9 ⍝ incorrect parity</a>
|
||||||
<a class="sourceLine" id="cb14-11" title="11"> digits←¯1</a>
|
<a class="sourceLine" id="cb17-11" title="11"> digits←¯1</a>
|
||||||
<a class="sourceLine" id="cb14-12" title="12"> :ElseIf (⊃⌽digits)≠CheckDigit ¯1↓digits ⍝ incorrect check digit</a>
|
<a class="sourceLine" id="cb17-12" title="12"> :ElseIf (⊃⌽digits)≠CheckDigit ¯1↓digits ⍝ incorrect check digit</a>
|
||||||
<a class="sourceLine" id="cb14-13" title="13"> digits←¯1</a>
|
<a class="sourceLine" id="cb17-13" title="13"> digits←¯1</a>
|
||||||
<a class="sourceLine" id="cb14-14" title="14"> :EndIf</a>
|
<a class="sourceLine" id="cb17-14" title="14"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb14-15" title="15"> :EndIf</a>
|
<a class="sourceLine" id="cb17-15" title="15"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb14-16" title="16">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb17-16" title="16">∇</a></code></pre></div>
|
||||||
<h2 id="problem-8-balancing-the-scales">Problem 8 – Balancing the Scales</h2>
|
<h2 id="problem-8-balancing-the-scales">Problem 8 – Balancing the Scales</h2>
|
||||||
<div class="sourceCode" id="cb15"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb15-1" title="1">∇ parts←Balance nums;subsets;partitions</a>
|
<div class="sourceCode" id="cb18"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb18-1" title="1">∇ parts←Balance nums;subsets;partitions</a>
|
||||||
<a class="sourceLine" id="cb15-2" title="2"> ⍝ This is a brute force solution, running in</a>
|
<a class="sourceLine" id="cb18-2" title="2"> ⍝ This is a brute force solution, running in</a>
|
||||||
<a class="sourceLine" id="cb15-3" title="3"> ⍝ exponential time. We generate all the possible</a>
|
<a class="sourceLine" id="cb18-3" title="3"> ⍝ exponential time. We generate all the possible</a>
|
||||||
<a class="sourceLine" id="cb15-4" title="4"> ⍝ partitions, filter out those which are not</a>
|
<a class="sourceLine" id="cb18-4" title="4"> ⍝ partitions, filter out those which are not</a>
|
||||||
<a class="sourceLine" id="cb15-5" title="5"> ⍝ balanced, and return the first matching one. There</a>
|
<a class="sourceLine" id="cb18-5" title="5"> ⍝ balanced, and return the first matching one. There</a>
|
||||||
<a class="sourceLine" id="cb15-6" title="6"> ⍝ are more advanced approach running in</a>
|
<a class="sourceLine" id="cb18-6" title="6"> ⍝ are more advanced approach running in</a>
|
||||||
<a class="sourceLine" id="cb15-7" title="7"> ⍝ pseudo-polynomial time (based on dynamic</a>
|
<a class="sourceLine" id="cb18-7" title="7"> ⍝ pseudo-polynomial time (based on dynamic</a>
|
||||||
<a class="sourceLine" id="cb15-8" title="8"> ⍝ programming, see the "Partition problem" Wikipedia</a>
|
<a class="sourceLine" id="cb18-8" title="8"> ⍝ programming, see the "Partition problem" Wikipedia</a>
|
||||||
<a class="sourceLine" id="cb15-9" title="9"> ⍝ page), but they are not warranted here, as the</a>
|
<a class="sourceLine" id="cb18-9" title="9"> ⍝ page), but they are not warranted here, as the</a>
|
||||||
<a class="sourceLine" id="cb15-10" title="10"> ⍝ input size remains fairly small.</a>
|
<a class="sourceLine" id="cb18-10" title="10"> ⍝ input size remains fairly small.</a>
|
||||||
<a class="sourceLine" id="cb15-11" title="11"></a>
|
<a class="sourceLine" id="cb18-11" title="11"></a>
|
||||||
<a class="sourceLine" id="cb15-12" title="12"> ⍝ Generate all partitions of a vector of a given</a>
|
<a class="sourceLine" id="cb18-12" title="12"> ⍝ Generate all partitions of a vector of a given</a>
|
||||||
<a class="sourceLine" id="cb15-13" title="13"> ⍝ size, as binary mask vectors.</a>
|
<a class="sourceLine" id="cb18-13" title="13"> ⍝ size, as binary mask vectors.</a>
|
||||||
<a class="sourceLine" id="cb15-14" title="14"> subsets←{1↓2⊥⍣¯1⍳2*⍵}</a>
|
<a class="sourceLine" id="cb18-14" title="14"> subsets←{1↓2⊥⍣¯1⍳2*⍵}</a>
|
||||||
<a class="sourceLine" id="cb15-15" title="15"> ⍝ Keep only the subsets whose sum is exactly</a>
|
<a class="sourceLine" id="cb18-15" title="15"> ⍝ Keep only the subsets whose sum is exactly</a>
|
||||||
<a class="sourceLine" id="cb15-16" title="16"> ⍝ (+/nums)÷2.</a>
|
<a class="sourceLine" id="cb18-16" title="16"> ⍝ (+/nums)÷2.</a>
|
||||||
<a class="sourceLine" id="cb15-17" title="17"> partitions←nums{((2÷⍨+/⍺)=⍺+.×⍵)/⍵}subsets⍴nums</a>
|
<a class="sourceLine" id="cb18-17" title="17"> partitions←nums{((2÷⍨+/⍺)=⍺+.×⍵)/⍵}subsets⍴nums</a>
|
||||||
<a class="sourceLine" id="cb15-18" title="18"> :If 0=≢,partitions</a>
|
<a class="sourceLine" id="cb18-18" title="18"> :If 0=≢,partitions</a>
|
||||||
<a class="sourceLine" id="cb15-19" title="19"> ⍝ If no partition satisfy the above</a>
|
<a class="sourceLine" id="cb18-19" title="19"> ⍝ If no partition satisfy the above</a>
|
||||||
<a class="sourceLine" id="cb15-20" title="20"> ⍝ criterion, we return ⍬.</a>
|
<a class="sourceLine" id="cb18-20" title="20"> ⍝ criterion, we return ⍬.</a>
|
||||||
<a class="sourceLine" id="cb15-21" title="21"> parts←⍬</a>
|
<a class="sourceLine" id="cb18-21" title="21"> parts←⍬</a>
|
||||||
<a class="sourceLine" id="cb15-22" title="22"> :Else</a>
|
<a class="sourceLine" id="cb18-22" title="22"> :Else</a>
|
||||||
<a class="sourceLine" id="cb15-23" title="23"> ⍝ Otherwise, we return the first possible</a>
|
<a class="sourceLine" id="cb18-23" title="23"> ⍝ Otherwise, we return the first possible</a>
|
||||||
<a class="sourceLine" id="cb15-24" title="24"> ⍝ partition.</a>
|
<a class="sourceLine" id="cb18-24" title="24"> ⍝ partition.</a>
|
||||||
<a class="sourceLine" id="cb15-25" title="25"> parts←nums{((⊂,(⊂~))⊃↓⍉⍵)/¨2⍴⊂⍺}partitions</a>
|
<a class="sourceLine" id="cb18-25" title="25"> parts←nums{((⊂,(⊂~))⊃↓⍉⍵)/¨2⍴⊂⍺}partitions</a>
|
||||||
<a class="sourceLine" id="cb15-26" title="26"> :EndIf</a>
|
<a class="sourceLine" id="cb18-26" title="26"> :EndIf</a>
|
||||||
<a class="sourceLine" id="cb15-27" title="27">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb18-27" title="27">∇</a></code></pre></div>
|
||||||
<h2 id="problem-9-upwardly-mobile">Problem 9 – Upwardly Mobile</h2>
|
<h2 id="problem-9-upwardly-mobile">Problem 9 – Upwardly Mobile</h2>
|
||||||
<div class="sourceCode" id="cb16"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb16-1" title="1">∇ weights←Weights filename;mobile;branches;mat</a>
|
<div class="sourceCode" id="cb19"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb19-1" title="1">∇ weights←Weights filename;mobile;branches;mat</a>
|
||||||
<a class="sourceLine" id="cb16-2" title="2"> ⍝ Put your code and comments below here</a>
|
<a class="sourceLine" id="cb19-2" title="2"> ⍝ Put your code and comments below here</a>
|
||||||
<a class="sourceLine" id="cb16-3" title="3"></a>
|
<a class="sourceLine" id="cb19-3" title="3"></a>
|
||||||
<a class="sourceLine" id="cb16-4" title="4"> ⍝ Parse the mobile input file.</a>
|
<a class="sourceLine" id="cb19-4" title="4"> ⍝ Parse the mobile input file.</a>
|
||||||
<a class="sourceLine" id="cb16-5" title="5"> mobile←↑⊃⎕NGET filename 1</a>
|
<a class="sourceLine" id="cb19-5" title="5"> mobile←↑⊃⎕NGET filename 1</a>
|
||||||
<a class="sourceLine" id="cb16-6" title="6"> branches←⍸mobile∊'┌┴┐'</a>
|
<a class="sourceLine" id="cb19-6" title="6"> branches←⍸mobile∊'┌┴┐'</a>
|
||||||
<a class="sourceLine" id="cb16-7" title="7"> ⍝ TODO: Build the matrix of coefficients mat.</a>
|
<a class="sourceLine" id="cb19-7" title="7"> ⍝ TODO: Build the matrix of coefficients mat.</a>
|
||||||
<a class="sourceLine" id="cb16-8" title="8"></a>
|
<a class="sourceLine" id="cb19-8" title="8"></a>
|
||||||
<a class="sourceLine" id="cb16-9" title="9"> ⍝ Solve the system of equations (arbitrarily setting</a>
|
<a class="sourceLine" id="cb19-9" title="9"> ⍝ Solve the system of equations (arbitrarily setting</a>
|
||||||
<a class="sourceLine" id="cb16-10" title="10"> ⍝ the first variable at 1 because the system is</a>
|
<a class="sourceLine" id="cb19-10" title="10"> ⍝ the first variable at 1 because the system is</a>
|
||||||
<a class="sourceLine" id="cb16-11" title="11"> ⍝ overdetermined), then multiply the coefficients by</a>
|
<a class="sourceLine" id="cb19-11" title="11"> ⍝ overdetermined), then multiply the coefficients by</a>
|
||||||
<a class="sourceLine" id="cb16-12" title="12"> ⍝ their least common multiple to get the smallest</a>
|
<a class="sourceLine" id="cb19-12" title="12"> ⍝ their least common multiple to get the smallest</a>
|
||||||
<a class="sourceLine" id="cb16-13" title="13"> ⍝ integer weights.</a>
|
<a class="sourceLine" id="cb19-13" title="13"> ⍝ integer weights.</a>
|
||||||
<a class="sourceLine" id="cb16-14" title="14"> weights←((1∘,)×(∧/÷))mat[;1]⌹1↓[2]mat</a>
|
<a class="sourceLine" id="cb19-14" title="14"> weights←((1∘,)×(∧/÷))mat[;1]⌹1↓[2]mat</a>
|
||||||
<a class="sourceLine" id="cb16-15" title="15">∇</a></code></pre></div>
|
<a class="sourceLine" id="cb19-15" title="15">∇</a></code></pre></div>
|
||||||
<div class="sourceCode" id="cb17"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb17-1" title="1"> :EndNamespace</a>
|
<div class="sourceCode" id="cb20"><pre class="sourceCode default"><code class="sourceCode default"><a class="sourceLine" id="cb20-1" title="1"> :EndNamespace</a>
|
||||||
<a class="sourceLine" id="cb17-2" title="2">:EndNamespace</a></code></pre></div>
|
<a class="sourceLine" id="cb20-2" title="2">:EndNamespace</a></code></pre></div>
|
||||||
</section>
|
</section>
|
||||||
</article>
|
</article>
|
||||||
]]></description>
|
]]></description>
|
||||||
|
|
|
@ -46,6 +46,17 @@ explanations for every problem below.
|
||||||
∇
|
∇
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
This is a very straightforward implementation of the algorithm
|
||||||
|
describe in the problem description. I decided to switch explicitly on
|
||||||
|
the size of the input vector because I feel it is more natural. For
|
||||||
|
the cases with 5 or 7 judges, we use Drop (~↓~) to remove the lowest
|
||||||
|
and highest scores.
|
||||||
|
|
||||||
|
At the end, we sum up the scores with ~+/~ and multiply them by
|
||||||
|
~dd~. The last operation, ~2(⍎⍕)~, is a train using [[https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Format%20Dyadic.htm][Format (Dyadic)]] to
|
||||||
|
round to 2 decimal places, and [[https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Execute.htm][Execute]] to get actual numbers and not
|
||||||
|
strings.
|
||||||
|
|
||||||
* Problem 2 -- Another Step in the Proper Direction
|
* Problem 2 -- Another Step in the Proper Direction
|
||||||
|
|
||||||
#+begin_src default
|
#+begin_src default
|
||||||
|
@ -65,6 +76,20 @@ explanations for every problem below.
|
||||||
∇
|
∇
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
This is an extension to [[./dyalog-apl-competition-2020-phase-1.html#stepping-in-the-proper-direction][Problem 5 of Phase I]]. In each case, we compute
|
||||||
|
the "segments", i.e., the steps starting from 0. In a last step,
|
||||||
|
common to all cases, we add the correct starting point and correct the
|
||||||
|
direction if need be.
|
||||||
|
|
||||||
|
To compute equally-sized steps, we first divide the segment $[0, 1]$
|
||||||
|
in ~p~ equal segments with ~(⍳p)÷p~. This subdivision can then be
|
||||||
|
multiplied by the width to obtain the required segments.
|
||||||
|
|
||||||
|
When ~p~ is the step size, we just divide the width by the step size
|
||||||
|
(rounded to the next largest integer) to get the required number of
|
||||||
|
segments. If the last segment is too large, we "crop" it to the width
|
||||||
|
with Minimum (~⌊~).
|
||||||
|
|
||||||
* Problem 3 -- Past Tasks Blast
|
* Problem 3 -- Past Tasks Blast
|
||||||
|
|
||||||
#+begin_src default
|
#+begin_src default
|
||||||
|
@ -75,16 +100,55 @@ explanations for every problem below.
|
||||||
∇
|
∇
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
I decided to use ~HttpCommand~ for this task, since it is simply one
|
||||||
|
~]load HttpCommand~ away and should be platform-independent.
|
||||||
|
|
||||||
|
Parsing XML is not something I consider "fun" in the best of cases,
|
||||||
|
and I feel like APL is not the best language to do this kind of
|
||||||
|
thing. Given how simple the task is, I just decided to find the
|
||||||
|
relevant bits with a regular expression using [[https://help.dyalog.com/18.0/index.htm#Language/System%20Functions/r.htm][Replace and Search]]
|
||||||
|
(~⎕S~).
|
||||||
|
|
||||||
|
After finding all the strings vaguely resembling a PDF file name (only
|
||||||
|
alphanumeric characters and underscores, with a =.pdf= extension), I
|
||||||
|
just concatenate them to the base URL of the Dyalog domain.
|
||||||
|
|
||||||
* Problem 4 -- Bioinformatics
|
* Problem 4 -- Bioinformatics
|
||||||
|
|
||||||
|
The first task can be solved by decomposing it into several functions.
|
||||||
|
|
||||||
#+begin_src default
|
#+begin_src default
|
||||||
⍝ Test if a DNA string is a reverse palindrome.
|
⍝ Test if a DNA string is a reverse palindrome.
|
||||||
isrevp←{⍵≡⌽'TAGC'['ATCG'⍳⍵]}
|
isrevp←{⍵≡⌽'TAGC'['ATCG'⍳⍵]}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
⍝ Generate all subarrays (position, length) pairs, for
|
First, we compute the complement of a DNA string (using simple
|
||||||
⍝ 4 ≤ length ≤ 12.
|
indexing) and test if its Reverse (~⌽~) is equal to the original
|
||||||
|
string.
|
||||||
|
|
||||||
|
#+begin_src default
|
||||||
|
⍝ Generate all subarrays (position, length) pairs, for 4 ≤ length ≤ 12.
|
||||||
subarrays←{⊃,/(⍳⍵),¨¨3↓¨⍳¨12⌊1+⍵-⍳⍵}
|
subarrays←{⊃,/(⍳⍵),¨¨3↓¨⍳¨12⌊1+⍵-⍳⍵}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
We first compute all the possible lengths for each starting point. For
|
||||||
|
instance, the last element cannot have any (position, length) pair
|
||||||
|
associated to it, because there is no three element following it. So
|
||||||
|
we crop the possible lengths to $[3, 12]$. For instance for an array
|
||||||
|
of size 10:
|
||||||
|
|
||||||
|
#+begin_src default
|
||||||
|
{3↓¨⍳¨12⌊1+⍵-⍳⍵}10
|
||||||
|
┌──────────────┬───────────┬─────────┬───────┬─────┬───┬─┬┬┬┐
|
||||||
|
│4 5 6 7 8 9 10│4 5 6 7 8 9│4 5 6 7 8│4 5 6 7│4 5 6│4 5│4││││
|
||||||
|
└──────────────┴───────────┴─────────┴───────┴─────┴───┴─┴┴┴┘
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Then, we just add the corresponding starting position to each length
|
||||||
|
(1 for the first block, 2 for the second, and so on). Finally, we
|
||||||
|
flatten everything.
|
||||||
|
|
||||||
|
#+begin_src default
|
||||||
∇ r←revp dna;positions
|
∇ r←revp dna;positions
|
||||||
positions←subarrays⍴dna
|
positions←subarrays⍴dna
|
||||||
⍝ Filter subarrays which are reverse palindromes.
|
⍝ Filter subarrays which are reverse palindromes.
|
||||||
|
@ -92,10 +156,26 @@ explanations for every problem below.
|
||||||
∇
|
∇
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
For each possible (position, length) pair, we get the corresponding
|
||||||
|
DNA substring with ~dna[¯1+⍵[1]+⍳⍵[2]]~ (adding ~¯1~ is necessary
|
||||||
|
because ~⎕IO←1~). We test if this substring is a reverse palindrome
|
||||||
|
using ~isrevp~ above. [[https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Replicate.htm][Replicate]] (~/~) then selects only the (position,
|
||||||
|
length) pairs for which the substring is a reverse palindrome.
|
||||||
|
|
||||||
|
The second task is just about counting the number of subsets modulo
|
||||||
|
1,000,000. So we just need to compute $2^n \mod 1000000$ for any
|
||||||
|
positive integer $n\leq1000$.
|
||||||
|
|
||||||
#+begin_src default
|
#+begin_src default
|
||||||
sset←{((1E6|2∘×)⍣⍵)1}
|
sset←{((1E6|2∘×)⍣⍵)1}
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
Since we cannot just compute $2^n$ directly and take the remainder, we
|
||||||
|
use modular arithmetic to stay mod 1,000,000 during the whole
|
||||||
|
computation. The dfn ~(1E6|2∘×)~ doubles its argument mod
|
||||||
|
1,000,000. So we just apply this function $n$ times using the [[https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Operators/Power%20Operator.htm][Power]]
|
||||||
|
operator (~⍣~), with an initial value of 1.
|
||||||
|
|
||||||
* Problem 5 -- Future and Present Value
|
* Problem 5 -- Future and Present Value
|
||||||
|
|
||||||
#+begin_src default
|
#+begin_src default
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue