I decided to do Advent of Code this year in D, and the following is my solution to day 8.
Algorithm aside, I was specifically wondering if there was a better way to use ranges in a recursive manner here. I feel like I should be able to do write the functions in a more generic way (not just int[]
, avoiding the .array
in main
), and without destroying the original array in the process - avoiding the temporary variable p1
.
My use of the header
variable seems suspect to me as well - basically I want a popFront
that returns a value, I think, but have been unable to find anything like that.
I'm also happy to hear general advice about usual best practices and efficiencies.
import std.algorithm;
import std.conv;
import std.file;
import std.range;
import std.stdio;
import std.string;
int count_metadata(ref int[] r)
{
auto header = r.take(2);
int num_child = header.front;
int num_metadata = header.back;
r = r.drop(2);
int count;
for (int i; i < num_child; i++) {
count += r.count_metadata;
}
count += r.take(num_metadata).sum;
r = r.drop(num_metadata);
return count;
}
int node_value(ref int[] r)
{
auto header = r.take(2);
int num_child = header.front;
int num_metadata = header.back;
r = r.drop(2);
int[] child_values;
for (int i; i < num_child; i++) {
child_values ~= node_value(r);
}
int count;
if (num_child == 0) {
count = r.take(num_metadata).sum;
} else {
// ignore out of range
count = r.take(num_metadata).filter!(a => 0 < a && a <= child_values.length).map!(a => child_values[a - 1]).sum;
}
r = r.drop(num_metadata);
return count;
}
void main(string[] args)
{
// integers separated by spaces
auto input = readText(args[1]).split.map!(a => to!int(a)).array;
//auto input = [2, 3, 0, 3, 10, 11, 12, 1, 1, 0, 1, 99, 2, 1, 1, 2];
auto p1 = input.dup;
writeln("Metadata total: ", count_metadata(p1));
writeln("Node value: ", node_value(input));
}
(args[1]
is a file with integers separated by spaces, sample input is commented out below it.)