My AoC program in D is just as fast as in Python

MrJay mrjcraft2021 at gmail.com
Wed Nov 26 06:14:55 UTC 2025


On Tuesday, 25 November 2025 at 22:31:30 UTC, MrJay wrote:
> On Tuesday, 25 November 2025 at 22:19:19 UTC, MrJay wrote:
>> when you are comparing two languages you have to be careful to 
>> not accidentally add accidental bottlenecks, where you are not 
>> comparing the bottle neck rather than the languages
>
> really didnt like how I explained this to restate it
>
> profiling is quite difficult, and must be done with care 
> because its very easy to profile a bottleneck rather than the 
> application or code it self.
>

> even as an array of bytes its 1mb
> as bits its 125000 bytes
> or 125 kilobytes
> and every instruction would be much faster as well, and every 
> lookup should also be faster

I rewrote my own version of the AOC using a BitArray
I tried to keep the dependencies as low as possible, so more code 
than is necessary.
I could also do more optimizations but I wanted the code to at 
least be simple.
only optimization I did do is just avoid allocating, and or do 
allocations up front in bulk. most of that doesn't matter, this 
is still a pretty simple version of the code regardless.

```d
import std.stdio;
import std.bitmanip;
import core.memory;
//correct output 569999

BitArray[1000] lights;

     void main() {
           GC.disable; // I disable the GC as I know where the 
program allocates
           start("input.txt");
     }

     long start(string filename) {
           foreach(ref k; lights) {
                 k.length = 1000; // allocates here
           }
           auto f = File(filename,"r");
           char[] buf; // slightly unnecessary optimization
           buf.reserve(64); // line length shouldnt be more than 
64, minimizes allocations
           while(!f.eof) {
                 f.readln(buf);
                 if(buf.length < 5) continue;
                 parse_line(buf[0..$]);
           }
           long total;
           foreach(ba; lights) total += ba.count;

           writeln(total);
           return 0;
     }

@nogc nothrow :

     int index_of(T)(T[] str, T d) {
           foreach(i, c; str) {
                 if(c == d) {
                       return cast(int) i;
                 }
           }
           return -1;
     }

     int[4] parse_points(char[] line) {
           int[2] spaces;
           spaces[0] = line.index_of(' ');
           spaces[1] = cast(int)(spaces[0]+("through".length+1)); 
// can do this constant as through is consistent
           int[2] p1 = line[0..spaces[0]].parse_point;
           int[2] p2 = line[spaces[1]+1..$-1].parse_point;
           return [p1[0],p1[1],p2[0],p2[1]];
     }

     int[2] parse_point(char[] pair) {
           int commaloc = pair.index_of(',');
           int i1 = pair[0..commaloc].parse_int;
           int i2 = pair[commaloc+1..$].parse_int;
           return [i1,i2];
     }

     int parse_int(char[] str) {
           import std.math : pow;
           int pwr = cast(int) str.length-1;
           int total = 0;
           foreach(c;str) {
                 long v = c - '0';
                 if(v >= 0 && v <= 9) {
                       v = v*pow(10, pwr);
                       total += v;
                       pwr -= 1;
                 } else {
                       break;
                 }
           }
           return total;
     }

     void parse_line(char[] line) {
           line = line[line.index_of(' ')+1..$]; // removes the 
first wort
           int[4] points;
           bool on = line[0..2] == "on"; // if second word is on
           bool off = line[0..3] == "off"; // if second word is off
           if(on || off) {
                 line = line[line.index_of(' ')+1..$];
                 points = parse_points(line); // I use slices here 
no allocations
                 auto p1 = points[0..2];
                 auto p2 = points[2..$];
                 for(int i = p1[0]; i <= p2[0]; i++) {
                       for(int j = p1[1]; j <= p2[1]; j++) {
                             lights[i][j] = on; // on is the 
boolean on this also decides which op to do
                       }
                 }
           } else { // if second word is neither
                 points = parse_points(line); // I use slices here 
no allocations
                 auto p1 = points[0..2];
                 auto p2 = points[2..$];
                 for(int i = p1[0]; i <= p2[0]; i++) {
                       for(int j = p1[1]; j <= p2[1]; j++) {
                             lights[i].flip(j); // used the flip 
function built into BitArray
                       }
                 }
           }
     }
     ```


More information about the Digitalmars-d-learn mailing list