From 3e2478468c10188bbb50fde4041f84431e5c77fe Mon Sep 17 00:00:00 2001 From: Andinus Date: Sat, 12 Dec 2020 20:03:38 +0530 Subject: Add day-12 solution --- 2020/day-12/README.org | 226 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 2020/day-12/README.org (limited to '2020/day-12/README.org') 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] = ; +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 -- cgit 1.4.1-2-gfad0