git

My personal website source code
Log | Files | Refs | Submodules | README | LICENSE

commit ba46c4a60107dfc1d3e1a741f97f4a43f3521aeb
parent 0609c12d75d3f721012696f2b3197b521e60e7b1
Author: Luís Ferreira <contact@lsferreira.net>
Date:   Thu,  2 Dec 2021 20:23:06 +0000

posts: Add 'Zettelkasten #3: Solution in D for Advent of Code 2021, Day 2'

Signed-off-by: Luís Ferreira <contact@lsferreira.net>

Diffstat:
Acontent/posts/zet-3-aoc-2021-02.md | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+), 0 deletions(-)

diff --git a/content/posts/zet-3-aoc-2021-02.md b/content/posts/zet-3-aoc-2021-02.md @@ -0,0 +1,109 @@ +--- +title: 'Zettelkasten #3: Solution in D for Advent of Code 2021, Day 2' +date: '2021-12-02T19:02:00+01:00' +tags: ['zettelkasten', 'zet', 'dlang', 'aoc', 'aoc2021', 'adventofcode'] +description: "This post describes, in detail, my solution in the D programming +language for the 2nd puzzle of the Advent of Code 2021." +--- + +## 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](https://adventofcode.com/2021/day/2). + +## 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: + +```d +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: + +```d +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: + +```d +auto res = folded[0] * folded[1]; +``` + +### Full solution + +```d +[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 + +```d +[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 +```