BuzzFizz

From Esolang
Jump to: navigation, search

BuzzFizz is an esoteric programming language created by User:ais523 in 2017. It's a typical imperative programming language that aims to be low-level enough to implement easily, powerful enough for it to be fairly clear how to implement most popular problems, and yet not powerful enough to be Turing-complete – although in theory it has an infinite amount of storage, it can only retrieve a finite subset of it.

Data storage

A BuzzFizz program stores data in bignum counters (each initially zero) and constants. A constant never changes while it has a value; however, if a previously undefined constant is used, the program will input a number from the user and use that as the value of the constant (thus making it possible to take input). It's also possible to re-undefine an initially undefined constant, meaning that input will again be taken the next time it is used.

Counters can never be decremented or assigned, only incremented. However, the value in a counter is retrieved by determining whether the counter divides into a constant, or whether a constant divides into the counter.

Additionally, there's a single Boolean flag, the "else flag"; this is initially true.

Syntax

A BuzzFizz program consists of a sequence of commands, separated by newlines. Horizontal whitespace is ignored except inside keywords, numbers and identifiers, as are blank lines. The commands are:

  • #characters: Does nothing. The characters can't contain a newline.
  • counter++: Increments the given counter.
  • print counter: Prints the value of the given counter (no newline).
  • print constant: Prints the value of the given constant (no newline).
  • print "characters": Prints the given characters more or less literally (except that backslash-escapes are processed more or less as in C), no newline unless there's one inside the string. The characters can't contain a newline or unescaped ".
  • clear constant: Re-undefines the given initially undefined constant.
  • if expression: command: If the expression is true, clears the else flag, then runs the command. Otherwise does nothing.
  • else: command: If the else flag is true, runs the command. Then (unconditionally) sets the else flag.
  • loop: Sets the else flag and returns to the start of the program.

An initially defined constant is written as a decimal number, and its value is equal to its name. An initially undefined constant is written as an identifier (i.e. letter first, then any number of letters and digits). A counter is written as an identifier preceded by $.

An expression is written as counter\constant or constant\counter; this determines whether the first-mentioned value divides into the second (true) or fails to divide into the second (false).

Examples

FizzBuzz

# Read input into max. To do that, just reference max.
# To ensure that input is read before the first iteration,
# we use a pointless conditional.
if max\$a: # do nothing
else: # do nothing

# $a is the counter.
$a++
# if-if-else construct checking whether 3 and 5 divide
# into the number.
if 3\$a: print "Fizz"
if 5\$a: print "Buzz"
else: print $a
# Write the trailing newline.
print "\n"

# Loop if there is more to write.
if max\$a: # do nothing
else: loop

Primality tester

# Start $a at 1. $u is 1 all program, except for the start.
if 2\$u: $a++
if 2\$u: $u++
else: # reset else flag

$a++
# n is prime if a equals n, i.e. n divides a.
# n is composite if a divides n.
# Otherwise, try a higher value of a.
# We use $x to suppress messages.
if n\$u: print "1 is neither prime nor composite!\n"
if n\$u: $x++
if n\$a: if 2\$x: print "Prime!\n"
if n\$a: if 2\$x: $x++
if $a\n: if 2\$x: print "Composite!\n"
else: loop

Add two numbers

# Ensure we have initialized.
# Counts initialize to 1, total to 2, as 0 is not a valid input.
if 2\$init: $count1++
if 2\$init: $count2++
if 2\$init: $total++
if 2\$init: $total++
if 2\$init: $init++

# Set $incr1, $incr2 to whether $count1, $count2 equal $in1, $in2.
if 2\$incr1: $incr1++
if in1\$count1: $incr1++
$incr1++
if 2\$incr2: $incr2++
if in2\$count2: $incr2++
$incr2++

if 2\$incr1: $count1++
if 2\$incr1: $total++
if 2\$incr2: $count2++
if 2\$incr2: $total++
if 2\$incr1: loop
if 2\$incr2: loop

print $total
print "\n"

Computational class

There are only finitely many distinguishable values of each counter; once a counter reaches one more than twice the lowest common multiple of all constants, that's effectively equivalent to the counter having been set to one more than the LCM (unless user input is used to redefine a constant), because divisibility tests cannot recognise an LCM-sized difference. The number of bits of data that can be stored is therefore proportional, for any given program, to the number of bits used to express the inputs, making the language a linear bounded automaton. It's currently unclear whether it's complete in this respect (i.e. whether it can simulate all linear bounded automata), but the author suspects not. It is, however, clear from the above examples that the program is more powerful than a finite state machine.

External resources

The author has written a rudimentary compiler from BuzzFizz to Perl (that uses a character set smaller than ASCII and doesn't understand all possible escapes inside strings; this is good enough to run most programs but would struggle to write a quine). The source code is here, but because it's written in a currently unreleased/unfinished language, the compiled version is probably more useful (if less readable).