Using just rationals for part 1.
authorNeil Smith <neil.git@njae.me.uk>
Wed, 11 Dec 2019 17:48:15 +0000 (17:48 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Wed, 11 Dec 2019 17:48:15 +0000 (17:48 +0000)
advent10/package.yaml
advent10/src/advent10.hs
advent10/src/advent10i.hs [new file with mode: 0644]
problems/day09.html [new file with mode: 0644]
problems/day10.html [new file with mode: 0644]

index 75a923ba53d3f21a47a85687a5f9ae32fc04047c..9069b19864f1876fa8622df3a87fb1ee46f7177b 100644 (file)
@@ -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
index 95c02870fec114a547d37631cdd4c154f14a0fb8..ba90ba1429788b160e2b4aaaa95eeb7b03075b7f 100644 (file)
@@ -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 (file)
index 0000000..78a68af
--- /dev/null
@@ -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 (file)
index 0000000..4895749
--- /dev/null
@@ -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">&nbsp;&nbsp;&nbsp;<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&amp;url=https%3A%2F%2Fadventofcode%2Ecom%2F2019%2Fday%2F9&amp;related=ericwastl&amp;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 (file)
index 0000000..93130dd
--- /dev/null
@@ -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">&nbsp;&nbsp;&nbsp;<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&amp;url=https%3A%2F%2Fadventofcode%2Ecom%2F2019%2Fday%2F10&amp;related=ericwastl&amp;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