<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://quuxplusone.github.io/blog/feed.xml" rel="self" type="application/atom+xml" /><link href="https://quuxplusone.github.io/blog/" rel="alternate" type="text/html" /><updated>2026-10-12T16:40:25+00:00</updated><id>https://quuxplusone.github.io/blog/feed.xml</id><title type="html">Arthur O’Dwyer</title><subtitle>Stuff mostly about C++</subtitle><entry><title type="html">Is a sized random-access range always common?</title><link href="https://quuxplusone.github.io/blog/2026/10/12/sized-random-access-range/" rel="alternate" type="text/html" title="Is a sized random-access range always common?" /><published>2026-10-12T00:01:00+00:00</published><updated>2026-10-12T00:01:00+00:00</updated><id>https://quuxplusone.github.io/blog/2026/10/12/sized-random-access-range</id><content type="html" xml:base="https://quuxplusone.github.io/blog/2026/10/12/sized-random-access-range/"><![CDATA[<p><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3411r6.html#proposed-design">P3411R6 <code class="language-plaintext highlighter-rouge">any_view</code></a>
proposes for C++29 a design for a type-erased Ranges view. The idea (as usual with type erasure) is
to permit replacing templated code like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>template&lt;std::ranges::range R&gt;
void f(R&amp;&amp; rg) {
  bool b = std::ranges::is_heap(rg, std::greater&lt;&gt;());
  assert(b);
}

int a[] = {1,2,3,4,5};
std::vector&lt;int&gt; v = {1,2,3,4,5};
f(a);
f(v);
f(std::views::iota(1, 6));
f(std::vector&lt;int&gt;{1,2,3,4,5});
</code></pre></div></div>

<p>with non-templated code like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// This is not a function template!
void g(std::ranges::any_view&lt;int, std::ranges::any_view_options::random_access, int&gt; rg) {
  bool b = std::ranges::is_heap(rg, std::greater&lt;&gt;());
  assert(b);
}

g(a);
g(v);
g(std::views::iota(1, 6));
g(std::vector&lt;int&gt;{1,2,3,4,5});
</code></pre></div></div>

<p>Because there are so many different flavors of range, <code class="language-plaintext highlighter-rouge">any_view</code> takes a few template parameters
to specify what kind of range you mean — just like <code class="language-plaintext highlighter-rouge">std::function</code> takes a function signature as
a template parameter to specify what kind of function you mean. In the example above, we specify
that <code class="language-plaintext highlighter-rouge">g</code> takes a type-erased copy of a <em>random-access</em> view <em>of a range of <code class="language-plaintext highlighter-rouge">int</code></em>. The third template
parameter forces the copy’s <code class="language-plaintext highlighter-rouge">reference</code> type to <code class="language-plaintext highlighter-rouge">int</code> (as opposed to <code class="language-plaintext highlighter-rouge">int&amp;</code> or <code class="language-plaintext highlighter-rouge">const int&amp;</code>), for the
benefit of <code class="language-plaintext highlighter-rouge">views::iota</code>.</p>

<p><code class="language-plaintext highlighter-rouge">any_view</code> inherits from <code class="language-plaintext highlighter-rouge">std::ranges::view_interface,</code> so it gets many convenient
member functions for free. For example,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>using enum std::ranges::any_view_options;
void g(std::ranges::any_view&lt;int, random_access, int&gt; rg) {
  assert(rg.front() == 1);
}
</code></pre></div></div>

<p>because <code class="language-plaintext highlighter-rouge">view_interface</code> provides <a href="https://en.cppreference.com/cpp/ranges/view_interface/front"><code class="language-plaintext highlighter-rouge">front</code></a>
whenever its iterator category is forward-or-better.
Recently on <a href="https://lists.isocpp.org/std-proposals/2026/10/19191.php">std-proposals</a> it was
noted that <code class="language-plaintext highlighter-rouge">back</code> is different:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>void h(std::ranges::any_view&lt;int, random_access | sized, int&gt; rg) {
  assert(rg.back() == 5);  // error
}
</code></pre></div></div>

<p>You might think <code class="language-plaintext highlighter-rouge">rg.back()</code> would be defined as equivalent to <code class="language-plaintext highlighter-rouge">rg[rg.size()-1]</code> — perfectly
well-defined for a <em>sized random-access</em> range as we have here — but in fact it’s defined as
<code class="language-plaintext highlighter-rouge">*prev(rg.end())</code>, which is well-defined only for <em>common bidirectional</em> ranges. (Recall that a <em>common</em> range
is one where <code class="language-plaintext highlighter-rouge">end()</code> returns the same iterator type as <code class="language-plaintext highlighter-rouge">begin()</code>, so that <code class="language-plaintext highlighter-rouge">prev(end())</code> is legal. For a general,
non-common, range, <code class="language-plaintext highlighter-rouge">end()</code> is allowed to return a sentinel that doesn’t support arithmetic.)</p>

<hr />

<p>The problem is already addressed inside the <code class="language-plaintext highlighter-rouge">views::common</code> adaptor itself. Ordinarily, to make a non-common
range into a <code class="language-plaintext highlighter-rouge">common_view</code>, you basically have to turn every iterator into a variant — a
<a href="https://eel.is/c++draft/iterators.common"><code class="language-plaintext highlighter-rouge">common_iterator&lt;I, S&gt;</code></a> — that can hold either an iterator
<em>or</em> a sentinel, and you represent <code class="language-plaintext highlighter-rouge">views::common(rg).end()</code> as <code class="language-plaintext highlighter-rouge">common_iterator&lt;I, S&gt;(rg.end())</code>.
Since a <code class="language-plaintext highlighter-rouge">common_iterator</code> value might hold a sentinel, <code class="language-plaintext highlighter-rouge">common_iterator</code> itself can’t support decrement;
it is always at best a forward iterator. <em>But,</em> in the special case where <code class="language-plaintext highlighter-rouge">rg</code> is a sized random-access range,
<code class="language-plaintext highlighter-rouge">views::common(rg)</code> does <em>not</em> use <code class="language-plaintext highlighter-rouge">common_iterator</code>: in that case <code class="language-plaintext highlighter-rouge">views::common(rg).end()</code> is represented
as <code class="language-plaintext highlighter-rouge">rg.begin() + rg.size()</code>. <a href="https://godbolt.org/z/W9rjxh93f">Godbolt</a>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct UnsizedRA {
  int *begin();
  std::unreachable_sentinel_t end();
};
UnsizedRA r1;
std::forward_iterator auto it1 = std::views::common(r1).begin();
static_assert(sizeof(it1) &gt; sizeof(int*));

struct SizedRA {
  int *begin();
  std::unreachable_sentinel_t end();
  int size() const;
};
SizedRA r2;
std::same_as&lt;int*&gt; auto it2 = std::views::common(r2).begin();
</code></pre></div></div>

<p>So, from the C++ user’s perspective, the way to deal with the absence of <code class="language-plaintext highlighter-rouge">any_view::back()</code>
in this odd corner case is simply to feed your sized random-access <code class="language-plaintext highlighter-rouge">any_view</code> to <code class="language-plaintext highlighter-rouge">views::common</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>void h(std::ranges::any_view&lt;int, random_access | sized, int&gt; rgin) {
  auto rg = std::views::common(std::move(rgin));
  static_assert(std::random_access_range&lt;decltype(rg)&gt;);
  static_assert(std::sized_range&lt;decltype(rg)&gt;);
  assert(rg.back() == 5);  // OK
}
</code></pre></div></div>

<hr />

<p><a href="https://cplusplus.github.io/LWG/issue4003">LWG 4003</a> asked whether we should “improve” the
definition of <code class="language-plaintext highlighter-rouge">view_interface::back()</code> so that it’d work if <em>either</em> of the expressions
<code class="language-plaintext highlighter-rouge">*prev(rg.end())</code> or <code class="language-plaintext highlighter-rouge">rg[rg.size()-1]</code> were valid. However, that direction was rejected, because
it was rightly pointed out that while this would solve the inconsistency in the API of <code class="language-plaintext highlighter-rouge">view_interface</code>
(and therefore <code class="language-plaintext highlighter-rouge">any_view</code>), it wouldn’t solve the basic inconsistency that right now the C++ user
can create a range type (like <code class="language-plaintext highlighter-rouge">SizedRA</code> above) that is</p>

<ul>
  <li>random-access,</li>
  <li>sized,</li>
  <li>but not common.</li>
</ul>

<p>Unfortunately, the library can’t exactly <em>forbid</em> such a type. At best it could amend some concept
definitions so that <code class="language-plaintext highlighter-rouge">SizedRA</code> would fail to be a <code class="language-plaintext highlighter-rouge">sized_range</code> — but that seems silly, because
<code class="language-plaintext highlighter-rouge">SizedRA</code> definitely <em>does</em> provide <code class="language-plaintext highlighter-rouge">size()</code>, and failing to recognize that fact would just
silently pessimize a bunch of Ranges algorithms.</p>

<blockquote>
  <p>I have the same pet peeve about <code class="language-plaintext highlighter-rouge">random_access_range</code>’s requiring <code class="language-plaintext highlighter-rouge">operator[]</code>. If you forget
to provide it, then your type just quietly degrades to a bidirectional range, pessimizing
some algorithms but not necessarily failing to compile.</p>
</blockquote>

<p>Alternatively — but this is a crazy idea — the library might amend the definition of
<a href="https://eel.is/c++draft/range.access#end"><code class="language-plaintext highlighter-rouge">ranges::end(rg)</code></a> to return a different type in this case,
so that <code class="language-plaintext highlighter-rouge">SizedRA</code> would become a common range! Given the current wording:</p>

<blockquote>
  <p>Given a subexpression E with type <code class="language-plaintext highlighter-rouge">T</code>, let <code class="language-plaintext highlighter-rouge">t</code> be an lvalue that denotes the reified object for <code class="language-plaintext highlighter-rouge">E</code>. Then:</p>
  <ul>
    <li>[…] if <code class="language-plaintext highlighter-rouge">T</code> is an array type, <code class="language-plaintext highlighter-rouge">ranges::end(E)</code> is expression-equivalent to <code class="language-plaintext highlighter-rouge">t + extent_v&lt;T&gt;</code>.</li>
    <li>Otherwise, if <code class="language-plaintext highlighter-rouge">auto(t.end())</code> is a valid expression whose type models <code class="language-plaintext highlighter-rouge">sentinel_for&lt;iterator_t&lt;T&gt;&gt;</code>, then <code class="language-plaintext highlighter-rouge">ranges::end(E)</code> is expression-equivalent to <code class="language-plaintext highlighter-rouge">auto(t.end())</code>.</li>
    <li>Otherwise, if <code class="language-plaintext highlighter-rouge">T</code> is a class or enumeration type and <code class="language-plaintext highlighter-rouge">auto(end(t))</code> is a valid expression
  whose type models <code class="language-plaintext highlighter-rouge">sentinel_for&lt;iterator_t&lt;T&gt;&gt;</code> […] then <code class="language-plaintext highlighter-rouge">ranges::end(E)</code> is expression-equivalent to that expression.</li>
  </ul>
</blockquote>

<p>we might remove the first bullet point and then add one at the end like:</p>

<ul>
  <li>[…] if <code class="language-plaintext highlighter-rouge">ranges::begin(t) + ranges::size(t)</code> is a valid expression whose type
  is <code class="language-plaintext highlighter-rouge">iterator_t&lt;T&gt;</code>, then <code class="language-plaintext highlighter-rouge">ranges::end(E)</code> is expression-equivalent to that expression.</li>
</ul>

