Back to Home

dc: programming on a stack calculator

dc — Unix stack calculator as a programming language with registers, macros, and recursion. The article breaks down the stack model, conditional constructs, FizzBuzz and Peg Solitaire examples with full code.

Programming FizzBuzz on dc: from stack to game
Advertisement 728x90

dc: The Calculator as a Programming Language for Developers

dc is a classic Unix calculator, older than the C language, included in standard distributions of most systems, including macOS. Behind its simple facade lies a full-fledged stack-based programming language with registers, macros, conditional constructs, and recursion. The core model is the stack: numbers and strings are pushed onto the stack via commands, operators pop the top elements, perform an action, and return the result.

First calculation: to sum 2 + 2, enter 2 2 + p. Here, 2 2 pushes the numbers onto the stack line by line, + adds the top two elements, and p prints the result.

2 2 +
p
4

The stack is the key element: every literal (number or [string]) pushes a value onto the top. Comments start with #.

Google AdInline article slot

Working with Registers and Variables

dc provides 256 registers (a-z, 0-9, and other characters) that store numbers or strings. Commands sR save the top of the stack into register R, and lR load it back. Registers maintain state independently of the main stack.

Example of saving and restoring a string:

[Hello world!] sx
lx
p
Hello world!

Registers are suitable for global variables. Numbers in registers are manipulated similarly to the stack: li loads i onto the stack.

Google AdInline article slot

Macros as Functions

Functions in dc are macros: strings stored in registers, executed with the command lRx, where x is the register. Macros are defined as [code] sR.

Example of a function to sum registers a and b:

[la lb +] sS
1 sa
2 sb
lSx
p
3

Macros support recursion and can call each other, forming subroutines.

Google AdInline article slot

Conditional Constructs

Branching is based on comparing the top two elements of the stack. Operators include =, >, <, !=, and others. If the condition is true, the macro from the specified register is executed.

[[Equal] p] sE
[[Non equal] p] sN
1 0
=E
1 0
!=N
Non equal

Comparisons consume two elements from the stack, leaving the result (0 or 1).

Recursive Loops

There are no loops, but recursion is implemented via macro self-calls. Example of printing numbers from 1 to 10:

[
	li p
	1 + si
	li 11 >C
] sC

1 si
lCx

Macro C prints i, increments it, and recursively calls itself while i < 11. The current i is already on the stack upon entry.

  • Advantages of recursion in dc: simplicity, no explicit loops.
  • Limitations: risk of stack overflow with deep recursion.
  • Alternatives: tail recursion minimizes stack usage.

FizzBuzz in dc

Implementation of FizzBuzz up to 100 demonstrates a combination of macros, conditions, and recursion. Key commands: P (print without newline), c (clear stack).

Full code:

[[Fizz] P 0 sd] sF
[[Buzz] P 0 sd] sB
[li 3 % 0 =F li 5 % 0 =B] sW
[10 P] sP
[li p c] sD
[
  1 sd
  lWx
  ld 0 =P
  ld 1 =D
  li 1 + si
  li 101 >M
] sM

1 si
lMx

Logic: flag d determines whether to print the number. Macro W checks divisibility by 3/5, setting Fizz/Buzz. P with 10 (LF) for a new line.

Advanced Applications: Peg Solitaire

dc allows solving complex tasks, such as Peg Solitaire—a puzzle with peg jumps on a board. The board state is encoded as a binary number, with manipulations via arithmetic and bitwise operations (shifts and masks are available).

Move validation formulas in RPN look complex due to bitwise checks but enable a complete game: from the initial configuration to the final peg.

This approach showcases dc as a tool for algorithm prototyping without compilation.

Key Takeaways

  • The stack is the foundation of all operations: literals push, operators pop/push results.
  • Registers (256 total) for state, macros for subroutines with lRx.
  • Conditions consume the stack, recursion replaces loops.
  • p/P for output, c for clearing, % for modulus.
  • Suitable for scripting, prototyping, and learning RPN.

— Editorial Team

Advertisement 728x90

Read Next