summary refs log tree commit diff stats
path: root/2020/day-12/README.org
diff options
context:
space:
mode:
authorAndinus <andinus@nand.sh>2020-12-12 20:03:38 +0530
committerAndinus <andinus@nand.sh>2020-12-12 20:03:38 +0530
commit3e2478468c10188bbb50fde4041f84431e5c77fe (patch)
tree4ee7a49ccfd62f08137a12c5108cd14147a74248 /2020/day-12/README.org
parent75c4e3cbcd4b2f7f47ebbebcc125d86c5b7e783b (diff)
downloadaoc-3e2478468c10188bbb50fde4041f84431e5c77fe.tar.gz
Add day-12 solution
Diffstat (limited to '2020/day-12/README.org')
-rw-r--r--2020/day-12/README.org226
1 files changed, 226 insertions, 0 deletions
diff --git a/2020/day-12/README.org b/2020/day-12/README.org
new file mode 100644
index 0000000..4127135
--- /dev/null
+++ b/2020/day-12/README.org
@@ -0,0 +1,226 @@
+#+SETUPFILE: ~/.emacs.d/org-templates/level-3.org
+#+HTML_LINK_UP: ../../index.html#2020
+#+OPTIONS: toc:1
+#+EXPORT_FILE_NAME: index
+#+TITLE: Day 12 - Rain Risk
+
+* Puzzle
+- This puzzle is taken from: https://adventofcode.com/2020/day/12
+
+Your ferry made decent progress toward the island, but the storm came in
+faster than anyone expected. The ferry needs to take evasive actions!
+
+Unfortunately, the ship's navigation computer seems to be
+malfunctioning; rather than giving a route directly to safety, it
+produced extremely circuitous instructions. When the captain uses the PA
+system to ask if anyone can help, you quickly volunteer.
+
+The navigation instructions (your puzzle input) consists of a sequence
+of single-character actions paired with integer input values. After
+staring at them for a few minutes, you work out what they probably mean:
+
+- Action N means to move north by the given value.
+- Action S means to move south by the given value.
+- Action E means to move east by the given value.
+- Action W means to move west by the given value.
+- Action L means to turn left the given number of degrees.
+- Action R means to turn right the given number of degrees.
+- Action F means to move forward by the given value in the direction the
+  ship is currently facing.
+
+The ship starts by facing east. Only the L and R actions change the
+direction the ship is facing. (That is, if the ship is facing east and
+the next instruction is N10, the ship would move north 10 units, but
+would still move east if the following action were F.)
+
+For example:
+#+BEGIN_SRC
+F10
+N3
+F7
+R90
+F11
+#+END_SRC
+
+These instructions would be handled as follows:
+
+- F10 would move the ship 10 units east (because the ship starts by
+  facing east) to east 10, north 0.
+- N3 would move the ship 3 units north to east 10, north 3.
+- F7 would move the ship another 7 units east (because the ship is still
+  facing east) to east 17, north 3.
+- R90 would cause the ship to turn right by 90 degrees and face south;
+  it remains at east 17, north 3.
+- F11 would move the ship 11 units south to east 17, south 8.
+
+At the end of these instructions, the ship's Manhattan distance (sum of
+the absolute values of its east/west position and its north/south
+position) from its starting position is 17 + 8 = 25.
+
+Figure out where the navigation instructions lead. What is the Manhattan
+distance between that location and the ship's starting position?
+** Part 2
+Before you can give the destination to the captain, you realize that the
+actual action meanings were printed on the back of the instructions the
+whole time.
+
+Almost all of the actions indicate how to move a waypoint which is
+relative to the ship's position:
+
+- Action N means to move the waypoint north by the given value.
+- Action S means to move the waypoint south by the given value.
+- Action E means to move the waypoint east by the given value.
+- Action W means to move the waypoint west by the given value.
+- Action L means to rotate the waypoint around the ship left
+  (counter-clockwise) the given number of degrees.
+- Action R means to rotate the waypoint around the ship right
+  (clockwise) the given number of degrees.
+- Action F means to move forward to the waypoint a number of times equal
+  to the given value.
+
+The waypoint starts 10 units east and 1 unit north relative to the ship.
+The waypoint is relative to the ship; that is, if the ship moves, the
+waypoint moves with it.
+
+For example, using the same instructions as above:
+
+- F10 moves the ship to the waypoint 10 times (a total of 100 units east
+  and 10 units north), leaving the ship at east 100, north 10. The
+  waypoint stays 10 units east and 1 unit north of the ship.
+- N3 moves the waypoint 3 units north to 10 units east and 4 units north
+  of the ship. The ship remains at east 100, north 10.
+- F7 moves the ship to the waypoint 7 times (a total of 70 units east
+  and 28 units north), leaving the ship at east 170, north 38. The
+  waypoint stays 10 units east and 4 units north of the ship.
+- R90 rotates the waypoint around the ship clockwise 90 degrees, moving
+  it to 4 units east and 10 units south of the ship. The ship remains at
+  east 170, north 38.
+- F11 moves the ship to the waypoint 11 times (a total of 44 units east
+  and 110 units south), leaving the ship at east 214, south 72. The
+  waypoint stays 4 units east and 10 units south of the ship.
+
+After these operations, the ship's Manhattan distance from its starting
+position is 214 + 72 = 286.
+
+Figure out where the navigation instructions actually lead. What is the
+Manhattan distance between that location and the ship's starting
+position?
+* Solution
+=@instructions= hold the instructions & =Instruction= is a token that will
+parse them. It seperates the action from value. =@ship= holds the position
+of ship, 0th index will hold east/west position where east is positive &
+1st index holds north/south position where north will be positive.
+#+BEGIN_SRC raku
+unit sub MAIN (
+    Int $part where * == 1|2 = 1 #= part to run (1 or 2)
+);
+
+my @instructions = "input".IO.lines;
+
+# east/west, north/south. east/north are positive.
+my Int @ship[2] = 0, 0;
+
+my token Instruction { (N|S|E|W|L|R|F) (\d+) };
+if $part == 1 {
+    ...
+} elsif $part == 2 {
+    ...
+}
+...
+#+END_SRC
+
+For part 1, =$facing= holds index that tells us the direction our ship is
+facing. =@directions= holds all the possible directions the ship face.
+Next we just follow the instructions for when the action is =N|S|E|W=. For
+action "L" & "R", we have to perform some checks to wrap =$facing= around.
+
+=$facing= holds the index of =@directions= & that is why it needs to be
+kept between 0 to 3. The for loop in "L" & "R" is for the number of time
+the turning action needs to be performed. For example, if the value is
+180 then we turn 2 times.
+
+"F" just handles how the ship goes forward according to which direction
+it is in.
+#+BEGIN_SRC raku
+my Str @directions[4] = <E S W N>;
+my Int $facing = 0;
+
+for @instructions -> $instruction {
+    if $instruction ~~ &Instruction -> $match {
+        given $match[0] {
+            when 'N' { @ship[1] += $match[1]; }
+            when 'S' { @ship[1] -= $match[1]; }
+            when 'E' { @ship[0] += $match[1]; }
+            when 'W' { @ship[0] -= $match[1]; }
+            when 'L' {
+                for 1..($match[1] / 90).Int {
+                    if $facing == 0 {
+                        $facing = 3;
+                    } else {
+                        $facing -= 1;
+                    }
+                }
+            }
+            when 'R' {
+                for 1..($match[1] / 90).Int {
+                    if $facing == 3 {
+                        $facing = 0;
+                    } else {
+                        $facing += 1;
+                    }
+                }
+            }
+            when 'F' {
+                given @directions[$facing] {
+                    when 'N' { @ship[1] += $match[1]; }
+                    when 'S' { @ship[1] -= $match[1]; }
+                    when 'E' { @ship[0] += $match[1]; }
+                    when 'W' { @ship[0] -= $match[1]; }
+                }
+            }
+        }
+    }
+}
+#+END_SRC
+
+For solution we just print the sum of numbers in =@ship=, their absolute
+values are considered.
+#+BEGIN_SRC raku
+say "Part $part: ", [+] @ship.map(*.abs);
+#+END_SRC
+** Part 2
+For part 2, we define =@waypoint= which will hold the position of the
+waypoint. =N|S|E|W= is modified according to the new rules, it'll update
+the position of waypoint now instead of the ship.
+
+"L" & "R" now rotate the waypoint in respective directions. And "F"
+moves the ship forward according to the new rules.
+#+BEGIN_SRC raku
+# east/west, north/south. east/north are positive.
+my Int @waypoint[2] = 10, 1;
+
+for @instructions -> $instruction {
+    if $instruction ~~ &Instruction -> $match {
+        given $match[0] {
+            when 'N' { @waypoint[1] += $match[1]; }
+            when 'S' { @waypoint[1] -= $match[1]; }
+            when 'E' { @waypoint[0] += $match[1]; }
+            when 'W' { @waypoint[0] -= $match[1]; }
+            when 'L' {
+                for 1..($match[1] / 90).Int {
+                    @waypoint = -@waypoint[1], @waypoint[0];
+                }
+            }
+            when 'R' {
+                for 1..($match[1] / 90).Int {
+                    @waypoint = @waypoint[1], -@waypoint[0];
+                }
+            }
+            when 'F' {
+                @ship[0] += @waypoint[0] * $match[1];
+                @ship[1] += @waypoint[1] * $match[1];
+            }
+        }
+    }
+}
+#+END_SRC