Termination
Here are 3 programs that print the numbers 1-100 using different termination strategies:
This program uses a straightforward conditional branch into an @
.
. . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . _ . . .
) ! { Ċ ; d ' : < > . { =
. . . . . . . . @ . . .
. . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . .
Run on Hexagony.net
This program uses the #
operator, which is a no-op when the current memory cell is zero, but otherwise can change the instruction path.
. . . . . . .
. . . . . . . @
. . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . . .
) ! { Ċ ; d ' : . # . { =
. . . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . .
Run on Hexagony.net
This program exits via division by zero error. This has the advantage of not requiring any branching or control flow operators to terminate.
. . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . . .
) ! { Ċ ; d ' - ' : } { =
. . . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . .
Run on Hexagony.net
Note that the first 2 programs work by redirecting control flow onto a path with an @
on it. But with careful adjustment, or just luck, the path the IP is redirected on may happen to run into a division by zero. For example, here's a slight modification on the first program that reuses the division operator to terminate:
. . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . _ . . .
) ! { Ċ ; d ' : < > . { =
. . . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . .
. . _ . . . . .
. . . . . . .
Run on Hexagony.net
Here is a program that prints all arguments separated by newlines and then exits with a div by zero error. It uses the fact that all arguments are zero-byte-terminated, and after all args are exhausted, reading a byte yields -1.
. . . . . .
. . . . . . .
. . . . . . . .
. . . . . . . . .
. > ) ' : } Ċ ; \ .
, < > ; . . . $ \ . .
. _ . . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . .
. . . . . .
Run on Hexagony.net
Powers of ten
Exponentiation can be useful in Hexagony, and powers of ten are particularly nice since multiplying a cell by ten can be accomplished by just using the 0
operator on the cell. Here is an exponentiation "subroutines" that can be called from the main IP with ]
, multiplying one cell adjacent to the cell it is called on n
by 10**n
:
. . . . . / $ >
. . . . . . > < $
. . . . . . \ [ / .
. . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . . .
} 0 . \ . . . . . . . . . . .
( ' < . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . .
. . . . . . . .
It can also become 100**n
by adding an extra zero in the empty slot.
Data Structures
Like brainfuck, Hexagony is a registerless language where all data structures have to be built into memory from scratch. However, in contrast to brainfuck, moving through memory is arguably even more cumbersome, and cells can store arbitrarily large integers. Because of this, it is often feasible to store entire data structures in a single cell. Here is an example in Python 3 of what creating a stack stored entirely inside a single integer might look like.
class HexagonyStack:
def __init__(self, size = 256):
self.stack = 0
self.cellSize = size
def push(self, val):
self.stack = self.stack * self.cellSize + val
def pop(self):
temp = self.stack % self.cellSize
self.stack //= self.cellSize
return temp
def peek(self, index):
return self.stack // (self.cellSize ** index) % self.cellSize
HXS = HexagonyStack(100)
HXS.push(20)
HXS.push(30)
print(HXS.peek(1)) # 20
print(HXS.pop()) # 30
print(HXS.pop()) # 20
print(HXS.pop()) # 0
It is notable that this type of stack by default has an infinite number of zeroes at the bottom.
Cell sizes that are powers of ten are often the best for golf since multiplication by ten takes a single operator, and powers of two seem to aid performance.
Although data stored like this takes some math just to interface with it, it may often still be shorter than trying to manage the data pointer across a complex memory structure.