konfettia guide for people

konfetti is a programming language made of confetti. A program is a scatter of colored paper strips on the ground, inside an outline drawn with a crayon, and running it means walking from strip to strip: the color says what to do, the position says where to go next.

Your first program

Five minutes, in the editor. You will make a program of four strips that reads a letter and writes it twice.

  1. Open the editor

    Open konfetti.ax, or, in the konfetti folder, run make serve and open localhost:8137/web/. You see a stone circle in a meadow, a cannon in the middle, and a panel of buttons on the right. The cannon fires once as the page opens.

  2. Fire

    Press Fire or Space two or three more times. Paper strips fly out, flutter down and lie where they land. Each strip is one bit of a program.

  3. Pick four strips

    Find a black , an orange and two white strips. Your pointer is a white glove: press on a strip and drag it to some empty stones, between the cannon and you. Lay them in a row: black, orange, white, white. Put their middles about one strip length apart. Which way a strip points does not matter.

  4. Draw the outline

    Press Crayon or C. Put the crayon down just past the black strip, at the end of the row away from the others, and drag an outline around all four. Let go: the outline closes itself.

    Whatever lies inside the outline is the program. The blue dot where the crayon touched down is the origin. Dark lines with a pale edge now join neighbouring strips, and a dark ring sits on the black one: the walk starts there, because it is the strip nearest the origin. If other strips ended up inside the outline, drag them out.

  5. Run it

    Type hi in the Input box and press Run. A yellow pointer hops from strip to strip. Black reads the h, orange copies it, and each white writes one copy. Output shows hh.

  6. Look inside

    Press Debug or D, then Step or N to run one strip at a time. Each step says what it did in plain words, and the stacks show the numbers the program holds. Then load the cat example from Examples… to see a program that loops.

Want more? Press Learn konfetti or L in the editor for twelve short lessons, or read the same lessons as tutorials under Learn konfetti, further down this page.

The thirteen colors

Each color is one instruction. The program works on a stack: a pile of whole numbers where you can only reach the top. Most colors take numbers off the top and put the answer back.

ColorOpWhat it does
redPUSHPushes 1. A run of reds in a row counts up instead, so n reds push n. -- n
orangeDUPCopies the top number. a -- a a
yellowSWAPSwaps the top two numbers. a b -- b a
greenADDAdds the top two numbers. a b -- a+b
cyanSUBSubtracts the top number from the one below it. a b -- a-b
blueMULMultiplies the top two numbers. a b -- a*b
purpleDIVMODDivides the number below the top by the top. Leaves the whole-number answer, then the remainder on top. Rounds down, so −7 ÷ 2 is −4 remainder 1. Dividing by 0 does nothing. a b -- a/b a%b
pinkBRANCHPops a number and picks the way on: zero goes straightest, positive turns furthest left, negative furthest right. a --
whiteOUTPops a number and writes it as one byte of output. 65 is the letter A. a --
blackINReads one byte of input and pushes it, or pushes −1 when the input has run out. -- c
brownDROPThrows the top number away. a --
silverSTASHMoves the top number from the main stack to the stash. a --
goldFETCHMoves the top number of the stash back to the main stack. -- a

On the ground every strip is one flat, bright color inside the same border: a dark line with a white hairline just inside it. The dark line makes a pale strip stand out on the pale stones, and the white one shows where a dark strip ends, so two black strips lying across each other still look like two.

How to read a b -- a+b: before the strip runs, the top two numbers are a and b, with b on top; afterwards a+b is there instead.

There is a second stack, the stash, for keeping a number out of the way: silver puts it there, gold brings it back. Input and output are bytes, numbers from 0 to 255; text is bytes, one for each letter from a to z or A to Z, digit or sign such as !, and several for other letters, such as é, and for emoji. A strip that needs more numbers than the stack holds does nothing. A konfetti program never crashes; sloppy confetti just misbehaves.

How the walk works

The walk goes from strip to strip. Each strip it lands on runs, then the walk picks the next one. Only three things matter: where each strip's middle is, its color, and which strip lies on top of which. Distances are in strip lengths.

Strips link to near neighbours

1.5 lengthstoo far: no link
Strips whose middles are at most one and a half lengths apart are linked. The walk only moves along links.

The start is the strip nearest the origin

the crayon outlineorigin (0, 0)start: the strip nearest the origin
The origin is where the crayon first touched the ground. The walk starts on the nearest strip, heading away from the origin.

Go straightest

25°: taken90°110°came from here:never straight backstraight on
From each strip the walk takes the linked strip that needs the smallest turn, left or right. It never goes straight back to the strip it just came from.

When two choices need the same turn, the nearer one wins, and after that the one listed first in the program text.

Pink picks one of three ways

zero: straight onpositive:leftmostnegative:rightmostarriving
Pink takes a number off the stack. Zero goes straightest, as usual. A positive number takes the way that turns furthest left; a negative number, furthest right.

With only one way on, all three choices are the same way. To compare two numbers, subtract them and then branch: zero means they were equal.

A strip on top covers the one below

red, alonedrop whitewhite counts;red is covered
If a strip lies less than half a length from one dropped later, the lower one is covered. A covered strip is not part of the program at all. To replace a strip, drop another on top of it.

A dead end stops the program

When no linked strip is left to go to, the program halts, which means it stops. The last strip still runs. To make a loop, bend the trail back into itself: the walk keeps going round until a pink sends it out.

Reds count

A red right after a red adds 1 to the number on top instead of pushing a new 1. So a run of five reds pushes 5. To push 3 and then 2, put another color between the runs.

Programs as text

Every program can be written down as text, one strip per line: its color, then x and y of its middle, as whole numbers. 1000 is one strip length. # starts a comment. The editor shows this text under Program; files of it end in .kft.

# prints "A" (8*8+1 = 65)
red     1000 0
red     2000 0
...
white  13000 0

The origin is (0, 0). x grows to the right and y away from you, as the editor first shows the stones. Lines go bottom of the pile first, so a later line lies on top of an earlier one.

The three examples

Pick them from Examples… in the editor, or find them in the examples folder.

hello: a straight line

origina run of 8 reds123456788DUP64MUL1PUSH65ADDAOUT
Under each strip: the top of the stack after it runs.

Eight reds push 8. Orange copies it, blue multiplies the two: 64. A red pushes 1 and green adds: 65. White writes 65, which is the letter A. Then the trail ends, and so does the program.

cat: a loop with an exit

INDUPPUSH 1ADDBRANCHOUTDROPorigin
The walk starts on black, the strip nearest the origin, heading up.

cat copies its input to its output. Black reads a byte, orange copies it, red and green add 1 to the copy. Pink takes that copy: any real byte plus 1 is positive, so the walk turns left to white, which writes the byte, and on round to black again. At the end of the input black pushes −1; plus 1 is zero, so pink goes straight on to brown, which drops the −1. Brown is a dead end, and the program stops.

count: a ring with an on-ramp

10 reds: 10square it, 3 timesthe ring
The whole of count.kft.
DUPMULPUSH 1SUBDUPBRANCHDROPn > 0zero
The ring, close up. The on-ramp joins at red from behind.

count makes 100,000,000 and counts it down to zero. It prints nothing; it is the speed test. Ten reds push 10. Three times, orange copies and blue multiplies, which squares the number: 100, 10,000, 100,000,000. Then the ring subtracts 1, copies the result and branches on it: positive turns left, back round the ring; zero goes straight on to brown. That is 400 million steps. The terminal version does them in about half a second.

Layout patterns

The editor

The editor is a meadow you can walk around in, painted like a watercolor pop-up book: flat painted trees, bushes, rocks, hills and clouds stand in layers around a circle of pale stones, and the grass bends in the wind. The panel on the right holds every control; the bubble at the top left says what to do next and what just happened.

On a phone the panel is a sheet at the bottom of the screen. Its edge shows the end of the output; tap or drag the handle to open it half way or all the way. Crayon, Fire and Run float just above it, with Check while a lesson is open. Each group of controls folds away: tap its title to open or close it.

As an app. konfetti can be installed, to open from its own icon like an app. In Chrome or Edge, press Install on the card that offers it a few seconds after the editor opens, or use the browser's own install button. On an iPhone or iPad, tap Share, then Add to Home Screen. After one visit, the editor also works offline.

As a desktop app. konfetti also comes as an app for macOS, Windows and Linux: the same editor in a window of its own, needing no browser and no internet. Download it from the releases page, under the newest release:

