Solution to In C

Back to Puzzle

Answer: DOUGH

by Alan Huang

This puzzle is a listing of 53 lines of C code, very vaguely ordered by length. Some of the lines are identical; others are clearly not valid C. We may suspect that our goal is to construct a valid program that follows the rules in the opening comment, and then see what it does when run.

Our first clue is the title and copyright year. In C is a piece of music composed in 1964 that consists of 53 melodic fragments, to be repeated any number of times or skipped at the discretion of each performer, but remaining in order. Each fragment thus corresponds to one line of the program; identical fragments give identical lines. The correspondence is based on the pitch of each note:

Ahexadecimal number
B♭control flow keyword
Bfunction
Ctype or type-related keyword
Dcharacter literal
Evariable
Fdecimal number
F♯++/−− (variable increment/decrement)
G&/* (pointer reference/dereference)
restcomment

In other words, the order in which these categories of thing appear in each line of C matches the order of the notes in the corresponding In C fragment. Things not in these categories (for example, parentheses and arithmetic or logical operators) have no musical counterpart; tied notes and consecutive rests count as one thing for matching purposes.

Using the score of In C, we can match everything up and determine the correct ordering of the lines, but this does not form a valid program. We still have to figure out how many times to repeat each line. We can do this by going through step by step and examining what the lines do, using the comments as signposts, and remembering that we have to set all the array entries. The final order and repeat counts are:

1int N; float Y; complex Z;Declare scratch variables.
1float F[23] = {Y =Declare the main array: 22 entries and a sentinel.
1/* The first array entry is used as scratch space, and so is one of the only entries that will be modified more than once. */ N = 41}; F[F[0] is comparatively easy to access via *F, so as the comment says, it houses some temporary values.
1/* This entry, around the middle of the array, is being set to its final value. */ N -= 32] = *F;This sets F[9].
1F[3] = *F; /* The value set here will, after the end of the program, be read as the letter E. */This sets F[3].
1typedefThis is the first line that is duplicated later on.
1/* The code up to here has run pretty normally, */ float T; T /* but this will soon no longer be true. */These types are just here to soak up some Cs.
1*P = 10 +OK: here we create P as a pointer into F, so it can move around over time and set various array entries.
1((isxdigit(*F) * /* The final program should not end up showing nondeterministic behavior. */isxdigit returns false, or 0, which cancels out the rand call...
1+rand())[&F]);...so this really just puts P at F + 10.
2-8, *P = (abs(*P) << abs(*P))The first repeated line. We need to fill this array entry, but running the line once leaves it at 0, and running it more than twice overflows, which is undefined behavior.
1% 69; *P /= fabs((float)Afterward, we just do some arithmetic for a while. This sets F[10].
1log(*P)); *(P + 4) = *P + /* The value set here will, after the end of the program, be read as the letter N. */ *F -However, we do see here the first use of -~/~-, which is very useful to fudge integers by one without using up a numeric literal. This sets F[14].
1~(int) asinh(*P); ++P;
1*P /* The value set here is a float that might not look exact, but will still pretty clearly give the letter S in the end. */This sets F[11].
1= *F * log10((int) trunc(
0free() volatile sin(); restrict exit() /* Uh-oh. */This line is nonsense.
1Y)); N--; Z = ~-(--P - F) + N *
1/* At this time, 5 out of 22 array entries should be set to their final values. */ *F;
1Z += N-- - (F - --P); *(F + N) = Z++ / ~-N; N++; (PFrom here we start using N as another index into F. This sets F[7].
3, ++PHere we increment P three times to skip past the already-set entries to the next blank one.
1)[N] = F[-~N]; Y = F[N--] = *F * 0x1.a895dp0; (exitHexadecimal float literals are valid C, but only if they have an exponent (in binary). This sets F[20] and F[8].
0, F[--N] = ++N + N-- / (++P - P--) + *P - 0x.accp4, exitThis concurrent modification is undefined behavior, however.
0); F[--N] = *(P - &Y + &N) / *F + *(P + 0xf); exit;And this is invalid pointer arithmetic.
1, F[--N] = *F + 0x1.b1aep21 / (0xdead + 0xbeef + 0xcafe + 0xf00d)), exitThis is fine. This sets F[6].
1; F[--N] = *F = 0x.9b3p5; exit - exit + exit - exit + exit,This is also fine (exit behaves as a pointer). This sets F[5] (and resets *F).
1Z -= N++; errno[P++] = *(F + -~N); *P = --Z / ~-N; (P++[N] = (errno is presumably 0 here, as nothing could have set it. This sets F[12] and F[13]. (Entry 19 is also set, but it will be modified again later.)
1Y)); N--; Z = ~-(--P - F) + N *Here Z finally becomes a complex number by using the imaginary constant I.
1I; *(F - ~(int) (This sets F[17].
0typedefDuplicated from before; invalid here.
1(*(F + 16) = *(F + lround(*F - tan(This sets F[16].
158)))) / *F + 13)) = *P * tan(208); *F =This sets F[0] (finally).
2*(P += 4); /* At this time, P should point to the last meaningful array entry. */Run twice so that the comment is true.
1*P = 10 +This sets F[21].
19-81 + (*F + sin(*F - cos(*F - tan(*F - fabs(*F))))); /* This line sets two array entries to their final values, */ if(*P == 0x0) *P = fabs((0x.29c2p0 * *F) * Z) - *F; --P; /* for a total of 18 out of 22. */ Z *= .638424 *Each repetition of this line sets *P if unset, then decrements P. This sets F[15] and F[4], and also passes the 18th entry but does not give it its final value. We stop when P is in position at F + 2 to fill in the next unset entry.
2-8, *P = (abs(*P) << abs(*P))Repeat twice for the same reason as last time.
1-0; *P /=This sets F[2].
2-0.795 * *F + sqrt(Repeat twice to make the parentheses line up.
1lround(*P)) + 3 ** P - !exit * (long) (Not exponentiation, just pointer dereference.
0+raise(9)Do not kill the program.
1+rand())[&F]);!exit gives 0 to cancel out the rand again.
0long time(); 0xe5cap3 voidThis line is nonsense.
118[F] = 1[F] = P[~-N] - (N ^ 12); YThis sets F[18] and F[1]. Y is set to 9 / 5.
1= 9. / N; P -= (int)
1'}' - '{'; *(P
0) = *(F + 'b' - Y * '5') /* Parse the extraction as follows: */ = *F /* ???? ?? ???? ? ?????? ???? ? (N), */ = *F /* using the current value of N at this time. */ = *F = *F + '\0'; P -= '\x4';Y is a float and so invalid in pointer arithmetic. The comments are valid, however. At this point, N is 5; see the extraction below.
1+ '\x13') = (N = ' ',This sets F[19], the last entry. N is set to 32.
1*F - *P / 30);
20[&N]; if(&Y) do { *P -=Here starts the final loop. This line must repeat twice for the braces to line up. What the loop does is subtract N = 32 from each array entry...
1-0; *P /=...and then divide it by Y = 9 / 5.
10[&Y]; } while
1(!&N); continue; }&N is guaranteed to be true, which breaks the inner do-while immediately, but the first iteration still goes off.
1while (*(++P));The outer do-while repeats until the sentinel at the end of F. (Using a G to represent a dereference of an increment is, technically, cheating, but it was the only reasonable way to make the loop work...)

