Halp! type system (__expand_field_0 error), compile time/runtime questions (AoC-2017 puzzle spoilers inside)

aliak something at something.com
Thu Dec 14 15:28:22 UTC 2017


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!




More information about the Digitalmars-d-learn mailing list