Regularity
From Maze
Contents[hide] |
The Grid: Regularity in Space
Textile Grids
Truchet Tiles
Imagine a square tile, bisected into two triangles, one black, one white. Imagine two such tiles, placed next to one another. Out of this simple configuration emerges a surprising number of possible arrangements. Sixty-four, to be precise, as each tile can be oriented four ways, shifting the apex of the black triangle from corner to corner. Now imagine a whole floor or tapestry covered with a regular pattern of these repeating tiles. This is the power of the Truchet Tile, so named because the Dominican priest Sebastien Truchet first described what he called the "fecundity of these combinations" in 1704, after experimenting with some ceramic tiles he came across at a building site for a chateau near Orléans (Smith 374).
Matching a single Truchet tile with another, and another, and another, and so on, a designer is able to create an incredible array of patterns. The interplay between the direction of each tile and the varying repetition of black and white -- of positive and negative -- produces designs that can range from grid-like patterns to mesmerizing, almost three-dimensional mazes. Unlike earlier Islamic patterns or Celtic designs, which both relied on multiple-sized shapes, the Truchet tile uses only a single size and a single shape (Smith 378). In his original 1704 essay, Truchet provided examples of thirty different patterns, barely evoking the aesthetic possibilities of his tiles, though he notes that he "found too great a number to report them all" (Smith 374). Truchet's work would be the inspiration for a latter book, Douat's modestly named Methode pour faire une infinite de desseins differents, which in turn had a considerable impact on 18th century European art (Smith 373).
Yet all of Truchet's and Douat's examples are regular patterns, symmetrical and repetitive. The mathematician Cyril Stanley Smith observes that even more compelling designs can be generated from Truchet tiles if "dissymmetries" are introduced. What happens when the regularity of a Truchet pattern is interrupted by randomness? Smith provides one example, a block of Truchet tiles arranged at random:
The latices of a grid are still visible, but randomness has made its mark, leaving imperfections that disrupt any nascent pattern. Unlike the examples Truchet and Douat give, there is no resolution to the structure. Smith continues to push the limits of the Truchet tiles' regularity by omitting colors from the tiles, leaving only the black diagonal line. Suddenly the four orientations of any given tile have been reduced to two. Smith does this trick with random array of Truchet tiles pictured above:
Suddenly the Truchet tiles have generated a design that looks unmistakably like the 10 PRINT maze. The grid still remains -- indicating the edges of each tile -- but the diagonals no longer seem to bound positive or negative space. Instead, they appear to be walls. In this Truchet tile-produced artifact the dynamic between regularity and its opposite come into play, suggesting that regularity is not an aspect of design that exists in isolation, but rather can only be defined by its limitations, by those moments when the regular becomes irregular.
The Grid in Modern and Contemporary Art
The Computer Screen
[Include the C64 screen 40 x 25 grid]
Repeating: Regularity in Time and Process
The Flow of Control
In any imperative programming language, commands are processed in a particular order that relates to the left-to-right, then top-to-bottom path that the Western reader's eyes stereotypically take along a page. If one types in two PRINT commands directly to the Commodore 64's BASIC interpreter, with a colon between them, like so:
PRINT "FIRST": PRINT "SECOND"
The result is
FIRST SECOND
The command on the left is executed first; then, probably not very surprisingly, the command on the right is carried out. In executing the following program, the topmost, leftmost command is run first, then the one to the right, and then the one on the next line, so that three lines that read FIRST, SECOND, and THIRD are printed:
10 PRINT "FIRST": PRINT "SECOND" 20 PRINT "THIRD"
The order in which these two lines are actually typed in by the programmer is completely irrelevant to how the program runs. The lines of a BASIC program are executed based on their line numbers, not based on when lines were entered.
There are some important ways to complicate this straightforward program flow. All of these ways involve branching, which causes program flow to continue at some other command rather than what would is, according to left-to-right, top-to-bottom program structure, the next one.
At the low level of machine code and its execution by the processor, the way program flow works is similar. Machine language is a sequence of numbers, and the next number is usually processed. However, an executing machine language program, like a high-level program in BASIC or another imperative language, can either continue to process the next instruction or can move out of sequence to process a different instruction. The standard case is when a processor continues to the next machine language instruction, just as the reader of a text moves to the next word or line. This involves incrementing the program counter so that it points to the place where the next instruction is located in memory. If the current instruction is one that can change the flow of control, however, the program may jump to a new memory location and a new piece of code.
Conditional and Unconditional Branching
There are two essential ways that the flow of control can change and a program can "branch," or continue at a new point. An unconditional branch always directs the program to jump to a new location, like the instruction "Go directly to Jail -- do not pass Go" in Monopoly. The assembly mnemonic for an unconditional branch is JMP; the corresponding BASIC keyword is GOTO.
When an unconditional branch is used to point back to an earlier instruction, it can accomplish repetition in process. In 10 PRINT, the GOTO command is used to cause the program to loop, so that the PRINT command is repeated again and again.
The other type of branch is a conditional branch, a type of instruction that is critical to general-purpose computing. There are many different types of conditional branches in assembly, since there are many different types of conditions. BEQ is "branch if equal," for instance; when used after a comparison (CMP), the branch will be taken only if the compared values are equal. BMI, "branch if minus," checks to see if the last computation resulted in a negative value. In BASIC, using the IF ... THEN statement is the most straightforward way to accomplish a conditional branch, as this program demonstrates:
10 INPUT A$ 20 IF A$ = "1" THEN PRINT "YOU TYPED ONE!" : END 30 PRINT "SOMETHING ELSE..."
If, after running this program, the user types just the digit "1" and then presses RETURN, all of the statements on line 20 will be executed. "YOU TYPED ONE!" will be printed and then the program will terminate as END instructs. This is another way to change the flow of the program, of course: use END or STOP to terminate the program. If STOP is used, the CONTINUE command can be issued to pick up where the program left off.
If the user types anything else before pressing RETURN, the flow of control moves to line 30; both the first PRINT statement and the END are skipped. "SOMETHING ELSE..." is printed instead.
This program, although written differently, does exactly the same thing:
10 INPUT A$ 20 IF A$ = "1" THEN GOTO 40 30 PRINT "SOMETHING ELSE..." : END 40 PRINT "YOU TYPED ONE!"
Instead of using the IF ... THEN to directly determine whether two statements (the PRINT and END statements) should be executed, this one changes the flow of control with GOTO. The GOTO statement is used to skip ahead past PRINT "SOMETHING ELSE..." and END to line 40. Although this isn't a very exciting program, it shows that unconditional branching can be used to move ahead in the sequence of lines; there is nothing about GOTO that means it must be used to repeat or loop.
Although there is no IF ... THEN statement in 10 PRINT, and the program does not by any interpretation contain a conditional branch, this short program does accomplish a very small-scale sort of variation. By computing 205.5+RND(1) and passing that value to the function CHR$, the program prints either PETSCII character 205 or PETSCII character 206. This variation between two characters is a one-bit variation, a selection from the smallest possible set of options. Yet, in combination with the regularity of a repeating processes and the regularity of the Commodore 64's screen grid, these selections take shape as something evocative and visually interesting.
Bounded and Unbounded Loops
10 PRINT works as it does because of its repetition of the PRINT statement, repetition that is unconditional: It will continue until something outside the program interrupts it, such as the user pressing the key labeled RUN STOP or unplugging the computer.
At a high level, programs can contain two types of loops: bounded (also called "finite") and unbounded (or "infinite"). 10 PRINT has the latter kind. If one is writing a program that is intended to produce some result and exit, it would be a mistake to include an unbounded loop. The unbounded loop does have legitimate uses, however. It can be used to keep an application, usually an interactive one, running and accepting input until the system is shut off or rebooted. This can be done, and is one, even on a Commodore 64.
Bounded loops are those that end under certain conditions. The exact conditions vary; some will continue until the program reaches a pre-defined exit state while others execute a specific number of times. If there are exit conditions for a loop at all, that implies the programmer was expecting some kind of change to be introduced as the program executes.
A common use of finite loops is to create an iterative process. Iteration is a special type of looping where the result of one pass through the loop influences the result of succeeding passes. The simplest example of an iterative process is nothing more than counting. Beginning with an initial value of 1. Adding 1 to this (that is, increment it) to produce 2. Performing the same incrementing operation again, to yield 3, and so on. If the program goes to some limit, say 10:
10 A=1 20 PRINT A 30 A=A+1 40 IF A<=10 GOTO 20
The loop is bounded. If line 40 is replaced with 40 GOTO 20, the loop is unbounded.
A conditional branch is what makes loop bounded -- it ends when the condition is met. An unconditoinal branch corresponds to an unbounded loop.
The bounded loop, and counting up or down to a particular value, is so important in programming that BASIC has its own special syntax for specifying that sort of loop, using the FOR ... TO and NEXT statements. The bounded program above could also be written:
10 FOR A=1 TO 10 20 PRINT A 30 NEXT
FOR ... TO ... STEP (Sidebar)
The FOR loop in BASIC is a bit more general than is shown in the example in the main text. It can be used not only to increment a variable, but also to change its value each time by any amount. A different increment is set using the STEP keyword. To show only the even numbers between 2 and 10:
10 FOR A=2 TO 10 STEP 2 20 PRINT A 30 NEXT
If STEP is omitted, it's the same as adding "STEP 1." The step value can be set to a negative number or even to zero. By setting the value to 0, an unbounded FOR loop can be created:
10 FOR A=1 TO 10 STEP 0 20 PRINT "FOREVER!" 30 NEXT
This allows for an alternate version of 10 PRINT, slightly longer but still a "one-liner" of no more than 80 characters, that uses a FOR loop instead of GOTO:
10 FOR A=1 TO 2 STEP 0 : PRINT CHR$(205.5+RND(1)); : NEXT
Is 10 PRINT Iterating?
From the discussion so far, it should be clear that 10 PRINT has an unbounded loop thanks to the unconditional branch at the end. There is nothing in the code, however, to indicate that 10 PRINT is an example of iteration. There are no variables like A that change value from one pass to the next -- there are no variables at all, in fact -- and the code inside the loop, and the way that code works, never changes. In the most strightforward sense, the BASIC program 10 PRINT CHR$(205.5+RND(1)); : GOTO 10 does not iterate.
Watching the program execute on screen shows hints that there is something changing as it runs, though: the position where a new character is displayed changes every time the loop executes, moving one location to the right until it reaches the 40th column; then, the display of characters continues on the next line in column 1. The entire contents of the screen also moves up by two lines, with the top two lines disappearing, once the display of characters reaches the bottom left position.
None of this is a direct result of any BASIC statements included in 10 PRINT. Displaying strings on the screen generally has this effect, since BASIC's PRINT command calls the Commodore 64 KERNAL's CHAROUT routine and produces output in this way. So, while 10 PRINT is not an iterative program, it invokes the iterative behavior of PRINT. In this case, the behvaior is a sort of incrementing, because ";" is used to display the next character immediate after the previous one and a string that is one character long is displayed in each pass. 10 PRINT's simplicity exposes the power of using simple, iterative steps to create a complex construction.
Works Cited
Smith, Cyril Stanley, and Pauline Boucher. “The Tiling Patterns of Sebastien Truchet and the Topology of Structural Hierarchy.” Leonardo 20.4 (1987) : 373-385.