Note: Usually, this might be where you’d expect a rigorous derivation or logical solve path. My confession is that I can’t give you that. When I say that we need an array entry to be set, that only means that we should generally expect the program to do things that have an effect; given the long cluephrase and constrained code, there isn’t much room to perform useless or redundant operations. I haven’t demonstrated that there aren’t other solutions that also leave the array filled but in a different state, and maybe that makes me a bad puzzle constructor.

The final program is available here. When compiled and run, it leaves a sequence of 22 values in F; promisingly, these values are all close to integers, and the first four convincingly spell out LINE in A1Z26. But then there are some negative values — what’s going on? Well, this is a C program, so it isn’t just A1Z26; it's actually ASCII minus 64. Using this we can extract the rest of the message:

012.001271L
18.999988I
214.015537N
35.000000E
4-11.9983594
5-7.0008689
613.999988N
715.000000O
819.999989T
95.000000E
10-10.9959315
1118.957855S
1215.000000O
1321.000002U
1414.004070N
154.004642D
1618.957855S
1712.001271L
188.999988I
1911.008636K
205.000000E
21-27.956041$
220.000000

In C fragment 49 note 5 is a B♭, and it corresponds to the keyword do in the first line of the final loop. This is supposed to sound like something with five letters (according to the last comment) that means “$”. If we pronounce “do” as in C, we won’t get anywhere. But if we pronounce it as in “doe, a deer” (fittingly representing C in fixed-note solfege), then it sounds like slang for money: DOUGH.

Author’s Notes

This was not originally intended to be a C esoterica puzzle. In my mind, the gold standard for this kind of puzzle is Efficiency, and I knew I wasn’t nearly good enough at either logic puzzles or C to match it. However, I did want a puzzle titled “In C” to exist in the world, and that meant having 53 pieces of something that would have to be repeated 0 or more times in the right order. Maybe that something is the input to a C program, or maybe some other part of the puzzle tells you how many times to repeat each piece, or maybe you actually have a char * and have to perform 53 conundrum-like steps on it that each keep it a valid word. But I kept coming back to the simplest expression of the concept as just 53 fragments of code. In order to make the In C score relevant, there would be some rigid (therefore highly constraining) logical correspondence used for reordering; furthermore, there aren’t really that many interesting ways to make solvers repeat a fragment N times. So I ended up having to pull a lot of dirty tricks; to quote this puzzle’s editor: “o god this code is a bit monstrous”

Here is a list of facts about the letter C.

In mathematics, C represents the complex numbers. Complex numbers are related to angles using the e = cos(θ) + i sin(θ) relation, which is occasionally abbreviated as cis(θ). “cis” in turn is occasionally found (Wikipedia says it’s European) as an abbreviation for the note C♯ (which does not appear in In C). C♯ is also a programming language. Going back to angles, they are measured in degrees, and another thing measured in degrees is temperature, where C stands for Celsius. F stands for Fahrenheit and is also a note. In programming, C is a hexadecimal digit, as are A through F, and in music, C can stand for 4/4 meter or common time (In C has no defined meter). In C has 53 parts; there are 53 non-exponent bits in a double-precision floating point number. MIDI assigns values from 0 to 127 to pitches, with middle C being 60, which lines up pretty well with ASCII. In C sounds somewhat like ANSI (it also sounds like the last half of Efficiency). A circled C represents copyright, which starts off the program.

Some traces of these remain in the puzzle. Z is a complex variable and the final loop converts Fahrenheit values to Celsius, both of which originally (when the concept was a bit simpler) the solver was supposed to figure out for themselves. Maybe plotting degrees as angles would have drawn out letters on the complex plane? It wasn’t really clear.

As long as I’m talking about puzzles that I want to exist but am not good enough to write, this seems as good a place as any to make the following offer. If you’re looking for an idea for a modern music crossover puzzle that goes as deep into the weeds as this one, you should write one about tone rows except they’re linguistic tones. We even have a title for you: “The Second Vietnamese School”. You’re welcome.

Finally: please never write real code that looks like this.