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