Advanced

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 OUT outputs the contents of an array using the Turing Tape method
  • GIVE UP terminates 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:

  1. Start with the ASCII code of the previous character (0 for the first character)
  2. Reverse the bits of that value
  3. Subtract the array value from the reversed bits
  4. 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:

PositionCharacterASCIICalculationArray Value
1H720 - rev(72)238
2e101rev(72) - rev(101)108
3l108rev(101) - rev(108)112
4l108rev(108) - rev(108)0
5o111rev(108) - rev(111)64
6,44rev(111) - rev(44)194
7(space)32rev(44) - rev(32)48
8W87rev(32) - rev(87)26
9o111rev(87) - rev(111)244
10r114rev(111) - rev(114)168
11l108rev(114) - rev(108)24
12d100rev(108) - rev(100)16
13!33rev(100) - rev(33)162

Running with Docker

The easiest way to run INTERCAL without installing the compiler locally:

1
2
3
4
5
# Pull the Ubuntu image
docker pull ubuntu:24.04

# Run the INTERCAL program (installs compiler, compiles, and runs)
docker run --rm -v $(pwd):/app -w /app ubuntu:24.04 sh -c 'apt-get update -qq && apt-get install -y -qq intercal >/dev/null 2>&1 && ick -b hello.i && ./hello'

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:

  1. Parses the INTERCAL source code
  2. Generates C code that implements the INTERCAL semantics
  3. Calls GCC to compile that C code to a binary
  4. The binary is named after your source file (without the .i extension)

Alternative: Verbose Output

If you want to see what’s happening during compilation:

1
docker run --rm -v $(pwd):/app -w /app ubuntu:24.04 sh -c 'apt-get update && apt-get install -y intercal && ick -b hello.i && ./hello'

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.

Running Today

All examples can be run using Docker:

docker pull ubuntu:24.04
Last updated: