Watrophy: code challenges by Robert SmithWed, 21 Mar 2018 05:23:04 +0000Robert Smith#38: Spirals2018-03-202018-03-20Robert Smithhttp://www.watrophy.com<p>Recall that the symbol $\mathbb{Z}^2$ denotes the set of all coordinate pairs with integer components.</p>
<p>A <strong>spiral of length $n\ge 1$</strong> is a counter-clockwise spiral starting at $(0,0)$ extending to the right to $(n,0)$, wrapping around so as to cover $\mathbb{Z}^2$ completely.</p>
<p>Consider the following spiral of length $2$.</p>
<pre><code>*--*--*--*--*--*
| |
* *--*--*--* *
| | (0,0) | |
* * x--*--x *
| | (2,0) |
* *--*--*--*--*
|
*--*--*--*--*--* ...</code></pre>
<p>The points of the spiral have a natural ordering. The above spiral can be written as a sequence $s$ where
$$
\begin{align}
s_0 &= (0,0), & s_3 &= (2,1),\\
s_1 &= (1,0), & s_4 &= (1,1),\\
s_2 &= (2,0), & s_5 &= (0,1),
\end{align}
$$
and so on.</p>
<p>There are three challenges. Given an $n\ge 1$, do the following.</p>
<ol>
<li><p>Given a $k\ge 0$, find $s_k$.</p></li>
<li><p>Given a point $(\alpha, \beta)\in\mathbb{Z}^2$, find the $k$ such that $s_k = (\alpha,\beta)$.</p></li>
<li><p>Print the spiral of length $2$ to the terminal by printing the values of $k$ in their correct positions. (And make it look nice by ensuring the numbers are aligned and reasonably spaced out.)</p></li>
</ol>
#37: Staircase Paths2018-02-102018-02-10Robert Smithhttp://www.watrophy.com<h2>Prerequisites</h2>
<p>The symbol $\mathbb{Z}^n$ denotes the set of all coordinate $n$-tuples with integer components. These are one kind of <strong>$n$-dimensional lattice</strong>.</p>
<p>Given two points $s=(s_1,\ldots, s_n)$ and $e=(e_1, \ldots, e_n)$, their <a href="https://en.wikipedia.org/wiki/Taxicab_geometry" ><strong>taxicab distance</strong></a> is $$\Vert s-e\Vert_1 := \sum_{i=1}^n\vert s_i-e_i\vert.$$</p>
<p>Given a complex number $z$, we denote its <strong>normalization</strong> as
$$\operatorname{N}(z) :=
\begin{cases}
0 & \text{if }z=0,\\
z/\vert z\vert & \text{otherwise.}
\end{cases}
$$</p>
<h2>Challenge</h2>
<p>A staircase path between two points, informally, is any path by going only right or up.</p>
<p>Formally, given the starting point $s \in\mathbb{Z}^n$ and ending point $e \in\mathbb{Z}^n$ with $s\leq e$ (i.e., each component of $s$ is less than or equal to each corresponding component of $e$), a <strong>staircase path</strong> is a sequence of $\ell:=1+\Vert s-e\Vert_1$ coordinates $\sigma_0,\ldots,\sigma_{\ell}$ with the following facts:</p>
<ol>
<li><p>$\sigma_0 = s$,</p></li>
<li><p>$s\leq \sigma_k \leq e$ (in the sense described above), and</p></li>
<li><p>exactly one component of $\sigma_{k+1} - \sigma_k$ is $1$, with the other $n-1$ components equal to $0$.</p></li>
</ol>
<p>Denote the <strong>set of all staircase paths</strong> from $s$ to $e$ as $\{s\to e\}$.</p>
<p><strong>Part 1</strong>: Verify that facts 1–3 imply $\sigma_{\ell} = e$.</p>
<p>Next, consider the set $\mathbb{T}^{m\times n}$ defined as $n\times m$ matrices whose entries are complex numbers of <a href="https://en.wikipedia.org/wiki/Circle_group" >unit modulus</a>. For consistency with the above, let's suppose the bottom-left element of each matrix is identified by $(1,1)$ and top-right element is $(n, m)$.</p>
<p><strong>Part 2</strong>: Implement the function
$$f : \mathbb{T}^{m\times n}\to \mathbb{T}\cup\{0\}$$
defined by
$$f(M) := \operatorname{N}\left(\sum_{\Sigma\in\{(1,1)\to(m,n)\}}\prod_{(x,y)\in\Sigma} M_{x,y}\right).$$</p>
<p><strong>Extra Credit</strong>: Generalize $f$ to work on a tensor of any order.</p>
#36: Falling Leaves2018-02-082018-02-08Robert Smithhttp://www.watrophy.com<p>Imagine you have a $k$-ary rooted tree $T$ defined by the following diagram:</p>
<pre><code> [ A ]
[ / \ ]
[ B C ]
T := [ / \ / \ ].
[ D E F G ]
[ / \ \ ]
[ H I J ]</code></pre>
<p>The leaves of $T$ are
$$\operatorname{leaves}(T) := \{\mathtt{H}, \mathtt{I}, \mathtt{E}, \mathtt{J}, \mathtt{G}\}.$$
Imagine the leaves fall off though an operation called $\operatorname{fall}$
so that $\operatorname{fall}(T)$ is</p>
<pre><code> [ A ]
[ / \ ]
fall(T) = [ B C ].
[ / / ]
[ D F ]</code></pre>
<p>After another iteration, we get $\operatorname{fall}^2(T)$, which is</p>
<pre><code> [ A ]
fall²(T) = [ / \ ].
[ B C ]</code></pre>
<p>And $\operatorname{fall}^3(T) = \mathtt{A}$, the root.</p>
<p>Write a function which takes <em>any</em> $k$-ary rooted tree $T$ and prints
out the sequence
$$\ell_i(T) := \big(\operatorname{leaves}\circ\operatorname{fall}^i\big)(T)$$
for $0\leq i \leq n$ where $n$ is defined such that
$\operatorname{fall}^n(T)$ is the root of $T$. (Since it is a
sequence, it should be printed in order.)</p>
<p>For the example above, in somewhat abbreviated notation, we have
$$\ell(T) := (\mathtt{HIEJG}, \mathtt{DF}, \mathtt{BC}, \mathtt{A}).$$</p>
<p><em>Thanks to <a href="https://medium.com/@stevenheidel" >Steven Heidel</a> for
telling me about this wonderful problem.</em></p>
#35: All CARs and CDRs2018-02-062018-02-06Robert Smithhttp://www.watrophy.com<p>Most Lisps have combinations of <code>car</code> and <code>cdr</code> built in, usually up
to four levels deep, e.g., <code>caaddr</code> and <code>cdaddr</code> are built-ins
referring to</p>
<pre><code><span class="code"><span class="paren1">(<span class="code"><i><span class="symbol">lambda</span></i> <span class="paren2">(<span class="code">x</span>)</span> <span class="paren2">(<span class="code">car <span class="paren3">(<span class="code">car <span class="paren4">(<span class="code">cdr <span class="paren5">(<span class="code">cdr x</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
<span class="comment">; and
</span><span class="paren1">(<span class="code"><i><span class="symbol">lambda</span></i> <span class="paren2">(<span class="code">x</span>)</span> <span class="paren2">(<span class="code">cdr <span class="paren3">(<span class="code">car <span class="paren4">(<span class="code">cdr <span class="paren5">(<span class="code">cdr x</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span></code></pre>
<p>respectively. Implement a macro <code>(generate-cxr n)</code> which generates the
definitions of all <code>car</code>/<code>cdr</code> combinations up to <code>n</code> times.</p>
<p>If your language doesn't support macros or dynamic definitions, write
a function of the same name which produces a list of all <code>car</code>/<code>cdr</code>
combinations as anonymous functions.</p>
<p><strong>Extra Credit</strong>: Implement this as efficiently as possible, using the
least amount of space.</p>
#34: All Manner of Brackets2018-02-062018-02-06Robert Smithhttp://www.watrophy.com<p>We all know the problem of checking/counting parentheses pairs. This
time, given a list of open and close characters which must match each
other, check if the expression is valid. For example, consider the
following pairs:</p>
<pre><code>(defparameter *open-close-pairs*
'((#\( . #\))
(#\[ . #\])
(#\{ . #\})
(#\< . #\>)))</code></pre>
<p>Write a function <code>validate</code> which takes a string like <code>"({<>[()]}[])"</code>
and a table of open-close pairs and return a Boolean indicating the
validity of the string.</p>
#33: Random Arithmetic Problems2018-01-312018-01-31Robert Smithhttp://www.watrophy.com<h3>Part 1</h3>
<p>Write a function <code>random-expression</code> which generates a random math
expression built up by numbers, <code>+</code>, unary/binary <code>-</code>, <code>*</code>, <code>/</code>, <code>^</code>,
and <code>sqrt</code>. There should be two outputs: (1) the generated expression
in unevaluated form, and (2) the evaluated answer. Decide on and
explain your choice of arguments to <code>random-expression</code> to bound the
<em>size</em> of the expression.</p>
<p><em>Bonus</em>: Write this in both a dynamically typed language and a
strictly typed language.</p>
<h3>Part 2</h3>
<p>Extend <code>evaluate-expression</code> to take into account a variable called
<code>operator-table</code> which contains the operators used in random
generation and their arities. For example, the default table might
look like this in Common Lisp:</p>
<pre><code><span class="code"><span class="paren1">(<span class="code"><i><span class="symbol">defvar</span></i> <span class="special">*operator-table*</span>
'<span class="paren2">(<span class="code"><span class="paren3">(<span class="code">+ 2</span>)</span>
<span class="paren3">(<span class="code">- 1 2</span>)</span> <span class="comment">; unary and binary -
</span> <span class="paren3">(<span class="code">* 2</span>)</span>
<span class="paren3">(<span class="code">/ 2</span>)</span>
<span class="paren3">(<span class="code">expt 2</span>)</span>
<span class="paren3">(<span class="code">sqrt 1</span>)</span></span>)</span></span>)</span></span></code></pre>
<p>Feel free to add information to the table as you see fit.</p>
#32: Promises from Scratch2018-01-312018-01-31Robert Smithhttp://www.watrophy.com<p>In the <a href="1-Delayed-Evaluation.html" >first challenge</a>, we created a
syntactic primitive called a <em>thunk</em> to construct delayed
computations, which could later be run by simply calling them.</p>
<p>However, there is a slight problem. Suppose we make the following thunk:</p>
<pre><code><span class="code"><span class="paren1">(<span class="code"><a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-8.html#%_idx_190" class="symbol"><i><span class="symbol">define</span></i></a> x <span class="paren2">(<span class="code">thunk <span class="paren3">(<span class="code"><a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_idx_624" class="symbol">display</a> <span class="string">"Hello!"</span></span>)</span> <span class="paren3">(<span class="code"><a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_idx_278" class="symbol">+</a> 1 1</span>)</span></span>)</span></span>)</span></span></code></pre>
<p>Then when we run the thunk by doing <code>(x)</code> in Scheme or <code>(funcall x)</code>
in Common Lisp, it will print <code>"Hello!"</code> and compute <code>2</code> on each
invocation. In Common Lisp notation:</p>
<pre><code><span class="code"><span class="paren1">(<span class="code"><i><span class="symbol">defvar</span></i> <span class="special">*thunk*</span>
<span class="paren2">(<span class="code">thunk
<span class="paren3">(<span class="code">format t <span class="string">"Hello!"</span></span>)</span>
<span class="paren3">(<span class="code">+ 1 1</span>)</span></span>)</span></span>)</span>
<span class="paren1">(<span class="code">funcall <span class="special">*thunk*</span></span>)</span>
<span class="comment">; Prints: Hello!
</span> <span class="comment">; Returns: 2
</span>
<span class="paren1">(<span class="code">funcall <span class="special">*thunk*</span></span>)</span>
<span class="comment">; Prints: Hello!
</span> <span class="comment">; Returns: 2</span></span></code></pre>
<p>This may not be desirable if we want to simulate things such as
<a href="https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_need" >call-by-need</a>
evaluation semantics.</p>
<p>In this exercise, create two abstractions, <code>delay</code> and <code>force</code> to
ameliorate this issue. The <code>delay</code> abstraction should be similar to
<code>thunk</code> in that it creates a delayed computation using <code>lambda</code>. We
call the result of <code>delay</code> a <em>promise</em>.</p>
<p>The abstraction <code>force</code> is responsible now for actually evaluating the
promise and producing an answer. However, using <code>force</code> a second time
will give back a cached result.</p>
<p>Here's an example in Common Lisp notation:</p>
<pre><code><span class="code"><span class="paren1">(<span class="code"><i><span class="symbol">defvar</span></i> <span class="special">*promise*</span>
<span class="paren2">(<span class="code">delay
<span class="paren3">(<span class="code">format t <span class="string">"Hello!"</span></span>)</span>
<span class="paren3">(<span class="code">+ 1 1</span>)</span></span>)</span></span>)</span>
<span class="paren1">(<span class="code">force <span class="special">*promise*</span></span>)</span>
<span class="comment">; Prints: Hello!
</span> <span class="comment">; Returns: 2
</span>
<span class="paren1">(<span class="code">force <span class="special">*promise*</span></span>)</span>
<span class="comment">; Does not print.
</span> <span class="comment">; Returns: 2</span></span></code></pre>
#31: Aperiodic Tiling2018-01-302018-01-30Robert Smithhttp://www.watrophy.com<p><a href="https://en.wikipedia.org/wiki/Wang_tile" >Wang tiles</a> are a collection
of oriented squares with colored edges such that when you place the
squares side-by-side with matching colors, the plane will tile
aperiodically. That is to say, <em>without rotating or reflecting the
tiles</em>, when placed according to the color matching rule, repetitions
of tiles cannot occur within contiguous sections of the plane, as soon
as the sections are large enough.</p>
<p>Wang tiles are specified by listing their colors starting with the top edge and going clockwise. One set of Wang tiles consists of 13 tiles using 4 colors. The tiles are listed below.</p>
<pre><code>Wang Tiles
----------
RRRG
BRBG Example Tile: RGBW
RGGG
WBRB Red
BBWB +----+
WWRW | | Green
RGBW White | |
BWBR +----+
BRWR Blue
GGBR
RWRG</code></pre>
<h3>Part 1</h3>
<p>Write a program that generates a random $M\times N$ rectangle of Wang tiles.</p>
<h3>Part 2</h3>
<p>Suppose the <em>centers</em> of the squares are placed in the plane at
integer lattice points. Then we can identify each square in the plane
by its center.</p>
<p>Write a function <code>(spiral n)</code> which gives the $n$th coordinate of a
spiral starting at $(0, 0)$ to $(1, 0)$ and proceeding
counterclockwise. The first few values are:</p>
<pre><code>0 => (0, 0) 3 => (0, 1) 6 => (-1, -1)
1 => (1, 0) 4 => (-1, 1) 7 => (0, -1)
2 => (1, 1) 5 => (-1, 0) 8 => (1, -1)</code></pre>
<p>With this, write a function <code>(wang-spiral n)</code> which produces a Wang
tiling valid on the coordinates <code>(spiral 0)</code> to <code>(spiral (- n 1))</code>.</p>
<h3>Extra Credit</h3>
<p>Draw your artwork.</p>
#30: Combinator Practice2018-01-302018-01-30Robert Smithhttp://www.watrophy.com<p>In <a href="15-Simple-Combinators.html" >Challenge #15</a>, we wrote a few simple
combinators. Here we write a few more.</p>
<p>In addition to combinator practice, this exercise will be written so
as to practice math notation comprehension.</p>
<p>For each of these, implement the combinator and write the most general
type for that combinator.</p>
<ol>
<li><p>Combinator $C_1$ which "flips" the arguments of binary function. It
takes $f : X\times Y\to Z$ to $C_1 f = f' : Y \times X \to Z$ such
that for all $x\in X$ and $y \in Y$, $$f(x,y) = f'(y,x).$$ This
combinator is an <em>involution</em> because $C_1^2$ is the identity.</p></li>
<li><p>Combinator $C_2$ which duplicates an argument to a binary
function. It takes $f : X\times X\to Z$ to $C_2 g = f' : X \to Z$
such that for all $x\in X$, $$f(x,x) = f(x).$$</p></li>
<li><p>Combinator $C_3$ which takes two functions with the same domain
$X$, and produces a function taking $x\in X$ and returning $(f(x),
g(x))$.</p></li>
<li><p>Combinator $C_4$ which takes a function, and produces a <em>curried</em>
function of two arguments, such that the second argument supplied
is effectively ignored.</p></li>
</ol>
<p><em>Fun Fact</em>: In Haskell, the combinators above are called <code>flip</code>, <code>join</code>,
<code>liftM2 (,)</code>, and <code>(const .)</code> respectively.</p>
#29: Multiplying Long-Hand2018-01-302018-01-30Robert Smithhttp://www.watrophy.com<p>Modern CPUs only support multiplying integers of a fixed size, which
is usually 32- or 64-bits.</p>
<p>In grade school, most of us learned how to multiply numbers long-hand;
we write the two numbers down, one above the other, and proceed to do
the multiplication. It often looks like so:</p>
<pre><code>
123
x 45
----
615
+ 492
------
5535</code></pre>
<p>If you've forgotten this method for multiplying, you might consult a
children's arithmetic book.</p>
<p>The goal of this exercise is to implement the long multiplication
algorithm. While not required, it is certainly convenient if your
language supports arbitrary precision integers out of the box.</p>
<h3>Part 1</h3>
<p>As testing utilities, write two functions:</p>
<ul>
<li><p><code>(digits n)</code> which takes a non-negative integer and produces a
list of base-10 digits from least to most significant. For
example, <code>(digits 123)</code> shall return <code>(3 2 1)</code>. Decide on what
<code>(digits 0)</code> should be.</p></li>
<li><p><code>(undigits dlist)</code> which does the opposite: takes a list of digits
and produces a non-negative integer.</p></li>
</ul>
<p>Furthermore, answer the following questions:</p>
<ul>
<li><p>Is any list of digits a valid representation of a non-negative integer?</p></li>
<li><p>What is the <em>precise</em> relationship between <code>digits</code> and <code>undigits</code>?</p></li>
</ul>
<h3>Part 2</h3>
<p>Implement the long multiplication algorithm as a function
<code>long-multiply</code> which takes two lists of base-10 numbers and produces
a list representing the product.</p>
<h3>Part 3</h3>
<p>Modify <code>long-multiply</code> to print out what the process might look like
with pencil and paper. For example:</p>
<pre><code><span class="code"><span class="paren1">(<span class="code">display-long-multiply '<span class="paren2">(<span class="code">3 2 1</span>)</span> '<span class="paren2">(<span class="code">5 4</span>)</span></span>)</span>
<span class="comment">; Outputs:
</span><span class="comment">;
</span><span class="comment">; 123
</span><span class="comment">; x 45
</span><span class="comment">; ----
</span><span class="comment">; 615
</span><span class="comment">; + 492
</span><span class="comment">; ------
</span><span class="comment">; 5535</span></span></code></pre>
<h3>Part 4</h3>
<p>If you implemented the previous parts successfully, you may not have
done so with absolute mathematical correctness. Without loss of
generality, suppose we are multiplying two $N$-digit numbers. Then, in
the second step of the algorithm, we will produce the $N$ terms that
we need to add up. When we perform the addition in each column, each
of which consist of at most $N$ base-10 digits, our sum will likely
exceed our digit size.</p>
<p>Answer these questions:</p>
<ol>
<li><p>What is the maximum size of a number we could sum to in a column?</p></li>
<li><p>What is an example of two numbers whose multiplication process
leads to that sum?</p></li>
<li><p>If we are truly constrained on a computer where every storable
register, be it in the processor or RAM, is limited to holding a
digit between 0 and 9, how can we modify the algorithm to
accommodate?</p></li>
</ol>
<p>Finally, perform the modifications to the algorithm.</p>