From: Neil Smith <neil.git@njae.me.uk> Date: Wed, 11 Dec 2019 17:48:15 +0000 (+0000) Subject: Using just rationals for part 1. X-Git-Url: https://git.njae.me.uk/?a=commitdiff_plain;h=7a21eab3c81fc8d8214c80b0c447b96b9d7c016b;p=advent-of-code-19.git Using just rationals for part 1. --- diff --git a/advent10/package.yaml b/advent10/package.yaml index 75a923b..9069b19 100644 --- a/advent10/package.yaml +++ b/advent10/package.yaml @@ -56,4 +56,12 @@ executables: dependencies: - base >= 2 && < 6 - containers + - linear + + advent10i: + main: advent10i.hs + source-dirs: src + dependencies: + - base >= 2 && < 6 + - containers - linear \ No newline at end of file diff --git a/advent10/src/advent10.hs b/advent10/src/advent10.hs index 95c0287..ba90ba1 100644 --- a/advent10/src/advent10.hs +++ b/advent10/src/advent10.hs @@ -1,17 +1,14 @@ import Data.Ratio import qualified Data.Set as S import qualified Data.Map.Strict as M --- import Data.Map.Strict ((!)) -import Linear (V2(..), (^+^), (^-^), (*^), (*^)) +import Linear (V2(..), (^+^), (*^)) import Linear.Metric (norm) import Data.List import Data.Ord - -type Bounds = (Int, Int) -type Position = V2 Int -type Delta = V2 (Ratio Int) +type Bounds = (Integer, Integer) +type Position = V2 Rational type Asteroids = S.Set Position @@ -30,12 +27,14 @@ main = do print $ part2 targets -part2 targets = 100 * x + y +part2 targets = numerator $ 100 * x + y where V2 x y = (targetSequence targets)!!199 bestVisible :: Bounds -> Asteroids -> (Position, Int) -bestVisible bounds asteroids = maximumBy (comparing snd) $ S.toList $ S.map (visibleCount bounds asteroids) asteroids +bestVisible bounds asteroids = maximumBy (comparing snd) + $ S.toList + $ S.map (visibleCount bounds asteroids) asteroids visibleCount :: Bounds -> Asteroids -> Position -> (Position, Int) visibleCount bounds asteroids origin = (origin, S.size $ visible bounds origin asteroids) @@ -53,22 +52,13 @@ screenings bounds origin@(V2 ox oy) screened0 target@(V2 tx ty) | origin == target = screened0 | otherwise = S.union screened0 screened where maxComponent = max (abs (tx - ox)) (abs (ty - oy)) - delta = V2 ((tx - ox) % maxComponent) ((ty - oy) % maxComponent) - startR = V2 (tx % 1) (ty % 1) - rawScreens = takeWhile (inBounds bounds) [startR ^+^ n *^ delta | n <- [1..]] - screens = filter isIntegral rawScreens - screenInteger = map integerVec screens - fullScreened = S.fromList screenInteger - screened = S.delete target fullScreened - -inBounds :: Bounds -> Delta -> Bool -inBounds (maxX, maxY) (V2 x y) = (x >= 0) && (x <= (maxX % 1)) && (y >= 0) && (y <= (maxY % 1)) + delta = V2 ((tx - ox) / maxComponent) ((ty - oy) / maxComponent) + rawScreens = takeWhile (inBounds bounds) [target ^+^ n *^ delta | n <- [1..]] + screened = S.fromList rawScreens -integerVec :: Delta -> Position -integerVec (V2 x y) = V2 (numerator x) (numerator y) +inBounds :: Bounds -> Position -> Bool +inBounds (maxX, maxY) (V2 x y) = (x >= 0) && (x <= (maxX % 1)) && (y >= 0) && (y <= (maxY % 1)) -isIntegral :: Delta -> Bool -isIntegral (V2 x y) = (denominator x == 1) && (denominator y == 1) makeTargets :: Position -> Asteroids -> Targets @@ -78,16 +68,12 @@ makeTargets origin asteroids = S.foldl' addTarget M.empty asteroids targetInfo :: Position -> Position -> TargetInfo targetInfo origin target = (angle, range) where V2 dx dy = target - origin - angle = atan2 (fromIntegral dy) (fromIntegral dx) + angle = atan2 (fromRational dy) (fromRational dx) -- recipRange = 1 / (norm (V2 (fromIntegral dy) (fromIntegral dx))) - range = norm (V2 (fromIntegral dy) (fromIntegral dx)) + range = norm (V2 (fromRational dy) (fromRational dx)) -possibleTargets :: Float -> Targets -> Targets -possibleTargets angle targets = M.filterWithKey (\(a, _) _ -> a > angle) targets - -firstTarget :: Targets -> (TargetInfo, Position) -firstTarget targets = M.findMin targets +targetSequence :: Targets -> [Position] targetSequence targets = targetNext ((- pi / 2) - 0.001) targets targetNext :: Float -> Targets -> [Position] @@ -100,12 +86,18 @@ targetNext angle targets targets' = M.delete (targetAngle, targetRange) targets angle' = targetAngle +possibleTargets :: Float -> Targets -> Targets +possibleTargets angle targets = M.filterWithKey (\(a, _) _ -> a > angle) targets + +firstTarget :: Targets -> (TargetInfo, Position) +firstTarget targets = M.findMin targets + successfulParse :: String -> (Asteroids, Bounds) -successfulParse input = ( S.fromList [(V2 x y) | x <- [0..maxX], y <- [0..maxY] +successfulParse input = ( S.fromList [(V2 (fromIntegral x % 1) (fromIntegral y % 1)) | x <- [0..maxX], y <- [0..maxY] , isAsteroid x y ] - , (maxX, maxY) + , (fromIntegral maxX, fromIntegral maxY) ) where grid = lines input maxX = (length $ head grid) - 1 diff --git a/advent10/src/advent10i.hs b/advent10/src/advent10i.hs new file mode 100644 index 0000000..78a68af --- /dev/null +++ b/advent10/src/advent10i.hs @@ -0,0 +1,121 @@ +import Data.Ratio +import qualified Data.Set as S +import qualified Data.Map.Strict as M +-- import Data.Map.Strict ((!)) +-- import Linear (V2(..), (^+^), (^-^), (*^), (*^)) +import Linear (V2(..), (^+^), (*^)) +import Linear.Metric (norm) + +import Data.List +import Data.Ord + + +type Bounds = (Int, Int) +type Position = V2 Int +type Delta = V2 (Ratio Int) + +type Asteroids = S.Set Position + +type TargetInfo = (Float, Float) +type Targets = M.Map TargetInfo Position + +main :: IO () +main = do + text <- readFile "data/advent10.txt" + let (asteroids, bounds) = successfulParse text + -- print asteroids + let (monitor, visCount) = bestVisible bounds asteroids + print visCount -- part 1 + let targets = makeTargets monitor (S.delete monitor asteroids) + -- print targets + print $ part2 targets + + +part2 targets = 100 * x + y + where V2 x y = (targetSequence targets)!!199 + + +bestVisible :: Bounds -> Asteroids -> (Position, Int) +bestVisible bounds asteroids = maximumBy (comparing snd) $ S.toList $ S.map (visibleCount bounds asteroids) asteroids + +visibleCount :: Bounds -> Asteroids -> Position -> (Position, Int) +visibleCount bounds asteroids origin = (origin, S.size $ visible bounds origin asteroids) + +visible :: Bounds -> Position -> Asteroids -> Asteroids +visible bounds origin asteroids = S.delete origin $ S.difference asteroids screened + where screened = allScreenings bounds origin asteroids + +allScreenings :: Bounds -> Position -> Asteroids -> Asteroids +allScreenings bounds origin asteroids = S.foldl' (screenings bounds origin) S.empty asteroids + + +screenings :: Bounds -> Position -> Asteroids -> Position -> Asteroids +screenings bounds origin@(V2 ox oy) screened0 target@(V2 tx ty) + | origin == target = screened0 + | otherwise = S.union screened0 screened + where maxComponent = max (abs (tx - ox)) (abs (ty - oy)) + delta = V2 ((tx - ox) % maxComponent) ((ty - oy) % maxComponent) + startR = V2 (tx % 1) (ty % 1) + rawScreens = takeWhile (inBounds bounds) [startR ^+^ n *^ delta | n <- [1..]] + screens = filter isIntegral rawScreens + screenInteger = map integerVec screens + fullScreened = S.fromList screenInteger + screened = S.delete target fullScreened + +inBounds :: Bounds -> Delta -> Bool +inBounds (maxX, maxY) (V2 x y) = (x >= 0) && (x <= (maxX % 1)) && (y >= 0) && (y <= (maxY % 1)) + +integerVec :: Delta -> Position +integerVec (V2 x y) = V2 (numerator x) (numerator y) + +isIntegral :: Delta -> Bool +isIntegral (V2 x y) = (denominator x == 1) && (denominator y == 1) + + +makeTargets :: Position -> Asteroids -> Targets +makeTargets origin asteroids = S.foldl' addTarget M.empty asteroids + where addTarget m t = M.insert (targetInfo origin t) t m + +targetInfo :: Position -> Position -> TargetInfo +targetInfo origin target = (angle, range) + where V2 dx dy = target - origin + angle = atan2 (fromIntegral dy) (fromIntegral dx) + -- recipRange = 1 / (norm (V2 (fromIntegral dy) (fromIntegral dx))) + range = norm (V2 (fromIntegral dy) (fromIntegral dx)) + +possibleTargets :: Float -> Targets -> Targets +possibleTargets angle targets = M.filterWithKey (\(a, _) _ -> a > angle) targets + +firstTarget :: Targets -> (TargetInfo, Position) +firstTarget targets = M.findMin targets + +targetSequence targets = targetNext ((- pi / 2) - 0.001) targets + +targetNext :: Float -> Targets -> [Position] +targetNext angle targets + | M.null targets = [] + | M.null possibles = targetNext (- pi) targets + | otherwise = (target:(targetNext angle' targets')) + where possibles = possibleTargets angle targets + ((targetAngle, targetRange), target) = firstTarget possibles + targets' = M.delete (targetAngle, targetRange) targets + angle' = targetAngle + + +successfulParse :: String -> (Asteroids, Bounds) +successfulParse input = ( S.fromList [(V2 x y) | x <- [0..maxX], y <- [0..maxY] + , isAsteroid x y + ] + , (maxX, maxY) + ) + where grid = lines input + maxX = (length $ head grid) - 1 + maxY = (length grid) - 1 + isAsteroid x y = (grid!!y)!!x == '#' + + +showPattern (maxX, maxY) asteroids = unlines rows + where rows = [[cell x y | x <- [0..maxX]] | y <- [0..maxY] ] + cell x y = if S.member (V2 x y) asteroids then '#' else '.' + + \ No newline at end of file diff --git a/problems/day09.html b/problems/day09.html new file mode 100644 index 0000000..4895749 --- /dev/null +++ b/problems/day09.html @@ -0,0 +1,151 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> +<meta charset="utf-8"/> +<title>Day 9 - Advent of Code 2019</title> +<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]--> +<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'> +<link rel="stylesheet" type="text/css" href="/static/style.css?24"/> +<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/> +<link rel="shortcut icon" href="/favicon.png"/> +</head><!-- + + + + +Oh, hello! Funny seeing you here. + +I appreciate your enthusiasm, but you aren't going to find much down here. +There certainly aren't clues to any of the puzzles. The best surprises don't +even appear in the source until you unlock them for real. + +Please be careful with automated requests; I'm not a massive company, and I can +only take so much traffic. Please be considerate so that everyone gets to play. + +If you're curious about how Advent of Code works, it's running on some custom +Perl code. Other than a few integrations (auth, analytics, ads, social media), +I built the whole thing myself, including the design, animations, prose, and +all of the puzzles. + +The puzzles are most of the work; preparing a new calendar and a new set of +puzzles each year takes all of my free time for 4-5 months. A lot of effort +went into building this thing - I hope you're enjoying playing it as much as I +enjoyed making it for you! + +If you'd like to hang out, I'm @ericwastl on Twitter. + +- Eric Wastl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--> +<body> +<header><div><h1 class="title-global"><a href="/">Advent of Code</a></h1><nav><ul><li><a href="/2019/about">[About]</a></li><li><a href="/2019/events">[Events]</a></li><li><a href="https://teespring.com/adventofcode-2019" target="_blank">[Shop]</a></li><li><a href="/2019/settings">[Settings]</a></li><li><a href="/2019/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2019/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <span class="star-count">20*</span></div></div><div><h1 class="title-event"> <span class="title-event-wrap">var y=</span><a href="/2019">2019</a><span class="title-event-wrap">;</span></h1><nav><ul><li><a href="/2019">[Calendar]</a></li><li><a href="/2019/support">[AoC++]</a></li><li><a href="/2019/sponsors">[Sponsors]</a></li><li><a href="/2019/leaderboard">[Leaderboard]</a></li><li><a href="/2019/stats">[Stats]</a></li></ul></nav></div></header> + +<div id="sidebar"> +<div id="sponsor"><div class="quiet">Our <a href="/2019/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://www.ing.jobs/Global/Careers/expertise/Tech.htm" target="_blank" onclick="if(ga)ga('send','event','sponsor','sidebar',this.href);" rel="noopener">ING</a> - Tech is simply at the core of what we do.</div></div> +</div><!--/sidebar--> + +<main> +<script>window.addEventListener('click', function(e,s,r){if(e.target.nodeName==='CODE'&&e.detail===3){s=window.getSelection();s.removeAllRanges();r=document.createRange();r.selectNodeContents(e.target);s.addRange(r);}});</script> +<article class="day-desc"><h2>--- Day 9: Sensor Boost ---</h2><p>You've just said goodbye to the rebooted rover and left Mars when you receive a faint distress signal coming from the asteroid belt. It must be the Ceres monitoring station!</p> +<p>In order to lock on to the signal, you'll need to boost your sensors. The Elves send up the latest <em>BOOST</em> program - Basic Operation Of System Test.</p> +<p>While BOOST (your puzzle input) is capable of boosting your sensors, for <span title="Oh sure, NOW safety is a priority.">tenuous safety reasons</span>, it refuses to do so until the computer it runs on passes some checks to demonstrate it is a <em>complete Intcode computer</em>.</p> +<p><a href="5">Your existing Intcode computer</a> is missing one key feature: it needs support for parameters in <em>relative mode</em>.</p> +<p>Parameters in mode <code>2</code>, <em>relative mode</em>, behave very similarly to parameters in <em>position mode</em>: the parameter is interpreted as a position. Like position mode, parameters in relative mode can be read from or written to.</p> +<p>The important difference is that relative mode parameters don't count from address <code>0</code>. Instead, they count from a value called the <em>relative base</em>. The <em>relative base</em> starts at <code>0</code>.</p> +<p>The address a relative mode parameter refers to is itself <em>plus</em> the current <em>relative base</em>. When the relative base is <code>0</code>, relative mode parameters and position mode parameters with the same value refer to the same address.</p> +<p>For example, given a relative base of <code>50</code>, a relative mode parameter of <code>-7</code> refers to memory address <code>50 + -7 = <em>43</em></code>.</p> +<p>The relative base is modified with the <em>relative base offset</em> instruction:</p> +<ul> +<li>Opcode <code>9</code> <em>adjusts the relative base</em> by the value of its only parameter. The relative base increases (or decreases, if the value is negative) by the value of the parameter.</li> +</ul> +<p>For example, if the relative base is <code>2000</code>, then after the instruction <code>109,19</code>, the relative base would be <code>2019</code>. If the next instruction were <code>204,-34</code>, then the value at address <code>1985</code> would be output.</p> +<p>Your Intcode computer will also need a few other capabilities:</p> +<ul> +<li>The computer's available memory should be much larger than the initial program. Memory beyond the initial program starts with the value <code>0</code> and can be read or written like any other memory. (It is invalid to try to access memory at a negative address, though.)</li> +<li>The computer should have support for large numbers. Some instructions near the beginning of the BOOST program will verify this capability.</li> +</ul> +<p>Here are some example programs that use these features:</p> +<ul> +<li><code>109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99</code> takes no input and produces a <a href="https://en.wikipedia.org/wiki/Quine_(computing)">copy of itself</a> as output.</li> +<li><code>1102,34915192,34915192,7,4,7,99,0</code> should output a 16-digit number.</li> +<li><code>104,1125899906842624,99</code> should output the large number in the middle.</li> +</ul> +<p>The BOOST program will ask for a single input; run it in test mode by providing it the value <code>1</code>. It will perform a series of checks on each opcode, output any opcodes (and the associated parameter modes) that seem to be functioning incorrectly, and finally output a BOOST keycode.</p> +<p>Once your Intcode computer is fully functional, the BOOST program should report no malfunctioning opcodes when run in test mode; it should only output a single value, the BOOST keycode. <em>What BOOST keycode does it produce?</em></p> +</article> +<p>Your puzzle answer was <code>3340912345</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p><em>You now have a complete Intcode computer.</em></p> +<p>Finally, you can lock on to the Ceres distress signal! You just need to boost your sensors using the BOOST program.</p> +<p>The program runs in sensor boost mode by providing the input instruction the value <code>2</code>. Once run, it will boost the sensors automatically, but it might take a few seconds to complete the operation on slower hardware. In sensor boost mode, the program will output a single value: <em>the coordinates of the distress signal</em>.</p> +<p>Run the BOOST program in sensor boost mode. <em>What are the coordinates of the distress signal?</em></p> +</article> +<p>Your puzzle answer was <code>51754</code>.</p><p class="day-success">Both parts of this puzzle are complete! They provide two gold stars: **</p> +<p>At this point, you should <a href="/2019">return to your Advent calendar</a> and try another puzzle.</p> +<p>If you still want to see it, you can <a href="9/input" target="_blank">get your puzzle input</a>.</p> +<p>You can also <span class="share">[Share<span class="share-content">on + <a href="https://twitter.com/intent/tweet?text=I%27ve+completed+%22Sensor+Boost%22+%2D+Day+9+%2D+Advent+of+Code+2019&url=https%3A%2F%2Fadventofcode%2Ecom%2F2019%2Fday%2F9&related=ericwastl&hashtags=AdventOfCode" target="_blank">Twitter</a> + <a href="javascript:void(0);" onclick="var mastodon_instance=prompt('Mastodon Instance / Server Name?'); if(typeof mastodon_instance==='string' && mastodon_instance.length){this.href='https://'+mastodon_instance+'/share?text=I%27ve+completed+%22Sensor+Boost%22+%2D+Day+9+%2D+Advent+of+Code+2019+%23AdventOfCode+https%3A%2F%2Fadventofcode%2Ecom%2F2019%2Fday%2F9'}else{return false;}" target="_blank">Mastodon</a +></span>]</span> this puzzle.</p> +</main> + +<!-- ga --> +<script> +(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ +(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), +m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) +})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); +ga('create', 'UA-69522494-1', 'auto'); +ga('set', 'anonymizeIp', true); +ga('send', 'pageview'); +</script> +<!-- /ga --> +</body> +</html> \ No newline at end of file diff --git a/problems/day10.html b/problems/day10.html new file mode 100644 index 0000000..93130dd --- /dev/null +++ b/problems/day10.html @@ -0,0 +1,267 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> +<meta charset="utf-8"/> +<title>Day 10 - Advent of Code 2019</title> +<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]--> +<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'> +<link rel="stylesheet" type="text/css" href="/static/style.css?24"/> +<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/> +<link rel="shortcut icon" href="/favicon.png"/> +</head><!-- + + + + +Oh, hello! Funny seeing you here. + +I appreciate your enthusiasm, but you aren't going to find much down here. +There certainly aren't clues to any of the puzzles. The best surprises don't +even appear in the source until you unlock them for real. + +Please be careful with automated requests; I'm not a massive company, and I can +only take so much traffic. Please be considerate so that everyone gets to play. + +If you're curious about how Advent of Code works, it's running on some custom +Perl code. Other than a few integrations (auth, analytics, ads, social media), +I built the whole thing myself, including the design, animations, prose, and +all of the puzzles. + +The puzzles are most of the work; preparing a new calendar and a new set of +puzzles each year takes all of my free time for 4-5 months. A lot of effort +went into building this thing - I hope you're enjoying playing it as much as I +enjoyed making it for you! + +If you'd like to hang out, I'm @ericwastl on Twitter. + +- Eric Wastl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--> +<body> +<header><div><h1 class="title-global"><a href="/">Advent of Code</a></h1><nav><ul><li><a href="/2019/about">[About]</a></li><li><a href="/2019/events">[Events]</a></li><li><a href="https://teespring.com/adventofcode-2019" target="_blank">[Shop]</a></li><li><a href="/2019/settings">[Settings]</a></li><li><a href="/2019/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2019/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <span class="star-count">20*</span></div></div><div><h1 class="title-event"> <span class="title-event-wrap">0x0000|</span><a href="/2019">2019</a><span class="title-event-wrap"></span></h1><nav><ul><li><a href="/2019">[Calendar]</a></li><li><a href="/2019/support">[AoC++]</a></li><li><a href="/2019/sponsors">[Sponsors]</a></li><li><a href="/2019/leaderboard">[Leaderboard]</a></li><li><a href="/2019/stats">[Stats]</a></li></ul></nav></div></header> + +<div id="sidebar"> +<div id="sponsor"><div class="quiet">Our <a href="/2019/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://www.codethink.co.uk/" target="_blank" onclick="if(ga)ga('send','event','sponsor','sidebar',this.href);" rel="noopener">Codethink Ltd.</a> - Codethink is a software services company, expert in the use of Open Source technologies for systems software engineering.</div></div> +</div><!--/sidebar--> + +<main> +<script>window.addEventListener('click', function(e,s,r){if(e.target.nodeName==='CODE'&&e.detail===3){s=window.getSelection();s.removeAllRanges();r=document.createRange();r.selectNodeContents(e.target);s.addRange(r);}});</script> +<article class="day-desc"><h2>--- Day 10: Monitoring Station ---</h2><p>You fly into the asteroid belt and reach the Ceres monitoring station. The Elves here have an emergency: they're having trouble tracking all of the asteroids and can't be sure they're safe.</p> +<p>The Elves would like to build a new monitoring station in a nearby area of space; they hand you a map of all of the asteroids in that region (your puzzle input).</p> +<p>The map indicates whether each position is empty (<code>.</code>) or contains an asteroid (<code>#</code>). The asteroids are much smaller than they appear on the map, and every asteroid is exactly in the center of its marked position. The asteroids can be described with <code>X,Y</code> coordinates where <code>X</code> is the distance from the left edge and <code>Y</code> is the distance from the top edge (so the top-left corner is <code>0,0</code> and the position immediately to its right is <code>1,0</code>).</p> +<p>Your job is to figure out which asteroid would be the best place to build a <em>new monitoring station</em>. A monitoring station can <em>detect</em> any asteroid to which it has <em>direct line of sight</em> - that is, there cannot be another asteroid <em>exactly</em> between them. This line of sight can be at any angle, not just lines aligned to the grid or <span title="The Elves on Ceres are clearly not concerned with honor.">diagonally</span>. The <em>best</em> location is the asteroid that can <em>detect</em> the largest number of other asteroids.</p> +<p>For example, consider the following map:</p> +<pre><code>.#..# +..... +##### +....# +...<em>#</em># +</code></pre> +<p>The best location for a new monitoring station on this map is the highlighted asteroid at <code>3,4</code> because it can detect <code>8</code> asteroids, more than any other location. (The only asteroid it cannot detect is the one at <code>1,0</code>; its view of this asteroid is blocked by the asteroid at <code>2,2</code>.) All other asteroids are worse locations; they can detect <code>7</code> or fewer other asteroids. Here is the number of other asteroids a monitoring station on each asteroid could detect:</p> +<pre><code>.7..7 +..... +67775 +....7 +...87 +</code></pre> +<p>Here is an asteroid (<code>#</code>) and some examples of the ways its line of sight might be blocked. If there were another asteroid at the location of a capital letter, the locations marked with the corresponding lowercase letter would be blocked and could not be detected:</p> +<pre><code>#......... +...A...... +...B..a... +.EDCG....a +..F.c.b... +.....c.... +..efd.c.gb +.......c.. +....f...c. +...e..d..c +</code></pre> +<p>Here are some larger examples:</p> +<ul> +<li><p>Best is <code>5,8</code> with <code>33</code> other asteroids detected:</p> +<pre><code>......#.#. +#..#.#.... +..#######. +.#.#.###.. +.#..#..... +..#....#.# +#..#....#. +.##.#..### +##...<em>#</em>..#. +.#....#### +</code></pre></li> +<li><p>Best is <code>1,2</code> with <code>35</code> other asteroids detected:</p> +<pre><code>#.#...#.#. +.###....#. +.<em>#</em>....#... +##.#.#.#.# +....#.#.#. +.##..###.# +..#...##.. +..##....## +......#... +.####.###. +</code></pre></li> +<li><p>Best is <code>6,3</code> with <code>41</code> other asteroids detected:</p> +<pre><code>.#..#..### +####.###.# +....###.#. +..###.<em>#</em>#.# +##.##.#.#. +....###..# +..#.#..#.# +#..#.#.### +.##...##.# +.....#.#.. +</code></pre></li> +<li><p>Best is <code>11,13</code> with <code>210</code> other asteroids detected:</p> +<pre><code>.#..##.###...####### +##.############..##. +.#.######.########.# +.###.#######.####.#. +#####.##.#.##.###.## +..#####..#.######### +#################### +#.####....###.#.#.## +##.################# +#####.##.###..####.. +..######..##.####### +####.##.####...##..# +.#####..#.######.### +##...#.####<em>#</em>#####... +#.##########.####### +.####.#.###.###.#.## +....##.##.###..##### +.#.#.###########.### +#.#.#.#####.####.### +###.##.####.##.#..## +</code></pre></li> +</ul> +<p>Find the best location for a new monitoring station. <em>How many other asteroids can be detected from that location?</em></p> +</article> +<p>Your puzzle answer was <code>221</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p>Once you give them the coordinates, the Elves quickly deploy an Instant Monitoring Station to the location and discover <span title="The Elves on Ceres just have a unique system of values, that's all.">the worst</span>: there are simply too many asteroids.</p> +<p>The only solution is <em>complete vaporization by giant laser</em>.</p> +<p>Fortunately, in addition to an asteroid scanner, the new monitoring station also comes equipped with a giant rotating laser perfect for vaporizing asteroids. The laser starts by pointing <em>up</em> and always rotates <em>clockwise</em>, vaporizing any asteroid it hits.</p> +<p>If multiple asteroids are <em>exactly</em> in line with the station, the laser only has enough power to vaporize <em>one</em> of them before continuing its rotation. In other words, the same asteroids that can be <em>detected</em> can be vaporized, but if vaporizing one asteroid makes another one detectable, the newly-detected asteroid won't be vaporized until the laser has returned to the same position by rotating a full 360 degrees.</p> +<p>For example, consider the following map, where the asteroid with the new monitoring station (and laser) is marked <code>X</code>:</p> +<pre><code>.#....#####...#.. +##...##.#####..## +##...#...#.#####. +..#.....X...###.. +..#.#.....#....## +</code></pre> +<p>The first nine asteroids to get vaporized, in order, would be:</p> +<pre><code>.#....###<em>2</em><em>4</em>...#.. +##...##.<em>1</em><em>3</em>#<em>6</em><em>7</em>..<em>9</em># +##...#...<em>5</em>.<em>8</em>####. +..#.....X...###.. +..#.#.....#....## +</code></pre> +<p>Note that some asteroids (the ones behind the asteroids marked <code>1</code>, <code>5</code>, and <code>7</code>) won't have a chance to be vaporized until the next full rotation. The laser continues rotating; the next nine to be vaporized are:</p> +<pre><code>.#....###.....#.. +##...##...#.....# +##...#......<em>1</em><em>2</em><em>3</em><em>4</em>. +..#.....X...<em>5</em>##.. +..#.<em>9</em>.....<em>8</em>....<em>7</em><em>6</em> +</code></pre> +<p>The next nine to be vaporized are then:</p> +<pre><code>.<em>8</em>....###.....#.. +<em>5</em><em>6</em>...<em>9</em>#...#.....# +<em>3</em><em>4</em>...<em>7</em>........... +..<em>2</em>.....X....##.. +..<em>1</em>.............. +</code></pre> +<p>Finally, the laser completes its first full rotation (<code>1</code> through <code>3</code>), a second rotation (<code>4</code> through <code>8</code>), and vaporizes the last asteroid (<code>9</code>) partway through its third rotation:</p> +<pre><code>......<em>2</em><em>3</em><em>4</em>.....<em>6</em>.. +......<em>1</em>...<em>5</em>.....<em>7</em> +................. +........X....<em>8</em><em>9</em>.. +................. +</code></pre> +<p>In the large example above (the one with the best monitoring station location at <code>11,13</code>):</p> +<ul> +<li>The 1st asteroid to be vaporized is at <code>11,12</code>.</li> +<li>The 2nd asteroid to be vaporized is at <code>12,1</code>.</li> +<li>The 3rd asteroid to be vaporized is at <code>12,2</code>.</li> +<li>The 10th asteroid to be vaporized is at <code>12,8</code>.</li> +<li>The 20th asteroid to be vaporized is at <code>16,0</code>.</li> +<li>The 50th asteroid to be vaporized is at <code>16,9</code>.</li> +<li>The 100th asteroid to be vaporized is at <code>10,16</code>.</li> +<li>The 199th asteroid to be vaporized is at <code>9,6</code>.</li> +<li><em>The 200th asteroid to be vaporized is at <code>8,2</code>.</em></li> +<li>The 201st asteroid to be vaporized is at <code>10,9</code>.</li> +<li>The 299th and final asteroid to be vaporized is at <code>11,1</code>.</li> +</ul> +<p>The Elves are placing bets on which will be the <em>200th</em> asteroid to be vaporized. Win the bet by determining which asteroid that will be; <em>what do you get if you multiply its X coordinate by <code>100</code> and then add its Y coordinate?</em> (For example, <code>8,2</code> becomes <em><code>802</code></em>.)</p> +</article> +<p>Your puzzle answer was <code>806</code>.</p><p class="day-success">Both parts of this puzzle are complete! They provide two gold stars: **</p> +<p>At this point, you should <a href="/2019">return to your Advent calendar</a> and try another puzzle.</p> +<p>If you still want to see it, you can <a href="10/input" target="_blank">get your puzzle input</a>.</p> +<p>You can also <span class="share">[Share<span class="share-content">on + <a href="https://twitter.com/intent/tweet?text=I%27ve+completed+%22Monitoring+Station%22+%2D+Day+10+%2D+Advent+of+Code+2019&url=https%3A%2F%2Fadventofcode%2Ecom%2F2019%2Fday%2F10&related=ericwastl&hashtags=AdventOfCode" target="_blank">Twitter</a> + <a href="javascript:void(0);" onclick="var mastodon_instance=prompt('Mastodon Instance / Server Name?'); if(typeof mastodon_instance==='string' && mastodon_instance.length){this.href='https://'+mastodon_instance+'/share?text=I%27ve+completed+%22Monitoring+Station%22+%2D+Day+10+%2D+Advent+of+Code+2019+%23AdventOfCode+https%3A%2F%2Fadventofcode%2Ecom%2F2019%2Fday%2F10'}else{return false;}" target="_blank">Mastodon</a +></span>]</span> this puzzle.</p> +</main> + +<!-- ga --> +<script> +(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ +(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), +m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) +})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); +ga('create', 'UA-69522494-1', 'auto'); +ga('set', 'anonymizeIp', true); +ga('send', 'pageview'); +</script> +<!-- /ga --> +</body> +</html> \ No newline at end of file