<p>I say “remove the first” because <code class="language-plaintext highlighter-rouge">ranges::size(t)</code> is already equivalent to <code class="language-plaintext highlighter-rouge">extent_v&lt;T&gt;</code> when <code class="language-plaintext highlighter-rouge">T</code> is an array type;
this amendment would just generalize the array case. Core-language arrays are already a kind of type
that provide a <code class="language-plaintext highlighter-rouge">begin</code> (sort of) but no iterator-returning <code class="language-plaintext highlighter-rouge">end</code> (in fact, no <code class="language-plaintext highlighter-rouge">end</code> at all); this amendment
would handle other kinds of ranges that provide a <code class="language-plaintext highlighter-rouge">begin</code> but no iterator-returning <code class="language-plaintext highlighter-rouge">end</code>.</p>

<p>I say “add one at the end” because <a href="https://eel.is/c++draft/range.access#range.prim.size-2.5"><code class="language-plaintext highlighter-rouge">ranges::size</code></a> itself
already has a bullet point defining <code class="language-plaintext highlighter-rouge">ranges::size(rg)</code> in terms of <code class="language-plaintext highlighter-rouge">ranges::end(rg) - ranges::begin(rg)</code>, and
we don’t want a circular dependency there. The bullet point in <code class="language-plaintext highlighter-rouge">ranges::size</code> basically enforces that any
<em>random-access common</em> range is by definition <em>sized</em> (as long as you go through <code class="language-plaintext highlighter-rouge">ranges::size</code> instead of <code class="language-plaintext highlighter-rouge">t.size()</code>);
the proposed bullet point here would enforce that any <em>random-access sized</em> range is by definition <em>common</em>
(as long as you go through <code class="language-plaintext highlighter-rouge">ranges::end</code> instead of <code class="language-plaintext highlighter-rouge">t.end()</code>).</p>

<p>One obvious problem — and I bet there are also less obvious ones — is that the amendment above would make</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct NotCurrentlyARange {
  int *begin();
  int size();
};
</code></pre></div></div>

<p>into a Ranges <code class="language-plaintext highlighter-rouge">range</code>, even though it wouldn’t be iterable by a core-language <code class="language-plaintext highlighter-rouge">for</code>-loop. The
mismatch between core-language ranges and library Ranges is already arguably a problem: see
<a href="/blog/2024/12/09/foreach-versus-for/">“When <code class="language-plaintext highlighter-rouge">ranges::for_each</code> behaves differently from <code class="language-plaintext highlighter-rouge">for</code>”</a> (2024-12-09).
Let’s not make the existing problem worse!</p>

<hr />

<p>Since piping a sized random-access range through <code class="language-plaintext highlighter-rouge">views::common</code> already Does The Right Thing, and since
trying to use <code class="language-plaintext highlighter-rouge">back()</code> on an <code class="language-plaintext highlighter-rouge">any_view</code> is already a super niche problem, I’m inclined to think the
status quo is perfectly acceptable. But, at the same time, since we can’t forbid types like <code class="language-plaintext highlighter-rouge">SizedRA</code> at the language level,
and since trying to “fix” them at the level of <code class="language-plaintext highlighter-rouge">ranges::end</code> is crazy, and since <code class="language-plaintext highlighter-rouge">view_interface::back</code>
admittedly doesn’t work quite right… why <em>not</em> just fix <code class="language-plaintext highlighter-rouge">view_interface::back</code> in the way
<a href="https://cplusplus.github.io/LWG/issue4003">LWG 4003</a> originally proposed?</p>]]></content><author><name></name></author><category term="library-design" /><category term="proposal" /><category term="ranges" /><category term="type-erasure" /><summary type="html"><![CDATA[P3411R6 any_view proposes for C++29 a design for a type-erased Ranges view. The idea (as usual with type erasure) is to permit replacing templated code like this:]]></summary></entry><entry><title type="html">Recursive `make` and `-j`</title><link href="https://quuxplusone.github.io/blog/2026/09/30/recursive-make-j/" rel="alternate" type="text/html" title="Recursive `make` and `-j`" /><published>2026-09-30T00:01:00+00:00</published><updated>2026-09-30T00:01:00+00:00</updated><id>https://quuxplusone.github.io/blog/2026/09/30/recursive-make-j</id><content type="html" xml:base="https://quuxplusone.github.io/blog/2026/09/30/recursive-make-j/"><![CDATA[<p>Today I looked into “recursive” invocations of <code class="language-plaintext highlighter-rouge">make</code>; that is, cases in which a Makefile
recipe itself invokes <code class="language-plaintext highlighter-rouge">make</code>.
<a href="https://www.gnu.org/software/make/manual/make.html#Recursion">The official documentation</a>
is quite good, but since I’m working with a range of different GNU Make versions, I looked
at how the behavior has changed over time, from GNU Make 3.81 to 4.3.</p>

<p>Basically, the issue is that if you have a recipe in your Makefile like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ser:
    make -C subdir
</code></pre></div></div>

<p>and then you run <code class="language-plaintext highlighter-rouge">make -j4 ser</code>, recent versions of GNU Make will give a warning
(<code class="language-plaintext highlighter-rouge">jobserver unavailable: using -j1</code>). And you’ll lose the parallelism you wanted,
because the “jobserver” (basically, the <code class="language-plaintext highlighter-rouge">-j</code> option) isn’t forwarded to the child <code class="language-plaintext highlighter-rouge">make</code>.
And, incidentally, it won’t necessarily use the same <code class="language-plaintext highlighter-rouge">make</code> binary that <em>you</em> invoked;
it’ll run whatever <code class="language-plaintext highlighter-rouge">make</code> happens to be in your path.</p>

<p>You can fix all three of those issues by prefixing <code class="language-plaintext highlighter-rouge">+</code> to the recipe line,
or (since that feels uncomfortably magical) replacing <code class="language-plaintext highlighter-rouge">make</code> with <code class="language-plaintext highlighter-rouge">$(MAKE)</code>.
More on this at the end of the post. Now that we’re forwarding the “jobserver”
properly, I wondered, how <em>exactly</em> do the various <code class="language-plaintext highlighter-rouge">-j</code> options interact,
when you specify one degree of parallelism on the command line and another
in the recursive recipe?</p>

<p>Here’s the pair of Makefiles I used for my test:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>detab -E -4 - &gt;Makefile &lt;&lt;EOF
ser:
    make -C subdir
par2:
    make -j2 -C subdir
par4:
    make -j4 -C subdir
par:
    make -j -C subdir
serplus:
    +make -C subdir
par2plus:
    +make -j2 -C subdir
par4plus:
    +make -j4 -C subdir
parplus:
    +make -j -C subdir
sermake:
    $(MAKE) -C subdir
par2make:
    $(MAKE) -j2 -C subdir
par4make:
    $(MAKE) -j4 -C subdir
parmake:
    $(MAKE) -j -C subdir
EOF
mkdir subdir
detab -E -4 - &gt;subdir/Makefile &lt;&lt;EOF
all: one two three four five
one:
    echo 'one' &amp;&amp; sleep 1 &amp;&amp; echo 'ONE'
two:
    echo 'two' &amp;&amp; sleep 1 &amp;&amp; echo 'TWO'
three:
    echo 'thr' &amp;&amp; sleep 1 &amp;&amp; echo 'THR'
four:
    echo 'fou' &amp;&amp; sleep 1 &amp;&amp; echo 'FOU'
five:
    echo 'fiv' &amp;&amp; sleep 1 &amp;&amp; echo 'FIV'
EOF
</code></pre></div></div>

<p>Then I tested running <code class="language-plaintext highlighter-rouge">make ser</code>, <code class="language-plaintext highlighter-rouge">make -j2 ser</code>, etc., on
various versions of Make available to me.</p>

<p>Here’s GNU Make 3.81 (on OS X). The number in each cell indicates
the number of recipes running in parallel. The four rows marked with a dagger †
differ among the versions of Make I tested; those idioms are
“non-portable” and IMHO should be avoided in practice.</p>

<table>
  <thead>
    <tr>
      <th><code class="language-plaintext highlighter-rouge">make</code>…</th>
      <th> </th>
      <th><code class="language-plaintext highlighter-rouge">-j2</code></th>
      <th><code class="language-plaintext highlighter-rouge">-j4</code></th>
      <th><code class="language-plaintext highlighter-rouge">-j</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ser</code><sup>†</sup></td>
      <td>1</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">serplus</code></td>
      <td>1</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sermake</code></td>
      <td>1</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par2</code></td>
      <td>2</td>
      <td>2<sup>b</sup></td>
      <td>2<sup>b</sup></td>
      <td>2</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par2plus</code></td>
      <td>2</td>
      <td>2<sup>b</sup></td>
      <td>2<sup>b</sup></td>
      <td>2</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par2make</code></td>
      <td>2</td>
      <td>2<sup>b</sup></td>
      <td>2<sup>b</sup></td>
      <td>2</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par4</code></td>
      <td>4</td>
      <td>4<sup>b</sup></td>
      <td>4<sup>b</sup></td>
      <td>4</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par4plus</code></td>
      <td>4</td>
      <td>4<sup>b</sup></td>
      <td>4<sup>b</sup></td>
      <td>4</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par4make</code></td>
      <td>4</td>
      <td>4<sup>b</sup></td>
      <td>4<sup>b</sup></td>
      <td>4</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par</code><sup>†</sup></td>
      <td>∞</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">parplus</code><sup>†</sup></td>
      <td>∞</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">parmake</code><sup>†</sup></td>
      <td>∞</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
  </tbody>
</table>

<p>In the table above, “b” indicates this warning:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ make -j2 par2
make[1]: warning: -jN forced in submake: disabling jobserver mode.
</code></pre></div></div>

<p>GNU Make 4.0 (on Debian 8.11):</p>

<table>
  <thead>
    <tr>
      <th><code class="language-plaintext highlighter-rouge">make</code>…</th>
      <th> </th>
      <th><code class="language-plaintext highlighter-rouge">-j2</code></th>
      <th><code class="language-plaintext highlighter-rouge">-j4</code></th>
      <th><code class="language-plaintext highlighter-rouge">-j</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ser</code><sup>†</sup></td>
      <td>1</td>
      <td>1<sup>a</sup></td>
      <td>1<sup>a</sup></td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">serplus</code></td>
      <td>1</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sermake</code></td>
      <td>1</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par2</code></td>
      <td>2</td>
      <td>2<sup>b</sup></td>
      <td>2<sup>b</sup></td>
      <td>2</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par2plus</code></td>
      <td>2</td>
      <td>2<sup>b</sup></td>
      <td>2<sup>b</sup></td>
      <td>2</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par2make</code></td>
      <td>2</td>
      <td>2<sup>b</sup></td>
      <td>2<sup>b</sup></td>
      <td>2</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par4</code></td>
      <td>4</td>
      <td>4<sup>b</sup></td>
      <td>4<sup>b</sup></td>
      <td>4</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par4plus</code></td>
      <td>4</td>
      <td>4<sup>b</sup></td>
      <td>4<sup>b</sup></td>
      <td>4</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par4make</code></td>
      <td>4</td>
      <td>4<sup>b</sup></td>
      <td>4<sup>b</sup></td>
      <td>4</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par</code><sup>†</sup></td>
      <td>∞</td>
      <td>1<sup>a</sup></td>
      <td>1<sup>a</sup></td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">parplus</code><sup>†</sup></td>
      <td>∞</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">parmake</code><sup>†</sup></td>
      <td>∞</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
  </tbody>
</table>

<p>In the table above, “a” and “b” indicate these two warnings, respectively:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ make -j2 ser
make[1]: warning: jobserver unavailable: using -j1.  Add '+' to parent make rule.

$ make -j2 par2
make[1]: warning: -jN forced in submake: disabling jobserver mode.
</code></pre></div></div>