In the app, Docs opens this guide in a second window (closing the editor's window quits the app, guide included), and your theme, Mute and the lessons you have passed are remembered. Save asks where to keep the program, with the name program.kft filled in, and Open… shows the system's own file chooser.

Wind in the app: on Windows and Linux the app cannot tell where you are, so the wind there is always made up, marked (made up: no location). On a Mac, the first time you press Wind, macOS asks whether Konfetti may use your location, and says what for. Say yes and you get the real wind where you are. Choose Don't Allow and the wind is made up, as in a browser that says no. macOS remembers your answer; to change it, open System Settings, Privacy & Security, Location Services, and find Konfetti in the list. If you leave the question unanswered for a minute, the wind is made up that time: answer the question, then press Wind off and on.

The first time you open it, your computer may stop the app, because nobody has paid Apple or Microsoft to vouch for it. If you trust it:

To build the app yourself, for the computer you are on: with the konfetti folder and Rust, install one tool, then make app. It takes a few minutes the first time. On a Mac the result is src-tauri/target/release/bundle/macos/Konfetti.app.

cargo install tauri-cli --version "^2" --locked
make app

In the meadow

The glove
Over the meadow, your mouse pointer is a white cartoon glove. Press on a strip and drag it to move it; the glove pinches while it carries. Drop a strip on another to cover it. On a touch screen, press a finger on a strip and drag. A touch that just misses still takes the nearest strip within a fingertip, and in a pile the one on top.
Double-click a strip
Flicks it into the air. It lands somewhere nearby. On a touch screen, tap it twice.
Moving the view
Drag the ground to turn around, scroll to zoom, right-drag to slide. On a touch screen, drag with one finger to turn, pinch to zoom and slide two fingers to move.
What the marks mean
The blue line is the crayon outline and the blue dot is the origin. Dark lines with a pale edge join linked strips. A dark ring marks the start. While a program runs, a yellow pointer, outlined in ink, floats over the strip that runs next. The faint curved pencil lines on the ground are only the joins between the stones.

The panel

ControlWhat it does
konfetti logoA puff of paper confetti. Just for fun.
Mute MTurns all sound off or on. See Sound.
DocsOpens this guide: in a new tab, or in the desktop app in a second window.
Learn konfetti LOpens the lessons. See Learn mode.
Fire SpaceShoots a burst of 40 strips of random colors from the cannon.
Crayon CPick it, then drag on the stones to draw an outline. It closes itself when you let go. The dot where it touched down is the origin. Drawing again replaces the outline.
Wind WBrings in the real wind where you are. See Wind and the flag.
RunWalks the program strip by strip, five a second unless you change the speed in the debugger. Output and stacks change as it goes.
Run fastRuns the program flat out and shows the result.
StopStops a run.
Debug DOpens the debugger. See Debug mode.
InputThe text the program reads, one byte at a time, with black strips.
OutputWhat the program wrote with white strips, or what went wrong. Past 64 KB it shows only the end, after a ….
StacksThe main stack and the stash as rows of boxes, bottom on the left, the top one marked. A number that is a letter shows the letter too.
As text (.kft)The program inside the outline as text, kept up to date as you move strips. Save keeps it for you.
Load textLays out the text in the box as strips in front of the cannon, with a fresh outline around them. A program too big to lie there slides toward the cannon, just far enough to be on the stones; a burst fired after that can land on it, and loading it again clears that away. It replaces all the confetti. It stops a run first; if the text is not a program, the confetti stays as it was and Output says why.
Examples…Loads hello, cat or count; dad, countdown, compare or reverse, the programs of tutorials 13 to 16; aventyret, which writes Hello, Äventyret; 8ball, which answers the question in Input with Yes, No or Maybe; calc, a calculator: put 3 4 + 2 * in Input (numbers first, then what to do with them) and it writes 14; or infix, a calculator for sums as they are usually written: (4 + 3) * 2 writes 14, and 4 + 3 * 2 writes 10.
SaveSaves the text in the box as a file, program.kft, where your browser keeps downloads (the desktop app asks where). It is plain text: the terminal's konfetti runs the same file.
Open…Chooses a .kft file and lays it out, as Load text does with the text in the box.
BuildMakes the text in the box into a web page that runs it, program.html, saved as Save saves (the Mac app asks where). It is the page the terminal's konfetti build --html makes: open it in any browser, straight from the file, and send it to anyone. If the text is not a program, nothing is built and Output says why.
Sweep outsideRemoves the litter: every landed strip outside the outline, except a lesson's spare strips.
Clear allRemoves every strip and the outline.
ColorsThe thirteen colors. Hold the pointer over one to read what it does.
How it worksA short reminder of the rules.
ThemeChanges the look of the panel. See Themes.

Learn mode

Press Learn konfetti at the top of the panel, or L, for twelve short lessons, from running a first program to writing a loop. A card opens with the list. A tick marks the lessons you have passed, and the first one you have not passed says start here or next. You can do them in any order. The editor remembers which you passed, in this browser. The same lessons are on this page as tutorials 1 to 12.

Picking a lesson clears the ground and lays out its program inside a crayon outline. The spare strips you need lie in a row just outside the outline, and Input holds the text the lesson starts with. Wind, a run and the crayon are stopped first, and the debugger closes. The card says what the lesson is about, what to do, and the goal.

Check my program
Runs the program in the outline on a few inputs and compares what it writes with what it should write. If it is right every time, the cannon fires and the lesson is ticked off. If not, the card shows what it should have written and what it wrote, one box per character, with the first wrong one marked; or it says the program had not stopped after 1,000,000 steps.
Hint
Shows a hint. Press it again for a more direct one. After the last hint it says Show me, which lays out a finished program.
Watch it run
Opens the debugger on the program, paused before its first strip. Press Step or N.
Start over
Lays the lesson's program and spare strips out again.
Next lesson
Appears once the program passes. After the last lesson it says Back to lessons.
Lessons and Leave
Back to the list, or out of learn mode. Leaving keeps the confetti where it is.

Keys

KeyDoes
SpaceFire
CPick up or put down the crayon
WWind on or off
MMute on or off
DDebug mode on or off
LLearn mode on or off
N P RIn debug mode: Step, Play or pause, Restart

Keys do nothing while you type in a text box. When a button has keyboard focus, Space presses that button instead of firing.

Debug mode

Debug mode shows a program running one strip at a time, and says in words what each strip did. Press Debug or D. A dock opens at the bottom (at the top on a phone) with the program loaded and paused on its first strip.

Step N
Runs one strip.
Play P
Runs strip after strip, and pauses when pressed again.
Restart R
Back to the start, paused, with the confetti as it lies now.
Speed
How many strips a second Play runs: 1 to 30, 5 to begin with. Plain Run uses the same speed.
Status line
Paused or playing, how many steps have run, and which strip is next.
Explanation
Point at any strip, or touch it on a touch screen, to read what it does, and whether it is covered or outside the outline.
Trace
The last 30 steps, newest first, each in plain words. For example: 3 red PUSH #2 pushed 1, went straight on to #3 green.
Stacks
Both stacks as boxes, the top one marked TOP. A number that is a letter shows the letter: 97 shows 'a'.

In the meadow, every strip of the program gets a label with its number and its instruction. NOW marks the strip about to run and NEXT the one after it, with an arrow for the turn; on the ground, a yellow ring and a yellow arrow, both outlined in ink, show the same. START and the origin are labelled too. Covered strips are struck through and marked covered. Far-away labels shrink to just the number.

If you move strips before the first step, the paused program follows along. After that, the status line asks you to press Restart. Run fast does not keep a trace.

Themes

Four looks for the panel, the hint, the lesson card and the debugger. The meadow stays the same.

Switch with the buttons at the bottom of the panel, or add ?theme=craft (or paper, toybox or arcade) to the address. The editor remembers the theme you last picked with the buttons in this browser.

Sound

The editor makes every sound itself as it plays; there are no sound files. You hear the cannon, each strip landing, strips being picked up and put down, a flick, the crayon scratching as you draw, and the outline closing. While a program runs, every step plays a note. Each color has its own note, all from the same five-note scale, so any program sounds like a tune. Output, the end of a run and mistakes have sounds too. Birds call now and then. With the wind on, you hear it rise and fall with the gusts.

Browsers stay silent until you click or press a key on the page, so the sound starts then. Mute or M turns it all off, and the editor remembers that in this browser. When the tab is hidden, it goes quiet by itself.

Wind and the flag

Press Wind or W to bring in the real wind. Your browser asks for your location (in the desktop app, macOS asks on a Mac, and Windows and Linux have none to give); konfetti rounds it to about 10 km and asks the free weather service Open-Meteo for the wind there right now. The panel shows it, for example 5.7 m/s from 196°: the speed, and the compass direction it blows from. If you say no, or the weather cannot be reached, the editor makes up a wind of 3 to 10 m/s and says so. Press Wind again to stop it.

The flag on the tall pole at the back left of the stone circle shows the wind. With the wind off it hangs limp. As the wind grows it lifts, streams away downwind and ripples faster, so you can read both direction and strength from it. Even with the wind off, the grass and trees sway, the clouds drift and the windmill turns in a light breeze of their own; turn the wind on and they follow the real one.

Save the program before you turn the wind on. Open… puts it back exactly.

In the terminal

The editor is one way to run konfetti; the terminal is another. Building needs Rust with its WebAssembly target, and Python 3 for the editor's little web server.

rustup target add wasm32-unknown-unknown
make          # build konfetti and the editor's runtime
make test     # run the tests
make serve    # start the editor

make serve serves the editor at localhost:8137/web/.

Run a program

./target/release/konfetti examples/hello.kft
echo hi | ./target/release/konfetti examples/cat.kft

The first prints A; the second prints hi. The program reads what you pipe into it. With nothing piped in, it waits for you to type: finish with Ctrl+D. Output goes to the screen.

To save a program from the editor, copy the text under Program into a file ending in .kft.

Watch every step

echo hi | ./target/release/konfetti --trace examples/cat.kft

--trace prints one line per step to the error stream: the strip's number in the file, its color and position, then both stacks, top on the right.

bit 0    black   (0, 1000)  main [104]  stash []
bit 1    orange  (0, 2200)  main [104, 104]  stash []

Make a program into a command

./target/release/konfetti build examples/cat.kft -o cat
echo hi | ./cat

build writes one file that runs your program, about half a megabyte: the konfetti runtime with your program inside. It runs on the same kind of computer as the one that built it, without konfetti installed. It reads and writes like konfetti cat.kft does, and ignores anything you type after its name. A program with a mistake in it fails to build, so you find out straight away.

On a Mac, a built program that was downloaded from the internet is blocked, like any app from an unknown developer. It cannot be signed to get past that: your program sits after the end of the runtime, and Apple's signing tool refuses such a file. If you trust it, this lets it run:

xattr -d com.apple.quarantine ./cat

Make a program into a web page

./target/release/konfetti build examples/cat.kft --html -o cat.html

This writes a single page, about 70 KB, with the runtime and your program inside. Open it in a browser straight from the file: it needs no server and no internet. It has an Input box, Run (or Ctrl+Enter, ⌘+Enter on a Mac, in the input), Stop for programs that run long, the Output (its last 256 KB, after a …, when there is more), and the program itself under The program. Send it to anyone. The editor's Build button makes the same page from the text in its box.

Run a .kft file directly

Make the first line of the file

#!/usr/bin/env konfetti

then chmod +x prog.kft. With konfetti in a folder on your PATH, ./prog.kft runs it. To konfetti the line is just a comment.

When it ends

konfetti exits with 0 when the program halts, 1 when a file cannot be read or written or the program has a mistake, and 2 when the command itself is wrong, after printing how to use it. Mistakes look like this:

konfetti: bad.kft: line 1: unknown color `teal`

When something goes wrong

The meadow does not appear, or the buttons do nothing.
Open it through the web server with make serve, not by opening index.html as a file. No Rust? python3 -m http.server 8137 in the konfetti folder serves it too, with the runtime that comes ready built.
"Nothing to run: draw an outline with the crayon first."
Press Crayon and draw an outline around your strips.
The program starts at the wrong strip.
It starts at the strip nearest the blue origin dot. Draw the outline again, touching down right next to the strip you want first.
It stops too soon.
Look at the lines between strips: a gap of more than one and a half lengths breaks the trail, and a stray strip nearby can steal a turn. Turn on Debug and step through to see where it goes.
It never stops.
Press Stop. Every path needs a dead end, and a pink to leave each loop. Check that the exit is not linked to another part of the trail.
A strip seems to be ignored.
It may be covered by a strip on top, or outside the outline. In debug mode, point at it to find out.
A number comes out wrong.
Two runs of reds that touch are one number: three reds then two reds is 5. Put another color between them.
The wind wrecked my program.
Turn the wind off, then drag the strips back, or paste the program text and press Load text.
There is no sound.
Click once in the page; browsers wait for that. Check that Mute is off.
The editor is slow.
Add ?grass=20000 to the address for a thinner meadow.
In the terminal, the program just sits there.
It is waiting for input. Type some and press Ctrl+D, or pipe input in with echo.
"unknown color" or "expected color x y".
Each line needs one of the thirteen color names, then two whole numbers. The message gives the line number.

Learn konfetti

Seventeen tutorials, to read in order. Each one ends with a program that works: one you ran, changed or made. The first twelve follow the twelve lessons of the editor's learn mode, with the same programs. The next four go further, and design new programs from nothing. The last one is about finding mistakes. A cheat sheet closes the page.

Two ways to follow along

How to read the diagrams

Each diagram is drawn from the program's file. Every strip sits at its real position, seen from above: x grows to the right and y up the page, which is away from you in the editor. The strips are drawn shorter than they are, so that the arrows fit between them.

How to read the step tables

The tables are made with konfetti --trace, which prints one line per step. Each row is one step: the strip that ran, what it did, and the stacks after it ran, with the top on the right. The stash has a column only where the program uses it. Output is everything written so far. A box like 255 is a byte that is not a letter, digit or sign.

1Follow the trail

You will learn what a program is, where the walk starts, and what black and white strips do.

A konfetti program is a trail of paper strips. Running it means walking along the trail, from strip to strip. Each strip the walk lands on does one small thing, chosen by its color. The walk starts on the strip nearest the origin and stops where the trail ends.

This program has two colors. A black strip reads the next character of the input. A white strip writes a character to the output. The trail goes black, white, black, white, so the program reads a character and writes it, twice.

Each letter from a to z or A to Z, each digit from 0 to 9, and signs such as ! and ? are one character. Other letters, such as é or å, count as several, and so do emoji and some signs, such as €. Black reads them one part at a time.

0123origin
lessons/walk.solution.kft, which is also the lesson's starting program: four strips in a row, starting next to the origin.
# Reads two characters and writes each one straight back.
black    1200      0
white    2400      0
black    3600      0
white    4800      0

Each line is one strip: its color, then the x and y of its middle. 1000 is one strip length, so these strips are 1.2 lengths apart. The first strip is 1.2 lengths from the origin; the others are further away, so the walk starts on strip 0, heading away from the origin, along the row.

Step by step

printf 'Hi' | ./target/release/konfetti --trace lessons/walk.solution.kft
StepStripWhat it didMainOutput
1#0 blackread H (72)72
2#1 whitewrote H (72)emptyH
3#2 blackread i (105)105H
4#3 whitewrote i (105). Dead end: stopemptyHi

The program writes Hi. Look at the Main column: black does not keep the letter itself but its number, 72 for H, and white turns the number back into a letter. Tutorial 3 is about that column.

Try next

In the editor, start lesson 1, press Watch it run, then Step (or N) four times. The debugger says in words what each step did, like the table above. Then type another word into Input and press Run.

Exercises

  1. What does the program write when the input is Yo!?
    Answer

    Yo. There are only two black strips, so only two characters are read. The ! is never read.

  2. And when the input is just H?
    Answer

    H and then a byte with the number 255, which is not a letter. When the input has run out, black pushes −1. White writes the lowest 8 bits of a number, and for −1 those make 255. Tutorial 9 uses the −1 to notice the end of the input, and tutorial 10 to stop there.

2Make the trail longer

You will learn when two strips are linked, and how to add strips to a trail.

The walk only moves between strips that are linked. Two strips are linked when their middles are at most one and a half lengths apart: 1500 in the text. In the editor a dark line joins every linked pair. (See How the walk works for a picture.)

The lesson starts with the program of tutorial 1, which echoes two characters. With Hey as input it writes He: the y is never read. You add one black and one white at the end of the row.

012345origin
lessons/trail.solution.kft. Strips 4 and 5, in dashed frames, are the two you add.
# Echoes three characters: one black and one white for each.
black    1200      0
white    2400      0
black    3600      0
white    4800      0
black    6000      0
white    7200      0

Neighbours are 1200 apart, so each strip is linked to the one before it and the one after it. Strips two places apart are 2400 apart: too far to link. So the walk has exactly one way on from each strip, and it follows the row.

Step by step

printf 'Hey' | ./target/release/konfetti --trace lessons/trail.solution.kft
StepStripWhat it didMainOutput
1#0 blackread H (72)72
2#1 whitewrote H (72)emptyH
3#2 blackread e (101)101H
4#3 whitewrote e (101)emptyHe
5#4 blackread y (121)121He
6#5 whitewrote y (121). Dead end: stopemptyHey

Try next

In the editor, drag strip 5 a little away from strip 4 and watch the line between them. It disappears once the middles are more than 1.5 lengths apart, and then Check my program fails: the walk stops at strip 4. Drag it back.

Do not drop a new strip right on top of another one. A strip whose middle lies less than half a length from the middle of a strip dropped later is covered, and is no longer part of the program. Tutorial 8 is about that.

Exercises

  1. What does the finished program write when the input is Hello?
    Answer

    Hel: three blacks read three characters.

  2. Where would the next black and white go, to copy four characters?
    Answer

    At (8400, 0) and (9600, 0), continuing the row 1200 apart. With Hey! as input this writes Hey!.

    # lessons/trail.solution.kft with one more black and white: four characters.
    black    1200      0
    white    2400      0
    black    3600      0
    white    4800      0
    black    6000      0
    white    7200      0
    black    8400      0
    white    9600      0

3The stack

You will learn that characters are numbers, what the stack is, and what push and pop mean.

To a computer, text is numbers. Each character has one: a is 97, b is 98, A is 65, a space is 32. The program keeps numbers on a stack: a pile where only the top one can be reached. Putting a number on top is a push; taking the top one off is a pop.

So this is exactly what the two colors do. Black reads one character and pushes its number. White pops the top number and writes it as a character. A number that was pushed last is popped first.

0123origin
lessons/stack.solution.kft. The starting program has only the two blacks; you add the two whites.
# Reads two characters, then writes them: the one read last comes out first.
black    1200      0
black    2400      0
white    3600      0
white    4800      0

Step by step

printf 'no' | ./target/release/konfetti --trace lessons/stack.solution.kft
StepStripWhat it didMainOutput
1#0 blackread n (110)110
2#1 blackread o (111)110 111
3#2 whitewrote o (111)110o
4#3 whitewrote n (110). Dead end: stopemptyon

After both blacks the stack holds 110 (n) and, on top of it, 111 (o). The first white pops the top one, so o comes out first: the program turns no into on.

Try next

Run it in the editor with Watch it run, and watch the Stacks boxes grow and shrink. The box marked top is the one the next strip will reach.

Exercises

  1. What does the program write for up?
    Answer

    pu.

  2. And for abc?
    Answer

    ba. Only two characters are read; c stays in the input.

4Adding

You will learn what red and green do, and how to read a stack effect such as a b -- a+b.

Red pushes the number 1, unless it runs right after another red: tutorial 5 is about that. Green pops the top two numbers and pushes their sum. Written as a stack effect, green is a b -- a+b: before it runs, the top two numbers are a and b, with b on top; afterwards a+b is there instead.

So black, red, green, white reads a character, adds 1 to its number and writes the result: the next letter.

0123origin
lessons/add.solution.kft. The lesson starts with the black strip alone.
# Reads a character, adds 1 to its number, writes the result.
black    1200      0
red      2400      0
green    3600      0
white    4800      0

Step by step

printf 'a' | ./target/release/konfetti --trace lessons/add.solution.kft
StepStripWhat it didMainOutput
1#0 blackread a (97)97
2#1 redpushed 197 1
3#2 green97 + 1 = 9898
4#3 whitewrote b (98). Dead end: stopemptyb

With H (72) it writes I (73).

Try next

If Check my program says it wrote the number 1 instead of b, white came right after red and wrote the 1 that red had just pushed. Green has to come between them, to add that 1 to 97. Press Watch it run and look at the stack when the walk reaches white: it must hold just 98.

Exercises

  1. What does the program write for z?
    Answer

    {. z is 122, and 123 is the curly bracket.

  2. Which input makes it write A?
    Answer

    @, which is 64.

5Counting with red

You will learn how a run of reds makes a number, and what ends a run.

A red that runs right after another red does not push a new 1. It adds 1 to the number on top instead. So one red pushes 1, two reds in a row push 2, and n reds in a row push n. A strip of any other color ends the run: the next red pushes a fresh 1.

012345origin
lessons/count.solution.kft. The lesson starts with black and one red; you add two reds, green and white.
# Reads a character, adds 3 to its number, writes the result.
black    1200      0
red      2400      0
red      3600      0
red      4800      0
green    6000      0
white    7200      0

Step by step

printf 'a' | ./target/release/konfetti --trace lessons/count.solution.kft
StepStripWhat it didMainOutput
1#0 blackread a (97)97
2#1 redpushed 197 1
3#2 redcounted up to 297 2
4#3 redcounted up to 397 3
5#4 green97 + 3 = 100100
6#5 whitewrote d (100). Dead end: stopemptyd

Strip 1 pushes 1, because the strip before it, black, is not red. Strips 2 and 3 each count the top up by one. Green then adds 3 to 97, and white writes 100, which is d. With H the program writes K.

Try next

The editor's debugger says pushed 1 for the first red, then counted up to 2 (run of 2) and counted up to 3 (run of 3). In the terminal, --trace shows only the stack: 97 1, then 97 2, then 97 3.

Exercises

  1. What does the program write for w?
    Answer

    z: 119 + 3 = 122.

  2. How many reds in a row would turn a into z?
    Answer

    25, because z is 122 and a is 97. That makes a long trail; tutorial 7 shows a shorter way to make big numbers.

6Turning corners

You will learn how the walk picks the next strip when it has a choice.

A trail does not have to be straight. After each strip, the walk looks at the strips linked to it, leaves out the one it just came from, and takes the one that needs the smallest turn, left or right. Going straight on needs no turn at all, so it always wins when it is possible.

The starting program should turn a into b, like tutorial 4, with the trail turning a corner at green. But a brown strip lies straight ahead of green, and brown pops the number and throws it away:

01234origin
Before: lessons/corner.start.kft. From green, brown is straight on and white is a 90° turn. The walk goes to brown.
0123origin
After: lessons/corner.solution.kft. With brown dragged out of the outline (faded), white is the only way on.

Step by step

Before, with a: the walk skips strip 3 and writes nothing.

printf 'a' | ./target/release/konfetti --trace lessons/corner.start.kft
StepStripWhat it didMainOutput
1#0 blackread a (97)97
2#1 redpushed 197 1
3#2 green97 + 1 = 9898
4#4 brownthrew away 98. Dead end: stopempty

After: the walk turns left at green.

printf 'a' | ./target/release/konfetti --trace lessons/corner.solution.kft
StepStripWhat it didMainOutput
1#0 blackread a (97)97
2#1 redpushed 197 1
3#2 green97 + 1 = 98, turned left98
4#3 whitewrote b (98). Dead end: stopemptyb
# With nothing straight ahead of green, the walk turns left to white.
black    1200      0
red      2400      0
green    3600      0
white    3600   1200

Left and right are as the walk sees them, like a person walking along the trail. Here the walk heads along the row, and white lies to its left.

Try next

A strip outside the crayon outline is not part of the program, so dragging brown across the outline takes it out. Brown is still lying there, but the program text in As text (.kft), under Program, no longer lists it.

Exercises

  1. In the starting program, what is on the stack when the walk stops?
    Answer

    Nothing. Green left 98 on the stack, and brown threw it away (see the first table).

  2. Instead of dragging brown out, drop a white strip right on top of it. What does the program write for a?
    Answer

    b. The new white covers brown and is straight ahead of green, so the walk goes there and writes 98. Nothing lies beyond it, so the walk stops; the white at the corner is never reached.

    # lessons/corner.start.kft with a white dropped on the brown: brown is
    # covered, and the walk goes straight on to the new white. a -> b.
    black    1200      0
    red      2400      0
    green    3600      0
    white    3600   1200
    brown    4800      0
    white    4800      0

7Big numbers

You will learn what orange and blue do, and how to make a big number from a few strips.

To write A without reading it, a program has to make 65 itself. 65 reds in a row would do it. A shorter way: 65 is 8 × 8 + 1. Orange copies the top number (a -- a a), and blue multiplies the top two (a b -- a*b). So eight reds, orange, blue make 64; one more red and green make 65; white writes it.

This program reads no input. Its first row is eight reds that go round a corner. That changes nothing: they still run one right after another, so they push 8. The rest of the trail comes back in a second row, two lengths above the first, so that the rows cannot link to each other.

0123456789101112origin
lessons/multiply.solution.kft. The lesson starts with the eight reds; you add strips 8 to 12.
# 8, copied, multiplied: 64. Plus 1 is 65, the letter A.
red      1200      0
red      2400      0
red      3600      0
red      4800      0
red      6000      0
red      7200      0
red      7200   1200
red      7200   2400
orange   6000   2400
blue     4800   2400
red      3600   2400
green    2400   2400
white    1200   2400

Step by step

./target/release/konfetti --trace lessons/multiply.solution.kft
StepStripWhat it didMainOutput
1#0 redpushed 11
2#1 redcounted up to 22
3#2 redcounted up to 33
4#3 redcounted up to 44
5#4 redcounted up to 55
6#5 redcounted up to 6, turned left6
7#6 redcounted up to 77
8#7 redcounted up to 8, turned left8
9#8 orangecopied 88 8
10#9 blue8 × 8 = 6464
11#10 redpushed 164 1
12#11 green64 + 1 = 6565
13#12 whitewrote A (65). Dead end: stopemptyA

The red at step 11 pushes a fresh 1, because the strip before it is blue. The program writes A. examples/hello.kft is the same program in one straight row.

Try next

This program never reads, so it needs no input. Change the red at strip 10 into a run of two reds, and it writes B.

Exercises

  1. Which strips make 100?
    Answer

    Ten reds, orange, blue: 10 × 10. Tutorial 13 starts that way, and after its twelfth step the stack holds 100.

  2. Why does the red after blue push 1, and not add 1 to 64?
    Answer

    A red only counts up when the strip that ran just before it was red. Before this one ran blue.

8Covering a strip

You will learn what a pile of strips means, and how to replace a strip.

A strip that lies on top of another covers it, and a covered strip is not part of the program. Exactly: a strip is covered when a strip above it has its middle less than half a length (500) from its own middle. In the text, a later line lies above an earlier one.

The starting program adds 1, like tutorial 4. To make it subtract 1 instead, drop a cyan strip on green. Cyan subtracts: a b -- a-b, the lower number minus the top one.

0134origingreen (2) is covered
lessons/cover.solution.kft. Cyan (4) lies exactly on green (2), shown faded and turned underneath.
# The cyan strip lies on the green one and covers it: subtract instead of add.
black    1200      0
red      2400      0
green    3400      0
white    4400      0
cyan     3400      0

Cyan is the last line, so it lies on top. Green is 0 from cyan, less than 500, so green is covered. Covered strips link to nothing, so the trail now runs red, cyan, white.

Step by step

printf 'b' | ./target/release/konfetti --trace lessons/cover.solution.kft
StepStripWhat it didMainOutput
1#0 blackread b (98)98
2#1 redpushed 198 1
3#4 cyan98 − 1 = 9797
4#3 whitewrote a (97). Dead end: stopemptya

Strip 2 never appears: it is not in the program any more. The program turns b into a, and I into H.

Try next

In debug mode the editor labels a covered strip covered and crosses its name out. Point at it to read why.

Exercises

  1. What does the finished program write for a?
    Answer

    `, the backtick, which is 96.

  2. Move the cyan line above the green line in the text. What does the program write for b now?
    Answer

    c. Now cyan is lower in the pile, so green covers cyan, and green adds.

    # The cyan of lessons/cover.solution.kft listed before green: now cyan is
    # lower in the pile, so green covers cyan and still adds. b -> c.
    black    1200      0
    red      2400      0
    cyan     3400      0
    green    3400      0
    white    4400      0

9Choosing a way

You will learn how pink makes a choice, and how a program notices the end of its input.

Pink pops a number and picks where the walk goes next. A positive number takes the way that turns furthest left. A negative number takes the way that turns furthest right. Zero takes the straightest way, as every other color does.

When the input has run out, black pushes −1. Every character you can type has a positive number, so a pink right after reading tells the two apart. Pink uses up the number it pops, so orange copies it first: one copy for pink, one to write.

01234originpositive: leftnegative: right
lessons/branch.solution.kft. The solid arrows are the walk with a as input, the dashed one the walk with no input. You add white (4), on the left arm.
# Positive turns left to white. Negative (no input) turns right to brown.
black    1200      0
orange   2400      0
pink     3600      0
brown    4200  -1040
white    4200   1040

Step by step

With a:

printf 'a' | ./target/release/konfetti --trace lessons/branch.solution.kft
StepStripWhat it didMainOutput
1#0 blackread a (97)97
2#1 orangecopied 9797 97
3#2 pinkpopped 97, positive, turned left97
4#4 whitewrote a (97). Dead end: stopemptya

With no input:

./target/release/konfetti --trace lessons/branch.solution.kft < /dev/null
StepStripWhat it didMainOutput
1#0 blackthe input has run out: pushed −1−1
2#1 orangecopied −1−1 −1
3#2 pinkpopped −1, negative, turned right−1
4#3 brownthrew away −1. Dead end: stopempty

Each line of the trace starts with the number of the strip that ran, so you can see which arm was taken: 4 for a, 3 for no input. The program writes a for a and nothing for no input.

The two arms are each 60° off straight on. A zero would be a tie between them, and a tie goes to the nearer strip, then to the one listed first in the file: here that is brown. No character you can type is 0, so it does not come up.

Try next

In the editor, run it twice with Watch it run: once with a in Input and once with Input empty. The debugger draws an arrow for the turn pink takes.

Exercises

  1. What does the program write for ab?
    Answer

    a. It reads only once.

  2. Swap white and brown, so that white is on the right arm. What does it write for a, and for no input?
    Answer

    For a it writes nothing: 97 is positive, so pink turns left, to brown. For no input it writes a byte 255: −1 turns right, to white, which writes −1 as 255.

    # lessons/branch.solution.kft with white and brown swapped: white on the
    # right arm. a -> nothing; no input -> byte 255.
    black    1200      0
    orange   2400      0
    pink     3600      0
    white    4200  -1040
    brown    4200   1040

10A loop

You will learn how to repeat: bend the trail into a ring, and leave it with pink.

To do something again and again, bend the trail back into itself. The walk goes round and round the ring. A pink on the ring decides, each time round, whether to go on round or to leave.

This ring is the program of tutorial 9 with black, orange and pink on three corners of a square, white on the fourth, and brown beyond pink. From pink, white is a left turn and brown a right turn. So every character (positive) turns left, to white, which writes it and leads back to black. At the end of the input, −1 turns right, to brown, a dead end.

01234originexit
lessons/loop.solution.kft. The walk goes round counter-clockwise: black, orange, pink, white, black again. You add white (4).
# White closes the ring: pink turns left to it, and it leads back to black.
black       0   1200
orange      0   2400
pink    -1200   2400
brown   -1200   3700
white   -1200   1200

Step by step

printf 'abc' | ./target/release/konfetti --trace lessons/loop.solution.kft
StepStripWhat it didMainOutput
1#0 blackread a (97)97
2#1 orangecopied 97, turned left97 97
3#2 pinkpopped 97, positive, turned left97
4#4 whitewrote a (97), turned leftemptya
5#0 blackread b (98), turned left98a
6#1 orangecopied 98, turned left98 98a
7#2 pinkpopped 98, positive, turned left98a
8#4 whitewrote b (98), turned leftemptyab
9#0 blackread c (99), turned left99ab
10#1 orangecopied 99, turned left99 99ab
11#2 pinkpopped 99, positive, turned left99ab
12#4 whitewrote c (99), turned leftemptyabc
13#0 blackthe input has run out: pushed −1, turned left−1abc
14#1 orangecopied −1, turned left−1 −1abc
15#2 pinkpopped −1, negative, turned right−1abc
16#3 brownthrew away −1. Dead end: stopemptyabc

Each time round takes four steps and writes one character. This program is a cat: it copies its whole input, Hi! to Hi!. examples/cat.kft does the same with a different test: it adds 1 to the copy, so that the end of the input is a zero and goes straight on.

A zero byte, which you cannot type, is a tie at pink: white and brown are both a 90° turn. The nearer one wins: white, 1200 from pink, against brown at 1300. So this ring copies zero bytes too.

Try next

Watch it run in the editor with Play (P) and a low speed. A ring that the walk can never leave is a program that never stops; tutorial 17 shows one.

Exercises

  1. How many steps does the program take for abc, and why?
    Answer

    16: four for each of the three characters, and four more to read the end of the input and leave by brown.

  2. What happens if the brown strip is missing?
    Answer

    At the end of the input, pink takes the rightmost way, but the only way on is white, back round the ring. White writes 255 and black reads −1 again, for ever. Tutorial 17 has this program, examples/mistakes/noexit.kft.

11The stash

You will learn how to put a number aside on the second stack, the stash.

There is a second stack, the stash. Silver moves the top number of the main stack onto the stash. Gold moves the top number of the stash back onto the main stack. Nothing else touches the stash.

In tutorial 3, two blacks and two whites wrote a word backwards, because the character read last was on top. To keep the order, put the second character aside, write the first, then fetch the second and write it.

012345origin
lessons/stash.solution.kft. The lesson starts with the two blacks; you add silver, white, gold, white.
# Puts the second character aside, writes the first, then fetches and writes the second.
black    1200      0
black    2400      0
silver   3600      0
white    4800      0
gold     6000      0
white    7200      0

Step by step

printf 'no' | ./target/release/konfetti --trace lessons/stash.solution.kft
StepStripWhat it didMainStashOutput
1#0 blackread n (110)110empty
2#1 blackread o (111)110 111empty
3#2 silvermoved 111 to the stash110111
4#3 whitewrote n (110)empty111n
5#4 goldtook 111 back from the stash111emptyn
6#5 whitewrote o (111). Dead end: stopemptyemptyno

The program writes no.

Try next

The editor shows both stacks under Stacks, each as a row of boxes.

Exercises

  1. What does the program write for just x?
    Answer

    x and then a byte 255. The second black pushes −1, silver puts it in the stash, white writes x, gold brings the −1 back, and the last white writes it as 255.

12Challenge: a secret code

You will learn to put a loop and arithmetic together, and to think about which way the walk goes round.

The program should read a whole message and write every character one number higher, so that HAL becomes IBM. It is the copying ring of tutorial 10, stretched into a ring of six places. Between pink and white the character's number is on the stack, so that is where to add 1: red, then green, as in tutorial 4.

The walk goes round counter-clockwise, so the first empty place after pink is the one to its left in the picture. That one must push 1, and the next must add.

0123456origin
lessons/code.solution.kft, a ring of six with sides 1100 long. You add red (5) and green (6). Brown (4) is the exit.
# The copying ring with red and green before white: every character goes up by 1.
black       0   1100
orange    550   2053
pink        0   3006
white   -1100   1100
brown     850   3855
red     -1100   3006
green   -1650   2053

From the origin the walk heads up to black. From black, orange is a 30° turn to the right and white a 90° turn to the left, so the walk goes to orange first: counter-clockwise. At pink, red is a 60° turn to the left and brown a 75° turn to the right.

Step by step

printf 'HAL' | ./target/release/konfetti --trace lessons/code.solution.kft
StepStripWhat it didMainOutput
1#0 blackread H (72), turned right72
2#1 orangecopied 72, turned left72 72
3#2 pinkpopped 72, positive, turned left72
4#5 redpushed 1, turned left72 1
5#6 green72 + 1 = 73, turned left73
6#3 whitewrote I (73), turned leftemptyI
7#0 blackread A (65), turned left65I
8#1 orangecopied 65, turned left65 65I
9#2 pinkpopped 65, positive, turned left65I
10#5 redpushed 1, turned left65 1I
11#6 green65 + 1 = 66, turned left66I
12#3 whitewrote B (66), turned leftemptyIB
13#0 blackread L (76), turned left76IB
14#1 orangecopied 76, turned left76 76IB
15#2 pinkpopped 76, positive, turned left76IB
16#5 redpushed 1, turned left76 1IB
17#6 green76 + 1 = 77, turned left77IB
18#3 whitewrote M (77), turned leftemptyIBM
19#0 blackthe input has run out: pushed −1, turned left−1IBM
20#1 orangecopied −1, turned left−1 −1IBM
21#2 pinkpopped −1, negative, turned right−1IBM
22#4 brownthrew away −1. Dead end: stopemptyIBM

It writes IBM, and abc becomes bcd.

Try next

In the editor, press Watch it run and then Play, and watch the walk go round once for each character.

Exercises

  1. Cover green with a cyan strip. What does the program write for IBM?
    Answer

    HAL. Cyan subtracts the 1, so the program decodes. (The lesson's check then says no, because it still asks for the first code.)

    # lessons/code.solution.kft with a cyan dropped on green: subtract instead
    # of add. IBM -> HAL.
    black       0   1100
    orange    550   2053
    pink        0   3006
    white   -1100   1100
    brown     850   3855
    red     -1100   3006
    green   -1650   2053
    cyan    -1650   2053
  2. What does the finished program write for z?
    Answer

    {, as in tutorial 4.

Going further

The next four tutorials make new programs from nothing. Each one goes the same way, and you can use it for your own programs:

  1. Plan. Write the instructions as a list, with the stack after each one. Work out the numbers you need.
  2. Lay it out. Put the strips on a grid 1200 apart, so that each one links only to its four straight neighbours. Fold long trails into rows, put loops into rings, put each pink where the trail forks, and end every path in a dead end.
  3. Check it. Run it with --trace and compare each step with the plan.

The plans below are shown as the finished program's trace, so every stack in them is what really happens. All four are in the editor's Examples… menu, as dad, countdown, compare and reverse.

13Writing a word

You will learn to build the numbers of a word, to keep a copy of a number for later, and to fold a long trail into rows.

The task: write the word dad, without reading anything.

Plan

StepStripWhat it didMainOutput
1#0 redpushed 11
2#1 redcounted up to 22
3#2 redcounted up to 33
4#3 redcounted up to 44
5#4 redcounted up to 55
6#5 redcounted up to 66
7#6 redcounted up to 7, turned left7
8#7 redcounted up to 88
9#8 redcounted up to 9, turned left9
10#9 redcounted up to 1010
11#10 orangecopied 1010 10
12#11 blue10 × 10 = 100100
13#12 orangecopied 100100 100
14#13 whitewrote d (100)100d
15#14 orangecopied 100, turned right100 100d
16#15 redpushed 1100 100 1d
17#16 redcounted up to 2, turned right100 100 2d
18#17 redcounted up to 3100 100 3d
19#18 cyan100 − 3 = 97100 97d
20#19 whitewrote a (97)100da
21#20 whitewrote d (100). Dead end: stopemptydad

Layout

That is 21 strips. In one row 1200 apart they would reach 25 lengths. Fold the trail into rows of seven, like tutorial 7:

Reds that go round a bend are still a run, so the bend can fall anywhere in the ten reds.

01234567891011121314151617181920origin
examples/dad.kft: three rows, folded at two bends.
# dad: writes the word "dad". d is 100 = 10*10, a is 97 = 100-3.
# Keep a copy of 100 under everything; the last white writes it.
# Three rows, two lengths apart, joined by one strip at each bend.
red      1200     0   # 1
red      2400     0   # 2
red      3600     0   # 3
red      4800     0   # 4
red      6000     0   # 5
red      7200     0   # 6
red      8400     0   # 7
red      8400  1200   # 8      (the run goes on round the bend)
red      8400  2400   # 9
red      7200  2400   # 10
orange   6000  2400   # 10 10
blue     4800  2400   # 100
orange   3600  2400   # 100 100
white    2400  2400   # 100          writes d
orange   1200  2400   # 100 100
red      1200  3600   # 100 100 1
red      1200  4800   # 100 100 2
red      2400  4800   # 100 100 3
cyan     3600  4800   # 100 97
white    4800  4800   # 100          writes a
white    6000  4800   #              writes d

Run it

./target/release/konfetti examples/dad.kft

It writes dad.

Try next

Make it write bad: b is 98, so the first letter needs 100 − 2. Plan it first, with the stack after each strip.

14Counting down

You will learn the difference between a digit and a number, swapping the top two numbers with yellow, a loop that runs a set number of times, keeping a constant in the stash, and joining a ring safely.

The task: read one digit, then write the digits from it down to 1. 5 should give 54321.

Plan

The part before the loop, the on-ramp, with 2 as input:

StepStripWhat it didMainStashOutput
1#0 redpushed 11empty
2#1 redcounted up to 22empty
3#2 redcounted up to 33empty
4#3 redcounted up to 44empty
5#4 redcounted up to 55empty
6#5 redcounted up to 66empty
7#6 redcounted up to 7, turned left7empty
8#7 orangecopied 77 7empty
9#8 blue7 × 7 = 49, turned left49empty
10#9 redpushed 149 1empty
11#10 cyan49 − 1 = 4848empty
12#11 orangecopied 4848 48empty
13#12 silvermoved 48 to the stash4848
14#13 blackread 2 (50)48 5048
15#14 yellowswapped 48 and 50, turned right50 4848
16#15 cyan50 − 48 = 2248
17#16 orangecopied 2, turned right2 248

Then the loop, twice round, and out:

StepStripWhat it didMainStashOutput
18#17 goldtook 48 back from the stash, turned left2 2 48empty
19#18 orangecopied 482 2 48 48empty
20#19 silvermoved 48 to the stash2 2 4848
21#20 green2 + 48 = 50, turned left2 5048
22#21 whitewrote 2 (50)2482
23#22 redpushed 1, turned left2 1482
24#23 cyan2 − 1 = 11482
25#24 orangecopied 11 1482
26#25 pinkpopped 1, positive, turned left1482
27#26 orangecopied 11 1482
28#17 goldtook 48 back from the stash, turned left1 1 48empty2
29#18 orangecopied 481 1 48 48empty2
30#19 silvermoved 48 to the stash1 1 48482
31#20 green1 + 48 = 49, turned left1 49482
32#21 whitewrote 1 (49)14821
33#22 redpushed 1, turned left1 14821
34#23 cyan1 − 1 = 004821
35#24 orangecopied 00 04821
36#25 pinkpopped 0, zero, straight on04821
37#27 brownthrew away 0. Dead end: stopempty4821

Layout

0123456789101112131415161718192021222324252627originexitthe ringthe on-ramp
examples/countdown.kft. The on-ramp folds in two rows; the ring is joined at gold (17) from behind, by orange (16).
# countdown: reads one digit and writes the digits from it down to 1.
# 5 -> 54321. The ring writes before it tests, so 0 -> 0.
# The on-ramp makes 48 (the character 0) and keeps it in the stash,
# turns the digit into a number n, copies it and joins the ring at gold
# from behind: arriving from either side, the ring's next strip is the
# smallest turn.
red      1200     0   # 1
red      2400     0   # 2
red      3600     0   # 3
red      4800     0   # 4
red      6000     0   # 5
red      7200     0   # 6
red      8400     0   # 7
orange   8400  1200   # 7 7
blue     8400  2400   # 49
red      7200  2400   # 49 1
cyan     6000  2400   # 48
orange   4800  2400   # 48 48
silver   3600  2400   # 48            stash 48
black    2400  2400   # 48 c          (c = 53 for the digit 5)
yellow   1200  2400   # c 48
cyan     1200  3600   # n             (n = c - 48)
orange   1200  4800   # n n           on-ramp ends, joins the ring
gold     2650  4500   # n n 48        stash empty     (ring: join here)
orange   3850  4500   # n n 48 48
silver   5050  4500   # n n 48        stash 48
green    6250  4500   # n n+48
white    6250  5700   # n             writes the digit
red      6250  6900   # n 1
cyan     5050  6900   # n-1
orange   3850  6900   # n-1 n-1
pink     2650  6900   # n-1   positive: left, round again; zero: straight on
orange   2650  5700   # n-1 n-1       back to gold
brown    1450  6900   # (zero) dead end, halt

Run it

printf '5' | ./target/release/konfetti examples/countdown.kft

It writes 54321, and 9 gives 987654321.

With 0 it writes 0: the ring writes first and tests afterwards, so it always writes at least one digit. After writing 0 it subtracts 1, and −1 at pink takes the rightmost way, which is the exit too: straight on is the rightmost of the two ways.

Try next

Change it to count down to 0 instead of 1. Hint: test n before subtracting.

15Comparing two characters

You will learn to compare by subtracting, to use all three ways out of a pink, and to do the shared work before a fork.

The task: read two characters a and b, and write < if a comes before b, = if they are the same, and > if a comes after b.

Plan

StepStripWhat it didMainOutput
1#0 redpushed 11
2#1 redcounted up to 22
3#2 redcounted up to 33
4#3 redcounted up to 44
5#4 redcounted up to 55
6#5 redcounted up to 6, turned left6
7#6 redcounted up to 77
8#7 redcounted up to 8, turned left8
9#8 orangecopied 88 8
10#9 blue8 × 8 = 6464
11#10 redpushed 164 1
12#11 redcounted up to 264 2
13#12 redcounted up to 3, turned right64 3
14#13 cyan64 − 3 = 6161
15#14 blackread a (97)61 97
16#15 blackread b (98)61 97 98
17#16 cyan97 − 98 = −161 −1
18#17 pinkpopped −1, negative, turned right61
19#22 redpushed 161 1
20#23 cyan61 − 1 = 6060
21#24 whitewrote < (60). Dead end: stopempty<

Layout

0123456789101112131415161718192021222324origin=><
examples/compare.kft. Solid: the walk for ab; dashed: the arms that ba and aa take.
# compare: reads two characters a and b and writes <, = or >.
# Make 61 (=) first, then branch on a-b: each arm only adjusts 61.
# Zero goes straight on to =, positive turns left to > (62),
# negative turns right to < (60).
red      1200     0   # 1
red      2400     0   # 2
red      3600     0   # 3
red      4800     0   # 4
red      6000     0   # 5
red      7200     0   # 6
red      7200  1200   # 7
red      7200  2400   # 8
orange   6000  2400   # 8 8
blue     4800  2400   # 64
red      3600  2400   # 64 1
red      2400  2400   # 64 2
red      1200  2400   # 64 3
cyan     1200  3600   # 61
black    1200  4800   # 61 a
black    1200  6000   # 61 a b
cyan     1200  7200   # 61 a-b
pink     1200  8400   # 61
white    1200  9600   # zero, straight on:   writes =
red         0  8400   # positive, left:      61 1
green   -1200  8400   #                      62
white   -2400  8400   #                      writes >
red      2400  8400   # negative, right:     61 1
cyan     3600  8400   #                      60
white    4800  8400   #                      writes <

Run it

printf 'ab' | ./target/release/konfetti examples/compare.kft
InputWritesWhy
ab<97 − 98 = −1: right
ba>98 − 97 = 1: left
aa=97 − 97 = 0: straight on
Za<Z is 90: capitals come before small letters
a>the second black pushes −1: 97 − (−1) = 98

Try next

Write the later of the two characters instead of a sign. Keep copies of both in the stash before subtracting, and fetch the right one on each arm.

16Reversing the input

You will learn to store any number of values on the stash, to mark where they end, and to run two loops one after the other.

The task: write the whole input backwards. stressed should become desserts.

Plan

With ab as input, all of it:

StepStripWhat it didMainStashOutput
1#0 redpushed 11empty
2#1 orangecopied 11 1empty
3#2 cyan1 − 1 = 00empty
4#3 silvermoved 0 to the stash, turned rightempty0
5#4 blackread a (97), turned left970
6#5 orangecopied 97, turned left97 970
7#6 redpushed 197 97 10
8#7 green97 + 1 = 98, turned left97 980
9#8 pinkpopped 98, positive, turned left970
10#9 silvermoved 97 to the stashempty0 97
11#4 blackread b (98), turned left980 97
12#5 orangecopied 98, turned left98 980 97
13#6 redpushed 198 98 10 97
14#7 green98 + 1 = 99, turned left98 990 97
15#8 pinkpopped 99, positive, turned left980 97
16#9 silvermoved 98 to the stashempty0 97 98
17#4 blackthe input has run out: pushed −1, turned left−10 97 98
18#5 orangecopied −1, turned left−1 −10 97 98
19#6 redpushed 1−1 −1 10 97 98
20#7 green−1 + 1 = 0, turned left−1 00 97 98
21#8 pinkpopped 0, zero, straight on−10 97 98
22#10 brownthrew away −1, turned rightempty0 97 98
23#11 goldtook 98 back from the stash, turned left980 97
24#12 orangecopied 98, turned left98 980 97
25#13 pinkpopped 98, positive, turned left980 97
26#14 whitewrote b (98), turned leftempty0 97b
27#11 goldtook 97 back from the stash, turned left970b
28#12 orangecopied 97, turned left97 970b
29#13 pinkpopped 97, positive, turned left970b
30#14 whitewrote a (97), turned leftempty0ba
31#11 goldtook 0 back from the stash, turned left0emptyba
32#12 orangecopied 0, turned left0 0emptyba
33#13 pinkpopped 0, zero, straight on0emptyba
34#15 brownthrew away 0. Dead end: stopemptyemptyba

Layout

0123456789101112131415originring 1ring 2
examples/reverse.kft. The marker column goes up from the origin into ring 1; ring 1's exit goes down into ring 2.
# reverse: writes its input backwards. stressed -> desserts.
# A 0 goes into the stash first, as a marker. The first ring moves
# every character to the stash; the second fetches them back, last
# one first, and writes them until it fetches the 0.
# Each ring is joined at a corner from behind, like count.kft.
red         0  1200   # 1
orange      0  2400   # 1 1
cyan        0  3600   # 0
silver      0  4800   #               stash 0         joins ring 1
black     300  6250   # c                             (-1 at the end)
orange    300  7450   # c c
red      -900  7450   # c c 1
green   -2100  7450   # c c+1
pink    -2100  6250   # c   positive: left; zero (end of input): straight on
silver   -900  6250   #               stash 0 ... c   back to black
brown   -2100  5050   # (the -1 dropped)              joins ring 2
gold    -3550  5350   # x             (the last character first)
orange  -4750  5350   # x x
pink    -4750  4150   # x   positive: left; zero (the marker): straight on
white   -3550  4150   #               writes x, back to gold
brown   -4750  2950   # (the 0 dropped) dead end, halt

Run it

printf 'stressed' | ./target/release/konfetti examples/reverse.kft

It writes desserts. abc gives cba, and no input gives nothing.

One limit: a zero byte in the input looks like the marker. a, a zero byte, b gives just b. Typed text never holds one.

Try next

Make it write each line backwards, keeping the lines in order. You need a second test in ring 1, for the newline (10), and a way back into it after ring 2.

17When it does not work

You will learn five mistakes beginners often make, how to spot each one, and how to mend it.

Two tools show what a program really does:

In both, compare each step with your plan. The first step that differs is where the mistake is. The broken programs below are in examples/mistakes.

Two runs of red touch

The plan: read a character, push 3, push 2, multiply them to 6, add: a to g. Instead it writes a byte that is not a letter.

012345678origin
examples/mistakes/runs.kft: five reds in a row, round a bend.
printf 'a' | ./target/release/konfetti --trace examples/mistakes/runs.kft
bit 0    black   (1200, 0)  main [97]  stash []
bit 1    red     (2400, 0)  main [97, 1]  stash []
bit 2    red     (3600, 0)  main [97, 2]  stash []
bit 3    red     (4800, 0)  main [97, 3]  stash []
bit 4    red     (6000, 0)  main [97, 4]  stash []
bit 5    red     (6000, 1200)  main [97, 5]  stash []
bit 6    blue    (6000, 2400)  main [485]  stash []
bit 7    green   (4800, 2400)  main [485]  stash []
bit 8    white   (3600, 2400)  main []  stash []

What the trace shows. After strip 5 the plan says 97 3 2, but the stack holds 97 5: the five reds were one run. Blue then multiplies 97 by 5, green finds only one number and does nothing, and white writes 485, whose lowest 8 bits are byte 229.

The fix. Put a strip of another color between the runs. There is no color that does nothing, but orange then brown copies the top and throws the copy away, which comes to the same. Now it writes g.

012345678910origin
examples/mistakes/runs-fixed.kft: orange (4) and brown (5) split the reds into 3 and 2.

Two rows too close

The plan: copy four characters, with the trail folded back in a second row. It copies them, then never stops.

01234567origin
examples/mistakes/rows.kft: the second row is 1200 above the first, so every strip is linked to the one beside it in the other row.
printf 'abcd' | ./target/release/konfetti --trace \
  examples/mistakes/rows.kft 2>&1 >/dev/null | head -n 10
bit 0    black   (1200, 0)  main [97]  stash []
bit 1    white   (2400, 0)  main []  stash []
bit 2    black   (3600, 0)  main [98]  stash []
bit 3    white   (4800, 0)  main []  stash []
bit 4    black   (4800, 1200)  main [99]  stash []
bit 5    white   (3600, 1200)  main []  stash []
bit 6    black   (2400, 1200)  main [100]  stash []
bit 7    white   (1200, 1200)  main []  stash []
bit 0    black   (1200, 0)  main [-1]  stash []
bit 1    white   (2400, 0)  main []  stash []

What the trace shows. After strip 7, the end of the second row, the walk does not stop: it goes on to strip 0 and round again. Strip 0 lies 1200 below strip 7, so they are linked, and at the end of the row that link is the only way on. Along the rows the walk went straight on, because straight beats a 90° turn, so the cross-links did no harm until then. The program writes abcd and then bytes 255 for ever. 2>&1 >/dev/null sends the trace into head and the output away; head stops it after 10 lines.

The fix. Rows two lengths apart, with one strip at the bend. In the editor, check that no line joins the rows except at the bend.

01234567origin
examples/mistakes/rows-fixed.kft copies abcd and stops.

The walk starts at the wrong end

The plan: black, red, green, white, which turns a into b. It writes nothing.

0123origin
examples/mistakes/start.kft: the right trail, but white is nearest the origin.
printf 'a' | ./target/release/konfetti --trace examples/mistakes/start.kft
bit 0    white   (1200, 0)  main []  stash []
bit 1    green   (2400, 0)  main []  stash []
bit 2    red     (3600, 0)  main [1]  stash []
bit 3    black   (4800, 0)  main [1, 97]  stash []

What the trace shows. The first line is white, not black. The walk starts on the strip nearest the origin, so it runs the trail backwards: white and green find nothing to work on, red pushes 1, and black reads last.

The fix. Make black the strip nearest the origin. In the editor, draw the outline again and touch the crayon down next to the black strip; the ring that marks the start moves there. In a file, move the strips instead: lessons/add.solution.kft is this program the right way round. After moving a whole program, always check which strip is now nearest (0, 0).

A covered strip

The plan is the same again, but this program turns a into a.

023originred (1) is covered
examples/mistakes/covered.kft: green was dropped less than half a length from red, and lies on top of it.
printf 'a' | ./target/release/konfetti --trace examples/mistakes/covered.kft
bit 0    black   (1200, 0)  main [97]  stash []
bit 2    green   (2200, 350)  main [97]  stash []
bit 3    white   (3600, 0)  main []  stash []

What the trace shows. Strip 1 is missing: the walk goes from black straight to green. Green is listed after red, so it lies on top, and its middle is 403 from red's, less than 500. Red is covered. Green then has only one number and does nothing, and white writes the 97 it was given.

The fix. Keep strips at least half a length apart unless you mean to cover one; on a grid 1200 apart nothing is covered by accident. In debug mode the editor crosses the covered strip's label out. lessons/add.solution.kft is this program with good spacing.

A loop with no way out

The plan: copy the input, like tutorial 10. It copies it, then never stops.

0123origin
examples/mistakes/noexit.kft: the ring of tutorial 10 without its brown exit.
printf 'abc' | ./target/release/konfetti --trace \
  examples/mistakes/noexit.kft 2>&1 >/dev/null | head -n 16
bit 0    black   (0, 1200)  main [97]  stash []
bit 1    orange  (0, 2400)  main [97, 97]  stash []
bit 2    pink    (-1200, 2400)  main [97]  stash []
bit 3    white   (-1200, 1200)  main []  stash []
bit 0    black   (0, 1200)  main [98]  stash []
bit 1    orange  (0, 2400)  main [98, 98]  stash []
bit 2    pink    (-1200, 2400)  main [98]  stash []
bit 3    white   (-1200, 1200)  main []  stash []
bit 0    black   (0, 1200)  main [99]  stash []
bit 1    orange  (0, 2400)  main [99, 99]  stash []
bit 2    pink    (-1200, 2400)  main [99]  stash []
bit 3    white   (-1200, 1200)  main []  stash []
bit 0    black   (0, 1200)  main [-1]  stash []
bit 1    orange  (0, 2400)  main [-1, -1]  stash []
bit 2    pink    (-1200, 2400)  main [-1]  stash []
bit 3    white   (-1200, 1200)  main []  stash []

What the trace shows. At the end of the input black pushes −1 (line 13), and pink takes the rightmost way, as it should. But the only way on from pink is white, a left turn back into the ring. White writes 255 and black reads −1 again, for ever: the output is abc followed by endless bytes 255.

The fix. Give every loop a way out, on the side its pink sends the last number: here a brown strip to the right of pink, as in lessons/loop.solution.kft. Make sure the exit's last strip is a dead end, more than 1.5 lengths from the rest of the trail.

In the editor, Stop ends a run that goes on too long, and in learn mode Check my program says when a program had not stopped after 1,000,000 steps. In the terminal, press Ctrl+C.

Cheat sheet

ColorOpStackDoes
redPUSH-- 1pushes 1; right after a red, adds 1 to the top instead
orangeDUPa -- a acopies the top
yellowSWAPa b -- b aswaps the top two
greenADDa b -- a+badds
cyanSUBa b -- a-bsubtracts the top from the one below
blueMULa b -- a*bmultiplies
purpleDIVMODa b -- a/b a%bdivides, rounding down; remainder on top; by 0 does nothing
pinkBRANCHa --zero: straightest; positive: leftmost; negative: rightmost
whiteOUTa --writes the lowest 8 bits of a as a byte
blackIN-- creads a byte, or pushes −1 at the end of the input
brownDROPa --throws the top away
silverSTASHa --moves the top to the stash
goldFETCH-- amoves the top of the stash back

Top of the stack on the right. A strip without enough numbers to work on does nothing; so does gold with an empty stash. Pink with nothing to pop goes straightest.

The five rules of walking

  1. Links. Two strips are linked when their middles are at most 1.5 lengths apart (1500).
  2. Start. The walk starts on the strip nearest the origin, heading away from the origin, or toward larger x if the strip lies exactly on the origin. A tie goes to the one listed first.
  3. Step. Run the strip, then move to a linked strip, never the one just left, taking the smallest turn. A tie goes to the nearer strip, then to the one listed first.
  4. Branch. After pink: zero goes straightest, positive takes the leftmost way, negative the rightmost.
  5. Stop. With no way on, the program halts. The last strip still runs.

Piles. A strip less than half a length (500) from a strip listed after it is covered: out of the program. Numbers. n reds in a row push n; any other color ends the run.

Handy pieces

ToUse
Push 0red, orange, cyan, not right after a red
Do nothingorange, brown
Copy the top of the stashgold, orange, silver (the stash must not be empty)
Compare a and bcyan, then pink: zero means equal, positive means a is larger
Read until the input endsblack, orange, red, green, pink: zero means the end
Rows that do not linktwo lengths apart, one strip at each bend
Join a ringat a corner, from behind: 1450 back along the way the ring leaves the corner, and 300 toward the side the ring comes from (tutorial 14)
A character to its number0 48, A 65, a 97, space 32, newline 10