A spiral of length $n\ge 1$ is a counterclockwise spiral starting at $(0,0)$ extending to the right to $(n,0)$, wrapping around so as to cover $\mathbb{Z}^2$ completely.
Consider the following spiral of length $2$.
******
 
* **** *
  (0,0)  
* * x*x *
  (2,0) 
* *****

****** ...
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.
There are three challenges. Given an $n\ge 1$, do the following.
Given a $k\ge 0$, find $s_k$.
Given a point $(\alpha, \beta)\in\mathbb{Z}^2$, find the $k$ such that $s_k = (\alpha,\beta)$.
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.)
The symbol $\mathbb{Z}^n$ denotes the set of all coordinate $n$tuples with integer components. These are one kind of $n$dimensional lattice.
Given two points $s=(s_1,\ldots, s_n)$ and $e=(e_1, \ldots, e_n)$, their taxicab distance is $$\Vert se\Vert_1 := \sum_{i=1}^n\vert s_ie_i\vert.$$
Given a complex number $z$, we denote its normalization as $$\operatorname{N}(z) := \begin{cases} 0 & \text{if }z=0,\\ z/\vert z\vert & \text{otherwise.} \end{cases} $$
A staircase path between two points, informally, is any path by going only right or up.
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 staircase path is a sequence of $\ell:=1+\Vert se\Vert_1$ coordinates $\sigma_0,\ldots,\sigma_{\ell}$ with the following facts:
$\sigma_0 = s$,
$s\leq \sigma_k \leq e$ (in the sense described above), and
exactly one component of $\sigma_{k+1}  \sigma_k$ is $1$, with the other $n1$ components equal to $0$.
Denote the set of all staircase paths from $s$ to $e$ as $\{s\to e\}$.
Part 1: Verify that facts 1–3 imply $\sigma_{\ell} = e$.
Next, consider the set $\mathbb{T}^{m\times n}$ defined as $n\times m$ matrices whose entries are complex numbers of unit modulus. For consistency with the above, let's suppose the bottomleft element of each matrix is identified by $(1,1)$ and topright element is $(n, m)$.
Part 2: 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).$$
Extra Credit: Generalize $f$ to work on a tensor of any order.
]]> [ A ]
[ / \ ]
[ B C ]
T := [ / \ / \ ].
[ D E F G ]
[ / \ \ ]
[ H I J ]
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
[ A ]
[ / \ ]
fall(T) = [ B C ].
[ / / ]
[ D F ]
After another iteration, we get $\operatorname{fall}^2(T)$, which is
[ A ]
fall²(T) = [ / \ ].
[ B C ]
And $\operatorname{fall}^3(T) = \mathtt{A}$, the root.
Write a function which takes any $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.)
For the example above, in somewhat abbreviated notation, we have $$\ell(T) := (\mathtt{HIEJG}, \mathtt{DF}, \mathtt{BC}, \mathtt{A}).$$
Thanks to Steven Heidel for telling me about this wonderful problem.
]]>car
and cdr
built in, usually up
to four levels deep, e.g., caaddr
and cdaddr
are builtins
referring to
(lambda (x) (car (car (cdr (cdr x)))))
; and
(lambda (x) (cdr (car (cdr (cdr x)))))
respectively. Implement a macro (generatecxr n)
which generates the
definitions of all car
/cdr
combinations up to n
times.
If your language doesn't support macros or dynamic definitions, write
a function of the same name which produces a list of all car
/cdr
combinations as anonymous functions.
Extra Credit: Implement this as efficiently as possible, using the least amount of space.
]]>(defparameter *openclosepairs*
'((#\( . #\))
(#\[ . #\])
(#\{ . #\})
(#\< . #\>)))
Write a function validate
which takes a string like "({<>[()]}[])"
and a table of openclose pairs and return a Boolean indicating the
validity of the string.
Write a function randomexpression
which generates a random math
expression built up by numbers, +
, unary/binary 
, *
, /
, ^
,
and sqrt
. 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 randomexpression
to bound the
size of the expression.
Bonus: Write this in both a dynamically typed language and a strictly typed language.
Extend evaluateexpression
to take into account a variable called
operatortable
which contains the operators used in random
generation and their arities. For example, the default table might
look like this in Common Lisp:
(defvar *operatortable*
'((+ 2)
( 1 2) ; unary and binary 
(* 2)
(/ 2)
(expt 2)
(sqrt 1)))
Feel free to add information to the table as you see fit.
]]>However, there is a slight problem. Suppose we make the following thunk:
(define x (thunk (display "Hello!") (+ 1 1)))
Then when we run the thunk by doing (x)
in Scheme or (funcall x)
in Common Lisp, it will print "Hello!"
and compute 2
on each
invocation. In Common Lisp notation:
(defvar *thunk*
(thunk
(format t "Hello!")
(+ 1 1)))
(funcall *thunk*)
; Prints: Hello!
; Returns: 2
(funcall *thunk*)
; Prints: Hello!
; Returns: 2
This may not be desirable if we want to simulate things such as callbyneed evaluation semantics.
In this exercise, create two abstractions, delay
and force
to
ameliorate this issue. The delay
abstraction should be similar to
thunk
in that it creates a delayed computation using lambda
. We
call the result of delay
a promise.
The abstraction force
is responsible now for actually evaluating the
promise and producing an answer. However, using force
a second time
will give back a cached result.
Here's an example in Common Lisp notation:
(defvar *promise*
(delay
(format t "Hello!")
(+ 1 1)))
(force *promise*)
; Prints: Hello!
; Returns: 2
(force *promise*)
; Does not print.
; Returns: 2
]]>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.
Wang Tiles