<p>GNU Make 4.2.1 (on Rocky 8.10) and GNU Make 4.3 (on Red Hat 9 or Ubuntu 22.04)
tweak the latter error message to include the value of <code class="language-plaintext highlighter-rouge">N</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ make -j2 par
make[1]: warning: -j0 forced in submake: resetting jobserver mode.
$ make -j2 par2
make[1]: warning: -j2 forced in submake: resetting jobserver mode.
</code></pre></div></div>

<p>and also change the behavior of rows <code class="language-plaintext highlighter-rouge">par</code>, <code class="language-plaintext highlighter-rouge">parplus</code>, and <code class="language-plaintext highlighter-rouge">parmake</code>:</p>

<table>
  <thead>
    <tr>
      <th><code class="language-plaintext highlighter-rouge">make</code>…</th>
      <th> </th>
      <th><code class="language-plaintext highlighter-rouge">-j2</code></th>
      <th><code class="language-plaintext highlighter-rouge">-j4</code></th>
      <th><code class="language-plaintext highlighter-rouge">-j</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ser</code><sup>†</sup></td>
      <td>1</td>
      <td>1<sup>a</sup></td>
      <td>1<sup>a</sup></td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">serplus</code></td>
      <td>1</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sermake</code></td>
      <td>1</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par2</code></td>
      <td>2</td>
      <td>2<sup>b</sup></td>
      <td>2<sup>b</sup></td>
      <td>2</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par2plus</code></td>
      <td>2</td>
      <td>2<sup>b</sup></td>
      <td>2<sup>b</sup></td>
      <td>2</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par2make</code></td>
      <td>2</td>
      <td>2<sup>b</sup></td>
      <td>2<sup>b</sup></td>
      <td>2</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par4</code></td>
      <td>4</td>
      <td>4<sup>b</sup></td>
      <td>4<sup>b</sup></td>
      <td>4</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par4plus</code></td>
      <td>4</td>
      <td>4<sup>b</sup></td>
      <td>4<sup>b</sup></td>
      <td>4</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par4make</code></td>
      <td>4</td>
      <td>4<sup>b</sup></td>
      <td>4<sup>b</sup></td>
      <td>4</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par</code><sup>†</sup></td>
      <td>∞</td>
      <td>∞<sup>b</sup></td>
      <td>∞<sup>b</sup></td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">parplus</code><sup>†</sup></td>
      <td>∞</td>
      <td>∞<sup>b</sup></td>
      <td>∞<sup>b</sup></td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">parmake</code><sup>†</sup></td>
      <td>∞</td>
      <td>∞<sup>b</sup></td>
      <td>∞<sup>b</sup></td>
      <td>∞</td>
    </tr>
  </tbody>
</table>

<p>Warning “a,” which explicitly tells you to “Add <code class="language-plaintext highlighter-rouge">'+'</code> to parent make rule,” will indeed
always vanish if you prefix the <code class="language-plaintext highlighter-rouge">make</code>-containing line with <code class="language-plaintext highlighter-rouge">+</code>, like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>serplus:
    +make -C subdir
</code></pre></div></div>

<p>I find that solution as uncomfortably magical as <a href="https://www.gnu.org/software/make/manual/make.html#Echoing">prefix <code class="language-plaintext highlighter-rouge">@</code></a>
or <a href="https://www.gnu.org/software/make/manual/make.html#Errors">prefix <code class="language-plaintext highlighter-rouge">-</code></a>.
(Personally, I’d rather see “<code class="language-plaintext highlighter-rouge">|| true</code>” at the end of a recipe line than a magic “<code class="language-plaintext highlighter-rouge">-</code>” at the beginning.)
A solution that’s less magic-looking (although equally magic under the hood, apparently)
is to use <code class="language-plaintext highlighter-rouge">$(MAKE)</code>, like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sermake:
    $(MAKE) -C subdir
</code></pre></div></div>

<p>Neither method silences warning “b,” about “resetting jobserver mode,” though.</p>

<p>What we really want is a row that would look like <code class="language-plaintext highlighter-rouge">fantasy</code> below.
But at the moment, it seems we have to choose our preferred tradeoff from
one of the quoted rows, instead.</p>

<table>
  <thead>
    <tr>
      <th><code class="language-plaintext highlighter-rouge">make</code>…</th>
      <th> </th>
      <th><code class="language-plaintext highlighter-rouge">-j2</code></th>
      <th><code class="language-plaintext highlighter-rouge">-j4</code></th>
      <th><code class="language-plaintext highlighter-rouge">-j</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">fantasy</code></td>
      <td>nprocs</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sermake</code></td>
      <td>1</td>
      <td>2</td>
      <td>4</td>
      <td>∞</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">par4make</code></td>
      <td>4</td>
      <td>4b</td>
      <td>4b</td>
      <td>4</td>
    </tr>
  </tbody>
</table>]]></content><author><name></name></author><category term="concurrency" /><category term="makefiles" /><category term="sre" /><summary type="html"><![CDATA[Today I looked into “recursive” invocations of make; that is, cases in which a Makefile recipe itself invokes make. The official documentation is quite good, but since I’m working with a range of different GNU Make versions, I looked at how the behavior has changed over time, from GNU Make 3.81 to 4.3.]]></summary></entry><entry><title type="html">Spelling the type of a “self” parameter with Reflection</title><link href="https://quuxplusone.github.io/blog/2026/09/15/self/" rel="alternate" type="text/html" title="Spelling the type of a “self” parameter with Reflection" /><published>2026-09-15T00:01:00+00:00</published><updated>2026-09-15T00:01:00+00:00</updated><id>https://quuxplusone.github.io/blog/2026/09/15/self</id><content type="html" xml:base="https://quuxplusone.github.io/blog/2026/09/15/self/"><![CDATA[<p>Over on <a href="https://lists.isocpp.org/std-proposals/2026/09/19076.php">std-proposals</a>,
it was pointed out that using C++23 “explicit object parameter”
syntax without using <code class="language-plaintext highlighter-rouge">auto</code> (since <code class="language-plaintext highlighter-rouge">auto</code> makes your member function into a
template, changing its semantics) is sometimes cumbersome:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct MyLengthilyNamedClass {
  int i_;
  int f(this MyLengthilyNamedClass self) { return self.i_; }
};
</code></pre></div></div>

<p>You can shorten each member function declaration at the expense of
some repetitive boilerplate up front:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct MyLengthilyNamedClass {
  using Self = MyLengthilyNamedClass;
  int i_;
  int f(this Self self) { return self.i_; }
};
</code></pre></div></div>

<p>Sebastian Wittmeier <a href="https://lists.isocpp.org/std-proposals/2026/09/19076.php">observes</a>
that we can eliminate that boilerplate’s error-prone repetition
of the class name <code class="language-plaintext highlighter-rouge">MyLengthilyNamedClass</code> by using C++26 Reflection:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct MyLengthilyNamedClass {
  using Self = [: std::meta::current_class() :];
  int i_;
  int f(this Self self) { return self.i_; }
};
</code></pre></div></div>

<p>Thibault Ricord-Marchal <a href="https://lists.isocpp.org/std-proposals/2026/09/19116.php">observes</a>
that because the values of defaulted template arguments are evaluated in the context of the “caller,”
rather than where they appear lexically, we can even factor out that boilerplate to the top level:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>template&lt;std::meta::info R = std::meta::current_class()&gt;
using Self = [: R :];

struct MyLengthilyNamedClass {
  int i_;
  int f(this Self&lt;&gt; self) { return self.i_; }
};
</code></pre></div></div>

<p>Now, in these toy examples, I see no reason to prefer any of the above snippets over
the simple idiomatic <em>implicit</em>-object-parameter member function we’ve been writing since
the dawn of time:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct MyLengthilyNamedClass {
  int i_;
  int f() const { return i_; }
};
</code></pre></div></div>

<p>But notice the difference in calling convention. Our first four snippets pass <code class="language-plaintext highlighter-rouge">self</code>
by value, while the ordinary <code class="language-plaintext highlighter-rouge">f() const</code> needs to do a memory load through the <code class="language-plaintext highlighter-rouge">this</code>
pointer. I could just barely imagine a situation where that cost mattered.
(<a href="https://godbolt.org/z/cEWYaoox1">Godbolt.</a>)</p>

<hr />

<p>I imagine one might find other uses for <code class="language-plaintext highlighter-rouge">Self&lt;&gt;</code>. Off the top of my head,
it provides a way to shorten some of the boilerplate of special member functions:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct MyLengthilyNamedClass {
  MyLengthilyNamedClass(const MyLengthilyNamedClass&amp;) = default;
  MyLengthilyNamedClass&amp; operator=(const MyLengthilyNamedClass&amp;) = default;
};
</code></pre></div></div>

<p><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2952r2.html">P2952</a>, coming soon
to C++29, will permit <code class="language-plaintext highlighter-rouge">auto</code>’ing the assignment operator’s return type:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct MyLengthilyNamedClass {
  MyLengthilyNamedClass(const MyLengthilyNamedClass&amp;) = default;
  auto&amp; operator=(const MyLengthilyNamedClass&amp;) = default;
};
</code></pre></div></div>

<p>But with <code class="language-plaintext highlighter-rouge">Self&lt;&gt;</code>, you could shorten fully three of the four repetitions (<a href="https://godbolt.org/z/x967o7jGx">Godbolt</a>):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct MyLengthilyNamedClass {
  MyLengthilyNamedClass(const Self&lt;&gt;&amp;) = default;
  Self&lt;&gt;&amp; operator=(const Self&lt;&gt;&amp;) = default;
};
</code></pre></div></div>

<p>I wouldn’t want to see that in my own codebases. But it’s an idea.</p>]]></content><author><name></name></author><category term="explicit-object-parameters" /><category term="reflection" /><category term="pearls" /><summary type="html"><![CDATA[Over on std-proposals, it was pointed out that using C++23 “explicit object parameter” syntax without using auto (since auto makes your member function into a template, changing its semantics) is sometimes cumbersome:]]></summary></entry><entry><title type="html">Color Wheel combinatorics</title><link href="https://quuxplusone.github.io/blog/2026/09/08/color-wheel/" rel="alternate" type="text/html" title="Color Wheel combinatorics" /><published>2026-09-08T00:01:00+00:00</published><updated>2026-09-08T00:01:00+00:00</updated><id>https://quuxplusone.github.io/blog/2026/09/08/color-wheel</id><content type="html" xml:base="https://quuxplusone.github.io/blog/2026/09/08/color-wheel/"><![CDATA[<p>Over the weekend I was introduced to a Looney Labs pyramid game called
<a href="https://www.looneylabs.com/content/color-wheel">“Color Wheel.”</a>
This is a solitaire (or purely cooperative) game similar to
<a href="https://en.wikipedia.org/wiki/Peg_solitaire">peg solitaire</a>. It’s played
on a decagonal 40-space board, with three trios of pyramids in each of
seven colors: 63 pieces total.</p>

<p>After populating the board with 40 random pyramids from the stash such that
no two adjacent pyramids share a color, your goal is to use the fewest moves
to finish the game — where a “move” swaps two pyramids of the same color and/or
size, and the game is “finished” when each color occupies its own contiguous
region of the board.</p>

<p>The official rules encourage you to finish the game within 27 moves, mainly
because the <em>Pyramid Arcade</em> box happens to contain 27 more pyramids, and
you use those to keep score.
If the game had said “within 23 moves,” then you could have used
the 23 leftover colored pyramids to keep score instead.</p>

<p><b>How many possible Color Wheel setups are there in total?</b></p>

