Marketing Pitch and Impressions#

D is a general-purpose programming language with static typing, systems-level access, and C-like syntax. With the D Programming Language, write fast, read fast, and run fast.

dlang.org

Unfortunately most of the systems programming languages I’ve used in AoC 2025 appear to have lost the systems-programming race to Rust and maybe Go. That’s something of a shame, as D seems like a worthy modern alternative to C and C++.

One feature that I found appealing, and largely the reason I looked at D in the first place, is the distinction D makes between const (a read-only view of data that might be changed by someone else) and immutable (data that can never change). Unfortunately this distinction doesn’t really come into play in this particular solution.

Another thing that is quite nice is the ability to mark functions as pure and @safe. This gives the compiler more information to optimize and check code for safety and purity.

Visual Studio Code support for D is excellent.

The Code#

The standout feature demonstrated here is Compile Time Function Execution (CTFE). Because D’s compiler front-end is so powerful, I was able to compute the entire solution during compilation. The runtime executable simply prints the pre-calculated constants. I verified this by inspecting the generated assembly— the main() function just calls writeln(...) twice with constants.

The underlying algorithm is again pretty straightfoward. Just take the biggest digit from the current string that leaves enough digits to fill in the remainder of the n-digit number. The exact same algorithm is used for part 1 and part 2, just with differing lengths.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
module d03;

import std;

pure @safe long helper(const int[] currentBank, int digits, long acc) {
  if (digits == 0)
    return acc;
  const maxIndex = currentBank[0 .. $ - (digits - 1)].maxIndex;
  const bestJolt = currentBank[maxIndex];
  const remainingBank = currentBank[maxIndex + 1 .. $];
  return helper(remainingBank, digits - 1, acc * 10 + bestJolt);
}

pure @safe long getMaxJolts(int[][] data, int count) {
  return data
    .map!(bank => helper(bank, count, 0))
    .sum;
}

pure @safe int[][] parseData(string content) {
  return content
    .splitLines
    .map!(line => line.strip.map!(c => c - '0').array.to!(int[]))
    .array;
}

void main() {
  enum fileContent = import("y25d03.txt");
  enum banks = fileContent.parseData();
  enum result1 = banks.getMaxJolts(2);
  enum result2 = banks.getMaxJolts(12);

  writeln("Result1: ", result1);
  writeln("Result2: ", result2);
}

Install D and run#

D has three major compilers: DMD (reference), LDC (LLVM-based), and GDC (GCC-based). DMD does not, as yet, have an aarch64 backend, so I used LDC on my Mac.

# I installed via Homebrew
brew install ldc

# From the website: install DMD
curl -fsS https://dlang.org/install.sh | bash -s dmd

# Compile and Run
ldc2 -J. -run d03.d