Warning: following has Advent of Code 2017 (day 14 and day 10) spoilers incase you are doing those challenges. And apologies for the slightly long post, I'm unsure how much information is needed here and am a bit clueless. Any help would be much appreciated.

=====

Ok, so I'm trying to get through these daily code puzzles with D. Most of my troubles so far have come from trying to coax the type system in to behaving how I want/expect, and parsing input data at compile time. My background is a fair amount of C++ in the past, and these days Swift (just incase it helps with explaining things)

(fun little tidbit, we're a decent size group at work doing these challenges in many languages and D is usually second in performance after C! :) - other contenders include python, go, scala, scheme, elixr, elm, javascript, fortran(!), kotlin, and quite a few more - one nut job actually decided to do a different language every day this month)

So for executing each of these puzzles (they all have two parts) I have the following setup:

app.d:

  import _day14;
  enum data = process(import("day14.txt")); // load input file
  void main() { solveA(data); solveB(data) }

So input processing is compile time, and solutions are executed at runtime (i think?). Today's problem involves a custom hash function that was developed on day 10 of the calendar.

So in my "_14.d" file I have this at the top:

  // takes a string, hashes it and returns 32 character hex string
  module _14;
  import _10: knotHashHex = solveB;

Today's problem requires this hex string to be converted in to binary (i.e. each hex char to 4 binary chars) - I am aware that an optimization here would be to use bits instead of chars but meh :p. So I have this defined:

  // Takes "af49cb351fa..." -> "0010010111011..."
  alias knotHash = (string input)
    => knotHashHex(input)
.map!binary // converts a dchar to a binary string so 'f' -> "1111"
        .join;

So my app first calls "process" on the input data (which is a random string for today) and then the output of that goes in to solveA and solveB of my day14 module. My "process" function for today is this:

  // size "immutable size = 128;"
// The puzzle requires a 128x128 grid of 1's and 0's so we reuse the input string
  //   each round and just append a "-i" to it.
  auto process(string input) {
    return size
        .iota
        .map!(i => input ~ "-" ~ i.text)
        .array
        .map!knotHash
  }

So the output type of this function is:
MapResult!(function (string input) => join(map(solveB(input))), string[])

My solveA part works fine, you're supposed to count the number of 1's in the grid so it's a simple:

  auto solveA(ReturnType!process grid) {
    return grid
        .join
        .count!q{a == '1'};
  }

The next part is where I start to have problems. It involves a recursive depth-first-search approach so I have a function that recurses:

void visit(ref string[] grid, int i, int j, ref bool[size][size] visited) {
    // check stuff and call visit again
  }

And my solveB looks like this:

  auto solveB(ReturnType!process grid) {
    auto arrayGrid = grid.array; // convert to string[]
    // more code then at some point I call:
    visit(arrayGrid, i, j, visited);
  }

So up to here everything works. But now I don't like that I have a "grid.array" inside solveB but not in solveA. Seems asymmetrical. So I figured I could just change my "process" function above to return an array directly by just adding a ".array" to the pipeline.

Then I get this error:

Error: couldn't find field __expand_field_0 of type ulong in Tuple(0LU, 117)

117 is the ascii code for 'u' btw, which happens to be the first character in my random input string. This error is coming from inside my day 10's "solveB" function (which is imported in day 14 as "knotHashHex"). It comes from here:

  int[] rotate(int[] list, int[] lengths) {
    auto range = list.cycle;
foreach (skip, length; lengths.enumerate) { // <-- here is error
      //  do stuff to range
    }
    return list;
  }

So it says something about ulong and expanding a tuple type. But I'm having a hard time with this error message.

Questions: What does it mean? It can't expand field 0 (the ulong) in to my skip variable? Why not? And most importantly, why is it having trouble here during my "process" function, but not screaming when I call "grid.array" in my "solveB" function? What am I doing wrong?

So anyway, Halp!


Reply via email to