<p>A quick Monte Carlo experiment
(<a href="/blog/code/2026-09-08-color-wheel-counter.py">source</a>)
suggests that there are about
\(2.003\times 10^{46}\) distinct Color Wheel setups, up to rotation and reflection.
There are another \(2.195\times 10^{49}\) distinct midgame positions (i.e. positions
flouting setup’s no-color-adjacency criterion). Both kinds of positions
have an average branching factor of roughly 327 (standard deviation about 5).</p>

<p><b>What fraction of Color Wheel setups are solvable within 27 moves? Within 23?</b></p>

<p>I have no idea. Pretty trivially we can observe that every Color Wheel game
must take at least six moves to complete: The game starts with 40 connected components,
and the best possible move replaces 8 components with 2. Five perfect moves
could reduce the number of components to 10, but a solved board has even fewer
(no more than 7).</p>

<p>It’s easy to construct a valid setup that’s solvable in seven moves.
I doubt that any valid setup is solvable in six.</p>

<p><img src="/blog/images/2026-09-08-solvable-in-7.jpg" alt="A configuration solvable in seven moves" /></p>

<p>How about the number of moves that suffices to solve any setup — what’s
<a href="https://mathworld.wolfram.com/GodsNumber.html">God’s Number</a>
for Color Wheel? I’ve got only another trivial observation: the 40 pyramids
on the board can be selection-sorted into any configuration at all using no more
than 39 unconstrained swaps, and any unconstrained swap can be simulated by at most
5 valid moves. (If the pieces match in size, swap them in one move; otherwise, if any
of the six pieces that share color with one and size with the other is on the board,
use three swaps; otherwise, find \(p_1, p_2\) of the same size, \(p_1\) sharing color
with one and \(p_2\) sharing color with the other, and use five swaps.) That gives us
a comically loose upper bound — 195 moves certainly suffice.</p>

<p><b>Challenge: Write a Color Wheel solver.</b></p>

<p>Here’s <a href="/blog/code/2026-09-08-color-wheel-solver.py">a vibe-coded Color Wheel solver</a>
that can do the average board in about 33.8 moves (standard deviation about 4.5);
<a href="/blog/code/2026-09-08-worst-case.txt">the worst case</a> I’ve seen so far took 50 moves.
This is dramatically worse than the rules’ suggestion of 27 moves! Is that more readily
explained by the badness of this solver’s heuristics, or by the conjecture that most
Color Wheel boards are not solvable in 27 moves?</p>

<p><img src="/blog/images/2026-09-08-solver-histogram.png" alt="Histogram of solution lengths found by this solver" /></p>

<p>The Python code that generated that plot was:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import matplotlib.pyplot as plt
plt.hist(values, bins=[x-0.5 for x in range(20, 52)], edgecolor="white", color="#4f81bd")
plt.xticks(range(20, 51, 2))
plt.xlabel("Number of moves taken by the heuristic solver")
plt.show()
</code></pre></div></div>]]></content><author><name></name></author><category term="board-games" /><category term="help-wanted" /><category term="math" /><category term="puzzles" /><summary type="html"><![CDATA[Over the weekend I was introduced to a Looney Labs pyramid game called “Color Wheel.” This is a solitaire (or purely cooperative) game similar to peg solitaire. It’s played on a decagonal 40-space board, with three trios of pyramids in each of seven colors: 63 pieces total.]]></summary></entry><entry><title type="html">Tennyson and Babbage? No! Trevelyan</title><link href="https://quuxplusone.github.io/blog/2026/08/27/babbage-and-tennyson/" rel="alternate" type="text/html" title="Tennyson and Babbage? No! Trevelyan" /><published>2026-08-27T00:01:00+00:00</published><updated>2026-08-27T00:01:00+00:00</updated><id>https://quuxplusone.github.io/blog/2026/08/27/babbage-and-tennyson</id><content type="html" xml:base="https://quuxplusone.github.io/blog/2026/08/27/babbage-and-tennyson/"><![CDATA[<p>From the preface to Edward Cook’s
<a href="https://babel.hathitrust.org/cgi/pt?id=uc1.b3576128&amp;seq=17"><em>More Literary Recreations</em></a>
(1919), page xiii:</p>

<blockquote>
  <p>In [my previous book’s] chapter about “The Second Thoughts of Poets” …
I <a href="https://archive.org/details/literaryrecreati00cook/page/270">fathered on Babbage</a>
a delightful emendation of two lines in Tennyson’s
“Vision of Sin,” which I now restore to its rightful author. The emendation
is to be found in Letter vii. of <em>The Competition Wallah.</em> It is attributed
to “a friend who is passionately devoted to the study of the laws of
sanitation and mortality. He carries his enthusiasm on the subject so
far as to tinge with it his view of every conceivable matter — religious,
political, and literary. He once wrote an anonymous letter to the Laureate,
commenting on the lines in the <em>Vision of Sin</em>:</p>

  <p>Every moment dies a man, / Every moment one is born.</p>

  <p>He observed, with great truth, that if this statement were correct the population
of the world would remain stationary, and urged the poet to alter the lines thus:</p>

  <p>Every moment dies a man, / And one and one-sixteenth is born.</p>

  <p>He owned that the exact figure was one, decimal point, ought, four, seven;
but (as he said) some allowance must be made for metre.” I must hope that
Sir George Trevelyan will forgive me for having invested his <em>jeu d’esprit</em>
with a mythical origin.</p>
</blockquote>

<p>Indeed the anecdote, exactly as quoted, appears in George Trevelyan’s
<a href="https://books.google.com/books?id=WNYMAAAAIAAJ&amp;pg=PA243"><em>The Competition Wallah</em></a> (1864),
at the end of the seventh letter, titled “About Calcutta and its Climate.”
This comic essay was first published in <em>Macmillan’s Magazine</em> <b>9</b>:49 (November 1863),
<a href="https://babel.hathitrust.org/cgi/pt?id=hvd.32044092674381&amp;seq=154">pp. 117–135</a>,
datelined “April 12, 1863.”</p>

<p>The false attribution to Babbage was likely originated by David Ker in <em>Harper’s Magazine</em>
<b>81</b>:483 (August 1890), <a href="https://babel.hathitrust.org/cgi/pt?id=coo.31924079630475&amp;seq=498">p. 486</a>.
Ker presents his version as a “story, which, if not literally true, certainly deserves to be so.”</p>

<p>The attribution may have been suggested by the fact that Babbage had authored in 1826
<a href="https://babel.hathitrust.org/cgi/pt?id=hvd.32044004635306&amp;seq=7"><em>A Comparative View of the Various Institutions for the Assurance of Lives</em></a>
(a treatise on the mathematics of life insurance),
which originated this widely reprinted observation:</p>

<blockquote>
  <p>Nothing is more proverbially uncertain than the duration of human life,
when the maxim is applied to an individual; yet there are few things less
subject to fluctuation than the average duration of a multitude of individuals. …
Among the inhabitants of a kingdom, the uniformity is such, that the excess of deaths
in any year above the average number seldom exceeds a small fractional part of the whole.</p>
</blockquote>

<p>See also:</p>

<ul>
  <li><a href="/blog/2018/09/26/pray-mister-babbage/">“Pray-Mister-Babbage problems”</a> (2018-09-26)</li>
