blog/_site/posts/dyalog-apl-competition-2020-phase-2.html

262 lines
31 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes">
<meta name="description" content="Dimitri Lozeve's blog: Dyalog APL Problem Solving Competition 2020 — Phase II">
<title>Dimitri Lozeve - Dyalog APL Problem Solving Competition 2020 — Phase II</title>
<link rel="stylesheet" href="../css/tufte.css" />
<link rel="stylesheet" href="../css/pandoc.css" />
<link rel="stylesheet" href="../css/default.css" />
<link rel="stylesheet" href="../css/syntax.css" />
<!-- RSS feed -->
<link rel="alternate" type="application/rss+xml" title="Dimitri Lozeve's blog" href="../rss.xml" />
<!-- MathJax -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
</head>
<body>
<article>
<header>
<nav>
<a href="../">Home</a>
<a href="../archive.html">Posts</a>
<a href="../projects.html">Projects</a>
<a href="../cv.html">CV</a>
<a href="../contact.html">Contact</a>
</nav>
<h1 class="title">Dyalog APL Problem Solving Competition 2020 — Phase II</h1>
<p class="subtitle">Annotated Solutions</p>
<p class="byline">August 2, 2020</p>
</header>
<section>
<div id="toc"><h2>Table of Contents</h2><ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#problem-1-take-a-dive">Problem 1 Take a Dive</a></li>
<li><a href="#problem-2-another-step-in-the-proper-direction">Problem 2 Another Step in the Proper Direction</a></li>
<li><a href="#problem-3-past-tasks-blast">Problem 3 Past Tasks Blast</a></li>
<li><a href="#problem-4-bioinformatics">Problem 4 Bioinformatics</a></li>
<li><a href="#problem-5-future-and-present-value">Problem 5 Future and Present Value</a></li>
<li><a href="#problem-6-merge">Problem 6 Merge</a></li>
<li><a href="#problem-7-upc">Problem 7 UPC</a></li>
<li><a href="#problem-8-balancing-the-scales">Problem 8 Balancing the Scales</a></li>
<li><a href="#problem-9-upwardly-mobile">Problem 9 Upwardly Mobile</a></li>
</ul></div>
<h2 id="introduction">Introduction</h2>
<p>After <a href="./dyalog-apl-competition-2020-phase-1.html">Phase I</a>, here are my solutions to Phase II problems. The full code is included in the post, but everything is also available <a href="https://github.com/dlozeve/apl-competition-2020">on GitHub</a>.</p>
<p>A PDF of the problems descriptions is available on <a href="https://www.dyalogaplcompetition.com/">the competition website</a>, or directly from <a href="https://github.com/dlozeve/apl-competition-2020/blob/master/Contest2020/2020%20APL%20Problem%20Solving%20Competition%20Phase%20II%20Problems.pdf">my GitHub repo</a>.</p>
<p>The submission guidelines gave a template where everything is defined in a <code>Contest2020.Problems</code> Namespace. I kept the default values for <code>⎕IO</code> and <code>⎕ML</code> because the problems were not particularly easier with <code>⎕IO←0</code>.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a>:Namespace Contest2020</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a> :Namespace Problems</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a> (⎕IO ⎕ML ⎕WX)←1 1 3</span></code></pre></div>
<h2 id="problem-1-take-a-dive">Problem 1 Take a Dive</h2>
<div class="sourceCode" id="cb2"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a>∇ score←dd DiveScore scores</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a> :If 7=≢scores</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a> scores←scores[¯2↓2↓⍋scores]</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a> :ElseIf 5=≢scores</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a> scores←scores[¯1↓1↓⍋scores]</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a> :Else</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a> scores←scores</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a> :EndIf</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true"></a> score←2(⍎⍕)dd×+/scores</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true"></a></span></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>
<div class="sourceCode" id="cb3"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a>∇ steps←{p}Steps fromTo;segments;width</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a> width←|-/fromTo</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a> :If 0=⎕NC'p' ⍝ No left argument: same as Problem 5 of Phase I</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a> segments←0,width</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a> :ElseIf p&lt;0 ⍝ -⌊p is the number of equally-sized steps to take</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a> segments←(-⌊p){0,⍵×⍺÷⍨⍳⍺}width</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a> :ElseIf p&gt;0 ⍝ p is the step size</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a> segments←p{⍵⌊×0,⍳⌈⍵÷⍺}width</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true"></a> :ElseIf p=0 ⍝ As if we took zero step</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a> segments←0</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a> :EndIf</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a> ⍝ Take into account the start point and the direction.</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a> steps←fromTo{(⊃⍺)+(-×-/)×⍵}segments</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a></span></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>
<div class="sourceCode" id="cb4"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a>∇ urls←PastTasks url;r;paths</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a> r←HttpCommand.Get url</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a> paths←('[a-zA-Z0-9_/]+\.pdf'⎕S'&amp;')r.Data</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true"></a> urls←('https://www.dyalog.com/'∘,)¨paths</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a></span></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>
<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"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a>⍝ Test if a DNA string is a reverse palindrome.</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a>isrevp←{⍵≡⌽'TAGC'['ATCG'⍳⍵]}</span></code></pre></div>
<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>
<div class="sourceCode" id="cb6"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a>⍝ Generate all subarrays (position, length) pairs, for 4 ≤ length ≤ 12.</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a>subarrays←{⊃,/(⍳⍵),¨¨3↓¨¨12⌊1+⍵-⍳⍵}</span></code></pre></div>
<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>
<div class="sourceCode" id="cb7"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a> {3↓¨¨12⌊1+⍵-⍳⍵}10</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a>┌──────────────┬───────────┬─────────┬───────┬─────┬───┬─┬┬┬┐</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a>│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││││</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a>└──────────────┴───────────┴─────────┴───────┴─────┴───┴─┴┴┴┘</span></code></pre></div>
<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>
<div class="sourceCode" id="cb8"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a>∇ r←revp dna;positions</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a> positions←subarraysdna</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a> ⍝ Filter subarrays which are reverse palindromes.</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a> r←↑({isrevp dna[¯1+⍵[1]+⍳⍵[2]]}¨positions)/positions</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a></span></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"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a>sset←{((1E6|2∘×)⍣⍵)1}</span></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>
<p>First solution: <code>((1+⊢)⊥⊣)</code> computes the total return for a vector of amounts <code></code> and a vector of rates <code></code>. It is applied to every prefix subarray of amounts and rates to get all intermediate values. However, this has quadratic complexity.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true"></a>rr←(,\⊣)((1+⊢)⊥⊣)¨(,\⊢)</span></code></pre></div>
<p>Second solution: We want to be able to use the recurrence relation (<code>recur</code>) and scan through the vectors of amounts and rates, accumulating the total value at every time step. However, APL evaluation is right-associative, so a simple <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Operators/Scan.htm">Scan</a> (<code>recur\amounts,¨values</code>) would not give the correct result, since <code>recur</code> is not associative and we need to evaluate it left-to-right. (In any case, in this case, Scan would have quadratic complexity, so would not bring any benefit over the previous solution.) What we need is something akin to Haskells <code>scanl</code> function, which would evaluate left to right in <span class="math inline">\(O(n)\)</span> time<span><label for="sn-0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0" class="margin-toggle" /><span class="sidenote">There is an interesting <a href="https://stackoverflow.com/a/25100675/8864368">StackOverflow answer</a> explaining the behaviour of Scan, and compares it to Haskells <code>scanl</code> function.<br />
<br />
</span></span>. This is what we do here, accumulating values from left to right. (This is inspired from <a href="https://dfns.dyalog.com/c_ascan.htm"><code>dfns.ascan</code></a>, although heavily simplified.)</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a>rr←{recur←{⍵[1]+×1+⍵[2]} ⋄ 1↓⌽⊃{(⊂(⊃⍵)recur),⍵}/⌽⍺,¨⍵}</span></code></pre></div>
<p>For the second task, there is an explicit formula for cashflow calculations, so we can just apply it.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a>pv←{+/⍺÷×\1+⍵}</span></code></pre></div>
<h2 id="problem-6-merge">Problem 6 Merge</h2>
<div class="sourceCode" id="cb13"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true"></a>∇ text←templateFile Merge jsonFile;template;ns</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true"></a> template←⊃⎕NGET templateFile 1</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true"></a> ns←⎕JSON⊃⎕NGET jsonFile</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true"></a> ⍝ We use a simple regex search and replace on the</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true"></a> ⍝ template.</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true"></a> text←↑('@[a-zA-Z]*@'⎕R{ns getval ¯1↓1↓⍵.Match})template</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true"></a></span></code></pre></div>
<p>We first read the template and the JSON values from their files. The <a href="https://help.dyalog.com/18.0/index.htm#Language/System%20Functions/nget.htm"><code>⎕NGET</code></a> function read simple text files, and <a href="https://help.dyalog.com/18.0/index.htm#Language/System%20Functions/json.htm"><code>⎕JSON</code></a> extracts the key-value pairs as a namespace.</p>
<p>Assuming all variable names contain only letters, we match the regex <code>@[a-zA-Z]*@</code> to match variable names enclosed between <code>@</code> symbols. The function <code>getval</code> then returns the appropriate value, and we can replace the variable name in the template.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true"></a>∇ val←ns getval var</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true"></a> :If ''≡var ⍝ literal '@'</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true"></a> val←'@'</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true"></a> :ElseIf (⊂var)∊ns.⎕NL ¯2</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true"></a> val←⍕ns⍎var</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true"></a> :Else</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true"></a> val←'???'</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true"></a> :EndIf</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true"></a></span></code></pre></div>
<p>This function takes the namespace matching the variable names to their respective values, and the name of the variable.</p>
<ul>
<li>If the variable name is empty, we matched the string <code>@@</code>, which corresponds to a literal <code>@</code>.</li>
<li>If the variable name is present in the namespace, we query the namespace to get the required value.</li>
<li>Otherwise, we have an unknown variable, so we replace it with <code>???</code>.</li>
</ul>
<h2 id="problem-7-upc">Problem 7 UPC</h2>
<div class="sourceCode" id="cb15"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true"></a>CheckDigit←{10|-⍵+.×113 1}</span></code></pre></div>
<p>The check digit satisfies the equation <span class="math display">\[ 3 x_{1}+x_{2}+3 x_{3}+x_{4}+3 x_{5}+x_{6}+3 x_{7}+x_{8}+3 x_{9}+x_{10}+3 x_{11}+x_{12} \equiv 0 \bmod 10, \]</span> therefore, <span class="math display">\[ x_{12} \equiv -(3 x_{1}+x_{2}+3 x_{3}+x_{4}+3 x_{5}+x_{6}+3 x_{7}+x_{8}+3 x_{9}+x_{10}+3 x_{11}) \bmod 10. \]</span></p>
<p>Translated to APL, we just take the dot product between the first 11 digits of the barcode with <code>113 1</code>, negate it, and take the remainder by 10.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true"></a>⍝ Left and right representations of digits. Decoding</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true"></a>⍝ the binary representation from decimal is more</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true"></a>⍝ compact than writing everything explicitly.</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true"></a>lrepr←⍉(72)13 25 19 61 35 49 47 59 55 11</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true"></a>rrepr←~¨lrepr</span></code></pre></div>
<p>For the second task, the first thing we need to do is save the representation of digits. To save space, I did not encode the binary representation explicitly, instead using a decimal representation that I then decode in base 2. The right representation is just the bitwise negation.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true"></a>∇ bits←WriteUPC digits;left;right</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true"></a> :If (11=≢digits)∧∧/digits∊0,9</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true"></a> left←,lrepr[1+6↑digits;]</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true"></a> right←,rrepr[1+6↓digits,CheckDigit digits;]</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true"></a> bits←1 0 1,left,0 1 0 1 0,right,1 0 1</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true"></a> :Else</span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true"></a> bits←¯1</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true"></a> :EndIf</span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true"></a></span></code></pre></div>
<p>First of all, if the vector <code>digits</code> does not have exactly 11 elements, all between 0 and 9, it is an error and we return <code>¯1</code>.</p>
<p>Then, we take the first 6 digits and encode them with <code>lrepr</code>, and the last 5 digits plus the check digit encoded with <code>rrepr</code>. In each case, adding 1 is necessary because <code>⎕IO←1</code>. We return the final bit array with the required beginning, middle, and end guard patterns.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true"></a>∇ digits←ReadUPC bits</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true"></a> :If 95≠bits ⍝ incorrect number of bits</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true"></a> digits←¯1</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true"></a> :Else</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true"></a> ⍝ Test if the barcode was scanned right-to-left.</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true"></a> :If 0=2|+/bits[3+7]</span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true"></a> bits←⌽bits</span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true"></a> :EndIf</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true"></a> digits←({¯1+lrepr⍵}¨(7/6)⊆42↑3↓bits),{¯1+rrepr⍵}¨(7/6)⊆¯42↑¯3↓bits</span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true"></a> :If ~∧/digits∊0,9 ⍝ incorrect parity</span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true"></a> digits←¯1</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true"></a> :ElseIf (⊃⌽digits)≠CheckDigit ¯1↓digits ⍝ incorrect check digit</span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true"></a> digits←¯1</span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true"></a> :EndIf</span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true"></a> :EndIf</span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true"></a></span></code></pre></div>
<ul>
<li>If we dont have the correct number of bits, we return <code>¯1</code>.</li>
<li>We test the first digit for its parity, to determine if its actually a left representation. If its not, we reverse the bit array.</li>
<li>Then, we take the bit array representing the right digits (<code>¯42↑¯3↓bits</code>), separate the different digits using <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Partition.htm">Partition</a> (<code></code>), and look up each of them in the <code>rrepr</code> vector using <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Index%20Of.htm">Index Of</a> (<code></code>). We do the same for the left digits.</li>
<li>Final checks for the range of the digits (i.e., if the representations could not be found in the <code>lrepr</code> and <code>rrepr</code> vectors), and for the check digit.</li>
</ul>
<h2 id="problem-8-balancing-the-scales">Problem 8 Balancing the Scales</h2>
<div class="sourceCode" id="cb19"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true"></a>∇ parts←Balance nums;subsets;partitions</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true"></a> ⍝ This is a brute force solution, running in</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true"></a> ⍝ exponential time. We generate all the possible</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true"></a> ⍝ partitions, filter out those which are not</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true"></a> ⍝ balanced, and return the first matching one. There</span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true"></a> ⍝ are more advanced approach running in</span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true"></a> ⍝ pseudo-polynomial time (based on dynamic</span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true"></a> ⍝ programming, see the &quot;Partition problem&quot; Wikipedia</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true"></a> ⍝ page), but they are not warranted here, as the</span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true"></a> ⍝ input size remains fairly small.</span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true"></a></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true"></a> ⍝ Generate all partitions of a vector of a given</span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true"></a> ⍝ size, as binary mask vectors.</span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true"></a> subsets←{1↓2⊥⍣¯12*⍵}</span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true"></a> ⍝ Keep only the subsets whose sum is exactly</span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true"></a> ⍝ (+/nums)÷2.</span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true"></a> partitions←nums{((2÷⍨+/)=+.×⍵)/⍵}subsetsnums</span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true"></a> :If 0=≢,partitions</span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true"></a> ⍝ If no partition satisfy the above</span>
<span id="cb19-20"><a href="#cb19-20" aria-hidden="true"></a> ⍝ criterion, we return ⍬.</span>
<span id="cb19-21"><a href="#cb19-21" aria-hidden="true"></a> parts←⍬</span>
<span id="cb19-22"><a href="#cb19-22" aria-hidden="true"></a> :Else</span>
<span id="cb19-23"><a href="#cb19-23" aria-hidden="true"></a> ⍝ Otherwise, we return the first possible</span>
<span id="cb19-24"><a href="#cb19-24" aria-hidden="true"></a> ⍝ partition.</span>
<span id="cb19-25"><a href="#cb19-25" aria-hidden="true"></a> parts←nums{((⊂,(⊂~))⊃↓⍉⍵)/¨2}partitions</span>
<span id="cb19-26"><a href="#cb19-26" aria-hidden="true"></a> :EndIf</span>
<span id="cb19-27"><a href="#cb19-27" aria-hidden="true"></a></span></code></pre></div>
<h2 id="problem-9-upwardly-mobile">Problem 9 Upwardly Mobile</h2>
<p>This is the only problem that I didnt complete. It required parsing the files containing the graphical representations of the trees, which was needlessly complex and, quite frankly, hard and boring with a language like APL.</p>
<p>However, the next part is interesting: once we have a matrix of coefficients representing the relationships between the weights, we can solve the system of equations. <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/Matrix%20Divide.htm">Matrix Divide</a> (<code></code>) will find one solution to the system. Since the system is overdetermined, we fix <code>A=1</code> to find one possible solution. Since we want integer weights, the solution we find is smaller than the one we want, and may contain fractional weights. So we multiply everything by the <a href="https://help.dyalog.com/18.0/index.htm#Language/Primitive%20Functions/And%20Lowest%20Common%20Multiple.htm">Lowest Common Multiple</a> (<code></code>) to get the smallest integer weights.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true"></a>∇ weights←Weights filename;mobile;branches;mat</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true"></a> ⍝ Put your code and comments below here</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true"></a></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true"></a> ⍝ Parse the mobile input file.</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true"></a> mobile←↑⊃⎕NGET filename 1</span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true"></a> branches←⍸mobile∊'┌┴┐'</span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true"></a> ⍝ TODO: Build the matrix of coefficients mat.</span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true"></a></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true"></a> ⍝ Solve the system of equations (arbitrarily setting</span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true"></a> ⍝ the first variable at 1 because the system is</span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true"></a> ⍝ overdetermined), then multiply the coefficients by</span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true"></a> ⍝ their least common multiple to get the smallest</span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true"></a> ⍝ integer weights.</span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true"></a> weights←((1∘,)×(∧/÷))mat[;1]⌹1↓[2]mat</span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true"></a></span></code></pre></div>
<div class="sourceCode" id="cb21"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true"></a> :EndNamespace</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true"></a>:EndNamespace</span></code></pre></div>
</section>
</article>
<footer>
Site proudly generated by
<a href="http://jaspervdj.be/hakyll">Hakyll</a>
</footer>
</body>
</html>