git

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

zet-6-aoc-2021-05.md (3163B)


      1 ---
      2 title: 'Zettelkasten #6: Solution in D for Advent of Code 2021, Day 5'
      3 date: '2021-12-17T22:11:00+01:00'
      4 tags: ['zettelkasten', 'zet', 'dlang', 'aoc', 'aoc2021', 'adventofcode']
      5 description: "This post describes my solution in the D programming language for
      6 the 5th puzzle of the Advent of Code 2021."
      7 ---
      8 
      9 ## The challenge
     10 
     11 ### Part 1
     12 
     13 > You come across a field of hydrothermal vents on the ocean floor! These vents
     14 > constantly produce large, opaque clouds, so it would be best to avoid them if
     15 > possible.
     16 >
     17 > They tend to form in lines; the submarine helpfully produces a list of nearby
     18 > lines of vents (your puzzle input) for you to review.
     19 >
     20 > [...]
     21 >
     22 > Each line of vents is given as a line segment in the format x1,y1 -> x2,y2
     23 > where x1,y1 are the coordinates of one end the line segment and x2,y2 are the
     24 > coordinates of the other end. These line segments include the points at both
     25 > ends. In other words:
     26 >
     27 > - An entry like 1,1 -> 1,3 covers points 1,1, 1,2, and 1,3.
     28 > - An entry like 9,7 -> 7,7 covers points 9,7, 8,7, and 7,7.
     29 >
     30 > For now, only consider horizontal and vertical lines: lines where either x1 =
     31 > x2 or y1 = y2.
     32 >
     33 > [...]
     34 >
     35 > To avoid the most dangerous areas, you need to determine the number of points
     36 > where at least two lines overlap. [...]
     37 >
     38 > Consider only horizontal and vertical lines. At how many points do at least
     39 > two lines overlap?
     40 
     41 You can read the challenge more in depth,
     42 [here](https://adventofcode.com/2021/day/5).
     43 
     44 ### Part 2
     45 
     46 > Unfortunately, considering only horizontal and vertical lines doesn't give
     47 > you the full picture; you need to also consider diagonal lines.
     48 >
     49 > Because of the limits of the hydrothermal vent mapping system, the lines in
     50 > your list will only ever be horizontal, vertical, or a diagonal line at
     51 > exactly 45 degrees. In other words:
     52 >
     53 > - An entry like 1,1 -> 3,3 covers points 1,1, 2,2, and 3,3.
     54 > - An entry like 9,7 -> 7,9 covers points 9,7, 8,8, and 7,9.
     55 >
     56 > [...]
     57 >
     58 > Consider all of the lines. At how many points do at least two lines overlap?
     59 
     60 ## Full solution
     61 
     62 ```d
     63 auto input = stdin.byLineCopy()
     64     .map!`a.splitter(" -> ").map!"a.splitter(',').map!(to!long).array".array`.array;
     65 auto xy =input.map!(l => [max(l[0][0], l[1][0]), max(l[0][1],l[1][1])])
     66     .array.transposed.map!maxElement.array;
     67 size_t[][] a = new size_t[(xy[0]+1)*(xy[1]+1)].evenChunks(xy[1]+1).array;
     68 foreach(p; input) {
     69     if(p[0][0] == p[1][0])
     70         if(p[0][1] > p[1][1]) foreach(e; p[1][1]..p[0][1]+1) ++a[e][p[0][0]];
     71         else foreach(e; p[0][1]..p[1][1]+1) ++a[e][p[0][0]];
     72     else if(p[0][1] == p[1][1])
     73         if(p[1][0] > p[0][0]) foreach(e; p[0][0]..p[1][0]+1) ++a[p[0][1]][e];
     74         else foreach(e; p[1][0]..p[0][0]+1) ++a[p[0][1]][e];
     75     else if(1) // change this value to 0 for first part
     76     {
     77         auto x1 = p[0][0], x2 = p[1][0], y1 = p[0][1], y2 = p[1][1];
     78         if(x1 > x2) { swap(x1,x2); swap(y1, y2); }
     79         foreach(e; x1..x2+1)
     80             if(y2>y1) ++a[y1+(e-x1)][e];
     81             else ++a[y1-(e-x1)][e];
     82     }
     83 }
     84 // construct the map
     85 //a.map!(l => l.map!`a.to!string == "0" ? "." : a.to!string`.join).each!writeln;
     86 a.join.filter!"a > 1".count.writeln;
     87 ```