</ul>]]></content><author><name></name></author><category term="jokes" /><category term="old-shit" /><category term="math" /><category term="poetry" /><summary type="html"><![CDATA[From the preface to Edward Cook's [_More Literary Recreations_](https://babel.hathitrust.org/cgi/pt?id=uc1.b3576128&seq=17) (1919), page xiii: > In [my previous book's] chapter about "The Second Thoughts of Poets" ... > I [fathered on Babbage](https://archive.org/details/literaryrecreati00cook/page/270) > a delightful emendation of two lines in Tennyson's > "Vision of Sin," which I now restore to its rightful author.]]></summary></entry><entry><title type="html">Data members that want to use `size()`</title><link href="https://quuxplusone.github.io/blog/2026/08/25/size-idioms/" rel="alternate" type="text/html" title="Data members that want to use `size()`" /><published>2026-08-25T00:01:00+00:00</published><updated>2026-08-25T00:01:00+00:00</updated><id>https://quuxplusone.github.io/blog/2026/08/25/size-idioms</id><content type="html" xml:base="https://quuxplusone.github.io/blog/2026/08/25/size-idioms/"><![CDATA[<p>The following snippet doesn’t compile:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct A {
  static constexpr size_t size() { return 42; }
  int data_[size()];
};
</code></pre></div></div>

<p>The problem is that the size (and therefore the type) of data member <code class="language-plaintext highlighter-rouge">data_</code>
can’t be computed until we know the value of <code class="language-plaintext highlighter-rouge">size()</code>; but evaluating <code class="language-plaintext highlighter-rouge">size()</code>
requires <code class="language-plaintext highlighter-rouge">A</code> to be complete (<a href="https://eel.is/c++draft/class.mem#def:complete-class_context">[class.mem.general]</a>),
which won’t happen until the closing brace on the next line.</p>

<p>One workaround, obviously, is to repeat the magic number <code class="language-plaintext highlighter-rouge">42</code> in two places. That’s probably the
simplest option; but here are a few other workarounds.</p>

<h2 id="do-the-work-in-data_-instead-of-size">Do the work in <code class="language-plaintext highlighter-rouge">data_</code> instead of <code class="language-plaintext highlighter-rouge">size()</code></h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct B {
  constexpr size_t size() const { return std::size(data_); }
  int data_[42];
};
</code></pre></div></div>

<p>This one matches my advice in <a href="/blog/2020/08/06/array-size/">“The ‘array size constant’ antipattern”</a> (2020-08-06).
Sadly, now that <code class="language-plaintext highlighter-rouge">size()</code> depends on <code class="language-plaintext highlighter-rouge">data_</code>, we must make <code class="language-plaintext highlighter-rouge">size()</code> a non-static member function.
We can actually fix that by exploiting a quirk of unevaluated operands:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct C {
  static constexpr size_t size() { return sizeof(data_) / sizeof(data_[0]); }
  int data_[42];
};
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">std::size(data_)</code> treats <code class="language-plaintext highlighter-rouge">data_</code> as meaning <code class="language-plaintext highlighter-rouge">this-&gt;data_</code>, and requires a <code class="language-plaintext highlighter-rouge">this</code> pointer.
But <code class="language-plaintext highlighter-rouge">sizeof(data_)</code> treats <code class="language-plaintext highlighter-rouge">data_</code> as meaning <code class="language-plaintext highlighter-rouge">C::data_</code>, and is able to tell us the size of
that member “hypothetically,” without associating it with any particular <code class="language-plaintext highlighter-rouge">C</code> object.
Likewise <code class="language-plaintext highlighter-rouge">sizeof(data_[0])</code>, and even complicated expressions like <code class="language-plaintext highlighter-rouge">decltype(data_ + 1)</code> — as
long as the <em>id-expression</em> appears inside an unevaluated expression. This is specified in
<a href="https://eel.is/c++draft/expr.prim#id.general-4.3">[expr.prim.id]/4.3</a>
(via <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html">N2253</a>
“Extending <code class="language-plaintext highlighter-rouge">sizeof</code> to apply to non-static data members without an object,” 2007).</p>

<p>This approach is great when the array bound is just <code class="language-plaintext highlighter-rouge">42</code>, but it’s not so great when the
array bound is computed and lengthy to spell out. In that case, we might want a different workaround.</p>

<h2 id="introduce-a-static-constexpr-helper-variable">Introduce a static constexpr helper variable</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct D {
  static constexpr size_t N = 42;
  static constexpr size_t size() { return N; }
  int data_[N];
};
</code></pre></div></div>

<p>Notice that we can make <code class="language-plaintext highlighter-rouge">size()</code> return <code class="language-plaintext highlighter-rouge">N</code>, but we cannot flip it around and make <code class="language-plaintext highlighter-rouge">N</code>
initialized to <code class="language-plaintext highlighter-rouge">size()</code>…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct D_does_not_work {
  static constexpr size_t size() { return 42; }
  static constexpr size_t N = size(); // error
};
</code></pre></div></div>

<p>…for the same reason as the original failure. The value of <code class="language-plaintext highlighter-rouge">N</code> must be known
<em>at that point</em>, while the class type is still incomplete and <code class="language-plaintext highlighter-rouge">size()</code> is still
not evaluable.</p>

<h2 id="put-the-size-computation-outside-the-class">Put the size computation outside the class</h2>

<p>Obviously this is fine:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>static constexpr size_t E_size() { return 42; }
struct E {
  static constexpr size_t size() { return E_size(); }
  int data_[E_size()];
};
</code></pre></div></div>

<h2 id="put-size-in-a-base-class">Put <code class="language-plaintext highlighter-rouge">size()</code> in a base class</h2>

<p>This is also fine:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct Base {
  static constexpr size_t size() { return 42; }
};
struct F : Base {
  int data_[size()];
};
</code></pre></div></div>

<p>Here <code class="language-plaintext highlighter-rouge">size()</code> refers to <code class="language-plaintext highlighter-rouge">Base::size()</code>, and <code class="language-plaintext highlighter-rouge">Base</code> is a complete type. Perhaps surprisingly,
there’s an order dependency here: If you declare an <code class="language-plaintext highlighter-rouge">F::size()</code> before the declaration of <code class="language-plaintext highlighter-rouge">data_</code>
then you’ll be right back in case <code class="language-plaintext highlighter-rouge">A</code>, and get an error. But you can declare a new meaning for
<code class="language-plaintext highlighter-rouge">F::size()</code> <em>after</em> the declaration of <code class="language-plaintext highlighter-rouge">data_</code>, and the compiler won’t complain. (Should you do so?
No. Is it <a href="/blog/2019/08/02/the-tough-guide-to-cpp-acronyms/#ifndr">IFNDR</a> to do so?
Possibly; I’m not sure.)</p>

<h2 id="turn-size-into-a-data-member">Turn <code class="language-plaintext highlighter-rouge">size</code> into a data member</h2>

<p>See <a href="https://www.foonathan.net/2023/08/static-constexpr-integral_constant/">“The new static constexpr <code class="language-plaintext highlighter-rouge">integral_constant</code> idiom”</a>
(Jonathan Müller, August 2023). You can actually do this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct G {
  static constexpr std::integral_constant&lt;size_t, 42&gt; size = {};
  int data_[size()];
};
</code></pre></div></div>

<p>Here <code class="language-plaintext highlighter-rouge">size()</code> is not a function call, requiring a complete <code class="language-plaintext highlighter-rouge">G</code>; it’s an evaluation of the <code class="language-plaintext highlighter-rouge">operator()</code>
of a static data member, and data members (unlike member functions) are perfectly usable in
incomplete-class contexts.</p>

<p>This is maybe the cleanest-looking workaround out of all of these. But it seems like a bad idea
for social reasons; your coworkers will not <em>expect</em> <code class="language-plaintext highlighter-rouge">size</code> to be a static data member instead of a
member function!</p>

<p>In fact, C++26 Reflection might eventually make this a bad idea for technical reasons too:
surely many Reflection-based libraries will do things like “loop over all the member functions of <code class="language-plaintext highlighter-rouge">G</code>”
without considering that some of <code class="language-plaintext highlighter-rouge">G</code>’s member functions might be hiding among its static data members.
Notably, Ryan Keane’s type-erasure library <a href="https://github.com/RyanJK5/rjk-duck"><code class="language-plaintext highlighter-rouge">rjk::duck</code></a>
doesn’t understand this idiom. (<a href="https://godbolt.org/z/P66co4qzr">Godbolt.</a>)</p>

<p>Another surprising detail of this workaround is the redundant “<code class="language-plaintext highlighter-rouge">={}</code>.”
Try leaving it off; the code <em>means</em> the same thing (“default-initialize this object”),
but the compiler will no longer accept it! For historical reasons, C++ rejects any attempt
to default-initialize a <code class="language-plaintext highlighter-rouge">const</code> variable unless you put the initializer really explicitly
in the code. For some types, like <code class="language-plaintext highlighter-rouge">int</code>, this makes perfect sense:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>int x;        // OK
const int x;  // rejected, reasonably enough
</code></pre></div></div>

<p>but for other types it’s frankly annoying:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>std::true_type x;       // OK
const std::true_type x; // rejected for no good reason
</code></pre></div></div>

<p>See <a href="/blog/2019/12/04/mutable-divergence/">“Implementation divergence with <code class="language-plaintext highlighter-rouge">const int i;</code> and <code class="language-plaintext highlighter-rouge">mutable</code>”</a> (2019-12-04).</p>

<p>A core-language variation on this idea is to use a lambda, which incidentally removes the
redundancy:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct H {
  static constexpr auto size = [](){ return 42; };
  int data_[size()];
};
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">auto</code> keyword cannot be used to declare non-static data members, but static data members
(as here) are fair game: this version works in C++17 and later. (Before C++17, the lambda’s
<code class="language-plaintext highlighter-rouge">operator()</code> isn’t constexpr, so that <code class="language-plaintext highlighter-rouge">size()</code> isn’t a constant expression.)</p>

<h2 id="conclusion">Conclusion</h2>

<p>I wish there were a clear winner out of all these sub-par options.
I’ve placed them basically in the order I’d recommend them, starting with the
most straightforward and finishing with the one I found to have the greatest number
of identifiable disadvantages. (Which is too bad, because it’s also very clever!)</p>]]></content><author><name></name></author><category term="antipatterns" /><category term="constexpr" /><category term="cpplang-slack" /><category term="library-design" /><category term="reflection" /><summary type="html"><![CDATA[The following snippet doesn't compile: struct A { static constexpr size_t size() { return 42; } int data_[size()]; }; The problem is that the size (and therefore the type) of data member `data_` can't be computed until we know the value of `size()`; but evaluating `size()` requires `A` to be complete ([class.mem.general]), which won't happen until the closing brace on the next line. One workaround, obviously, is to repeat the magic number `42` in two places. That's probably the simplest option; but here are a few other workarounds.]]></summary></entry><entry><title type="html">Colourfields</title><link href="https://quuxplusone.github.io/blog/2026/08/05/colourfields/" rel="alternate" type="text/html" title="Colourfields" /><published>2026-08-05T00:01:00+00:00</published><updated>2026-08-05T00:01:00+00:00</updated><id>https://quuxplusone.github.io/blog/2026/08/05/colourfields</id><content type="html" xml:base="https://quuxplusone.github.io/blog/2026/08/05/colourfields/"><![CDATA[<p>Over on the (inexplicably login-walled) site “NewEnigma,”
Keith Austin <a href="https://www.newenigma.com/enigma/view/1277/Colourfields">writes</a>:</p>

<blockquote>
  <p>Draw a 4-by-4 grid. Colour each square red or blue. Select any square, S, and write 1 in it.
Then write 1 in every square you can reach from S by a series of moves, where each move is from
a square to an adjacent, horizontally, vertically, or diagonally, square of the same colour.</p>

  <p>Select any empty square, T, and write 2 in it. Then write 2 in every square you can reach from T
by a series of moves. Repeat this procedure for 3 and then 4 and so on until every square has a
number. The last number you write down is called the “score” for that colouring. If we imagine
the grid is the map of a farm, then you have divided the map into fields, one field for each number.</p>

  <p>(1) What is the largest score possible?</p>

  <p>(2) If we work with a 5-by-5 grid, what is the largest score possible?</p>
</blockquote>

<p>In brief: What is the maximum number of <em>queenwise-connected</em> monochromatic regions you
can make by coloring each square of an \(n\times n\) grid either red or blue? If we were asking about
rookwise-connected regions, the answer would obviously be \(n^2\). But queenwise-connected is
at least slightly less obvious!</p>

<p>For the 5-by-5 grid, the “obvious” answer is</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rBrBr
BBBBB
rBrBr
BBBBB
rBrBr
</code></pre></div></div>

<p>for a total of 10 regions. But the answer for 4×4 is not simply</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rBrB
BBBB
rBrB
BBBB
</code></pre></div></div>

<p>for a total of 5; you can in fact make 6 regions! (Once you’ve seen the trick it’s hard to unsee;
but I didn’t see it at first myself.)</p>

<p>Discussion on the <a href="https://groups.google.com/g/seqfan/c/ocmDmccx5mI/m/L3KqPGbiAgAJ">SeqFan</a> mailing list
tentatively produced the sequence: 1, 2, 5, 6, 10, 12, 17, 19, 26, (28?)… Here’s the pattern for
odd \(n\), and a <em>conjectured</em> pattern for all even \(n&gt;4\).</p>

<p><img src="/blog/images/2026-08-05-colourfields.svg" alt="" /></p>

