Befunge is definitely my favourite purely esoteric language. It has a very unique way of dealing with the program flow, and it takes programming to the next dimension. Literally.

Properties of the language:

  • Stack based.
  • In the base specification, limited program size.
  • Each of the statements takes a single character.
  • Main design goal: uniqueness and making a language as hard to compile as possible.
  • Control flow is done by directing the program to execute in a given direction on a grid of characters.
  • Topologically equivalent to a torus.
  • Self-modifying.
  • Turing completeness: in the base specification, no. For derivatives, yes. Check the article for more info.

    Befunge is a very peculiar language. The programs are actually grids of characters. Each character is a statement. What's the peculiarity? Well, using characters from this set: v^<>, the flow can be directed on the grid differently. What this means is that the program executes in two dimensions. Consider this Hello World (suboptimal, but I want to showcase how the flow works in Befunge):

  • >              v
    v  ,,,,,"Hello"<
    >48*,          v
    v,,,,,,"World!"<
    >25*,@

    The code execution starts in the upper left corner. The statement ">" tells the program flow to move right. Then, the program flow hits "v", which tells it to go down. Then, "<" tells it to move left, then characters are put on the stack of the program in order "o","l","l","e","H". "," pops the last value from the stack and prints it, so the first "," will print "H", the next "e" and so forth. This program flow changing and the stack operations continue till the "@" character, which terminates the program execution. Lets talk about the statements available in the original specification.

  • 0-9: Push that value on the stack.
  • +: Pop two values a and b, then push a+b (addition).
  • -: Pop two values a and b, then push b-a (substraction).
  • *: Pop two values a and b, then push a*b (multiplication).
  • /: Pop two values a and b, then push b/a rounded down (division).
  • %: Pop two values a and b, then push the remainder of b/a (modulo).
  • !: Pop a value. If the value is zero, push 1, otherwise push 0 (Logical NOT).
  • `: Pop two values a and b, then push 1 if b>a, otherwise zero (greater than).
  • >v<^: Change the direction of the program flow.
  • ?: Change the program flow into a random direction.
  • _: Pop a value. If 0, move right, otherwise move left.
  • |: Pop a value. If 0, move down, otherwise move up.
  • ": Start/end string mode. Values enclosed in "" will be pushed onto the stack as ASCII values one by one.
  • :: Duplicate value at the top of the stack.
  • ,: Pop value and print as character.
  • .: Pop value and print as integer.
  • $: Just pop the value.
  • \: Swap two values on top of the stack.
  • #: Skip next call (jump over it).
  • p: Pop three values a, b and c, then change the character at the position [a,b] in the program grid to the ASCII character of value c. This is what lets the program self-modify.
  • g: Pop two values a and b, then push the ASCII value of the character at the position [a,b] in the program.
  • &: Ask user for a number, push it.
  • ~: Ask user for a char, push it.
  • @: Terminate program.

    As you can see, most is done by stack operations and control flow statements. One peculiar property of how the program and control flow works is making loops. You see, to do that you actually need to make the control flow go in a loop. Consider this Hello World:

  • >              v<
    v  ,,,,,"Hello"<
    >48*,          v
    v,,,,,,"World!"<
    >25*,           ^

    This will print Hello World repeatedly forever. I think you see how the program flow goes back to the start. With | and _ and !, you can do conditional loops etc.

    Remember how I said that Befunge programs are topologically equivalent to tori? Well, that's right. What does that mean? Well, when the program flow hits one side of the program, it'll wrap around and start its journey on the other side again, sort of like if you were traversing a torus. Consider this Hello World:

    >    >         v
    v  ,,,,,"Hello"<
    >48*,          v
    v,,,,,,"World!"<
    >25*,v

    This'll do the same thing the earlier Hello World did - print "Hello World!" indefinitely, despite no apparent loop being used. However, the statement after the last print is v, which tells the flow to go down. However, there's nothing lower than that, so the program will wrap around and start at the top, in the 6th column, going down. The first statement it hits directs the flow to the start of the printing again, and we have a loop!

    Another peculiarity: there are no comments per se (at least in the base specification of the language). However, you can include comments by directing the program flow to avoid the comment. :)

    Remember how I said that Hello World was suboptimal? Well, here goes the optimal hello world.

    "!dlrow olleH">:#,_@

    How does that work? Well, first off, you don't need the ">" at the start, the flow goes by default to the right at the start. First we're pushing the Hello world string to use. Because of the fact it's all a stack operation, this has to be done 'backwards', so to speak. Then, a control flow statement we don't (yet) need. : duplicates the value on top of the stack, # makes the program jump over the print and hit the conditional. The duplicate value is popped, and since it's a character, the flow goes to the left. Character is popped and printed (gimme an "H"!). Then, # makes the program jump over :, the control flow statement directs it back and the last few steps repeat until the stack is empty. That's when the value popped by _ will be 0, and so the flow will go to the right, where the program will terminate. Simple, no? :) Also, the looped version (and printing the end of line character too):

    25*"!dlrow olleH">:#,_

    As you probably noticed by now, the link to the esoteric language page is actually a Befunge program. Guessing what it does is left as an exercise to the reader :).

    One thing I have to mention is Turing completeness. The base specification is not Turing complete. However, that is not due to the lack of necessary statements. In the base specification of the language, the Befunge program must fit in a 80x25 grid (widthxheight). The artificial space limitation breaks Turing completeness. However, there are many derivatives of the original Befunge. The most known one, Funge-98 lets you extend the grid indefinitely, which is sufficient to make the language Turing complete. Note that while the grid in Funge-98 can be extended indefinitely, it still behaves like a torus with respect to wrapping. Also of note, some derivatives let you program in more dimension, and there's an IDE that lets you program in up to 105 dimensions. But let's not go there, huh...

    I'll be adding to this page in the future. As a last thing (for now), the obfuscated program I've made for the 'random language printing my e-mail' on the esolang page.

    "xed">:#,_"moc"v
    >8++\4+:1-v>25#8*,@
    9    #    #    0
    ^::+1*5-4*83+2g<
    >25*1# +0v>::5-v
    p    ^  p<     \
    0 v:"emosa"+*52<
    * >1-::1+:v
    ^25" v@sp"< 

    Back to <@,,,,,"index"

    Processing took 0.05895