Your first program
Five minutes, in the editor. You will make a program of four strips that reads a letter and writes it twice.
Open the editor
Open konfetti.ax, or, in the konfetti folder, run
make serveand 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.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.
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.
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.
Run it
Type
hiin the Input box and press Run. A yellow pointer hops from strip to strip. Black reads theh, orange copies it, and each white writes one copy. Output showshh.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.
| Color | Op | What it does |
|---|---|---|
| red | PUSH | Pushes 1. A run of reds in a row counts up instead, so n reds push n. -- n |
| orange | DUP | Copies the top number. a -- a a |
| yellow | SWAP | Swaps the top two numbers. a b -- b a |
| green | ADD | Adds the top two numbers. a b -- a+b |
| cyan | SUB | Subtracts the top number from the one below it. a b -- a-b |
| blue | MUL | Multiplies the top two numbers. a b -- a*b |
| purple | DIVMOD | Divides 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 |
| pink | BRANCH | Pops a number and picks the way on: zero goes straightest, positive turns furthest left, negative furthest right. a -- |
| white | OUT | Pops a number and writes it as one byte of output. 65 is the letter A. a -- |
| black | IN | Reads one byte of input and pushes it, or pushes −1 when the input has run out. -- c |
| brown | DROP | Throws the top number away. a -- |
| silver | STASH | Moves the top number from the main stack to the stash. a -- |
| gold | FETCH | Moves 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
The start is the strip nearest the origin
Go straightest
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
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
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
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
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
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
- Spacing. Put middles 1.2 lengths apart on a grid. Then each strip links only to its four straight neighbours; the diagonal ones are 1.7 apart. At exactly 1 length apart, diagonals link too.
- Numbers. A run of reds is one number. Zero is red, orange, cyan: 1, a copy, subtract. Make big numbers by multiplying, as hello does.
- Corners. Where the trail bends and there is only one way on, nothing special is needed: the walk follows the bend.
- Forks. Put a pink where the trail splits. Decide which way is straight on, and put the loop or the exit there to match the sign you will branch on.
- Endings. End each path in a dead end. Brown makes a tidy last strip.
- Doing nothing. There is no color for "do nothing". Orange then brown copies and throws away, which changes nothing, even on an empty stack. Use it to pad a trail.
- Joining a loop. Do not join a loop at a right angle. Arriving from one of the two sides, the walk then has two 90° turns to choose between, and the tie is settled by which is nearer, then by text order. Join from behind instead, so the loop's next strip is always the smaller turn. count does this.
- Keep exits clear. An exit strip within one and a half lengths of another part of the trail links to it, and the program may never stop.
- Mind the origin. Moving a whole program changes which strip is nearest the origin, and the first heading. Check the start ring after moving things.
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:
- macOS 11 or later: the
.dmg. Open it and drag Konfetti to Applications. - Windows 10 or 11: the
-setup.exe. Run it; it installs konfetti for you alone. - Linux: the
.AppImage, which runs as it is once you let it (chmod +x Konfetti_*.AppImage), or the.debor.rpmpackage.
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:
- macOS: try to open it once, then open System Settings, Privacy & Security, and press Open Anyway. On macOS 14 and older, right-click the app and choose Open instead. In the terminal,
xattr -dr com.apple.quarantine /Applications/Konfetti.appdoes the same. - Windows: when the installer shows Windows protected your PC, press More info, then Run anyway.
- Linux: if the AppImage asks for FUSE, start it with
--appimage-extract-and-run. The app draws with WebKitGTK's older renderer, which works everywhere; to try the newer, faster one, start the app withWEBKIT_DISABLE_DMABUF_RENDERER=0in front of its name.
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
| Control | What it does |
|---|---|
| konfetti logo | A puff of paper confetti. Just for fun. |
| Mute M | Turns all sound off or on. See Sound. |
| Docs | Opens this guide: in a new tab, or in the desktop app in a second window. |
| Learn konfetti L | Opens the lessons. See Learn mode. |
| Fire Space | Shoots a burst of 40 strips of random colors from the cannon. |
| Crayon C | Pick 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 W | Brings in the real wind where you are. See Wind and the flag. |
| Run | Walks the program strip by strip, five a second unless you change the speed in the debugger. Output and stacks change as it goes. |
| Run fast | Runs the program flat out and shows the result. |
| Stop | Stops a run. |
| Debug D | Opens the debugger. See Debug mode. |
| Input | The text the program reads, one byte at a time, with black strips. |
| Output | What the program wrote with white strips, or what went wrong. Past 64 KB it shows only the end, after a …. |
| Stacks | The 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 text | Lays 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. |
| Save | Saves 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. |
| Build | Makes 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 outside | Removes the litter: every landed strip outside the outline, except a lesson's spare strips. |
| Clear all | Removes every strip and the outline. |
| Colors | The thirteen colors. Hold the pointer over one to read what it does. |
| How it works | A short reminder of the rules. |
| Theme | Changes 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
| Key | Does |
|---|---|
| Space | Fire |
| C | Pick up or put down the crayon |
| W | Wind on or off |
| M | Mute on or off |
| D | Debug mode on or off |
| L | Learn mode on or off |
| N P R | In 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.
- paper: torn sheets of cream watercolor paper, headings lettered by hand on pale washes. The default.
- toybox: chunky outlined buttons, like a toy.
- craft: paper notes held on with tape, in handwriting.
- arcade: a dark arcade cabinet with neon edges.
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.
- In the air, confetti drifts with the wind: about one strip length a second for every m/s.
- On the ground, strips only move in gusts, and slowly: about two or three lengths a minute in a 6 m/s wind. They never lift off again. All strips move at nearly the same pace, so a program keeps its shape for a while, but the whole pile creeps out of the crayon outline, which stays put.
- A strip that moves has new coordinates, so the wind rewrites your program. A run that has started keeps the program as it was when it started.
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 openingindex.htmlas a file. No Rust?python3 -m http.server 8137in 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=20000to 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
- In the editor. Press Learn konfetti or L and pick the lesson with the same number. The program is laid out for you, with the spare strips you need lying just outside the outline. Check my program tells you when it works.
- In the terminal. Every program in the tutorials is a file in the konfetti folder, under
lessonsorexamples. Build konfetti once withmake(see In the terminal), then run the commands given, from the konfetti folder. To change a program, copy its file and edit the copy. To see a file in the editor, paste its text into As text (.kft), under Program, and press Load text.
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.
- The number on a strip is its line in the file, counting from 0, leaving out comments and blank lines. Traces and the debugger use the same numbers.
- The blue dot is the origin. The dashed arrow from it is the first heading, and the ring marks the strip the walk starts on.
- Solid arrows show the walk for the input in the step table. Dashed arrows show ways that only other inputs take.
- A strip in a dashed frame is one the lesson asks you to add.
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.
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
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | read H (72) | 72 | |
| 2 | #1 white | wrote H (72) | empty | H |
| 3 | #2 black | read i (105) | 105 | H |
| 4 | #3 white | wrote i (105). Dead end: stop | empty | Hi |
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
- 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. - And when the input is just
H?Answer
Hand 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.
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
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | read H (72) | 72 | |
| 2 | #1 white | wrote H (72) | empty | H |
| 3 | #2 black | read e (101) | 101 | H |
| 4 | #3 white | wrote e (101) | empty | He |
| 5 | #4 black | read y (121) | 121 | He |
| 6 | #5 white | wrote y (121). Dead end: stop | empty | Hey |
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
- What does the finished program write when the input is
Hello?Answer
Hel: three blacks read three characters. - Where would the next black and white go, to copy four characters?
Answer
At
(8400, 0)and(9600, 0), continuing the row 1200 apart. WithHey!as input this writesHey!.# 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.
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
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | read n (110) | 110 | |
| 2 | #1 black | read o (111) | 110 111 | |
| 3 | #2 white | wrote o (111) | 110 | o |
| 4 | #3 white | wrote n (110). Dead end: stop | empty | on |
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
- What does the program write for
up?Answer
pu. - And for
abc?Answer
ba. Only two characters are read;cstays 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.
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
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | read a (97) | 97 | |
| 2 | #1 red | pushed 1 | 97 1 | |
| 3 | #2 green | 97 + 1 = 98 | 98 | |
| 4 | #3 white | wrote b (98). Dead end: stop | empty | b |
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
- What does the program write for
z?Answer
{.zis 122, and 123 is the curly bracket. - 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.
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
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | read a (97) | 97 | |
| 2 | #1 red | pushed 1 | 97 1 | |
| 3 | #2 red | counted up to 2 | 97 2 | |
| 4 | #3 red | counted up to 3 | 97 3 | |
| 5 | #4 green | 97 + 3 = 100 | 100 | |
| 6 | #5 white | wrote d (100). Dead end: stop | empty | d |
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
- What does the program write for
w?Answer
z: 119 + 3 = 122. - How many reds in a row would turn
aintoz?Answer
25, because
zis 122 andais 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:
lessons/corner.start.kft. From green, brown is straight on and white is a 90° turn. The walk goes to brown.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
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | read a (97) | 97 | |
| 2 | #1 red | pushed 1 | 97 1 | |
| 3 | #2 green | 97 + 1 = 98 | 98 | |
| 4 | #4 brown | threw away 98. Dead end: stop | empty |
After: the walk turns left at green.
printf 'a' | ./target/release/konfetti --trace lessons/corner.solution.kft
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | read a (97) | 97 | |
| 2 | #1 red | pushed 1 | 97 1 | |
| 3 | #2 green | 97 + 1 = 98, turned left | 98 | |
| 4 | #3 white | wrote b (98). Dead end: stop | empty | b |
# 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
- 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).
- 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.
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
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 red | pushed 1 | 1 | |
| 2 | #1 red | counted up to 2 | 2 | |
| 3 | #2 red | counted up to 3 | 3 | |
| 4 | #3 red | counted up to 4 | 4 | |
| 5 | #4 red | counted up to 5 | 5 | |
| 6 | #5 red | counted up to 6, turned left | 6 | |
| 7 | #6 red | counted up to 7 | 7 | |
| 8 | #7 red | counted up to 8, turned left | 8 | |
| 9 | #8 orange | copied 8 | 8 8 | |
| 10 | #9 blue | 8 × 8 = 64 | 64 | |
| 11 | #10 red | pushed 1 | 64 1 | |
| 12 | #11 green | 64 + 1 = 65 | 65 | |
| 13 | #12 white | wrote A (65). Dead end: stop | empty | A |
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
- 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.
- 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.
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
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | read b (98) | 98 | |
| 2 | #1 red | pushed 1 | 98 1 | |
| 3 | #4 cyan | 98 − 1 = 97 | 97 | |
| 4 | #3 white | wrote a (97). Dead end: stop | empty | a |
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
- What does the finished program write for
a?Answer
`, the backtick, which is 96. - Move the cyan line above the green line in the text. What does the program write for
bnow?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.
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
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | read a (97) | 97 | |
| 2 | #1 orange | copied 97 | 97 97 | |
| 3 | #2 pink | popped 97, positive, turned left | 97 | |
| 4 | #4 white | wrote a (97). Dead end: stop | empty | a |
With no input:
./target/release/konfetti --trace lessons/branch.solution.kft < /dev/null
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | the input has run out: pushed −1 | −1 | |
| 2 | #1 orange | copied −1 | −1 −1 | |
| 3 | #2 pink | popped −1, negative, turned right | −1 | |
| 4 | #3 brown | threw away −1. Dead end: stop | empty |
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
- What does the program write for
ab?Answer
a. It reads only once. - Swap white and brown, so that white is on the right arm. What does it write for
a, and for no input?Answer
For
ait writes nothing: 97 is positive, so pink turns left, to brown. For no input it writesa 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.
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
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | read a (97) | 97 | |
| 2 | #1 orange | copied 97, turned left | 97 97 | |
| 3 | #2 pink | popped 97, positive, turned left | 97 | |
| 4 | #4 white | wrote a (97), turned left | empty | a |
| 5 | #0 black | read b (98), turned left | 98 | a |
| 6 | #1 orange | copied 98, turned left | 98 98 | a |
| 7 | #2 pink | popped 98, positive, turned left | 98 | a |
| 8 | #4 white | wrote b (98), turned left | empty | ab |
| 9 | #0 black | read c (99), turned left | 99 | ab |
| 10 | #1 orange | copied 99, turned left | 99 99 | ab |
| 11 | #2 pink | popped 99, positive, turned left | 99 | ab |
| 12 | #4 white | wrote c (99), turned left | empty | abc |
| 13 | #0 black | the input has run out: pushed −1, turned left | −1 | abc |
| 14 | #1 orange | copied −1, turned left | −1 −1 | abc |
| 15 | #2 pink | popped −1, negative, turned right | −1 | abc |
| 16 | #3 brown | threw away −1. Dead end: stop | empty | abc |
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
- 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.
- 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.
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
| Step | Strip | What it did | Main | Stash | Output |
|---|---|---|---|---|---|
| 1 | #0 black | read n (110) | 110 | empty | |
| 2 | #1 black | read o (111) | 110 111 | empty | |
| 3 | #2 silver | moved 111 to the stash | 110 | 111 | |
| 4 | #3 white | wrote n (110) | empty | 111 | n |
| 5 | #4 gold | took 111 back from the stash | 111 | empty | n |
| 6 | #5 white | wrote o (111). Dead end: stop | empty | empty | no |
The program writes no.
Try next
The editor shows both stacks under Stacks, each as a row of boxes.
Exercises
- What does the program write for just
x?Answer
xand then a byte 255. The second black pushes −1, silver puts it in the stash, white writesx, 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.
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
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 black | read H (72), turned right | 72 | |
| 2 | #1 orange | copied 72, turned left | 72 72 | |
| 3 | #2 pink | popped 72, positive, turned left | 72 | |
| 4 | #5 red | pushed 1, turned left | 72 1 | |
| 5 | #6 green | 72 + 1 = 73, turned left | 73 | |
| 6 | #3 white | wrote I (73), turned left | empty | I |
| 7 | #0 black | read A (65), turned left | 65 | I |
| 8 | #1 orange | copied 65, turned left | 65 65 | I |
| 9 | #2 pink | popped 65, positive, turned left | 65 | I |
| 10 | #5 red | pushed 1, turned left | 65 1 | I |
| 11 | #6 green | 65 + 1 = 66, turned left | 66 | I |
| 12 | #3 white | wrote B (66), turned left | empty | IB |
| 13 | #0 black | read L (76), turned left | 76 | IB |
| 14 | #1 orange | copied 76, turned left | 76 76 | IB |
| 15 | #2 pink | popped 76, positive, turned left | 76 | IB |
| 16 | #5 red | pushed 1, turned left | 76 1 | IB |
| 17 | #6 green | 76 + 1 = 77, turned left | 77 | IB |
| 18 | #3 white | wrote M (77), turned left | empty | IBM |
| 19 | #0 black | the input has run out: pushed −1, turned left | −1 | IBM |
| 20 | #1 orange | copied −1, turned left | −1 −1 | IBM |
| 21 | #2 pink | popped −1, negative, turned right | −1 | IBM |
| 22 | #4 brown | threw away −1. Dead end: stop | empty | IBM |
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
- 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 - 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:
- Plan. Write the instructions as a list, with the stack after each one. Work out the numbers you need.
- 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.
- Check it. Run it with
--traceand 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
dis 100 andais 97. Both are close to 100, so make 100 once and keep it.- 100 is 10 × 10: ten reds push 10; orange copies it, blue multiplies. Twelve strips, instead of a hundred reds.
- White uses up the number it writes. To write
dand still have 100, copy it first: orange, white. ais 100 − 3: copy 100 again, push 3 with three reds, subtract with cyan, write.- The first copy of 100 is still at the bottom of the stack. One more white writes the last
d.
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 red | pushed 1 | 1 | |
| 2 | #1 red | counted up to 2 | 2 | |
| 3 | #2 red | counted up to 3 | 3 | |
| 4 | #3 red | counted up to 4 | 4 | |
| 5 | #4 red | counted up to 5 | 5 | |
| 6 | #5 red | counted up to 6 | 6 | |
| 7 | #6 red | counted up to 7, turned left | 7 | |
| 8 | #7 red | counted up to 8 | 8 | |
| 9 | #8 red | counted up to 9, turned left | 9 | |
| 10 | #9 red | counted up to 10 | 10 | |
| 11 | #10 orange | copied 10 | 10 10 | |
| 12 | #11 blue | 10 × 10 = 100 | 100 | |
| 13 | #12 orange | copied 100 | 100 100 | |
| 14 | #13 white | wrote d (100) | 100 | d |
| 15 | #14 orange | copied 100, turned right | 100 100 | d |
| 16 | #15 red | pushed 1 | 100 100 1 | d |
| 17 | #16 red | counted up to 2, turned right | 100 100 2 | d |
| 18 | #17 red | counted up to 3 | 100 100 3 | d |
| 19 | #18 cyan | 100 − 3 = 97 | 100 97 | d |
| 20 | #19 white | wrote a (97) | 100 | da |
| 21 | #20 white | wrote d (100). Dead end: stop | empty | dad |
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:
- Rows two lengths apart (2400). Rows 1200 apart would link to each other; tutorial 17 shows what goes wrong then.
- At each end, one strip at the bend, 1200 above the end of the row. It links to both rows; the strips around the bend are 1.7 lengths apart diagonally, too far to link.
- The first strip 1200 from the origin along
x, so that the walk starts there and heads along the first row.
Reds that go round a bend are still a run, so the bend can fall anywhere in the ten reds.
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
- A digit is a character, and characters are numbers:
0is 48,1is 49, up to9, which is 57. So the digit5is read as 53, and 53 − 48 gives the number 5. To write a number n from 0 to 9 as a digit, write n + 48. - 48 is needed every time round the loop. Make it once (7 × 7 − 1), copy it, and keep the copy in the stash. gold, orange, silver copies the top of the stash onto the main stack and leaves the stash as it was.
- The other 48 turns the digit into a number. It was made before the digit was read, so it lies under the 53, and cyan subtracts the top number from the one below it. So first yellow swaps the top two numbers (
a b -- b a): then 53 lies under 48, and cyan gives 53 − 48 = 5. - The loop: copy n, add 48 to the copy, write it, subtract 1 from n, copy, and let pink decide: positive goes round again, zero leaves.
The part before the loop, the on-ramp, with 2 as input:
| Step | Strip | What it did | Main | Stash | Output |
|---|---|---|---|---|---|
| 1 | #0 red | pushed 1 | 1 | empty | |
| 2 | #1 red | counted up to 2 | 2 | empty | |
| 3 | #2 red | counted up to 3 | 3 | empty | |
| 4 | #3 red | counted up to 4 | 4 | empty | |
| 5 | #4 red | counted up to 5 | 5 | empty | |
| 6 | #5 red | counted up to 6 | 6 | empty | |
| 7 | #6 red | counted up to 7, turned left | 7 | empty | |
| 8 | #7 orange | copied 7 | 7 7 | empty | |
| 9 | #8 blue | 7 × 7 = 49, turned left | 49 | empty | |
| 10 | #9 red | pushed 1 | 49 1 | empty | |
| 11 | #10 cyan | 49 − 1 = 48 | 48 | empty | |
| 12 | #11 orange | copied 48 | 48 48 | empty | |
| 13 | #12 silver | moved 48 to the stash | 48 | 48 | |
| 14 | #13 black | read 2 (50) | 48 50 | 48 | |
| 15 | #14 yellow | swapped 48 and 50, turned right | 50 48 | 48 | |
| 16 | #15 cyan | 50 − 48 = 2 | 2 | 48 | |
| 17 | #16 orange | copied 2, turned right | 2 2 | 48 |
Then the loop, twice round, and out:
| Step | Strip | What it did | Main | Stash | Output |
|---|---|---|---|---|---|
| 18 | #17 gold | took 48 back from the stash, turned left | 2 2 48 | empty | |
| 19 | #18 orange | copied 48 | 2 2 48 48 | empty | |
| 20 | #19 silver | moved 48 to the stash | 2 2 48 | 48 | |
| 21 | #20 green | 2 + 48 = 50, turned left | 2 50 | 48 | |
| 22 | #21 white | wrote 2 (50) | 2 | 48 | 2 |
| 23 | #22 red | pushed 1, turned left | 2 1 | 48 | 2 |
| 24 | #23 cyan | 2 − 1 = 1 | 1 | 48 | 2 |
| 25 | #24 orange | copied 1 | 1 1 | 48 | 2 |
| 26 | #25 pink | popped 1, positive, turned left | 1 | 48 | 2 |
| 27 | #26 orange | copied 1 | 1 1 | 48 | 2 |
| 28 | #17 gold | took 48 back from the stash, turned left | 1 1 48 | empty | 2 |
| 29 | #18 orange | copied 48 | 1 1 48 48 | empty | 2 |
| 30 | #19 silver | moved 48 to the stash | 1 1 48 | 48 | 2 |
| 31 | #20 green | 1 + 48 = 49, turned left | 1 49 | 48 | 2 |
| 32 | #21 white | wrote 1 (49) | 1 | 48 | 21 |
| 33 | #22 red | pushed 1, turned left | 1 1 | 48 | 21 |
| 34 | #23 cyan | 1 − 1 = 0 | 0 | 48 | 21 |
| 35 | #24 orange | copied 0 | 0 0 | 48 | 21 |
| 36 | #25 pink | popped 0, zero, straight on | 0 | 48 | 21 |
| 37 | #27 brown | threw away 0. Dead end: stop | empty | 48 | 21 |
Layout
- The ring. The loop has 10 strips. A rectangle 4 strips wide and 3 high has exactly 10 strips round its edge.
- The fork. Pink must send a positive number round the ring and a zero out. Zero goes straightest, and positive turns furthest left. So put pink on a corner where the ring turns left, and the exit straight on beyond the corner. Turning left at every corner means going round counter-clockwise.
- The join. The on-ramp has to join the ring somewhere, and that strip is then reached from two sides: from the on-ramp and from round the ring. From both, the walk must choose the ring's next strip. Do not join at a T, from straight beside the ring: then, arriving from one of the two sides, the walk has two 90° turns to choose between, and the tie is settled by which is nearer, then by the order of lines in the file.
- Join from behind, at a corner. The on-ramp's last strip lies 1450 back along the direction the ring leaves the corner, and 300 toward the side the ring comes from. This is the same as in
examples/count.kft. Arriving round the ring, the ring's next strip is a 90° turn and the on-ramp about 102°: the ring wins. Arriving from the on-ramp, the ring's next strip is about 12° and the other ring strip about 102°: the ring wins again. The on-ramp's last strip is 1.7 lengths from the ring strip above the corner, so they do not link. - Where the on-ramp joins. The ring is joined at gold, the strip after the ring's own copy of n, so the on-ramp makes that copy itself: its last strip is an orange.
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
- a − b is negative, zero or positive, and pink turns right, goes straight or turns left on exactly those. So: read both, subtract with cyan, branch.
<is 60,=is 61 and>is 62. Making 61 takes 14 strips (8 × 8 − 3), and doing that on every arm would triple it. Make 61 once, before reading, and leave it under everything. Then each arm only adjusts it: straight on writes it as it is, left adds 1, right subtracts 1.
| Step | Strip | What it did | Main | Output |
|---|---|---|---|---|
| 1 | #0 red | pushed 1 | 1 | |
| 2 | #1 red | counted up to 2 | 2 | |
| 3 | #2 red | counted up to 3 | 3 | |
| 4 | #3 red | counted up to 4 | 4 | |
| 5 | #4 red | counted up to 5 | 5 | |
| 6 | #5 red | counted up to 6, turned left | 6 | |
| 7 | #6 red | counted up to 7 | 7 | |
| 8 | #7 red | counted up to 8, turned left | 8 | |
| 9 | #8 orange | copied 8 | 8 8 | |
| 10 | #9 blue | 8 × 8 = 64 | 64 | |
| 11 | #10 red | pushed 1 | 64 1 | |
| 12 | #11 red | counted up to 2 | 64 2 | |
| 13 | #12 red | counted up to 3, turned right | 64 3 | |
| 14 | #13 cyan | 64 − 3 = 61 | 61 | |
| 15 | #14 black | read a (97) | 61 97 | |
| 16 | #15 black | read b (98) | 61 97 98 | |
| 17 | #16 cyan | 97 − 98 = −1 | 61 −1 | |
| 18 | #17 pink | popped −1, negative, turned right | 61 | |
| 19 | #22 red | pushed 1 | 61 1 | |
| 20 | #23 cyan | 61 − 1 = 60 | 60 | |
| 21 | #24 white | wrote < (60). Dead end: stop | empty | < |
Layout
- The 18 strips up to the fork fold into two rows of six, with a strip at each bend, and then a column, like tutorial 13.
- The fork must have room on three sides, so it goes at the end of the column, away from the rows. Each arm starts with a strip 1200 from pink: one straight on, one to the left, one to the right. The arms' first strips are 1.7 lengths from each other, too far to link.
- The arms are 90° apart, so there is no tie: straight on is 0°, the others 90° left and 90° right.
- Each arm ends in a dead end.
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
| Input | Writes | Why |
|---|---|---|
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
- A stack hands things back in the opposite order, which is exactly reversing. So move every character to the stash as it is read, then fetch them back and write them.
- When fetching, the program must know when to stop. Put a 0 in the stash first, as a marker. No character you can type is 0, so fetching a 0 means the stash is used up. Zero is red, orange, cyan: 1, a copy, 1 − 1.
- The first loop is the ring of
examples/cat.kft, with silver where cat has white: read, copy, add 1, branch. At the end of the input −1 + 1 is 0, and the walk goes straight on, out of the ring. Brown throws the −1 away. - The second loop: fetch, copy, branch. A character is positive: turn left to white, write, round again. The marker is zero: straight on to brown, which throws it away.
With ab as input, all of it:
| Step | Strip | What it did | Main | Stash | Output |
|---|---|---|---|---|---|
| 1 | #0 red | pushed 1 | 1 | empty | |
| 2 | #1 orange | copied 1 | 1 1 | empty | |
| 3 | #2 cyan | 1 − 1 = 0 | 0 | empty | |
| 4 | #3 silver | moved 0 to the stash, turned right | empty | 0 | |
| 5 | #4 black | read a (97), turned left | 97 | 0 | |
| 6 | #5 orange | copied 97, turned left | 97 97 | 0 | |
| 7 | #6 red | pushed 1 | 97 97 1 | 0 | |
| 8 | #7 green | 97 + 1 = 98, turned left | 97 98 | 0 | |
| 9 | #8 pink | popped 98, positive, turned left | 97 | 0 | |
| 10 | #9 silver | moved 97 to the stash | empty | 0 97 | |
| 11 | #4 black | read b (98), turned left | 98 | 0 97 | |
| 12 | #5 orange | copied 98, turned left | 98 98 | 0 97 | |
| 13 | #6 red | pushed 1 | 98 98 1 | 0 97 | |
| 14 | #7 green | 98 + 1 = 99, turned left | 98 99 | 0 97 | |
| 15 | #8 pink | popped 99, positive, turned left | 98 | 0 97 | |
| 16 | #9 silver | moved 98 to the stash | empty | 0 97 98 | |
| 17 | #4 black | the input has run out: pushed −1, turned left | −1 | 0 97 98 | |
| 18 | #5 orange | copied −1, turned left | −1 −1 | 0 97 98 | |
| 19 | #6 red | pushed 1 | −1 −1 1 | 0 97 98 | |
| 20 | #7 green | −1 + 1 = 0, turned left | −1 0 | 0 97 98 | |
| 21 | #8 pink | popped 0, zero, straight on | −1 | 0 97 98 | |
| 22 | #10 brown | threw away −1, turned right | empty | 0 97 98 | |
| 23 | #11 gold | took 98 back from the stash, turned left | 98 | 0 97 | |
| 24 | #12 orange | copied 98, turned left | 98 98 | 0 97 | |
| 25 | #13 pink | popped 98, positive, turned left | 98 | 0 97 | |
| 26 | #14 white | wrote b (98), turned left | empty | 0 97 | b |
| 27 | #11 gold | took 97 back from the stash, turned left | 97 | 0 | b |
| 28 | #12 orange | copied 97, turned left | 97 97 | 0 | b |
| 29 | #13 pink | popped 97, positive, turned left | 97 | 0 | b |
| 30 | #14 white | wrote a (97), turned left | empty | 0 | ba |
| 31 | #11 gold | took 0 back from the stash, turned left | 0 | empty | ba |
| 32 | #12 orange | copied 0, turned left | 0 0 | empty | ba |
| 33 | #13 pink | popped 0, zero, straight on | 0 | empty | ba |
| 34 | #15 brown | threw away 0. Dead end: stop | empty | empty | ba |
Layout
- Ring 1 is cat's ring: 3 by 2, counter-clockwise, with pink on a corner and the exit straight on below it.
- Ring 2 has four strips: a square, 2 by 2. Its pink is on a corner too, with its exit straight on.
- Two joins, both from behind at a corner, as in tutorial 14. The marker's silver (3) joins ring 1 at black (4): it lies 300 to the left of black and 1450 below it. Ring 1's exit, brown (10), is the on-ramp of ring 2: it joins at gold (11), 1450 to the right and 300 below.
- Ring 2 sits to the side of the marker column, so that no strip of it is within 1.5 lengths of another part of the trail.
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:
- Debug mode in the editor (D, then Step or N). Every strip gets a label with its number, covered strips are crossed out, and the trace says in words what each step did and where the walk turned.
--tracein the terminal: one line per step, with the strip's number, color and position, and both stacks after it.
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.
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.
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.
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.
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.
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.
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.
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
| Color | Op | Stack | Does |
|---|---|---|---|
| red | PUSH | -- 1 | pushes 1; right after a red, adds 1 to the top instead |
| orange | DUP | a -- a a | copies the top |
| yellow | SWAP | a b -- b a | swaps the top two |
| green | ADD | a b -- a+b | adds |
| cyan | SUB | a b -- a-b | subtracts the top from the one below |
| blue | MUL | a b -- a*b | multiplies |
| purple | DIVMOD | a b -- a/b a%b | divides, rounding down; remainder on top; by 0 does nothing |
| pink | BRANCH | a -- | zero: straightest; positive: leftmost; negative: rightmost |
| white | OUT | a -- | writes the lowest 8 bits of a as a byte |
| black | IN | -- c | reads a byte, or pushes −1 at the end of the input |
| brown | DROP | a -- | throws the top away |
| silver | STASH | a -- | moves the top to the stash |
| gold | FETCH | -- a | moves 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
- Links. Two strips are linked when their middles are at most 1.5 lengths apart (1500).
- Start. The walk starts on the strip nearest the origin, heading away from the origin, or toward larger
xif the strip lies exactly on the origin. A tie goes to the one listed first. - 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.
- Branch. After pink: zero goes straightest, positive takes the leftmost way, negative the rightmost.
- 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
| To | Use |
|---|---|
| Push 0 | red, orange, cyan, not right after a red |
| Do nothing | orange, brown |
| Copy the top of the stash | gold, orange, silver (the stash must not be empty) |
Compare a and b | cyan, then pink: zero means equal, positive means a is larger |
| Read until the input ends | black, orange, red, green, pink: zero means the end |
| Rows that do not link | two lengths apart, one strip at each bend |
| Join a ring | at 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 number | 0 48, A 65, a 97, space 32, newline 10 |