<p>For odd \(n\): \(\lceil n/2\rceil^2 + 1\) regions.
For even \(n&gt;4\): \(\lceil n/2\rceil^2 + 3\) regions.</p>]]></content><author><name></name></author><category term="math" /><category term="puzzles" /><summary type="html"><![CDATA[Over on the (inexplicably login-walled) site "NewEnigma," Keith Austin [writes](https://www.newenigma.com/enigma/view/1277/Colourfields): > Draw a 4-by-4 grid. Colour each square red or blue. Select any square, S, and write 1 in it. > Then write 1 in every square you can reach from S by a series of moves, where each move is from > a square to an adjacent, horizontally, vertically, or diagonally, square of the same colour [...] In brief: What is the maximum number of _queenwise-connected_ monochromatic regions you can make by coloring each square of an $$n\times n$$ grid either red or blue?]]></summary></entry><entry><title type="html">Möbius-strip crosswords</title><link href="https://quuxplusone.github.io/blog/2026/08/04/mobius-crossword/" rel="alternate" type="text/html" title="Möbius-strip crosswords" /><published>2026-08-04T00:01:00+00:00</published><updated>2026-08-04T00:01:00+00:00</updated><id>https://quuxplusone.github.io/blog/2026/08/04/mobius-crossword</id><content type="html" xml:base="https://quuxplusone.github.io/blog/2026/08/04/mobius-crossword/"><![CDATA[<p>Randall Rothenberg in the <em>New York Times</em> (1988-08-10) writes that although <a href="https://archive.is/K2Hw8">“Puzzle Makers Exchange Cross Words”</a>
about the fall of ERNE and ESNE and the rise of XEROX and PEACE PLAN, one
Robert Guilbert Sr.</p>

<blockquote>
  <p>was ignorant of the dispute two years ago when he developed a competitive crossword game
called Pago Pago and first became aware of crossword fans’ passion for the pastime.</p>
</blockquote>

<p>“Guilbert invented the crossword-based game Pago Pago” is repeated in
Thomas Frisbie, <a href="https://kolynychboss8.blogspot.com/2012/03/fan-passes-word-on-puzzle-hall-of-fame.html">“Fan passes word on puzzle hall of fame”</a>
(<em>Chicago Sun-Times</em>, 1988-08-14). (Thanks to Ben Zimmer for identifying the article!)
But that’s all I can find in print about Pago Pago.</p>

<p>Helene Hovanec’s article <a href="https://www.scribd.com/document/266289455/Robert-Guilbert-s-Crossword-Academy-by-Helene-Hovanec">“Robert Guilbert’s Crossword Academy”</a>
(<em>CROSSW RD</em>, Nov/Dec 1992) contains no text about Pago Pago, but does include this uncaptioned photograph
of Guilbert (1911–1990) hard at work:</p>

<p><img src="/blog/images/2026-08-04-guilbert.jpg" alt="" /></p>

<p>David Steinberg of the “Pre-Shortzian Puzzle Project” blog has mentioned Guilbert
<a href="http://www.preshortzianpuzzleproject.com/search/label/Robert%20Guilbert">several times</a>
in connection with Guilbert’s short-lived Crossword Academy, and even received in 2016
<a href="http://www.preshortzianpuzzleproject.com/2014/11/american-crossword-puzzle-academy.html">a very nice blog comment from Guilbert’s son Jonathan</a>
and <a href="http://www.preshortzianpuzzleproject.com/2017/09/charles-gersch-will-weng-submission-guidelines.html#:~:text=Robert%20Guilbert%20Update:">a little more via email</a>.
Jonathan wrote, in part:</p>

<blockquote>
  <p>In the photo he can be seen working on a puzzle that he designed as a “Moebius Strip” — an
“Infinity Crossword Puzzle” — a puzzle without a beginning and an end. He was going to have
this game manufactured and marketed under the name “Pago Pago,” I believe.</p>
</blockquote>

<p>Personally I suspect that Jonathan’s hunch was wrong: that the Möbius-strip puzzle and the “Pago Pago” puzzle-game
(whatever its nature was) were two separate projects. However, apparently on the strength
of Jonathan’s guess, the Möbius–Pago Pago hypothesis was reproduced as fact in Adrienne Raphel’s dissertation
<a href="https://dash.harvard.edu/server/api/core/bitstreams/b332a223-4785-4322-b81c-5e504bd2fde5/content">“The Crossword Mentality in Modern Literature and Culture”</a>
(Harvard, 2018):
“In 1986, Robert Guilbert, a former ad copywriter from Milwaukee who enjoyed
spending his retirement doing the puzzle, invented a game called Pago Pago, an infinite
crossword on a Möbius strip, and began to peddle it around to crossword fans.”
The same sentence appears in Raphel’s book
<a href="https://www.adrienneraphel.com/thinking-inside-the-box.html"><em>Thinking Inside the Box</em></a> (2020).
The game of telephone continues in Natan Last’s <a href="/blog/2026/07/28/puzzle-miscellany/"><em>Across the Universe</em></a> (2025):
“he’d invented a game called Pago Pago, an infinite crossword on a Möbius strip, and wanted to hawk
it to the greats.”</p>

<hr />

<p>UPDATE, 2026-08-13: Actually, Guilbert had already gotten <em>Pago Pago</em> into circulation
long before these articles were written! The July 1986 issue of <em>GAMES</em> magazine has
<a href="https://archive.org/details/Games-Magazine-July-1986-images/page/n61/mode/1up">a review</a>
of <em>Pago Pago</em> (Garden City, New York: Just Games). Indeed there’s no Möbius element;
the game is simply a pack of 24 William Lutwiniak crosswords plus rules for up to four
players to complete a set of grids competitively: fill squares for three minutes, then pass
the grid to your left and fill squares in your opponent’s old grid. Whoever fills in
the most squares correctly (“with penalties for errors and bonuses for correcting
opponents’ errors”) is the winner. The game has an entry
<a href="https://boardgamegeek.com/boardgame/24621/pago-pago">on BoardGameGeek</a>,
and as of this writing you can buy a copy for $25
<a href="https://www.ebay.com/itm/384956997282">on eBay</a>. (Thanks to Virginia Downes
for this information!)</p>

<hr />

<p>But what does a crossword on a Möbius strip look like, anyway? said I to myself.</p>

<p>Presumably it would be a crossword that loops around on itself from bottom to top (and vice versa).
A crossword that does that on all four edges would be “toroidal,” like this one
(which I found on <a href="https://www.andrews.edu/~calkins/math/webtexts/geom04xw.htm">Keith Calkins’ “tori crosswords” page</a>,
although I infer that Jeff Weeks was the author):</p>

<p><img src="/blog/images/2026-08-04-weeks-torus-crossword.svg" alt="A 4x4 toroidal crossword" /></p>

<p><a href="https://en.wikipedia.org/wiki/Jeffrey_Weeks_(mathematician)">Jeff Weeks</a> has made a bunch of these; see
<a href="https://momath.org/wp-content/uploads/me_handout_Weeks.pdf">this PDF</a> from MoMath. In fact he’s even made
crosswords “on a Klein bottle.” Here the right and left edges connect as before,
while the top and bottom edges connect with a Möbius half-twist.</p>

<p><img src="/blog/images/2026-08-04-weeks-kleinbottle-crossword.svg" alt="A 5x5 Klein-bottle crossword containing two 9-letter entries" /></p>

<p>The above crossword is neat because despite being 5x5, its two longest entries are 9 letters each.
But it’s less than perfectly satisfying in that half of the Across entries read right-to-left; and in
that if it actually wrapped around on itself with a half-twist, wouldn’t the letters wind up backwards
too? Then 6-Down wouldn’t be MESSENGER but
rather <nobr>ME<span style="display:inline-block;transform:scale(-1,1);">S</span><span style="display:inline-block;transform:scale(-1,1);">S</span><span style="display:inline-block;transform:scale(-1,1);">E</span><span style="display:inline-block;transform:scale(-1,1);">N</span><span style="display:inline-block;transform:scale(-1,1);">G</span>ER,</nobr> and
so on. (2-Down mirror-reverses very nicely, though!)</p>

<p>Now, a real mathematical Möbius strip, <a href="https://www.jstor.org/stable/24927595">says Martin Gardner</a>,</p>

<blockquote>
  <p>is what topologists call “nonorientable.”
Imagine the strip to be a true surface of zero thickness.
Embedded in this 2-space are <a href="/blog/2021/11/05/the-fourth-dimension/">flat creatures</a>
that are mirror-asymmetric (not
identical with their mirror images). If such a creature moves once around the
band to rejoin his fellows, he will have changed his parity and will have become
a mirror reflection of his former self.</p>
</blockquote>

<p>If our “flat creatures” are the letter-forms of the crossword entries, then when the crossword
loops around on itself the letter-forms will change parity: S becomes <span style="display:inline-block;transform:scale(-1,1);">S</span>,
and so on. So the only letters we seem to be able to use are the vertically symmetric ones, and
we’ll have great difficulty constructing any crossword more complex than the following
infinite jest:</p>

<p><img src="/blog/images/2026-08-04-haha.jpg" alt="A Möbius strip with &quot;HAHAHA...&quot; written vertically" /></p>

<p>Or we could loop horizontally with horizontally symmetric letters (HEEHEEHEE…). But to
create entries that aren’t infinitely long, we should create a <em>diagonal</em> “ladder” of words instead
— as I fancy I see Robert Guilbert doing in that photo! If our “ladder” runs diagonally
down and left, like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  ABC
 DEF
GHI
</code></pre></div></div>

<p>then we’ll be able to use letters whose axis of symmetry is on that 45-degree line, such as (of course) O and X,
but also L: “LOX” horizontally will flip to produce “XOL” as one of the Down entries. In fact we can also use W,
which (if you draw it just right) flips to become E; H, which flips to become I (with serifs); C, which flips
to become U; and even D, which (with long serifs) flips to become a nice round capital A.
This gives us enough degrees of freedom to create the following Möbius-strip crossword:</p>

<p><img src="/blog/images/2026-08-04-mobius-crossword.svg" alt="A Möbius crossword" /></p>

<p>Print out this strip and tape the ends together with a half-twist. Fill it out with a heavy
ink marker and you’ll find you only need to solve the first five clues — then you can flip the
strip over and read off the answers to the last five clues in the letter-forms that have bled
through the paper! (Or hold the back of the paper up to the light; or, for the really lazy,
just lay a mirror alongside it.)</p>

<p>Mine is not a <em>good</em> crossword. Not only does it have awful fill, it repeats entries:
six of the Acrosses are repeated among the Downs. But it was the best three-letter ladder I could find
even with computer assistance. My dictionary of <em>possible</em> answers consisted of only 23 pairs
of words. (Remember, every Across entry flips into a Down entry: if we have LAW across, we necessarily
get EDL down. And since EDL isn’t a word, LAW isn’t in our dictionary either.)
Words mirrorable this way of <em>more</em> than three letters are rare as hen’s teeth: HOWL flips into LEO I,
ALOE into WOLD, and ALOUD into A COLD; that’s about all.</p>

<p>Can you come up with a better Möbius-strip crossword? or do you have additional information on
Robert Guilbert’s Pago Pago and Möbius-strip projects?
<a href="mailto:arthur.j.odwyer@gmail.com">Email</a> and tell me about it!</p>

<hr />

<p>See also:</p>

<ul>
  <li><a href="/blog/2025/01/03/double-crossword/">“Fully Schrödinger crosswords”</a> (2025-01-03)</li>
</ul>]]></content><author><name></name></author><category term="crosswords" /><category term="math" /><category term="pretty-pictures" /><category term="puzzles" /><summary type="html"><![CDATA[Randall Rothenberg in the _New York Times_ (1988-08-10) writes that although ["Puzzle Makers Exchange Cross Words"](https://archive.is/K2Hw8) about the fall of ERNE and ESNE and the rise of XEROX and PEACE PLAN, one Robert Guilbert Sr. > was ignorant of the dispute two years ago when he developed a competitive crossword game > called Pago Pago and first became aware of crossword fans' passion for the pastime.]]></summary></entry><entry><title type="html">Kinton Ford’s _Canto I_</title><link href="https://quuxplusone.github.io/blog/2026/07/31/kinton-ford-inferno-i/" rel="alternate" type="text/html" title="Kinton Ford’s _Canto I_" /><published>2026-07-31T00:01:00+00:00</published><updated>2026-07-31T00:01:00+00:00</updated><id>https://quuxplusone.github.io/blog/2026/07/31/kinton-ford-inferno-i</id><content type="html" xml:base="https://quuxplusone.github.io/blog/2026/07/31/kinton-ford-inferno-i/"><![CDATA[<p>In <a href="/blog/2025/08/11/varaldo-and-chiti/">“Varaldo’s <em>Shahrazad</em> and Chiti’s <em>Centunesimo Canto</em>”</a>
(2025-08-11) I mentioned the existence of a lipogrammatic translation of Canto I of
Dante’s <em>Inferno</em> performed by one Kinton Ford (a pseudonym, as far as I know)
for Rick Whitaker’s now-defunct literary e-zine
<a href="https://web.archive.org/web/20240302015106/https://www.exquisitepandemicarchives.com/"><em>Exquisite Pandemic</em></a>
(2020–2021). A year later, seeing it’s still unavailable anywhere else online,
I feel justified in preserving that whole tour-de-force here for posterity.</p>

<p>Ford’s canto, like Dante’s, is exactly 136 lines of pure <em>terza rima</em>,
containing a few impressively novel rhymes and many powerful images. Notably
Ford finds room to expand Dante’s <em>Oh felice colui cu’ ivi elegge!</em> from one
line into three.</p>

<blockquote>
  <p>Just halfway through my own trip in our living,<br />
 Provisional, short world, I found that I<br />
 Had lost my path — woods dark and unforgiving<br />
Making my way so hard that I must sigh<br />
 If I would say how brutal was that wood,<br />
 To think on which will always horrify.<br />
If anything, it’s only dying could<br />
 Outdo that acrid wood’s malignity.<br />
 But I will turn from horror, towards that good<br />
Which also on that pathway, luckily,<br />
 I found, though I can’t say what hid all truth<br />
 Away in total blank stupidity.<br />
I cannot work out how it was, in sooth,<br />
 That in that gloom awaking, full of stupor,<br />
 I’d lost that saving road I took in youth.<br />
I got at last to what you’d call a croup or<br />
 Boundary of that dark and dismal hollow,<br />
 A bank of rocks transforming hill-wall to floor.<br />
To that bluff’s scapula my look did follow<br />
 Upwards still that guiding morning glow,<br />
 Bright from that star so holy to Apollo.<br />
Thus did that anxious horror, which had so<br />
 Brought churning with it, all that awful night,<br />
 To my soul’s pool, diminish, calm its flow.<br />
And as a man who pants hard, still in sight<br />
 Of billows which, almost, brought him to sink,<br />
 From land looks back on that main, full of fright,<br />
So did my spirit, panicking, still think<br />
 On that grim pass no mortal human can<br />
 Go out of without passing living’s brink.<br />
At last my body pausing for a span<br />
 Until invigoration from that stop<br />
 Could now allow it motion, though no plan<br />
Could show it how to go, with constant prop<br />
 On foot in back and downwards, sought to gain,<br />
 By climbing always upwards, that mount’s top.<br />
And lo! A cougar stood stock still, though plain<br />
 Its quick and light agility. No turning<br />
 Could pass it by. Upon its skin a rain<br />
Of spots, which I, that bright and airy morning<br />
 (As sun and star-companions Loving God<br />
 Had first spun, still did spin) saw as adorning<br />
That cat, a sign of succor I might laud,<br />
 During that blissful dawn, but not so bright<br />
 That I did not start shaking, on that road,<br />
At what was now arising in my sight:<br />
 A lion, drawn up high, intimidating,<br />
 So much that air and I, both full of fright<br />
About how it its stomach might start sating,<br />
 Must stop — for what? A wolf; and I was pavid,<br />
 So skinny was it, though anticipating<br />
It would sup soon on anything, for avid<br />
 It was for food: though lank it was full too:<br />
 That wolf so ruinous to man was gravid!<br />
And I was too — with fright! I could not do<br />
 What I was hoping for — to climb that hill.<br />
 Alas, I found no pathway round nor through.<br />
And as a man who’d got just what his will<br />
 Saw as most worth wishing of all things,<br />
 Now gasps on losing it, a poignant thrill<br />
Of brutal pain, transfixing with its stings<br />
 From that wolf, did I sob at, and I shrank<br />
 Darkwards, away from Sol’s loud blazonings.<br />
Back did I go, back to that lowland dank.<br />
 Abruptly in my sight shows up a man,<br />
 Who, dumb so long, I thought would sound as blank<br />
As our surround was. Straight to him I ran,<br />
 Still crying “Pity!” to him, “Man or shadow<br />
 Of a man!” “Not a man, but Mantuan,<br />
By birth,” was his account, “born sub Julio,<br />
 But it was good Augustus, though his gods<br />
 Did not say truth nor know your Christian Trio,<br />
Who was my king. My song got many nods,<br />
 All praising it as Roman history,<br />
 From Trojan loss to gain, against all odds,<br />
From burning Ilion to victory.<br />
 But why do you avoid that joyous mountain,<br />
 As though to climb you’d no ability?”<br />
“Now art thou Virgil? That riparian fountain,”<br />
 All blushingly I said, within his sight,<br />
 “Of words that all who follow find a sound in<br />
Which our own songs would sing too? If I might,<br />
 I’ll say how much I honor you, what study<br />
 I sanctify with loving to your light.<br />
But now look on that animal so bloody,<br />
 To you I turn for aid, to you I’m flying.<br />
 O horror!” “You must go this path, though muddy,”<br />
Did Virgil say, to try to hush my crying,<br />
 “If you would from this dark wood find a way.<br />
 For past that wolf can no amount of trying<br />
Attain that goal; whoso will try will pay<br />
 With his annihilation; hungrily,<br />
 Voraciously that wolf puts him away.<br />
Marrying many animals bodily,<br />
 It looks to go on doing so, until<br />
 A Sighthound, coming with finality,<br />
Shall bring its pain to culmination, kill<br />
 That awful wolf, who did not pity show.<br />
 That hound, consuming not, such is its will,<br />
Things of this world, but only what would go<br />
 With wisdom — loving all morality —<br />
 In fabrics of Franciscan monks will know<br />
His nation. Savior of low Italy<br />
 That hound is, land for which Camilla, dying<br />
 A maid, and Nisus, and his loving ally,<br />
And Turnus, all lay down for good. Now plying<br />
 Its way through any town that it might harry,<br />
 That wolf cannot avoid damnation, buying,<br />
Through vicious rivalry, a day to tarry,<br />
 So soon to finish. So I think it right<br />
 That I conduct you, and that you stay wary<br />
As onwards through this always-lasting night<br />
 You go, with sounds of always-lasting sorrow<br />
 Imploring total dying, not this blight.<br />
But going through, I will bring you tomorrow<br />
 To souls who, though in pain, stay happy with it,<br />
 Hoping to pay back soon what sin did borrow<br />
And climb salvation’s mount to that first orbit<br />
 To which I must not go. But if you will<br />
 You’ll find at that hill’s top a worthy spirit,<br />
Which I am not, as I did not fulfill<br />
 Writs laid down by that just, all-causing King,<br />
 Combatting what was law. His codicil<br />
About my task thus says: I may not bring<br />
 A pilgrim to his city. Though his might’s<br />
 Ubiquitous, from that city starts its ring<br />
Circling all worlds. O happy, any sights<br />
 Of Him; most so, who in that city strong<br />
 Find bright salvation in its million lights.”<br />
And I to him: “I pray, by your high song —<br />
 And by that God you did not know, I pray —<br />
 That you will as conductor, for as long<br />
As you can do so, bring us on that way<br />
 Of pain, at last to portals which saints hallow,<br />
 And far from this soil’s sorrow.” With no stay<br />
 On did Virgil go; downwards did I follow.</p>

  <p>  —Kinton Ford, 2020 or 2021</p>
</blockquote>

<p>Editorial notes: I adjusted some little punctuation relative to the <em>Exquisite Pandemic</em>
text. For example I removed a comma before “About how” and a period after “stay wary,”
changed a semicolon after “dank” to a period, and inserted commas around “though in pain.”</p>

<p>Though I didn’t alter them above, the confusing lines
“a poignant thrill / Of brutal pain, transfixing with its stings / From that wolf,
did I sob at, and I shrank / Darkwards” seem to detach the phrase “from that wolf”
a bit too much from “I shrank.” One might take this as a cleverly jarring bit of
<a href="https://en.wikipedia.org/wiki/Iconicity">textual iconicity</a> (“I” literally retreating behind
the “sob” to get away from the “wolf”), and/or one might prefer to imagine something more
straightforward like “…stings, / Brought sobs; and, wolf advancing, so I shrank”
or “…stings, / Shot through my gut, and from that wolf I shrank.”
I also find some disorder in the sentence beginning “Upon its skin a rain,”
but I’m less sure what might be done about that or even whether anything ought to be done,
beyond maybe changing the comma after “dawn” to a semicolon.</p>]]></content><author><name></name></author><category term="dante" /><category term="poetry" /><category term="transcription" /><category term="word-ways" /><summary type="html"><![CDATA[In “Varaldo’s Shahrazad and Chiti’s Centunesimo Canto” (2025-08-11) I mentioned the existence of a lipogrammatic translation of Canto I of Dante’s Inferno performed by one Kinton Ford (a pseudonym, as far as I know) for Rick Whitaker’s now-defunct literary e-zine Exquisite Pandemic (2020–2021). A year later, seeing it’s still unavailable anywhere else online, I feel justified in preserving that whole tour-de-force here for posterity.]]></summary></entry><entry><title type="html">How old is Ann?</title><link href="https://quuxplusone.github.io/blog/2026/07/29/how-old-is-ann/" rel="alternate" type="text/html" title="How old is Ann?" /><published>2026-07-29T00:01:00+00:00</published><updated>2026-07-29T00:01:00+00:00</updated><id>https://quuxplusone.github.io/blog/2026/07/29/how-old-is-ann</id><content type="html" xml:base="https://quuxplusone.github.io/blog/2026/07/29/how-old-is-ann/"><![CDATA[<p>From <a href="https://www.nytimes.com/1924/11/17/archives/topics-of-the-times.html">“Topics of the Times,”</a>
<em>New York Times</em> of 1924-11-17:</p>

<blockquote>
  <p>The amount and quality of intelligence utilized in the working out of cross-word
puzzles almost precisely equal those that were revealed some years ago when an
amazing — and discouraging — army of Americans filled the newspapers that cater
to such folk with triumphant solutions of an arithmetical problem concerning the
age of a supposititious Ann — a problem that any eighth-grade boy or girl who is
“all there” should have solved in his or her head in about thirty seconds.</p>
</blockquote>

<p>The older I get, the more sense it makes when the phrase “some years ago” turns out
to refer to something from two decades back. The problem, apparently first published
in the <em>New York World</em> circa 1903-10-09,<sup><a href="#footnote-or-in-the-new-york-pres">[1]</a></sup>
goes like this:</p>

<blockquote>
  <p>Mary is 24 years old. She is twice as old as Ann was
when Mary was as old as Ann is now. How old is Ann?</p>
</blockquote>

<p>(A writer to the <em>Montgomery</em> (Alabama) <em>Advertiser</em> of 1903-10-24
<a href="https://www.loc.gov/resource/sn84020645/1903-10-24/ed-1/?sp=4&amp;r=0.256,0.384,0.348,0.227,0">points out</a>
that you can get the apparently-most-common wrong answer if you read the puzzle
incorrectly as “She <em>was</em> twice as old as Ann was when Mary [sic] was as old as Ann now is.”)</p>

<p>The <em>New York Evening Post</em> (quoted in the <em>Princeton</em> (Minn.) <em>Union</em>)
<a href="https://www.loc.gov/resource/sn83016758/1903-10-29/ed-1/?sp=2">opined</a>:</p>

<blockquote>
  <p>“Wherever it may have originated — and this is itself a matter of
controversy — the problem concerning the ages of Ann and Mary
has caught the country’s fancy as few such things have since
‘<a href="https://en.wikipedia.org/wiki/Charles_Martin_Crandall#Pigs_in_Clover">Pigs in Clover</a>.’ ”</p>
</blockquote>

<p><img src="/blog/images/2026-07-29-ann-in-panama.jpg" alt="Flinn, in the Evening World of 1903-11-12" class="float-right" /></p>

<p><a href="https://archive.org/details/sim_billboard_1904-02-20_16_8/page/n1"><em>Billboard</em></a>
(1904-02-20): “The question ‘How Old Is Ann?’ has been dramatized
and was staged at White Plains. Barney Gerard, the author, makes Ann a mischievous
little girl, who refuses to go to school. The school authorities get after her to
punish her but must first find out how old she is. Complications result.” •
The <a href="https://www.loc.gov/resource/sn83030193/1903-11-17/ed-1/?sp=5"><em>New York Evening World</em></a>
(1903-11-17): “ ‘How Old Is Ann?’ is the title
of a new song which Frank Daniels sang last night at the Victoria
Theatre. When the opening lines sounded the audience settled back in its seats with
a sigh of relief. ‘At last,’ it meant just as if it was expressed in words,
‘we are going to find out how old that cussed sister of Mary is.’ But they didn’t,
and there’s where the fun came in. The song has a rattling chorus and a catchy tune.” •
Cartoonist <a href="https://strippersguide.blogspot.com/2018/02/ink-slinger-profiles-by-alex-jay-ed-f.html">Ed F. Flinn</a>
<a href="https://www.loc.gov/resource/sn83030193/1903-11-12/ed-1/?sp=10">fingered</a> Ann as the cause of the
<a href="https://en.wikipedia.org/wiki/Secession_of_Panama_from_Colombia">Panamanian secession</a>. •
The <em>World</em> of 1903-11-07 <a href="https://www.loc.gov/resource/sn83030193/1903-11-07/ed-1/?sp=4&amp;r=0.259,0.412,0.254,0.241,0">“revealed”</a>
the perpetrator of the problem as one “Mr.
<a href="https://en.wikipedia.org/wiki/Perkin_Warbeck">Perkin Warbeck</a>, of Newark, N.J.”</p>

<p>The <em>Philadelphia North American</em>
<a href="https://www.loc.gov/resource/sn86092356/1903-10-19/ed-1/?sp=2&amp;r=0.277,0.053,0.313,0.297,0">published</a>
“the answers of a few leading Philadelphians.”</p>

<blockquote>
  <p>“I don’t see why that simple question is puzzling anybody. I
knew Ann is 12 years old as soon as I saw the problem,” said
<a href="https://www.findagrave.com/memorial/91217774/frank_r-shattuck">Frank R. Shattuck</a>.
“There is no other solution, I tell you. Look here, I’ll explain
it to you. Mary is 24 years old. She is twice as old as Ann —
that’s a cinch. Of course, then, Ann is half Mary’s age, or 12
years. There ought to be a comma after ‘Ann,’ though.”</p>

  <p>It was suggested to Mr. Shattuck that there was no comma in the problem.</p>

  <p>“Doesn’t make any difference,” replied he promptly.
“Let’s see — twice as old as Ann ‘was.’ That ought to be ‘is’ —
as Mary was when Ann is. I’m not mixed up. I tell you, Ann is 12.”</p>
</blockquote>

<p>Not to be outdone, the <em>New York Evening World</em> published
on <a href="https://www.loc.gov/resource/sn83030193/1903-11-09/ed-1/?sp=5">1903-11-09</a>
and <a href="https://www.loc.gov/resource/sn83030193/1903-11-10/ed-1/?sp=9">1903-11-10</a>
the answers of “many prominent men of New York,” including:</p>

<blockquote>
  <p><span class="sc">Policeman Bert Gallagher:</span> “Ann is old enough to know better
than not tell her age when she knows how much trouble her silence is causing.
She ought to be ashamed.”</p>

  <!-- https://archive.org/details/sim_new-york-times_the-new-york-times_1912-10-28_62_20001/page/n10/mode/1up -->
  <p><span class="sc"><a href="https://archive.is/NLodr">John T. Meehan</a>:</span> “Ann was ninety years old. I know, because
she and her brother shook hands with Lafayette on his visit to New York in 1824.
Old Peter was the steward of the beanery for forty years, and he was ninety-two when
he died; Ann was three years younger. He and Ann used to sell newspapers on the
Vesey Street corner during Jackson’s first term. Why, Ann was— Oh, that <em>World</em>
question about the girl who’s twice as old as herself? I haven’t time to fuss
with that. I thought you were talking about old Peter Rose’s sister Ann.”</p>

  <!-- https://www.findagrave.com/memorial/187561976/timothy_patrick-sullivan -->
  <p><span class="sc"><a href="https://archive.is/FpboI">Timothy P. Sullivan</a>:</span>
“Just twice as old as she was when Mary was twice as old as Ann. That’s easy.
Six years ago Mary was eighteen and Ann was thirteen. To-day Mary is twenty-four
and Ann is nineteen. Figure it out for yourself. Don’t you see that if Mary
is twice as old as Ann was when Mary was— I mean twice as old as Mary when Ann
was half as old as Mary, consequently— but there, let the professors figure it
out. It’s as bad as <a href="https://wordhistories.net/2020/04/20/why-mouse-when-spins/">‘when is a mice when it spins.’</a> ”</p>
</blockquote>

<p>The <em>Wyoming Tribune</em> of 1903-10-28 calls it
<a href="https://www.loc.gov/resource/sn83025231/1903-10-28/ed-1/?sp=8">“No Puzzle At All”</a>:</p>

<blockquote>
  <p>Anyone could figure it out if they would stop to think. Ann is 16, of course,
because if Mary is twice as old as Ann was, all you have to do is to find out
when. Now she is 24, Ann’s age was 12, or twice six. Mary is now four times six,
which being divided by six, gives four. Add this to twelve, and there you are. <span class="sc">—Smith.</span></p>
</blockquote>

<p>adding:</p>

<blockquote>
  <p>When Mary had a little lamb, she was twice as old as Ann was when Ann was as old
as Mary now claims to be. How old is the sheep? <span class="sc">—James Barton Adams.</span></p>
</blockquote>

<p>A correspondent for the <em>Kansas Journal</em>
<a href="https://www.loc.gov/resource/sn83030214/1903-10-18/ed-1/?sp=8">wrote</a>:</p>

<blockquote>
  <p><span class="sc">Constant Reader,</span><br />
Ann is sixty-three years of age. Obviously,
Ann is as old now as Mary was when Mary was
half as old as her present age less the age of Ann
at the time she was half as old as Mary was when
she was twice as old as Ann is, unless you figure
that Ann was half as old as if she were twice
Mary’s present age, less Ann’s age when she was
twice as old as Mary is now, or twenty-four.
Twenty-four and fifteen are thirty-nine, and
twenty-four and thirty-nine are sixty-three, which
represents Mary’s present age subtracted from half
of Mary’s age at the time she was half as old as
Ann. I would not solve this problem for any one
but a constant reader.</p>
</blockquote>

<p>The <em>Washington Times</em> of 1903-10-27
<a href="https://www.loc.gov/resource/sn84026749/1903-10-27/ed-1/?sp=6&amp;r=0.418,0.568,0.155,0.147,0">prints</a>
an anonymous poet’s take:</p>

<blockquote>
  <p>I used to be contented and took comfort in my life,<br />
I dwelt in deep placidity, removed from care and strife,<br />
I never worried as I jogged along my even way,<br />
I worked a bit, I slept a bit, and still had time for play;<br />
I never had such things as nerves; my brain was clear and cool,<br />
But now I am a nervous wreck, and soon will be a fool.</p>

  <p>It came about in this wise: One fell day a genial friend,<br />
Whose mind is full of whist and chess and problems without end,<br />
Propounded in a guileless way a problem which, to scan,<br />
Seemed simple: All you had to do was find the age of Ann.<br />
Now, Ann is Mary’s sister, which you’ve no doubt heard before,<br />
And Mary— it is impolite, but Mary’s twenty-four.</p>

  <p>Now, Mary’s twenty-four, and she is twice as old today<br />
As Ann was when her sister was — that is, of course, to say,<br />
When Mary was — as old as Mary’s sister Ann is now.<br />
Which brings the question up to you: What’s Ann’s age, anyhow?<br />
That’s what my friend propounded, and I answered, at a pinch,<br />
“The problem you propound, sir, is dead easy — it’s a cinch.”</p>

  <p>I worked all day upon it, and I also worked all night,<br />
But somehow that confounded thing would never come out right:<br />
At first I figured it that Ann was twelve, then eight, then ten,<br />
And then I twisted it around and worked it out again.<br />
This time I learned, to my dismay, that figures disagree:<br />
That although Mary’s twenty-four, her sister’s sixty-three!</p>

  <p>I raved and swore; my hair I tore; I vented all my spleen<br />
Upon some luckless wight who said that Ann was sweet sixteen.<br />
I’ve worried nights, I’ve worried days, I cannot eat my meals;<br />
I jabber those confounded words until my poor brain reels;<br />
If this thing keeps up many moons, good-bye, old world — farewell!<br />
For me ’twill be the welcome grave, or else the padded cell.</p>
</blockquote>

<p>(A less entertaining, but more democratic, sampling of “Ann” correspondence
<a href="https://www.loc.gov/resource/sn83030193/1903-11-11/ed-1/?sp=5">appears</a>
in the <em>Evening World</em> of 1903-11-11.)</p>

<p>The craze was short-lived. By 1903-12-21 “Prof. Josh M. A. Long”
of the Society for the Prevention of Cruelty to Humor was
<a href="https://www.loc.gov/resource/sn83030193/1903-12-21/ed-1/?sp=13">advertising</a>
in the <em>World</em> for any information as to
“the whereabouts of ‘How Old Is Ann?’ Has been missing about ten days.
Recently released from the Old Jokes’ Home, last heard of in Harlem.”</p>

<hr />

<p>Footnote: Or in the <em>New York Press</em> of 1903-10-12, signed “John Mahon,”
if you believe a column from 1937
(<a href="https://panewsarchive.psu.edu/lccn/sn83031981/1937-11-26/ed-1/seq-5/"><em>Bellefonte</em> (Penn.) <em>Democratic-Watchman</em></a> 1937-11-26;
<a href="https://www.virginiachronicle.com/?a=d&amp;d=TSHE19371223.1.3"><em>South Hill</em> (Va.) <em>Enterprise</em></a> 1937-12-23).
Or maybe the <em>Press</em> of 1903-10-16
(<a href="https://www.virginiachronicle.com/?a=d&amp;d=HR19511005.1.2&amp;srpos=4"><em>Highland</em> (Va.) <em>Recorder</em></a> 1951-10-05).</p>

<p>But the true story, as <a href="https://archive.org/details/presbyterianstan47pres_0/page/n1220">relayed</a>
by <a href="https://www.findagrave.com/memorial/104101857/william_james-lampton">William J. Lampton</a>
in a <em>Scrap-Book</em> article titled <a href="https://babel.hathitrust.org/cgi/pt?id=njp.32101064164740&amp;seq=1116">“The Vicissitudes of a Problem”</a>
(August 1906), is that “How old is Ann?” first appeared in the <em>Newark Evening News</em> of 1903-04-21,
headlined <a href="https://newark.historyarchives.online/viewer?d=04011903-04301903&amp;cid=3401&amp;fn=newark_evening_news_usa_new_jersey_newark_19030421_english_6">“Stories of the Town.”</a>
The author was one <a href="https://www.findagrave.com/memorial/227767391/robert_duke-towne">Robert D. Towne</a>;
and when the meme didn’t catch at first in Newark, he tried again, Lampton says,
by sending it to the <em>Philadelphia North American</em> and signing it “Perkin Warbeck.”
Towne certainly let it be known that he was the “Ann” man
(<a href="https://archive.org/details/sim_editor-publisher_1905-02-11_4_38/page/2">1</a>,
<a href="https://archive.org/details/sim_editor-publisher_1911-02-25_10_35/page/2">2</a>,
<a href="https://archive.org/details/sim_editor-publisher_1903-12-19_3_26/page/n14">3</a>),
earning his obituary a spot among <em>Time</em> magazine’s
<a href="https://time.com/archive/6825337/milestones-mar-3-1952/">“Milestones”</a> of 1952-03-03.</p>

<hr />

<p>Now hear this, from the <em>Sequachee Valley</em> (Tenn.) <em>News</em> of
<a href="https://www.loc.gov/resource/sn89058250/1903-10-29/ed-1/?sp=1">1903-10-29</a>:</p>

<blockquote>
  <p>A man is twice the age his wife was when he was the age she is now.
When she reaches his present age, their combined years will be 100.
Find the age of each.</p>
</blockquote>

<p>See also:</p>

<ul>
  <li><a href="/blog/2019/08/01/what-is-8-divided-by-2-etc-etc/">“What is 8÷2(2+2)?”</a> (2019-08-01)</li>
</ul>]]></content><author><name></name></author><category term="jokes" /><category term="math" /><category term="memes" /><category term="old-shit" /><category term="poetry" /><category term="puzzles" /><summary type="html"><![CDATA[From “Topics of the Times,” New York Times of 1924-11-17:]]></summary></entry></feed>