Hello World in INTERCAL
Your first INTERCAL program - the classic Hello World example with Docker setup
Writing “Hello, World!” in INTERCAL is a journey into deliberate obfuscation. What takes one line in most languages requires understanding INTERCAL’s bizarre Turing Tape output encoding and its unique syntax. Welcome to the world of esoteric programming.
The Code
Create a file named hello.i:
DO ,1 <- #13
PLEASE DO ,1 SUB #1 <- #238
DO ,1 SUB #2 <- #108
DO ,1 SUB #3 <- #112
DO ,1 SUB #4 <- #0
DO ,1 SUB #5 <- #64
DO ,1 SUB #6 <- #194
DO ,1 SUB #7 <- #48
PLEASE DO ,1 SUB #8 <- #26
DO ,1 SUB #9 <- #244
DO ,1 SUB #10 <- #168
DO ,1 SUB #11 <- #24
DO ,1 SUB #12 <- #16
DO ,1 SUB #13 <- #162
PLEASE READ OUT ,1
PLEASE GIVE UP
Understanding the Code
This seemingly random collection of numbers actually encodes “Hello, World!” using INTERCAL’s Turing Tape output method. Let’s break it down.
Array Initialization
DO ,1 <- #13
This creates an array named ,1 (the comma indicates it’s a 16-bit array) with 13 elements. In INTERCAL:
,is called “tail” and denotes a 16-bit array#is called “mesh” and indicates a literal number<-is the assignment operator
Populating the Array
PLEASE DO ,1 SUB #1 <- #238
DO ,1 SUB #2 <- #108
SUB is INTERCAL’s array subscript operator. So ,1 SUB #1 means “element 1 of array ,1”. Each element is assigned a carefully calculated value.
The PLEASE Requirement
Notice that some lines start with PLEASE and others don’t. INTERCAL requires programs to be polite - but not too polite. If you don’t say PLEASE enough, the compiler rejects your program. If you say it too much, the compiler also rejects it for being sycophantic.
The generally accepted ratio is between 1/5 and 1/3 of your statements should include PLEASE.
Output and Termination
PLEASE READ OUT ,1
PLEASE GIVE UP
READ OUToutputs the contents of an array using the Turing Tape methodGIVE UPterminates the program (because of course it’s not called “END” or “EXIT”)
The Turing Tape Encoding
Here’s why those numbers aren’t the ASCII codes for “Hello, World!”:
INTERCAL uses a convoluted encoding scheme:
- Start with the ASCII code of the previous character (0 for the first character)
- Reverse the bits of that value
- Subtract the array value from the reversed bits
- Reverse the bits of the result to get the ASCII code of the output character
For example, to output ‘H’ (ASCII 72) as the first character:
- Previous character code: 0
- Bit-reverse of 0: 0
- We need bit-reverse of 72 = 18
- So: 0 - array_value = 18, meaning array_value = -18
- In 8-bit two’s complement: 256 - 18 = 238
That’s why the first array element is 238!
Calculation Table
Here’s how each character is encoded:
| Position | Character | ASCII | Calculation | Array Value |
|---|---|---|---|---|
| 1 | H | 72 | 0 - rev(72) | 238 |
| 2 | e | 101 | rev(72) - rev(101) | 108 |
| 3 | l | 108 | rev(101) - rev(108) | 112 |
| 4 | l | 108 | rev(108) - rev(108) | 0 |
| 5 | o | 111 | rev(108) - rev(111) | 64 |
| 6 | , | 44 | rev(111) - rev(44) | 194 |
| 7 | (space) | 32 | rev(44) - rev(32) | 48 |
| 8 | W | 87 | rev(32) - rev(87) | 26 |
| 9 | o | 111 | rev(87) - rev(111) | 244 |
| 10 | r | 114 | rev(111) - rev(114) | 168 |
| 11 | l | 108 | rev(114) - rev(108) | 24 |
| 12 | d | 100 | rev(108) - rev(100) | 16 |
| 13 | ! | 33 | rev(100) - rev(33) | 162 |
Running with Docker
The easiest way to run INTERCAL without installing the compiler locally:
| |
The -b flag tells the ick compiler to generate binary output. Without it, the compiler generates C code that would need further compilation.
Expected Output
Hello, World!
Understanding the Compilation Process
C-INTERCAL (the ick compiler) works in an unusual way:
- Parses the INTERCAL source code
- Generates C code that implements the INTERCAL semantics
- Calls GCC to compile that C code to a binary
- The binary is named after your source file (without the
.iextension)
Alternative: Verbose Output
If you want to see what’s happening during compilation:
| |
This shows the package installation output, which can be useful for debugging.
Common Errors
“ICL079I PROGRAMMER IS INSUFFICIENTLY POLITE”
You don’t have enough PLEASE statements. Add PLEASE to some of your DO statements.
“ICL099I PROGRAMMER IS OVERLY POLITE”
You have too many PLEASE statements. Remove PLEASE from some of your DO statements.
“ICL123I PROGRAM HAS DISAPPEARED INTO THE BLACK LAGOON”
This cryptic error means your program has a syntax error. Check your spacing and punctuation.
“ICL129I PROGRAM HAS GOTTEN LOST”
A control flow error - check any NEXT or COME FROM statements.
Simpler Examples
If the Hello World encoding is too complex to start with, try outputting a single character:
DO ,1 <- #1
DO ,1 SUB #1 <- #238
PLEASE READ OUT ,1
PLEASE GIVE UP
This outputs just “H” - the simplest possible INTERCAL output program.
Why Is It So Complicated?
The complexity is intentional. INTERCAL was designed to parody the programming languages of 1972, which often had:
- Arbitrary restrictions
- Poor documentation
- Confusing syntax
- Non-intuitive behavior
By making everything worse, Woods and Lyon created a language that highlights these problems through absurdist humor. The Turing Tape encoding is a perfect example - it’s not random; it’s a legitimate mathematical transformation. It’s just deliberately unhelpful.
Historical Note
INTERCAL was created on May 26, 1972, at Princeton University. It’s generally considered the first “esoteric” programming language - a language designed to be unusual, challenging, or humorous rather than practical.
The fact that we can still compile and run INTERCAL programs 50+ years later, using a modern Ubuntu container, is a testament to both the language’s influence on programming culture and the dedication of maintainers like Eric S. Raymond who kept C-INTERCAL alive.
Next Steps
If you survived this tutorial, you’re ready to explore more INTERCAL features:
- The infamous COME FROM statement
- Operand overloading with STASH and RETRIEVE
- The SELECT (~) and INTERLEAVE ($) operators
- ABSTAIN and REINSTATE for dynamic control flow
Or, sensibly, you might want to try a different esoteric language like Brainfuck - which is somehow more straightforward than INTERCAL.