The Universe of Discourse
http://blog.plover.com
The Universe of Discourse (Mark Dominus Blog)enWhy my book can be downloaded for free
http://blog.plover.com/2014/12/01#free-hop
<p>People are frequently surprised that my book, <em><a href="http://hop.perl.plover.com">Higher-Order
Perl</a></em>, is available as <a href="http://hop.perl.plover.com/book/">a free download
from my web site</a>. They ask if it
spoiled my sales, or if it was hard to convince the publisher. No and
no.</p>
<p>I sent the HOP proposal to five publishers, expecting that two or three would
turn it down, and that I would pick from the remaining two or three,
but somewhat to my dismay, all five offered to publish it, and I had
to decide who.</p>
<p>One of the five publishers was Morgan Kaufmann. I had never heard of
Morgan Kaufmann, but one day around 2002 I was reading the web site of
<a href="https://blogs.law.harvard.edu/philg/">Philip Greenspun</a>. Greenspun
was incredibly grouchy. He found fault with everything. But he had
nothing but praise for Morgan Kaufmann. I thought that if Morgan
Kaufmann had pleased Greenspun, who was nearly impossible to please,
then they must be really good, so I sent them the proposal. (They
eventually published the book, and did a superb job; I have never
regretted choosing them.)</p>
<p>But not only Morgan Kaufmann but four other publishers had offered to
publish the book. So I asked a number of people for advice. I
happened to be in London one week and Greenspun was giving a talk
there, which I went to see. After the talk I introduced myself and
asked for his advice about picking the publisher.</p>
<p>Greenspun reiterated his support for Morgan Kaufmann, but added that
the publisher was not important. Instead, he said, I should make sure
to negotiate permission to make the book available for free on my web
site. He told me that compared with the effort that you put into the
book, the money you get back is insignificant. So if you write a book
it should not be because you want to make a lot of money from it but
because you have an idea that you want to present to the world. And
as an author, you owe it to yourself to get your idea in front of as
many people as possible. By putting the book in your web site, you
make it available to many people who would not otherwise have access
to it: poor people, high school students, people in developing
countries, and so on.</p>
<p>I thought that Greenspun's idea made sense; I wanted my ideas about
programming to get to as many people as possible. Also, demanding
that I make the book available on my web site for free seemed like a
good way to narrow down the five publishers to two or three.</p>
<p>The first part of that plan worked out well. The second part not so
well: all five publishers agreed. Some agreed reluctantly and some
agreed willingly, but they all agreed. Eventually I had the book
published by Morgan Kaufmann, and after a delay that seemed long at
the time but in retrospect seems not so long, I put the book on my web
site. It has been downloaded many times. (It's hard to say how many,
since browsers often download just the portion of the PDF file that
they need to display.)</p>
<p>Would the book have made more money if it were not available as a free
download? We can't know for sure, but I don't think so. The book has
always sold well, and has made a significant amount of money for me
and for Morgan Kaufmann. The amount I made is small compared to the
amount of work I had to put in, just as Greenspun said, but it was
nothing to sneeze at either. Even now, ten years later, it is still
selling and I still get a royalty check every six months. For my book
to have lasted ten years is extremely rare. Most computer books
disappear without a trace after six months.</p>
<p>Part of this is that it's an unusually good book. But I think the
longevity is partly because it is available as a free
download. Imagine that person A asks a question on an Internet forum,
and person B says that HOP has a section that could help with the
question. If B wants to follow up, they now must find a copy of HOP.
If the book is out of print, this can be difficult. It may not be in
the library; it almost certainly isn't in the bookstore. Used copies
may be available, but you have to order them and have them shipped,
and if you don't like it once it arrives, you are stuck with it. The
barrier is just too high to be convenient. But since HOP is available
on my web site, A can include a link, or B can find it with an easy
web search. The barrier is gone! And now I have another reader who
might mention it to someone else, and they might even buy a copy.
Instead of drifting away into obscurity, HOP is a book that people can
recommend over and over.</p>
<p>So my conclusion is, Greenspun's advice was exactly correct. As an
author, you owe it to yourself to make your book available to as many
people as possible. And the publisher may agree, so be sure to ask.</p>
<p>[ Addendum: Some people are just getting the news, but the book was published in 2005, and has been available as a free download since 2008. ]</p>
Impostor syndrome
http://blog.plover.com/2014/11/30#impostor
<p>I don't have impostor syndrome about programming, advanced
mathematics, or public speaking. I cheerfully stand up in rooms
full of professional programmers and authoritatively tell them
what I think they should do.</p>
<p><a href="http://pic.blog.plover.com/brain/impostor/shelves.jpg"><img align="right" border=0 src="http://pic.blog.plover.com/brain/impostor/shelves-th.jpg"></a></p>
<p>However, when I put up shelves in the bathroom back in May, I
was a psychological mess. For every little thing that went
wrong—and there were quite a lot—I got all stressed out and
wondered why I dared to perform this task. The outcome was
good, but I had a lot of stress getting there.</p>
<p>I put in one plexiglass shelf, for which I had bought heavy-duty
wall anchors in case the kids leaned on it, and two metal
shelves higher up, which came with their own screws and anchors.</p>
<p>Here's a partial list of things that worried me:</p>
<ol>
<li>The two upper shelves came with a paper template that I held up to
the wall to mark where the holes should be drilled. What if the
two shelves were slightly different and their templates were
different and I needed to use both templates on the wall instead of
using the same template twice?</li>
<li>When I putting the heavy-duty wall anchors into the drywall, big
divots of plaster fell out of the wall around the anchors.</li>
<li>Then I filled in the holes with filler, and got filler in the screw holes
in the wall anchors, and stressed about this. What if the filler in
the sockets somehow prevented the screws from going into the
anchors or caused some other unforeseeable problem?</li>
<li>The filler looked sloppy and I worried that it would look absurdly
ugly to everyone who came into the bathroom. (The shelf would have hidden the ugly screw job from a normal view,
except that it was made of
plexiglass, so the filled holes were visible through it.)</li>
<li>I didn't know how big to drill the holes for the smaller wall
anchors and stressed about it, examining the wall anchor packaging
for some hint. There was none.</li>
<li>I wanted to insert the wall anchors into the holes with my rubber
mallet. Where the hell is it? Then I stressed about using a
claw hammer instead and maybe squishing the anchors, and spent a
while looking for a piece of wood or something to soften the hammer
blows. Eventually I gave up looking, wondering if I was dooming the
project.</li>
<li>I guessed how big to make the hole for the anchor, and was wrong;
my hole was too small. I didn't realize this until I had the first
anchor halfway in. Then I stressed that I might ruin it when I
pulled it back out of the wall.</li>
<li>Then I stressed about the size of the holes <em>again</em> when I drilled
larger holes. What if I make the hole too big, and then have to
fill all the holes and re-measure and re-drill the whole thing?</li>
<li>The anchors didn't go into two of the holes. I needed to yank them
back out, then redrill the holes, with the outer end a little
messy, or the anchors wouldn't go all the way into the holes.
Again I worried about spoiling the anchors.</li>
<li>When I drilled the holes, sometimes the drill suddenly went all the
way into the wall and the rotating chuck left a circular scar on
the paint.</li>
<li>Also, two of the holes didn't drill easily; I had to lean on the
drill really hard to get it to go through. For a while I was
concerned that there was some undrillable metal thing in the wall
<em>just</em> where I wanted my hole, and I would have to fill in all the
holes and remeasure and redrill the whole thing.</li>
<li>Even though I had marked the wall for the lower shelf by holding
the shelf against the wall and then poking a pencil through the
actual holes, when time came to put the bolts in place, I found
that the two holes were slightly too far apart. Somehow this
worked itself out.</li>
</ol>
<p>On review, I see that several of these worries could have been
completely avoided if I had had a supply of extra wall anchors.</p>
<p>Stuff that could have worried me but (rightly or wrongly) didn't:</p>
<ol>
<li><p>I knew enough to go to the store to buy wall anchors and
screws for the bottom shelf, which did not come with its own
hardware. There are a lot of different kinds of anchors, and
I did not worry too much that I was getting the wrong thing.</p></li>
<li><p>I was concerned (although not <em>worried</em>) that the screws
holding the bottom shelf to the wall might stress the plastic
too much and cause it to crack, either immediately or over
time. Obvious solution: insert washers between the screw
heads and the shelf. I went to the hardware store to get
nylon washers; they didn't have any. So I got thin metal
washers instead. I did <em>not</em> worry about this; I was sure
(perhaps wrongly) that metal washers would do the job.</p></li>
<li><p>When I asked the hardware people for plastic washers, they looked
totally blank. “Plastic... washers?” they asked, as if this were a
heretofore unimaginable combination. I could have felt like an
idiot, but instead I felt, correctly I think, that <em>they</em> were
idiots.</p></li>
<li><p>For some reason, I was not even slightly worried about properly
leveling the marks for the holes. I used a spirit level, which I
consider pretty fancy.</p></li>
<li><p>I was careful not to over-tighten the screws holding the
plexiglass shelf in place, so as to avoid cracking them, but
I was at no time afraid that I would somehow crack them
anyway.</p></li>
</ol>
<p>[Added in July: I have reread this article for the first time. I can
report that all the worries I had about whether the shelves would look
good have come to nothing; they all look just fine and I had forgotten
all the things I was afraid would look bad. But I really do need to
buy a couple of boxes of plastic wall anchors so I can stop worrying
about spoiling the four I have.]</p>
<p>[The shelves look crooked in the picture, but that is because I am
holding the camera crooked; in real life they look great.]</p>
<p>[ A later
visit to a better hardware store confirmed that plastic washers do
exist, and I did not hallucinate them. The rubber mallet still has not come to light.]</p>
Within this instrument, resides the Universe
http://blog.plover.com/2014/11/22#algebra
<p>When opportunity permits, I have been trying to teach my ten-year-old
daughter rudiments of algebra and group theory. Last night I posed
this problem:</p>
<blockquote>
<p>Mary and Sue are sisters. Today, Mary is three times as old as Sue;
in two years, she will be twice as old as Sue. How old are they
now?</p>
</blockquote>
<p>I have tried to teach Ms. 10 that these problems have several
phases. In the first phase you translate the problem into algebra, and
then in the second phase you manipulate the symbols, almost
mechanically, until the answer pops out as if by magic.</p>
<p>There is a third phase, which is pedagogically and practically
essential. This is to check that the solution is correct by
translating the results back to the context of the original problem.
It's surprising how often teachers neglect this step; it is as if a
magician who had made a rabbit vanish from behind a screen then
forgot to take away the screen to show the audience that the rabbit
had vanished.</p>
<p>Ms. 10 set up the equations, not as I would have done, but using four
unknowns, to represent the two ages today and the two ages in the
future:</p>
<p>$$\begin{align}
MT & = 3ST \\
MY & = 2SY \\
\end{align}
$$</p>
<p>(<img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24MT%24"> here is the name of a single variable, not a product of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24M%24">
and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24T%24">; the others should be understood similarly.)</p>
<p>“Good so far,” I said, “but you have four unknowns and only two
equations. You need to find two more relationships between the
unknowns.” She thought a bit and then wrote down the other two
relations:</p>
<p>$$\begin{align}
MY & = MT + 2 \\
SY & = ST + 2
\end{align}
$$</p>
<p>I would have written two equations in two unknowns:</p>
<p>$$\begin{align}
M_T & = 3S_T\\
M_T+2 & = 2(S_T + 2)
\end{align}
$$</p>
<p>but one of the best things about mathematics is that there are many
ways to solve each problem, and no method is privileged above any
other except perhaps for reasons of practicality. Ms. 10's translation
is different from what I would have done, and it requires more work in
phase 2, but it is correct, and I am not going to tell her to do it my
way. The method works <em>both</em> ways; this is one of its best features.
If the problem can be solved by thinking of it as a problem in two
unknowns, then it can <em>also</em> be solved by thinking of it as a problem
in four or in eleven unknowns. You need to find more relationships,
but they must exist and they can be found.</p>
<p>Ms. 10 may eventually want to learn a technically easier way to do it,
but to teach that right now would be what programmers call a premature
optimization. If her formulation of the problem requires more symbol
manipulation than what I would have done, that is all right; she needs
practice manipulating the symbols anyway.</p>
<p>She went ahead with the manipulations, reducing the system of four
equations to three, then two and then one, solving the one equation to
find the value of the single remaining unknown, and then substituting
that value back to find the other unknowns. One nice thing about these
simple problems is that when the solution is correct you can see it at
a glance: Mary is six years old and Sue is two, and in two years they
will be eight and four. Ms. 10 loves picking values for the unknowns
ahead of time, writing down a random set of relations among those
values, and then working the method and seeing the correct answer pop
out. I remember being endlessly delighted by almost the same thing
when I was a little older than her. In <em>The Dying Earth</em> Jack Vance
writes of a wizard who travels to an alternate universe to learn from
the master “the secret of renewed youth, many spells of the ancients,
and a strange abstract lore that Pandelume termed ‘Mathematics.’”</p>
<blockquote>
<p>“I find herein a wonderful beauty,” he told
Pandelume. “This is no science, this is art, where equations fall
away to elements like resolving chords, and where always prevails a
symmetry either explicit or multiplex, but always of a crystalline
serenity.”</p>
</blockquote>
<p>After Ms. 10 had solved this problem, I asked if she was game for
something a little weird, and she said she was, so I asked her:</p>
<blockquote>
<p>Mary and Sue are sisters. Today, Mary is three times as old as Sue;
in two years, they will be the same age. How old are they
now?</p>
</blockquote>
<p>“WHAAAAAT?” she said. She has a good number sense, and immediately
saw that this was a strange set of conditions. (If they aren't the
same age now, how can they be the same age in two years?) She asked
me what would happen. I said (truthfully) that I wasn't sure, and
suggested she work through it to find out. So she set up
the equations as before and worked out the solution, which is obvious
<em>once you see it</em>: Both girls are zero years old today, and zero is
three times as old as zero. Ms. 10 was thrilled and delighted, and
shared her discovery with her mother and her aunt.</p>
<p>There are some powerful lessons here. One is that the method works
even when the conditions seem to make no sense; often the results pop
out just the same, and can sometimes make sense of problems that seem
ill-posed or impossible. Once you have set up the equations, you can
just push the symbols around and the answer will emerge, like a
familiar building approached through a fog.</p>
<p>But another lesson, only hinted at so far, is that mathematics has its
own way of understanding things, and this is not always the way that
humans understand them. Goethe famously said that whatever you say to
mathematicians, they immediately translate it into their own language
and then it is something different; I think this is exactly what he
meant.</p>
<p>In this case it is not too much of a stretch to agree that Mary is
three times as old as Sue when they are both zero years old. But in
the future I plan to give Ms. 10 a problem that requires Mary and Sue
to have negative ages—say that Mary is twice as old as Sue today, but
in three years Sue will be twice as old—to demonstrate that the answer
that pops out may not be a reasonable one, or that the original
translation into mathematics can lose essential features of the
original problem. The solution that says that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24M_T%3d%2d2%2c%20S_T%3d%2d1%20%24"> is
mathematically irreproachable, and if the original problem had been
posed as “Find two numbers such that…” it would be perfectly correct.
But translated back to the original context of a problem that asks
about the ages of two sisters, the solution is unacceptable. This is
the point of the joke about the spherical cow.</p>
When do n and 2n have the same digits?
http://blog.plover.com/2014/07/23#dd
<p>[This article was published last month on <a href="http://math.blogoverflow.com/">the math.stackexchange
blog</a>, which seems to have died young,
despite many earnest-sounding promises beforehand from people who
claimed they would contribute material. I am repatriating it here.]</p>
<p>A <a href="http://math.stackexchange.com/questions/782334/interview-question-asked-in-yahoo?">recent question on math.stackexchange</a> asks for the smallest positive integer <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> for which the number <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242A%24"> has the same
decimal digits in some other order.</p>
<p>Math geeks may immediately realize that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24142857%24"> has this property, because it is the first 6 digits of the decimal expansion of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%2017%24">, and the cyclic behavior of the decimal expansion of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%20n7%24"> is well-known. But is this the <em>minimal</em> solution? It is not. Brute-force enumeration of the solutions quickly reveals that there are 12 solutions of 6 digits each, all permutations of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24142857%24">, and that larger solutions, such as 1025874 and 1257489 seem to follow a similar pattern. What is happening here?</p>
<p>Stuck in Dallas-Fort Worth airport one weekend, I did some work on the problem, and although I wasn't able to solve it completely, I made significant progress. I found a method that allows one to hand-calculate that there is no solution with fewer than six digits, and to enumerate all the solutions with 6 digits, including the minimal one. I found an explanation for the surprising behavior that solutions tend to be permutations of one another. The short form of the explanation is that there are fairly strict conditions on which <em>sets</em> of digits can appear in a solution of the problem. But once the set of digits is chosen, the conditions on that <em>order</em> of the digits in the solution are fairly lax.</p>
<p>So one typically sees, not only in base 10 but in other bases, that the solutions to this problem fall into a few classes that are all permutations of one another; this is exactly what happens in base 10 where all the 6-digit solutions are permutations of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24124578%24">. As the number of digits is allowed to increase, the strict first set of conditions relaxes a little, and other digit groups appear as solutions.</p>
<h3>Notation</h3>
<p>The property of interest, <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P_R%28A%29%24">, is that the numbers <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24B%3d2A%24"> have exactly the same base-<img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%24"> digits. We would like to find numbers <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> having property <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P_R%24"> for various <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%24">, and we are most interested in <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%3d10%24">. Suppose <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> is an <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">-digit numeral having property <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P_R%24">; let the (base-<img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%24">) digits of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> be <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_%7bn%2d1%7d%5cldots%20a_1a_0%24"> and similarly the digits of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24B%20%3d%202A%24"> are <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_%7bn%2d1%7d%5cldots%20b_1b_0%24">. The reader is encouraged to keep in mind the simple example of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%3d8%2c%20n%3d4%2c%20A%3d%5cmathtt%7b1042%7d%2c%20B%3d%5cmathtt%7b2104%7d%24"> which we will bring up from time to time.</p>
<p>Since the digits of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24B%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> are the same, in a different order, we may say that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_i%20%3d%20a_%7bP%28i%29%7d%24"> for some permutation <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24">. In general <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> might have more than one cycle, but we will suppose that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is a single cycle. All the following discussion of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> will apply to the individual cycles of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> in the case that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is a product of two or more cycles. For our example of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%3d%5cmathtt%7b1042%7d%2c%20b%3d%5cmathtt%7b2104%7d%24">, we have <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%20%3d%20%280%5c%2c1%5c%2c2%5c%2c3%29%24"> in cycle notation. We won't need to worry about the details of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24">, except to note that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24i%2c%20P%28i%29%2c%20P%28P%28i%29%29%2c%20%5cldots%2c%20P%5e%7bn%2d1%7d%28i%29%24"> completely exhaust the indices <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240%2e%20%5cldots%20n%2d1%24">, and that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%5en%28i%29%20%3d%20i%24"> because <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is an <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">-cycle.</p>
<h3>Conditions on the set of digits in a solution</h3>
<p>For each <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24i%24"> we have $$a_{P(i)} = b_{i} \equiv 2a_{i} + c_i\pmod R
$$ where the ‘carry bit’ <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c_i%24"> is either 0 or 1 and depends on whether there was a carry when doubling <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_%7bi%2d1%7d%24">. (When <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24i%3d0%24"> we are in the rightmost position and there is never a carry, so <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c_0%3d%200%24">.) We can then write:</p>
<p>$$\begin{align}
a_{P(P(i))} &= 2a_{P(i)} + c_{P(i)} \\
&= 2(2a_{i} + c_i) + c_{P(i)} &&= 4a_i + 2c_i + c_{P(i)}\\
a_{P(P(P(i)))} &= 2(4a_i + 2c_i + c_{P(P(i)})) + c_{P(i)} &&= 8a_i + 4c_i + 2c_{P(i)} + c_{P(P(i))}\\
&&&\vdots\\
a_{P^n(i)} &&&= 2^na_i + v
\end{align}
$$</p>
<p>all equations taken <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cbmod%20R%24">. But since <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is an <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">-cycle, <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%5en%28i%29%20%3d%20i%24">, so we have
$$a_i \equiv 2^na_i + v\pmod R$$ or equivalently $$\big(2^n-1\big)a_i + v \equiv 0\pmod
R\tag{$\star$}$$ where <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%5cin%5c%7b0%2c%5cldots%202%5en%2d1%5c%7d%24"> depends only on the values of the carry bits <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c_i%24">—the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c_i%24"> are precisely the binary digits of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24">.</p>
<p>Specifying a particular value of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_0%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> that satisfy this equation completely determines all the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%24">. For example, <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_0%20%3d%202%2c%20v%20%3d%20%5ccolor%7bdarkblue%7d%7b0010%7d_2%20%3d%202%24"> is a solution when <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%3d8%2c%20n%3d4%24"> because <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cbigl%282%5e4%2d1%5cbigr%29%5ccdot2%20%2b%202%5cequiv%200%5cpmod%208%24">, and this solution allows us to compute</p>
<p>$$\def\db#1{\color{darkblue}{#1}}\begin{align}
a_0&&&=2\\
a_{P(0)} &= 2a_0 &+ \db0 &= 4\\
a_{P^2(0)} &= 2a_{P(0)} &+ \db0 &= 0 \\
a_{P^3(0)} &= 2a_{P^2(0)} &+ \db1 &= 1\\ \hline
a_{P^4(0)} &= 2a_{P^3(0)} &+ \db0 &= 2\\
\end{align}$$</p>
<p>where the carry bits <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c_i%20%3d%20%5clangle%200%2c0%2c1%2c0%5crangle%24"> are visible in the third column, and all the sums are taken <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cpmod%208%24">. Note that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_%7bP%5en%280%29%7d%20%3d%20a_0%24"> as promised. This derivation of the entire set of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%24"> from a single one plus a choice of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> is crucial, so let's see one more example. Let's consider <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%3d10%2c%20n%3d3%24">. Then we want to choose <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_0%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> so that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cleft%282%5e3%2d1%5cright%29a_0%20%2b%20v%20%5cequiv%200%5cpmod%7b10%7d%24"> where <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%5cin%5c%7b0%5cldots%207%5c%7d%24">. One possible solution is <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%5c_0%20%3d%205%2c%20v%3d%5ccolor%7bdarkblue%7d%7b101%7d%5c_2%20%3d%205%24">. Then we can derive the other <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%24"> as follows:</p>
<p>$$\begin{align}
a_0&&&=5\\
a_{P(0)} &= 2a_0 &+ \db1 &= 1\\
a_{P^2(0)} &= 2a_{P(0)} &+ \db0 &= 2 \\\hline
a_{P^3(0)} &= 2a_{P^2(0)} &+ \db1 &= 5\\
\end{align}$$</p>
<p>And again we have <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_%7bP%5en%280%29%7d%3d%20a_0%24"> as required.</p>
<p>Since the bits of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> are used cyclically, not every pair of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%20a_0%2c%20v%5crangle%24"> will yield a different solution. Rotating the bits of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> and pairing them with different choices of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_0%24"> will yield the same cycle of digits starting from a different place. In the first example above, we had <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_0%20%3d%202%2c%20v%20%3d%200010_2%20%3d%202%24">. If we were to take <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_0%20%3d%204%2c%20v%20%3d%200100_2%20%3d%204%24"> (which also solves <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%28%5cstar%29%24">) we would get the same cycle of values of the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%24"> but starting from <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%244%24"> instead of from <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%24">, and similarly if we take <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_0%3d0%2c%20v%20%3d%201000_2%20%3d%208%24"> or <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_0%20%3d%201%2c%20v%20%3d%200001_2%24">. So we can narrow down the solution set of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%28%5cstar%29%24"> by considering only the so-called <a href="https://en.wikipedia.org/wiki/Bracelet_%28combinatorics%29">bracelets</a> of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> rather than all <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%5en%24"> possible values. Two values of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> are considered equivalent as bracelets if one is a rotation of the other. When a set of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24">-values are equivalent as bracelets, we need only consider one of them; the others will give the same cyclic sequence of digits, but starting in a different place. For <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d4%24">, for example, the bracelets are <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240000%2c%200001%2c%200011%2c%200101%2c%200111%2c%20%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241111%24">; the sequences <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240110%2c%201100%2c%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241001%24"> being equivalent to <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240011%24">, and so on.</p>
<h4>Example</h4>
<p>Let us take <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%3d9%2c%20n%3d3%24">, so we want to find 3-digit numerals with property <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P_9%24">. According to <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%28%5cstar%29%24"> we need <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%247a_i%20%2b%20v%20%5cequiv%200%5cpmod%7b9%7d%24"> where <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%5cin%5c%7b0%5cldots%0a7%5c%7d%24">. There are 9 possible values for <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%24">; for each one there is at most one possible value of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> that makes the sum zero:</p>
<p>$$\pi \approx 3 $$</p>
<p>$$\begin{array}{rrr}
a_i & 7a_i & v \\ \hline
0 & 0 & 0 \\
1 & 7 & 2 \\
2 & 14 & 4 \\
3 & 21 & 6 \\
4 & 28 & \\
5 & 35 & 1 \\
6 & 42 & 3 \\
7 & 49 & 5 \\
8 & 56 & 7 \\
\end{array}
$$</p>
<p>(For <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%3d4%24"> there is no solution.) We may disregard the non-bracelet values of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24">, as these will give us solutions that are the same as those given by bracelet values of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24">. The bracelets are:</p>
<p>$$\begin{array}{rl} 000 & 0 \\ 001 & 1 \\ 011 & 3 \\ 111 & 7 \end{array}$$</p>
<p>so we may disregard the solutions exacpt when <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%3d0%2c1%2c3%2c7%24">. Calculating the digit sequences from these four values of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> and the corresponding <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%24"> we find:</p>
<p>$$\begin{array}{ccl}
a_0 & v & \text{digits} \\ \hline
0 & 0 & 000 \\
5 & 1 & 512 \\
6 & 3 & 637 \\
8 & 7 & 888 \
\end{array}
$$</p>
<p>(In the second line, for example, we have <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%3d1%20%3d%20001_2%24">, so <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241%20%3d%202%5ccdot%205%20%2b%200%3b%202%20%3d%201%5ccdot%202%20%2b%200%3b%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%245%20%3d%202%5ccdot%202%20%2b%201%24">.)</p>
<p>Any number <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> of three digits, for which <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242A%24"> contains exactly the same three digits, in base 9, must therefore consist of exactly the digits <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24000%2c%20125%2c%20367%2c%24"> or <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24888%24">.</p>
<h4>A warning</h4>
<p>All the foregoing assumes that the permutation <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is <em>a single cycle</em>. In general, it may not be. Suppose we did an analysis like that above for <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%3d10%2c%20n%3d5%24"> and found that there was no possible digit set, other than the trivial set <code>00000</code>, that satisfied the governing equation <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%282%5e5%2d1%29a_0%20%2b%20v%5cequiv%200%5cpmod%7b10%7d%24">. This would <em>not</em> completely rule out a base-10 solution with 5 digits, because the analysis only rules out a <em>cyclic</em> set of digits. There could still be a solution where <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> was a product of a <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%24"> and a <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%243%24">-cycle, or a product of still smaller cycles.</p>
<p>Something like this occurs, for example, in the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d4%2c%20R%3d8%24"> case. Solving the governing equation <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%282%5e5%2d1%29a_0%20%2b%20v%20%5cequiv%200%5cpmod%208%24"> yields only four possible digit cycles, namely <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%7b0%2c1%2c2%2c4%5c%7d%2c%20%5c%7b1%2c3%2c6%2c4%5c%7d%2c%20%5c%7b2%2c5%2c2%2c5%5c%7d%24">, and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%7b3%2c7%2c6%2c5%5c%7d%24">. But there are several additional solutions: <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242500_8%5ccdot%202%20%3d%205200_8%2c%202750_8%5ccdot%202%20%3d%20%20%205720_8%2c%20%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242775_8%5ccdot%202%20%3d%205772_8%24">. These correspond to permutations <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> with more than one cycle. In the case of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%245720_8%24">, for example, <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> exchanges the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%245%24"> and the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%24">, and leaves the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240%24"> and the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%247%24"> fixed.</p>
<p>For this reason we cannot rule out the possibility of an <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">-digit solution without first considering all smaller <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">.</p>
<h4>The Large Equals Odd rule</h4>
<p>When <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%24"> is even there is a simple condition we can use to rule out certain sets of digits from being single-cycle solutions. Recall that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%3da_%7bn%2d1%7d%5cldots%20a_0%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24B%3db_%7bn%2d1%7d%5cldots%20b_0%24">. Let us agree that a digit <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24d%24"> is <em>large</em> if <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24d%5cge%20%5cfrac%20R2%24"> and <em>small</em> otherwise. That is, <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24d%24"> is large if, upon doubling, it causes a carry into the next column to the left.</p>
<p>Since <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_i%20%3d%282a_i%20%2b%20c_i%29%5cbmod%20R%24">, where the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c_i%24"> are carry bits, we see that, except for <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_0%24">, the digit <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_i%24"> is odd precisely when there is a carry from the next column to the right, which occurs precisely when <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_%7bi%2d1%7d%24"> is large. Thus the number of odd digits among <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_1%2c%5cldots%20b_%7bn%2d1%7d%24"> is equal to the number of large digits among <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_1%2c%5cldots%20a_%7bn%2d2%7d%24">.
This leaves the digits <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_0%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_%7bn%2d1%7d%24"> uncounted. But <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_0%24"> is never odd, since there is never a carry in the rightmost position, and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_%7bn%2d1%7d%24"> is always small (since otherwise <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24B%24"> would have <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%2b1%24"> digits, which is not allowed). So the number of large digits in <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> is exactly equal to the number of odd digits in <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24B%24">. And since <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24B%24"> have exactly the same digits, the number of large digits in <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> is equal to the number of odd digits in <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24">. Observe that this is the case for our running example <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241042_8%24">: there is one odd digit and one large digit (the 4).</p>
<p>When <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%24"> is odd the analogous condition is somewhat more complicated, but since the main case of interest is <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%3d10%24">, we have the useful rule that:</p>
<blockquote>
For <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%24"> even, the number of odd digits in any solution <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> is equal to the number of large digits in <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24">.
</blockquote>
<h1>Conditions on the order of digits in a solution</h1>
<p>We have determined, using the above method, that the digits <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%7b5%2c1%2c2%5c%7d%24"> might form a base-9 numeral with property <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P_9%24">. Now we would like to arrange them into a base-9 numeral that actually does have that property. Again let us write <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%20%3d%20a_2a_1a_0%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24B%3db_2b_1b_0%24">, with <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24B%3d2A%24">. Note that if <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%20%3d%201%24">, then <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_i%20%3d%203%24"> (if there was a carry from the next column to the right) or <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%24"> (if there was no carry), but since <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_i%3d3%24"> is impossible, we must have <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%20%3d%202%24"> and therefore <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_%7bi%2d1%7d%24"> must be small, since there is no carry into position <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24i%24">. But since <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_%7bi%2d1%7d%24"> is also one of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%7b5%2c1%2c2%5c%7d%24">, and it cannot also be <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241%24">, it must be <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%24">. This shows that the 1, unless it appears in the rightmost position, must be to the left of the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%24">; it cannot be to the left of the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%245%24">. Similarly, if <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%20%3d%202%24"> then <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_i%20%3d%205%24">, because <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%244%24"> is impossible, so the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%24"> must be to the left of a large digit, which must be the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%245%24">. Similar reasoning produces no constraint on the position of the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%245%24">; it could be to the left of a small digit (in which case it doubles to <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241%24">) or a large digit (in which case it doubles to <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%24">). We can summarize these findings as follows:</p>
<p>$$\begin{array}{cl}
\text{digit} & \text{to the left of} \\ \hline
1 & 1, 2, \text{end} \\
2 & 5 \\
5 & 1,2,5,\text{end}
\end{array}$$</p>
<p>Here “end” means that the indicated digit could be the rightmost.</p>
<p>Furthermore, the left digit of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> must be small (or else there would be a carry in the leftmost place and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242A%24"> would have 4 digits instead of 3) so it must be either 1 or 2. It is not hard to see from this table that the digits must be in the order <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24125%24"> or <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24251%24">, and indeed, both of those numbers have the required property: <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24125_9%5ccdot%202%20%3d%20251_9%24">, and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24251_9%5ccdot%202%20%3d%20512_9%24">.</p>
<p>This was a simple example, but in more complicated cases it is helpful to draw the order constraints as a graph. Suppose we draw a graph with one vertex for each digit, and one additional vertex to represent the end of the numeral. The graph has an edge from vertex <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> to <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%27%24"> whenever <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> can appear to the left of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%27%24">. Then the graph drawn for the table above looks like this:</p>
<p><img src="http://pic.plover.com/math-se-blog/double-digits/huhooa.png" alt="Graph for 125 base 9" /></p>
<p>A 3-digit numeral with property <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P_9%24"> corresponds to a path in this graph that starts at one of the nonzero small digits (marked in blue), ends at the red node marked ‘end’, and visits each node exactly once. Such a path is called <em><a href="https://en.wikipedia.org/wiki/Hamiltonian_path">hamiltonian</a></em>. Obviously, self-loops never occur in a hamiltonian path, so we will omit them from future diagrams.</p>
<p>Now we will consider the digit set <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24637%24">, again base 9. An analysis similar to the foregoing allows us to construct the following graph:</p>
<p><img src="http://pic.plover.com/math-se-blog/double-digits/ovecmp.png" alt="Graph for 367 base 9" /></p>
<p>Here it is immediately clear that the only hamiltonian path is <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%243%2d7%2d6%2d%5ctext%7bend%7d%24">, and indeed, <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24376_9%5ccdot%202%20%3d%20763_9%24">.</p>
<p>In general there might be multiple instances of a digit, and so multiple nodes labeled with that digit. Analysis of the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240%2c0%2c0%24"> case produces a graph with no legal start nodes and so no solutions, unless leading zeroes are allowed, in which case <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24000%24"> is a perfectly valid solution. Analysis of the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%248%2c8%2c8%24"> case produces a graph with no path to the end node and so no solutions. These two trivial patterns appear for all <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%24"> and all <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">, and we will ignore them from now on.</p>
<p>Returning to our ongoing example, <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241042%24"> in base 8, we see that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%24"> must double to <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%244%24">, so must be to the left of small digits, but <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%244%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240%24"> can double to either <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240%24"> or <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241%24"> and so could be to the left of anything. Here the constraints are so lax that the graph doesn't help us narrow them down much:</p>
<p><img src="http://pic.plover.com/math-se-blog/double-digits/mludlo.png" alt="Graph for 1024 base 8" /></p>
<p>Observing that the only arrow into the 4 is from 0, so that the 4 must follow the 0, and that the entire number must begin with 1 or 2, we can enumerate the solutions:</p>
<pre>
1042
1204
2041
2104
</pre>
<p>If leading zeroes are allowed we have also:</p>
<pre>
0412
0421
</pre>
<p>All of these are solutions in base 8.</p>
<h3>The case of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%3d10%24"></h3>
<p>Now we turn to our main problem, solutions in base 10.</p>
<p>To find <em>all</em> the solutions of length 6 requires an enumeration of smaller solutions, which, if they existed, might be concatenated into a solution of length 6. This is because our analysis of the digit sets that can appear in a solution assumes that the digits are permuted <em>cyclically</em>; that is, the permutations <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> that we considered had only one cycle each.</p>
<p>There are no smaller solutions, but to prove that the length 6 solutions are minimal, we must analyze the cases for smaller <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24"> and rule them out. We now produce a complete analysis of the base 10 case with <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%3d10%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%5cle%206%24">. For <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d1%24"> there is only the trivial solution of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240%24">, which we disregard. (The question asked for a positive number anyway.)</p>
<h4><img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d2%24"></h4>
<p>For <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d2%24">, we want to find solutions of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%243a_i%20%2b%20v%20%5cequiv%200%5cpmod%7b10%7d%24"> where <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> is a two-bit bracelet number, one of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%2400_2%2c%2001_2%2c%20%24"> or <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%2411_2%24">. Tabulating the values of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%5cin%5c%7b0%2c1%2c3%5c%7d%24"> that solve this equation we get:</p>
<p>$$\begin{array}{ccc}
v& a_i \\ \hline
0 & 0 \\
1& 3 \\
3& 9 \\
\end{array}$$</p>
<p>We can disregard the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%3d0%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%3d3%24"> solutions because the former yields the trivial solution <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%2400%24"> and the latter yields the nonsolution <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%2499%24">. So the only possibility we need to investigate further is <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%20%3d%203%2c%20v%20%3d%201%24">, which corresponds to the digit sequence <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%2436%24">: Doubling <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%243%24"> gives us <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%246%24"> and doubling <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%246%24">, plus a carry, gives us <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%243%24"> again.</p>
<p>But when we tabulate of which digits must be left of which informs us that there is no solution with just <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%243%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%246%24">, because the graph we get, once self-loops are eliminated, looks like this:</p>
<p><img src="http://pic.plover.com/math-se-blog/double-digits/xthkmc.png" alt="graph for 36 base 10" /></p>
<p>which obviously has no hamiltonian path. Thus there is no solution for <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%3d10%2c%20n%3d2%24">.</p>
<h4><img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d3%24"></h4>
<p>For <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d3%24"> we need to solve the equation <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%247a_i%20%2b%20v%20%5cequiv%200%5cpmod%7b10%7d%24"> where <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> is a bracelet number in <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%7b0%2c%5cldots%207%5c%7d%24">, specifically one of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240%2c1%2c3%2c%24"> or <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%247%24">. Since <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%247%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%2410%24"> are relatively prime, for each <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> there is a single <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%24"> that solves the equation.
Tabulating the possible values of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%24"> as before, and this time omitting rows with no solution, we have:</p>
<p>$$\begin{array}{rrl}
v & a_i & \text{digits}\\ \hline
0& 0 & 000\\
1& 7 & 748 \\
3& 1 & 125\\
7&9 & 999\\
\end{array}$$</p>
<p>The digit sequences <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240%2c0%2c0%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%249%2c9%2c9%24"> yield trivial solutions or nonsolutions as usual, and we will omit them in the future. The other two lines suggest the digit sets <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241%2c2%2c5%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%244%2c7%2c8%24">, both of which fails the “odd equals large” rule.</p>
<p>This analysis rules out the possibility of a digit set with <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_0%20%5cto%20a_1%20%5cto%20a_2%20%5cto%20a_1%24">, but it does not <em>completely</em> rule out a 3-digit solution, since one could be obtained by concatenating a one-digit and a two-digit solution, or three one-digit solutions. However, we know by now that no one- or two-digit solutions exist. Therefore there are no 3-digit solutions in base 10.</p>
<h4><img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d4%24"></h4>
<p>For <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d4%24"> the governing equation is <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%2415a_i%20%2b%20v%20%5cequiv%200%5cpmod%7b10%7d%24"> where <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> is a 4-bit bracelet number, one of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%7b0%2c1%2c3%2c5%2c7%2c15%5c%7d%24">. This is a little more complicated because <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cgcd%2815%2c10%29%5cne%201%24">. Tabulating the possible digit sets, we get:</p>
<p>$$\begin{array}{crrl}
a_i & 15a_i& v & \text{digits}\\ \hline
0 & 0 & 0 & 0000\\
1 & 5 & 5 & 1250\\
1 & 5 & 15 & 1375\\
2 & 0 & 0 & 2486\\
3 & 5 & 5 & 3749\\
3 & 5 & 15 & 3751\\
4 & 0 & 0 & 4862\\
5 & 5 & 5 & 5012\\
5 & 5 & 5 & 5137\\
6 & 0 & 0 & 6248\\
7 & 5 & 5 & 7493\\
7 & 5 & 5 & 7513\\
8 & 0 & 0 & 8624 \\
9 & 5 & 5 & 9874\\
9 & 5 & 15 & 9999 \\
\end{array}$$</p>
<p>where the second column has been reduced mod <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%2410%24">. Note that even restricting <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> to bracelet numbers the table still contains duplicate digit sequences; the 15 entries on the right contain only the six basic sequences <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240000%2c%200125%2c%201375%2c%202486%2c%203749%2c%204987%24">, and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%249999%24">. Of these, only <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240000%2c%209999%2c%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%243749%24"> obey the odd equals large criterion, and we will disregard <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%240000%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%249999%24"> as usual, leaving only <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%243749%24">. We construct the corresponding graph for this digit set as follows: <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%243%24"> must double to <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%247%24">, not <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%246%24">, so must be left of a large number <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%247%24"> or <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%249%24">. Similarly <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%244%24"> must be left of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%247%24"> or <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%249%24">. <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%249%24"> must also double to <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%249%24">, so must be left of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%247%24">. Finally, <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%247%24"> must double to <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%244%24">, so must be left of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%243%2c4%24"> or the end of the numeral. The corresponding graph is:</p>
<p><img src="http://pic.plover.com/math-se-blog/double-digits/wmelxc.png" alt="graph for 3749 base 10" /></p>
<p>which evidently has no hamiltonian path: whichever of 3 or 4 we start at, we cannot visit the other without passing through 7, and then we cannot reach the end node without passing through 7 a second time. So there is no solution with <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%3d10%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d4%24">.</p>
<h4><img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d5%24"></h4>
<p>We leave this case as an exercise. There are 8 solutions to the governing equation, all of which are ruled out by the odd equals large rule.</p>
<h4><img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d6%24"></h4>
<p>For <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d6%24"> the possible solutions are given by the governing equation <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%2463a_i%20%2b%20v%20%5cequiv%200%5cpmod%7b10%7d%24"> where <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24v%24"> is a 6-bit bracelet number, one of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%7b0%2c1%2c3%2c5%2c7%2c9%2c11%2c13%2c15%2c21%2c23%2c27%2c31%2c63%5c%7d%24">. Tabulating the possible digit sets, we get:</p>
<p>$$\begin{array}{crrl}
v & a_i & \text{digits}\\ \hline
0 & 0 & 000000\\
1 & 3 & 362486 \\
3 & 9 & 986249 \\
5 & 5 & 500012 \\
7 & 1 & 124875 \\
9 & 7 & 748748 \\
11 & 3 & 362501 \\
13 & 9 & 986374 \\
15 & 5 & 500137 \\
21 & 3 & 363636 \\
23 & 9 & 989899 \\
27 & 1 & 125125 \\
31 & 3 & 363751 \\
63 & 9 & 999999 \\
\end{array}$$</p>
<p>After ignoring <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24000000%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24999999%24"> as usual, the large equals odd rule allows us to ignore all the other sequences except <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24124875%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24363636%24">. The latter fails for the same reason that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%2436%24"> did when <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d2%24">. But <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24142857%24"> , the lone survivor, gives us a complicated derived graph containing many hamiltonian paths, every one of which is a solution to the problem:</p>
<p><img src="http://pic.plover.com/math-se-blog/double-digits/uswkfz.png" alt="graph for 124578 base 10" /></p>
<p>It is not hard to pick out from this graph the minimal solution <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24125874%24">, for which <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24125874%5ccdot%202%20%3d%20251748%24">, and also our old friend <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24142857%24"> for which <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24142857%5ccdot%202%20%3d%20285714%24">.</p>
<p>We see here the reason why all the small numbers with property <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P_%7b10%7d%24"> contain the digits <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24124578%24">. The constraints on <em>which</em> digits can appear in a solution are quite strict, and rule out all other sequences of six digits and all shorter sequences. But once a set of digits passes these stringent conditions, the constraints on it are much looser, because <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24B%24"> is only required to have the digits of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> in <em>some</em> order, and there are many possible orders, many of which will satisfy the rather loose conditions involving the distribution of the carry bits. This graph is typical: it has a set of small nodes and a set of large nodes, and each node is connected to either <em>all</em> the small nodes or <em>all</em> the large nodes, so that the graph has many edges, and, as in this case, a largish clique of small nodes and a largish clique of large nodes, and as a result many hamiltonian paths.</p>
<h3>Onward</h3>
<p>This analysis is tedious but is simple enough to perform by hand in under an hour. As <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24"> increases further, enumerating the solutions of the governing equation becomes very time-consuming. I wrote a simple computer program to perform the analysis for given <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24R%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">, and to emit the possible digit sets that satisfied the large equals odd criterion. I had wondered if <em>every</em> base-10 solution contained equal numbers of the digits <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241%2c2%2c4%2c8%2c5%2c%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%247%24">. This is the case for <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d7%24"> (where the only admissible digit set is <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%5c%7b1%2c2%2c4%2c5%2c7%2c8%5c%5c%7d%5ccup%5c%5c%7b9%5c%5c%7d%24">), for <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d8%24"> (where the only admissible sets are <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%5c%7b1%2c2%2c4%2c5%2c7%2c8%5c%5c%7d%5ccup%20%5c%5c%7b3%2c6%5c%5c%7d%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%5c%7b1%2c2%2c4%2c5%2c7%2c8%5c%5c%7d%5ccup%5c%5c%7b9%2c9%5c%5c%7d%24">), and for <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d9%24"> (where the only admissible sets are <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%5c%7b1%2c2%2c4%2c5%2c7%2c8%5c%5c%7d%5ccup%5c%5c%7b3%2c6%2c9%5c%5c%7d%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5c%5c%7b1%2c2%2c4%2c5%2c7%2c8%5c%5c%7d%5ccup%5c%5c%7b9%2c9%2c9%5c%5c%7d%24">). But when we reach <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d10%24"> the increasing number of bracelets has loosened up the requirements a little and there are 5 admissible digit sets. I picked two of the promising-seeming ones and quickly found by hand the solutions <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%244225561128%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241577438874%24">, both of which wreck any theory that the digits <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%241%2c2%2c4%2c5%2c8%2c7%24"> must all appear the same number of times.</p>
<h3>Acknowledgments</h3>
<p>Thanks to <a href="http://math.stackexchange.com/users/67848/karl-kronenfeld">Karl
Kronenfeld</a>
for corrections and many helpful suggestions.</p>
Placeholder texts
http://blog.plover.com/2014/03/02#placeholder
<p>This week there has been an article floating around about “<a href="http://www.elezea.com/2014/02/lorem-ipsum-gone-wrong/">What
happens when placeholder text doesn't get
replaced</a>.
This reminds me of the time I made this mistake myself.</p>
<p>In 1996 I was programming a web site for a large company which sold
cosmetics and skin care products in hundreds of department stores and
malls around the country. The technology to actually buy the stuff
online wasn't really mature yet, and the web was new enough that the
company was worried that selling online would anger the retail
channels. They wanted a web page where you would put in your
location and it would tell you where the nearby stores were.</p>
<p>The application was simple; it accepted a city and state, looked them
up in an on-disk hash table, and then returned a status code to the
page generator. The status code was for internal use only. For
example, if you didn't fill in the form completely, the program would
return the status code <code>MISSING</code>, which would trigger the templating
engine to build a page with a suitable complaint message. </p>
<p>If the form was filled out correctly, but there was no match in the
database, the program would return a status code that the front end
translated to a suitably apologetic message. The status code I
selected for this was <code>BACKWATER</code>.</p>
<p>Which was all very jolly, until one day there was a program bug and
some user in Podunk, Iowa submitted the form and got back a page with
<code>BACKWATER</code> in giant letters.</p>
<p>Anyone could have seen <em>that</em> coming; I have no excuse.</p>
Proof by contradiction
http://blog.plover.com/2014/03/01#IL-contradiction
<p>Intuitionistic logic is deeply misunderstood by people who have not
studied it closely; such people often seem to think that the
intuitionists were just a bunch of lunatics who rejected the law of
the excluded middle for no reason. One often hears that
intuitionistic logic rejects proof by contradiction. This is only half
true. It arises from a typically classical misunderstanding of
intuitionistic logic.</p>
<p>Intuitionists are perfectly happy to accept a reductio ad absurdum
proof of the following form:</p>
<p>$$(P\to \bot)\to \lnot P$$</p>
<p>Here <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cbot%24"> means an absurdity or a contradiction; <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%5cto%20%5cbot%24"> means that assuming
<img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> leads to absurdity, and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%28P%5cto%20%5cbot%29%5cto%20%20%5clnot%20P%24"> means that if assuming <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24">
leads to absurdity, then you can conclude that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is false. This
is a classic proof by contradiction, and it is intuitionistically
valid. In fact, in many formulations of intuitionistic logic, <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20P%24"> is
<em>defined</em> to mean <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%5cto%20%5cbot%24">.</p>
<p>What is rejected by intuitionistic logic is the similar-seeming claim
that:</p>
<p>$$(\lnot P\to \bot)\to P$$</p>
<p>This says that if assuming <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20P%24"> leads to absurdity, you can conclude
that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is true. This is <em>not</em> intuitionistically valid.</p>
<p>This is where people become puzzled if they only know classical
logic. “But those are the same thing!” they cry. “You just have to
replace <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> with <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20P%24"> in the first one, and you get the second.”</p>
<p>Not quite. If you replace <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> with <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20P%24"> in the first one, you do not get the second
one; you get:</p>
<p>$$(\lnot P\to \bot)\to \lnot \lnot P$$</p>
<p>People familiar with classical logic are so used to shuffling the <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20%24">
signs around and treating <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20%5clnot%20P%24"> the same as <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> that they often don't
notice when they are doing it. But in intuitionistic logic, <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20%5clnot%20P%24">
are not the same. <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20%5clnot%20P%24"> is weaker than <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24">, in the sense that
from <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> one can always conclude <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20%5clnot%20P%24">, but not always vice versa. Intuitionistic logic
is happy to agree that if <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20P%24"> leads to absurdity, then <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20%5clnot%20P%24">. But it
does not agree that this is sufficient to conclude <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24">.</p>
<p>As is often the case, it may be helpful to try to understand
intuitionistic logic as talking about provability instead of truth.
In classical logic, <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> means that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is true and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20P%24">
means that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is false. If <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is not false it is true, so <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20%5clnot%20P%24"> and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24">
mean the same thing. But in intuitionistic logic <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> means that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is
<em>provable</em>, and <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20P%24"> means that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is not provable. <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20%5clnot%20P%24"> means that it is
impossible to prove that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is not provable.</p>
<p>If <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is provable, it is certainly impossible to prove that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is not
provable. So <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> implies <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20%5clnot%20P%24">. But just because it is impossible to
prove that there is no proof of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> does not mean that <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> itself is
provable, so <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clnot%20%5clnot%20P%24"> does not imply <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24">.</p>
<p>Similarly,</p>
<p>$$(P\to \bot)\to \lnot P $$</p>
<p>means that if a proof of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> would lead to absurdity, then we may conclude
that there cannot be a proof of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24">. This is quite valid. But</p>
<p>$$(\lnot P\to \bot)\to P$$</p>
<p>means that if assuming that a proof of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is impossible leads to
absurdity, there must be a proof of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24">. But this itself isn't a
proof of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24">, nor is it enough to prove <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24">; it only shows that
there is no proof that proofs of <img src="https://chart.googleapis.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> are impossible.</p>
<p>[ Addendum 20141124: <a href="http://math.andrej.com/2010/03/29/proof-of-negation-and-proof-by-contradiction/">This article by Andrej Bauer</a> says much the same thing. ]</p>
2banner, which tells you when someone else is looking at the same web page
http://blog.plover.com/2014/02/27#2banner
<p>I was able to release a pretty nice piece of software today, courtesy
of my employer, ZipRecruiter. If you have a family of web pages, and
whenever you are looking at one you want to know when someone else is
looking at the same page, you can use my package. The package is
called <code>2banner</code>, because it pops up a banner on a page whenever two
people are looking at it. With permission from ZipRecruiter, I have
put it on github, and <a href="https://github.com/ZipRecruiter/2banner">you can download
and use it for free</a>.</p>
<p>A typical use case would be a customer service organization. Say your
users create requests for help, and the the customer service reps have
to answer the requests. There is a web page with a list of all the
unserviced requests, and each one has a link to a page with details
about what is requested and how to contact the person who made the
request. But it might sometimes happes that Fred and Mary
independently decide to service the same request, which is at best a
waste of effort, and at worst confusing for the customer who gets
email from both Fred and Mary and doesn't know how to respond. With
<code>2banner</code>, when Mary arrives at the customer's page, she sees a banner
in the corner that says <code>Fred is already looking at this page!</code>, and
at the same time a banner pops up in Fred's browser that says <code>Mary
has started looking at this page!</code> Then Mary knows that Fred is
already on the case, and she can take over a different one, or Fred
and Mary can communicate and decide which of them will deal with this
particular request.</p>
<p>You can similarly trick out the menu page itself, to hide the menu
items that someone is already looking out.</p>
<p>I wanted to use someone else's package for this, but I was not able to
find one, so I wrote one myself. It was not as hard as I had
expected. The system comprises three components:</p>
<ul>
<li><p>The back-end database for recording who started looking at which
pages and when. I assumed a SQL database and wrote a component that
uses Perl's <a href="https://metacpan.org/pod/DBIx::Class"><code>DBIx::Class</code></a>
module to access it, but it would be pretty easy throw this away and
use something else instead.</p></li>
<li><p>An API server that can propagate notifications like “user <em>X</em> is now
looking at page <em>Y</em>” and “user <em>X</em> is no longer looking at page <em>Y</em>”
into the database, and which can answer the question “who else is
looking at page <em>Y</em> right now?”. I used Perl's <a href="http://www.catalystframework.org/">Catalyst
framework</a> for this, because our
web app already runs under it. It would not be too hard to throw
this away and use something else instead. You could even write a
standalone server using <code>HTTP::Server</code>, and borrow most of the
existing code, and probably have it working in under an hour.</p></li>
<li><p>A JavaScript thingy that lives in the web page, sends the
appropriate notifications to the API server, and pops up the banner
when necessary. I used <a href="http://jquery.org/">jQuery</a> for this.
Probably there is something else you could use instead, but I have
no idea what it is, because I know next to nothing about front-end
web programming. I was happy to have the chance to learn a little
about jQuery for this project.</p></li>
</ul>
<p>Often a project seems easy but the more I think about it the harder it
seems. This project was the opposite. I thought it sounded hard, and
I didn't want to do it. It had been an outstanding request of the CS
people for some time, but I guess everyone else thought it sounded
hard too, because nobody did anything about it. But the longer I let
it percolate around in my head, the simpler it seemed. As I
considered it, one difficulty after another evaporated.</p>
<p>Other than the jQuery stuff, which I had never touched before, the
hardest part was deciding what to do about the API server. I could
easily have written a standalone, special-purpose API server, but I
felt like it was the wrong thing, and anyway, I didn't want to
administer one. But eventually I remembered that our main web site is
driven by Catalyst, which is itself a system for replying to HTTP
requests, which already has access to our database, and which
already knows which user is making each request.</p>
<p>So it was natural to say that the API was to send HTTP requests to
certain URLs on our web site, and easy-peasy to add a couple of
handlers to the existing Catalyst application to handle the API
requests, query the database, and send the right replies.</p>
<p>I don't know why it took me so long to think of doing the API server
with Catalyst. If it had been someone else's suggestion I would
probably feel dumb for not having thought of it myself, because in
hindsight it is <em>so</em> obvious. Happily, I did think of it, because it
is clearly the right solution for us.</p>
<p>It was not too hard to debug. The three components are largely
independent of one another. The draft version of the API server
responded to GET requests, which are easier to generate from the
browser than the POST requests that it should be getting. Since the
responses are in JSON, it was easy to see if the API server was
replying correctly.</p>
<p>I had to invent techniques for debugging the jQuery stuff. I didn't
know the right way to get diagnostic messages out of jQuery, so I put
a big text area on the web page, and had the jQuery routines write
diagnostic messages into it. I don't know if that's what other people
do, but I thought it worked pretty well. JavaScript is not my ideal
language, but I program in Perl all day, so I am not about to
complain. Programming the front end in JavaScript and watching stuff
happen on the page is fun! I like writing programs that make things
happen.</p>
<p><a href="https://github.com/ZipRecruiter/2banner">The package is in ZipRecruiter's GitHub
repository</a>, and is available
under a very lenient free license. Check it out.</p>
<p>(By the way, I really like working for ZipRecruiter, and <a href="https://www.ziprecruiter.com/hiring">we are
hiring Perl and Python
developers</a>. Please send
me email if you want to ask what it is like to work for them.) </p>
The perfect machine
http://blog.plover.com/2014/02/09#the-second-law
<p>You sometimes hear people claim that there is no perfectly efficient
machine, that every machine wastes some of its input energy in noise
or friction.</p>
<p>However, there is a counterexample. An electric space heater is
perfectly efficient. Its purpose is to heat the space around it, and
100% of the input energy is applied to this purpose. Even the
electrical energy lost to resistance in the cord you use to plug it
into the wall is converted to heat.</p>
<p>Wait, you say, the space heater does waste some of its energy. The
coils heat up, and they emit not only heat, but also light, which is
useless, being a dull orange color. Ah! But what happens when that
light hits the wall? Most of it is absorbed, and heats up the wall.
Some is reflected, and heats up a different wall instead.</p>
<p>Similarly, a small fraction of the energy is wasted in making a quiet
humming noise—until the sound waves are absorbed by the objects in the
room, heating them slightly.</p>
<p>Now it's true that some heat is lost when it's radiated from the
<em>outside</em> of the walls and ceiling. But some is also lost whenever
you open a window or a door, and you can't blame the space heater for
your lousy insulation. It heated the room as much as possible under
the circumstances.</p>
<p>So remember this when you hear someone complain that incandescent
light bulbs are wasteful of energy. They're only wasteful in warm
weather. In cold weather, they're free.</p>
Everything needs an ID
http://blog.plover.com/2014/02/08#GUID
<p>I wrote some time ago about <a href="http://blog.plover.com/prog/Moonpig.html#guids">Moonpig's use of
GUIDs</a>: every
significant object was given a unique ID. I said that this was a
useful strategy I had only learned from Rik, and I was surprised to
see how many previously tricky programming problems became simpler once
the GUIDs were available. Some of these tricky problems are artifacts
of Perl's somewhat limited implementation of hashes; hash keys must be
strings, and the GUID gives you an instantaneous answer to any
question about what the keys should be. </p>
<p>But it reminds me of a similar maxim which I was thinking about just
yesterday: Every table in a relational database should have a record
ID field. It often happens that I am designing some table and there
is no obvious need for such a field. I now always put one in anyway,
having long ago learned that I will inevitably want it for something.</p>
<p>Most recently I was building a table to record which web pages were
being currently visited by which users. A record in the table is
naturally identified by the pair of user ID and page URL; it is not
clear that it needs any further keys.</p>
<p>But I put in a record ID anyway, because my practice is to always put
in a record ID, and sure enough, within a few hours I was glad it
was there. The program I was writing has not yet needed to use the
record IDs. But to <em>test</em> the program I needed to insert and manipulate
some test records, and it was much easier to write this:</p>
<pre><code>update table set ... where record_id = 113;
</code></pre>
<p>than this:</p>
<pre><code>update table set ... where user_id = 97531 and url = 'http://hostname:port/long/path/that/is/hard/to/type';
</code></pre>
<p>If you ever end up with two objects in the program that represesent
record sets and you need to merge or intersect them synthetically,
having the record ID numbers automatically attached to the records
makes this quite trivial, whereas if you don't have them it is a pain
in the butt. You should never be in such a situation, perhaps, but
stranger things have happened. Just yesterday I found myself writing</p>
<pre><code> function relativize (pathPat) {
var dummyA = document.createElement('a');
dummyA.href = document.URL;
return "http://" + dummyA.host + pathPat;
}
</code></pre>
<p>which nobody should have to do either, and yet there I was. Sometimes
programming can be a dirty business.</p>
<p>During the bootstrapping of the user-url table project some records
with bad URLs were inserted by buggy code, and I needed to remove
them. The URLs all ended in <code>%</code> signs, and there's probably some easy
way to delete all the records where the URL ends in a <code>%</code> sign. But I
couldn't remember the syntax offhand, and looking up the escape
sequence for <code>LIKE</code> clauses would have taken a lot longer than what I
did do, which was:</p>
<pre><code>delete from table where record_id in (43, 47, 49)
</code></pre>
<p>So the rule is: giving things ID numbers should be the default,
because they are generally useful, like handles you can use to pick
things up with. You need a good reason to omit them.</p>
Why I like Java
http://blog.plover.com/2014/02/01#Java
<p>(<a href="http://geek.csdn.net/news/detail/6236">为什么我喜欢Java</a>)</p>
<p>My current employer uses an online quiz to pre-screen applicants for
open positions. The first question on the quiz is a triviality, just
to let the candidate get familiar with the submission and testing
system. The question is to write a program that copies standard input
to standard output. Candidates are allowed to answer the questions
using whatever language they prefer.</p>
<p>Sometimes we get candidates who get a zero score on the test. When I
see the report that they failed to answer even the trivial question,
my first thought is that this should not reflect badly on the
candidate. Clearly, the testing system itself is so hard to use
that the candidate was unable to submit even a trivial program, and
this is a failure of the testing system and not the candidate.</p>
<p>But it has happened more than once that when I look at the candidate's
incomplete submissions I see that the problem, at least this time, is
not necessarily in the testing system. There is another possible
problem that had not even occurred to me. The candidate failed the
trivial question because they tried to write the answer in Java.</p>
<p>I am reminded of Dijkstra's remark that the teaching of BASIC should
be rated as a criminal offense. Seeing the hapless candidate get
bowled over by a question that should be a mere formality makes me
wonder if the same might be said of Java.</p>
<p>I'm not sure. It's possible that this is still a failure of the quiz.
It's possible that the Java programmers have valuable skills that we
could use, despite their inability to produce even a trivial working
program in a short amount of time. I could be persuaded, but right
now I have a doubtful feeling.</p>
<p>When you learn Perl, Python, Ruby, or Javascript, one of the things
you learn is a body of technique for solving problems using hashes,
which are an integral part of the language. When you learn Haskell,
you similarly learn a body of technique for solving problems with lazy
lists and monads. These kinds of powerful general-purpose tools are
at the forefront of the language.</p>
<p>But when you learn Java, there aren't any powerful language features
you can use to solve many problems. Instead, you spend your time
learning a body of technique for solving problems <em>in the language</em>.
Java has hashes, but if you are aware of them at all, they are just
another piece of the immense <code>Collections</code> library, lost among the
many other sorts of collections, and you have no particular reason to
know about them or think about them. A good course of Java instruction
might emphasize the more useful parts of the Collections, but since
they're just another part of the library it may not be obvious that
hashes are any more or less useful than, say, <code>AbstractAction</code> or
<code>zipOutputStream</code>.</p>
<p>I was a professional Java programmer for three years (in a different
organization), and I have meant for some time to write up my thoughts
about it. I am often very bitter and sarcastic, and I willingly admit
that I am relentlessly negative and disagreeable, so it can be hard to
tell when I am in earnest about liking something. <a href="http://blog.plover.com/oops/who-farted.html">I once tried to
write a complimentary article about
Blosxom</a>, which has
generated my blog since 2006, and I completely failed; people thought
I was being critical, and I had to write <a href="http://blog.plover.com/oops/blosxom-sux.html">a followup
article</a> to clarify, and
people <em>still</em> thought I was dissing Blosxom. Because this article
about Java might be confused with sarcastic criticism, I must state
clearly that everything in this article about Java is in earnest, and
should be taken at face value. Including:</p>
<h3>I really like Java</h3>
<p>I am glad to have had the experience of programming in Java. I liked
programming in Java mainly because I found it very relaxing. With a
bad language, like say Fortran or <code>csh</code>, you struggle to do anything
at all, and the language fights with you every step of the way
forward. With a good language there is a different kind of struggle,
to take advantage of the language's strengths, to get the maximum
amount of functionality, and to achieve the clearest possible
expression.</p>
<p>Java is neither a good nor a bad language. It is a mediocre language,
and there is no struggle. In Haskell or even in Perl you are always
worrying about whether you are doing something in the cleanest and the
best way. In Java, you can forget about doing it in the cleanest or
the best way, because that is impossible. Whatever you do, however
hard you try, the code will come out mediocre, verbose, redundant, and
bloated, and the only thing you can do is relax and keep turning the
crank until the necessary amount of code has come out of the spout.
If it takes ten times as much code as it would to program in Haskell,
that is all right, because the IDE will generate half of it for you,
and you are still being paid to write the other half.</p>
<p>So you turn the crank, draw your paycheck, and you don't have to worry
about the fact that it takes at least twice as long and the design is
awful. You can't solve any really hard design problems, but there is
a book you can use to solve some of the medium-hard ones, and solving
those involves cranking out a lot more Java code, for which you will
also be paid. You are a coder, your job is to write code, and you
write a lot of code, so you are doing your job and everyone is happy.</p>
<p>You will not produce anything really brilliant, but you will probably
not produce anything too terrible either. The project might fail, but
if it does you can probably put the blame somewhere else. After all,
you produced 576 classes that contain 10,000 lines of Java code, all
of it seemingly essential, so you were doing <em>your</em> job. And nobody
can glare at you and demand to know why you used 576 classes when you
should have used 50, because in Java doing it with only 50 classes is
probably impossible.</p>
<p>(Different languages have different failure modes. With Perl, the
project might fail because you designed and implemented a pile of
shit, but there is a clever workaround for any problem, so you might
be able to keep it going long enough to hand it off to someone else,
and then when it fails it will be their fault, not yours. With Haskell
someone probably should have been fired in the first month for
choosing to do it in Haskell.)</p>
<p>So yes, I enjoyed programming in Java, and being relieved of the
responsibility for producing a quality product. It was pleasant to
not have to worry about whether I was doing a good job, or whether I
might be writing something hard to understand or to maintain. The
code was ridiculously verbose, of course, but that was not my
fault. It was all out of my hands.</p>
<p>So I like Java. But it is not a language I would choose for answering
test questions, unless maybe the grade was proportional to the number
of lines of code written. On the test, you need to finish quickly, so
you need to optimize for brevity and expressiveness. Java is many
things, but it is neither brief nor expressive.</p>
<p>When I see that some hapless job candidate struggled for 15 minutes
and 14 seconds to write a Java program for copying standard input to
standard output, and finally gave up, without even getting to the real
questions, it makes me sad that their education, which was probably
expensive, has not equipped them with with better tools or to do
something other than grind out Java code.</p>
Twingler, a generic data structure munger
http://blog.plover.com/2014/01/30#twingler
<p>(Like <a href="http://blog.plover.com/notes/">everything else in this section</a>,
these are notes for a project that was never completed.)</p>
<h3>Introduction</h3>
<p>These incomplete notes from 1997-2001 are grappling with the problem
of transforming data structures in a language like Perl, Python, Java,
Javascript, or even Haskell. A typical problem is to take an input of
this type:</p>
<pre><code> [
[Chi, Ill],
[NY, NY],
[Alb, NY],
[Spr, Ill],
[Tr, NJ],
[Ev, Ill],
]
</code></pre>
<p>and to transform it to an output of this type:</p>
<pre><code> { Ill => [Chi, Ev, Spr],
NY => [Alb, NY],
NJ => [Tr],
}
</code></pre>
<p>One frequently writes code of this sort, and it should be possible to
specify the transformation with some sort of high-level declarative
syntax that is easier to read and write than the following gibberish:</p>
<pre><code> my $out;
for my $pair (@$in) {
push @{$out->{$pair->[0]}}, $pair->[1];
}
for my $k (keys %$out) {
@{$out->{$k}} = sort @{$out->{$k}};
}
</code></pre>
<p>This is especially horrible in Perl, but it is bad in any language.
Here it is in a hypothetical language with a much less crusty syntax:</p>
<pre><code> for pair (in.items) :
out[pair[0]].append(pair[1])
for list (out.values) :
list.sort
</code></pre>
<p>You still can't see what it really going on without executing the code
in your head. It is hard for a beginner to write, and hard to anyone
to understand.</p>
<h3>Original undated notes from around 1997–1998</h3>
<p>Consider this data structure DS1:</p>
<pre><code> [
[Chi, Ill],
[NY, NY],
[Alb, NY],
[Spr, Ill], DS1
[Tr, NJ],
[Ev, Ill],
]
</code></pre>
<p>This could be transformed several ways:</p>
<pre><code> {
Chi => Ill,
NY => NY,
Alb => NY,
Spr => Ill, DS2
Tr => NJ,
Ev => Ill,
}
{ Ill => [Chi, Spr, Ev],
NY => [NY, Alb], DS3
NJ => Tr,
}
{ Ill => 3,
NY => 2,
NJ => 1,
}
[ Chi, Ill, NY, NY, Alb, NY, Spr, Ill, Tr, NJ, Ev, Ill] DS4
</code></pre>
<p>Basic idea: Transform original structure of nesting depth <em>N</em> into an
<em>N</em>-dimensional table. If <em>N</em>th nest is a hash, index table ranks by hash
keys; if an array, index by numbers. So for example, DS1 becomes</p>
<pre><code> 1 2
1 Chi Ill
2 NY NY
3 Alb NY
4 Spr Ill
5 Tr NJ
6 Ev Ill
</code></pre>
<p>Or maybe hashes should be handled a little differently? The original
basic idea was more about DS2 and transformed it into</p>
<pre><code> Ill NY NJ
Chi X
NY X
Alb X
Spr X
Tr X
Ev X
</code></pre>
<p>Maybe the rule is: For hashes, use a boolean table indexed by keys and
values; for arrays, use a string table index by integers.</p>
<p>Notation idea: Assign names to the dimensions of the table, say X
and Y. Then denote transformations by:</p>
<pre><code> [([X, Y])] (DS1)
{(X => Y)} (DS2)
{X => [Y]} (DS3)
[(X, Y)] (DS4)
</code></pre>
<p>The (...) are supposed to incdicate a chaining of elements within the
larger structure. But maybe this isn't right.</p>
<p>At the bottom: How do we say whether</p>
<pre><code> X=>Y, X=>Z
</code></pre>
<p>turns into</p>
<pre><code> [ X => Y, X => Z ] (chaining)
</code></pre>
<p>or [ X => [Y, Z] ] (accumulation)</p>
<p>Consider</p>
<pre><code> A B C
D . . .
E . .
F . .
</code></pre>
<p><code><...></code> means ITERATE over the thing inside and make a list of the
results. It's basically `map'. </p>
<p>Note that:</p>
<pre><code> <X,Y> |= (D,A,D,B,D,C,E,A,E,B,F,A,F,C)
<X,[<Y>]> |= (D,[A,B,C],E,[A,B],F,[A,C])
</code></pre>
<p>Brackets and braces just mean brackets and braces. Variables at the
same level of nesting imply a loop over the cartesian join. Variables
subnested imply a nested loop. So:</p>
<pre><code> <X,Y> means
for x in X
for y in Y
push @result, (x,y) if present(x,y);
</code></pre>
<p>But</p>
<pre><code> <X,<Y>> means
for x in X
for y in Y
push @yresult, (y) if present(x,y);
push @result, @yresult
</code></pre>
<p>Hmmm. Maybe there's a better syntax for this.</p>
<p>Well, with this plan:</p>
<pre><code> DS1: [ <[X,Y]> ]
DS2: { <X=>Y> }
DS3: { <X => [<Y>]> }
DS4: [ <X, Y> ]
</code></pre>
<p>It seems pretty flexible. You could just as easily write</p>
<pre><code> { <X => max(<Y>) }
</code></pre>
<p>and you'd get</p>
<pre><code> { D => C, E => B, F => C }
</code></pre>
<p>If there's a `count' function, you can get</p>
<pre><code> { D => 3, E => 2, F => 2 }
</code></pre>
<p>or maybe we'll just overload <code>scalar' to mean</code>count'.</p>
<p>Question: How to invert this process? That's important so that you
can ask it to convert one data structure to another.
Also, then you could write something like</p>
<pre><code> [ <city, state> ] |= { <state => [<city>] > }
</code></pre>
<p>and omit the X's and Y's.</p>
<p>Real example: From proddir. Given</p>
<pre><code> ID / NAME / SHADE / PALETTE / DESC
</code></pre>
<p>For example:</p>
<pre><code> A / AAA / red / pink / Aaa
B / BBB / yellow / tawny / Bbb
A / AAA / green / nude / Aaa
B / BBB / blue / violet / Bbb
C / CCC / black / nude / Ccc
</code></pre>
<p>Turn this into</p>
<pre><code> { A => [ AAA, [ [red, pink], [green, nude] ], Aaa],
B => [ BBB, [ [yellow, tawny], [blue, violet] ], Bbb],
C => [ CCC, [ [black, nude] ], CCC]
}
{ < ID => [
name,
[ <[shade, palette]> ]
desc
]>
}
</code></pre>
<p>Something interesting happened here. Suppose we have</p>
<pre><code> [ [A, B]
[A, B]
]
</code></pre>
<p>And we ask for <code><A, B></code>. Do we get (A, B, A, B), or just (A, B)? Does
it remove duplicate items for us or not? We might want either.</p>
<p>In the example above, why didn't we get</p>
<pre><code> { A => [ AAA, [ [red, pink], [green, nude] ], Aaa],
A => [ AAA, [ [red, pink], [green, nude] ], Aaa],
B => [ BBB, [ [yellow, tawny], [blue, violet] ], Bbb],
B => [ BBB, [ [yellow, tawny], [blue, violet] ], Bbb],
C => [ CCC, [ [black, nude] ], CCC]
}
</code></pre>
<p>If the outer iteration was supposed to be over all id-name-desc triples?
Maybe we need</p>
<pre><code> <...> all triples
<!...!> unique triples only
</code></pre>
<p>Then you could say</p>
<pre><code> <X> |= <!X!>
</code></pre>
<p>to indicate that you want to uniq a list.</p>
<p>But maybe the old notation already allowed this:</p>
<pre><code> <X> |= keys %{< X => 1 >}
</code></pre>
<p>It's still unclear how to write the example above, which has unique
key-triples. But it's in a hash, so it gets uniqed on ID anyway;
maybe that's all we need.</p>
<h3>1999-10-23</h3>
<p>Rather than defining some bizarre metalanguage to describe the
transformation, it might be easier all around if the user just enters
a sample input, a sample desired output, and lets the twingler figure
out what to do. Certainly the parser and internal representation will
be simpler.</p>
<p>For example:</p>
<pre><code> [ [ A, B ],
[ C, B ],
[ D, E ] ]
--------------
{ B => [A, C],
E => [D],
}
</code></pre>
<p>should be enough for it to figure out that the code is:</p>
<pre><code> for my $a1 (@$input) {
my ($e1, $e2) = @$a1;
push @{$output{$e2}}, $e1;
}
</code></pre>
<p>Advantage: After generating the code, it can run it on the sample
input to make sure that the output is correct; otherwise it has a bug.</p>
<p>Input grammar:</p>
<pre><code> %token ELEMENT
expr: array | hash ;
array: '[' csl ']' ;
csl: ELEMENT | ELEMENT ',' csl | /* empty */ ;
hash: '{' cspl '}' ;
cspl: pair | pair ',' cspl | /* empty */ ;
pair: ELEMENT '=>' ELEMENT;
</code></pre>
<p>Simple enough. Note that (...) lines are not allowed. They are only
useful at the top level. A later version can allow them. It can
replace the outer (...) with [...] or {...] as appropirate when it
sees the first top-level separator. (If there is a => at the top
level, it is a hash, otherwise an array.)</p>
<p>Idea for code generation: Generate pseudocode first. Then translate
to Perl. Then you can insert a peephole optimizer later. For
example</p>
<pre><code> foreachkey k (somehash) {
push somearray, $somehash{k}
}
</code></pre>
<p>could be optimized to</p>
<pre><code> somearray = values somehash;
</code></pre>
<p>add into hash: as key, add into value, replace value
add into array: at end only</p>
<p>How do we analyze something like: </p>
<pre><code> [ [ A, B ],
[ C, B ],
[ D, E ] ]
--------------
{ B => [A, C],
E => [D],
}
</code></pre>
<p>Idea: Analyze structure of input. Analyze structure of output and
figure out an expression to deposit each kind of output item. Iterate
over input items. Collect all input items into variables. Deposit
items into output in appropriate places.</p>
<p>For an input array, tag the items with index numbers.
See where the indices go in the output. Try to discern a pattern.
The above example:</p>
<pre><code> Try #1:
A: 1
B: 2
C: 1
B: 2 -- consistent with B above
D: 1
E: 2
Output: 2 => [1, 1]
2 => [1]
</code></pre>
<p>OK—2s are keys, 1s are array elements.</p>
<p>A different try fails:</p>
<pre><code> A: 1
B: 1
C: 2
B: 2 -- inconsistent, give up on this.
</code></pre>
<p>Now consider:</p>
<pre><code> [ [ A, B ],
[ C, B ],
[ D, E ] ]
--------------
{ A => B,
C => B,
D => E,
}
</code></pre>
<p>A,C,D get 1; B,E get 2. this works again.
1s are keys, 2s are values.</p>
<p>I need a way of describing an element of a nested data structure as a
simple descriptor so that I can figure out the mappings between
descriptors. For arrays and nested arrays, it's pretty easy: Use the
sequence of numeric indices. What about hashes? Just K/V?
Or does V need to be qualified with the key perhaps?</p>
<p>Example above:</p>
<pre><code> IN: A:11 B:12 22 C:21 D:31 E:32
OUT: A:K B:V C:K D:K E:V
</code></pre>
<p>Now try to find a mapping from the top set of labels to the bottom.
<code>x1 => K, x2 => V</code> works.</p>
<p>Problem with this:</p>
<pre><code> [ [ A, B ],
[ B, C ],
]
------------
{ A => B,
B => C,
}
</code></pre>
<p>is unresolvable. Still, maybe this works well enough in most common
cases. </p>
<p>Let's consider:</p>
<pre><code> [[ A , AAA , red , pink , Aaa],
[ B , BBB , yellow , tawny , Bbb],
[ A , AAA , green , nude , Aaa],
[ B , BBB , blue , violet , Bbb],
[ C , CCC , black , nude , Ccc],
]
-------------------------------------------------------------
{ A => [ AAA, [ [red, pink], [green, nude] ], Aaa],
B => [ BBB, [ [yellow, tawny], [blue, violet] ], Bbb],
C => [ CCC, [ [black, nude] ], CCC]
}
A: 00,20 => K
AAA: 01,21 => V0
red: 02 => V100
pink: 03 => V101
Aaa: 04 => V2
B: 10,30 => K
C: 40 => K
</code></pre>
<p>etc.</p>
<p>Conclusion: <code>x0 => K; x1 => V0; x2 => V100; x3 => V101; x4 => V2</code></p>
<p>How to reverse?</p>
<p>Simpler reverse example:</p>
<pre><code> { A => [ B, C ],
E => [ D ],
}
---------------------
[ [ A, B ],
[ A, C ],
[ E, D ],
]
A: K => 00, 10
B: V0 => 01
C: V1 => 11
D: V0 => 21
E: K => 20
</code></pre>
<p>Conclusion: <code>K => x0; V => x1</code>
This isn't enough information. Really, <code>V => k1</code>, where <code>k</code> is whatever
the key was!</p>
<p>What if V items have the associated key too?</p>
<pre><code> A: K => 00, 10
B: V{A}0=> 01
C: V{A}1=> 11
D: V{E}0=> 21
E: K => 20
</code></pre>
<p>Now there's enough information to realize that B amd C stay with the
A, if we're smart enough to figure out how to use it.</p>
<h3>2001-07-28</h3>
<p>Sent to Nyk Cowham</p>
<h3>2001-08-24</h3>
<p>Sent to Timur Shtatland</p>
<h3>2001-10-28</h3>
<p>Here's a great example. The output from <code>HTML::LinkExtor</code> is a list
like</p>
<pre><code> ([img, src, URL1, losrc, URL2],
[a, href, URL3],
...
)
</code></pre>
<p>we want to transform this into</p>
<pre><code> (URL1 => undef,
URL2 => undef,
URL3 => undef,
...
)
</code></pre>
Notes on a system for abbreviating SQL queries
http://blog.plover.com/2014/01/19#quirky
<p>(This post inaugurates <a href="http://blog.plover.com/notes/">a new section</a>
on my blog, for incomplete notes. It often happens that I have some
idea, usually for software, and I write up a bunch of miscellaneous
notes about it, and then never work on it. I'll use this section to
post some of those notes, mainly just because I think they might be
interesting, but also in the faint hope that someone might get
interested and do something with it.)</p>
<h3>Why are simple SQL queries so verbose?</h3>
<p>For example:</p>
<pre><code> UPDATE batches b
join products p using (product_id)
join clients c using (client_id)
SET b.scheduled_date = NOW()
WHERE b.scheduled_date > NOW()
and b.batch_processor = 'batchco'
and c.login_name = 'mjd' ;
</code></pre>
<p>(This is 208 characters.)</p>
<p>I guess about two-thirds of this is unavoidable, but those join-using
clauses ought to be omittable, or inferrable, or abbreviatable, or
something.</p>
<p><code>b.batch_processor</code> should be abbreviated to at least
<code>batch_processsor</code>, since that's the only field in those three tables
with that name. In fact it could probably be inferred from
<code>b_p</code>. Similarly <code>c.login_name</code> -> <code>login_name</code> -> <code>log</code> or <code>l_n</code>.</p>
<pre><code> update batches set sch_d = NOW()
where sch_d > NOW()
and bp = 'batchco'
and cl.ln = 'mjd'
</code></pre>
<p>(Only 94 characters.)</p>
<p><code>cl.ln</code> is inferrable: Only two tables begin with <code>cl</code>. None of the
field names in the <code>client_transaction_view</code> table look like
<code>ln</code>. So <code>cl.ln</code> unambiguously means <code>client.login_name</code>.</p>
<p>Then the question arises of how to join the batches to the clients.
This is the only really interesting part of this project, and the
basic rule is that it shouldn't do anything really clever. There is a
graph, which the program can figure out from looking at the foreign
key constraints. And the graph should clearly have a short path from
batches through products to clients.</p>
<p><code>bp</code> might be globally ambiguous, but it can be disambiguated by
assuming it's in one of the three tables involved.</p>
<p>If something <em>is</em> truly ambiguous, we can issue an intelligent request
for clarification:</p>
<pre><code>"bp" is ambiguous. Did you mean:
1. batches.batch_processor
2. batches.bun_predictor
0. None of the above
which? _
</code></pre>
<h3>Overview</h3>
<ol>
<li>Debreviate table names</li>
<li>Figure out required joins and join fields</li>
<li>Debreviate field names</li>
</ol>
<p>Can 1 and 2 really be separated? They can in the example above, but
maybe not in general.</p>
<p>I think separating 3 and putting it at the end is a good idea: don't
try to use field name abbreviations to disambiguate and debreviate
table names. Only go the other way. But this means that we can't
debreviate <code>cl</code>, since it might be <code>client_transaction_view</code>.</p>
<p>What if something like <code>cl</code> were left as ambiguous after stage 1, and
disambiguated only in stage 3? Then information would be unavailable
to the join resolution, which is the part that I really want to work.</p>
<h3>About abbreviations</h3>
<p>Abbreviations for <code>batch_processor</code>:</p>
<pre><code> bp
b_p
ba_pr
batch_p
</code></pre>
<p>There is a tradeoff here: the more different kinds of abbreviations
you accept, the more likely there are to be ambiguities.</p>
<h3>About table inference</h3>
<p>There could also be a preferences file that lists precedences for
tables and fields: if it lists <code>clients</code>, then anything that could
debreviate to <code>clients</code> or to <code>client_transaction_view</code>
automatically debreviates to <code>clients</code>. The first iteration could just
be a list of table names.</p>
<h3>About join inference</h3>
<p>Short join paths are preferred to long join paths.</p>
<p>If it takes a long time to generate the join graph, cache it. Build
it automatically on the first run, and then rebuild it on request
later on.</p>
<h3>More examples</h3>
<p>(this section blank)</p>
<h3>Implementation notes</h3>
<p>Maybe convert the input to a <code>SQL::Abstract</code> first, then walk the
resulting structure, first debreviating names, then inserting joins,
then debreviating the rest of the names. Then you can output the text
version of the result if you want to.</p>
<p>Note that this requires that the input be valid SQL. Your original
idea for the abbreviated SQL began with</p>
<pre><code> update set batches.sch_d = NOW()
</code></pre>
<p>rather than</p>
<pre><code> update batches set sch_d = NOW()
</code></pre>
<p>but the original version would probably be ruled out by this
implementation. In this case that is not a big deal, but this choice
of implementation might rule out more desirable abbreviations in the
future.</p>
<p>Correcting dumb mistakes in the SQL language design might be in
Quirky's purview. For example, suppose you do</p>
<pre><code> select * from table where (something)
</code></pre>
<h3>Application notes</h3>
<p>RJBS said he would be reluctant to use the abbreviated version of a
query in a program. I agree: it would be very foolish to do so,
because adding a table or a field might change the meaning of an
abbreviated SQL query that was written into a program ten years ago
and has worked ever since. This project was never intended to
abbreviate queries in program source code.</p>
<p>Quirky is mainly intended for one-off queries. I picture it going into
an improved replacement for the MySQL command-line client. It <em>might</em>
also find use in throwaway programs. I also picture a command-line
utility that reads your abbreviated query and prints the debreviated
version for inserting into your program.</p>
<h3>Miscellaneous notes</h3>
<p>(In the original document this section was blank. I have added here
some notes I made in pen on a printout of the foregoing, on an unknown
date.)</p>
<p>Maybe also abbreviate <code>update</code> => <code>u</code>, <code>where</code> => <code>w</code>, <code>and</code> => <code>&</code>. This cuts
the abbreviated query from 94 to 75 characters.</p>
<p>Since debreviation is easier [than join inference] do it first!</p>
<p>Another idea: "<code>id</code>" always means the main table's primary key field.</p>