Dyalog APL Problem Solving Competition 2020 — Phase II

Annotated Solutions

Table of Contents

Introduction

After Phase I, here are my solutions to Phase II problems. The full code is included in the post, but everything is also available on GitHub.

A PDF of the problems descriptions is available on the competition website, or directly from my GitHub repo.

The submission guidelines gave a template where everything is defined in a Contest2020.Problems Namespace. I kept the default values for ⎕IO and ⎕ML because the problems were not particularly easier with ⎕IO←0.

This post is still a work in progress! I will try to write explanations for every problem below.

Problem 1 – Take a Dive

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 Format (Dyadic) to round to 2 decimal places, and Execute to get actual numbers and not strings.

Problem 2 – Another Step in the Proper Direction

This is an extension to 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

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 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

The first task can be solved by decomposing it into several functions.

First, we compute the complement of a DNA string (using simple indexing) and test if its Reverse () is equal to the original string.

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:

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.

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. 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\).

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 Power operator (), with an initial value of 1.

Problem 5 – Future and Present Value

TODO

Problem 6 – Merge

We first read the template and the JSON values from their files. The ⎕NGET function read simple text files, and ⎕JSON extracts the key-value pairs as a namespace.

Assuming all variable names contain only letters, we match the regex @[a-zA-Z]*@ to match variable names enclosed between @ symbols. The function getval then returns the appropriate value, and we can replace the variable name in the template.

This function takes the namespace matching the variable names to their respective values, and the name of the variable.

Problem 7 – UPC

The check digit satisfies the equation \[ 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, \] therefore, \[ 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. \]

Translated to APL, we just take the dot product between the first 11 digits of the barcode with 11⍴3 1, negate it, and take the remainder by 10.

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.

First of all, if the vector digits does not have exactly 11 elements, all between 0 and 9, it is an error and we return ¯1.

Then, we take the first 6 digits and encode them with lrepr, and the last 5 digits plus the check digit encoded with rrepr. In each case, adding 1 is necessary because ⎕IO←1. We return the final bit array with the required beginning, middle, and end guard patterns.

Problem 8 – Balancing the Scales

TODO

Problem 9 – Upwardly Mobile

TODO