The challenge

It seems like the submarine can take a series of commands like forward 1, down 2, or up 3:

  • forward X increases the horizontal position by X units.
  • down X increases the depth by X units.
  • up X decreases the depth by X units.

Note that since you’re on a submarine, down and up affect your depth, and so they have the opposite result of what you might expect.

[…]

Calculate the horizontal position and depth you would have after following the planned course. What do you get if you multiply your final horizontal position by your final depth?

You can read the challenge more in depth, here.

Part 1

The idea here is to fold the values and increment or decrement fields, depending on the given operations. First, to efficiently recognize the operations, we can just compare the first byte, since they are unique (f for forward, d for down and u for up). A simple split and map can do the trick, easily:

auto parsed = input.map!split.map!"tuple(a.front[0], a.back.to!long)";

To fold the values in D we can use fold template. We need seed the fold with a tuple or a static array, starting at zero. Inside the fold we write the logic to increment or decrement the accumulator, according to the given rules:

auto folded = parsed.fold!((a,b) {        // fold the parsed input
        b[0] == 'f' ? a[0] += b[1]        // increment on forward
        : b[0] == 'd' ? a[1] += b[1]      // increment on down
        : b[0] == 'u' ? a[1] -= b[1] : 0; // decrement on up
        return a; })(tuple(0L,0L));       // seed it with zeros

And that’s it, now you just need to multiply the result of the fold:

auto res = folded[0] * folded[1];

Full solution

[stdin.byLine().map!split.map!"tuple(a.front[0], a.back.to!long)" // parse input
    .fold!((a,b) {                                                // fold the input
        b[0] == 'f' ? a[0] += b[1]                                // increment on forward
        : b[0] == 'd' ? a[1] += b[1]                              // increment on down
        : b[0] == 'u' ? a[1] -= b[1] : 0;                         // decrement on up
        return a; })(tuple(0L,0L))]                               // seed with zeros
    .map!"a[0] * a[1]".front.writeln;                             // multiply result

Part 2

Based on your calculations, the planned course doesn’t seem to make any sense. You find the submarine manual and discover that the process is actually slightly more complicated.

In addition to horizontal position and depth, you’ll also need to track a third value, aim, which also starts at 0. The commands also mean something entirely different than you first thought:

  • down X increases your aim by X units.
  • up X decreases your aim by X units.
  • forward X does two things:
    • It increases your horizontal position by X units.
    • It increases your depth by your aim multiplied by X.

[…]

Using this new interpretation of the commands, calculate the horizontal position and depth you would have after following the planned course. What do you get if you multiply your final horizontal position by your final depth?

The second part is pretty much the same as part one, except it uses an additional value in the fold and diffferent rules.

Full solution

[stdin.byLine().map!split.map!"tuple(a.front[0], a.back.to!long)" // parse input
    .fold!((a,b) {                                                // fold the input
        b[0] == 'f' ? a[0] += b[1] : 0;                           // increment on forward
        b[0] == 'f' ? a[1] += a[2] * b[1]                         // multiply w/ aim on forward
        : b[0] == 'd' ? a[2] += b[1]                              // increment aim on down
        : b[0] == 'u' ? a[2] -= b[1] : 0;                         // decrement aim on up
        return a; })(tuple(0L,0L,0L))]                            // seed with zeros
    .map!"a[0] * a[1]".front.writeln;                             // multiply result