RRRG
BRBG Example Tile: RGBW
RGGG
WBRB Red
BBWB ++
WWRW   Green
RGBW White  
BWBR ++
BRWR Blue
GGBR
RWRG
Write a program that generates a random $M\times N$ rectangle of Wang tiles.
Suppose the centers of the squares are placed in the plane at integer lattice points. Then we can identify each square in the plane by its center.
Write a function (spiral n)
which gives the $n$th coordinate of a
spiral starting at $(0, 0)$ to $(1, 0)$ and proceeding
counterclockwise. The first few values are:
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)
With this, write a function (wangspiral n)
which produces a Wang
tiling valid on the coordinates (spiral 0)
to (spiral ( n 1))
.
Draw your artwork.
]]>In addition to combinator practice, this exercise will be written so as to practice math notation comprehension.
For each of these, implement the combinator and write the most general type for that combinator.
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 involution because $C_1^2$ is the identity.
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).$$
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))$.
Combinator $C_4$ which takes a function, and produces a curried function of two arguments, such that the second argument supplied is effectively ignored.
Fun Fact: In Haskell, the combinators above are called flip
, join
,
liftM2 (,)
, and (const .)
respectively.
In grade school, most of us learned how to multiply numbers longhand; we write the two numbers down, one above the other, and proceed to do the multiplication. It often looks like so:
123
x 45

615
+ 492

5535
If you've forgotten this method for multiplying, you might consult a children's arithmetic book.
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.
As testing utilities, write two functions:
(digits n)
which takes a nonnegative integer and produces a
list of base10 digits from least to most significant. For
example, (digits 123)
shall return (3 2 1)
. Decide on what
(digits 0)
should be.
(undigits dlist)
which does the opposite: takes a list of digits
and produces a nonnegative integer.
Furthermore, answer the following questions:
Is any list of digits a valid representation of a nonnegative integer?
What is the precise relationship between digits
and undigits
?
Implement the long multiplication algorithm as a function
longmultiply
which takes two lists of base10 numbers and produces
a list representing the product.
Modify longmultiply
to print out what the process might look like
with pencil and paper. For example:
(displaylongmultiply '(3 2 1) '(5 4))
; Outputs:
;
; 123
; x 45
; 
; 615
; + 492
; 
; 5535
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$ base10 digits, our sum will likely exceed our digit size.
Answer these questions:
What is the maximum size of a number we could sum to in a column?
What is an example of two numbers whose multiplication process leads to that sum?
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?
Finally, perform the modifications to the algorithm.
]]>