, megaparsec
, containers
, pointedlist
+
+executable advent10
+ hs-source-dirs: src/advent10
+ main-is: advent10.hs
+ default-language: Haskell2010
+ build-depends: base >= 4.7 && < 5
+ , text
+ , megaparsec
+ , containers
+
+executable advent10iz
+ hs-source-dirs: src/advent10
+ main-is: advent10-iterate-zip.hs
+ default-language: Haskell2010
+ build-depends: base >= 4.7 && < 5
+ , text
+ , megaparsec
+ , containers
+
+executable advent11
+ hs-source-dirs: src/advent11
+ main-is: advent11.hs
+ default-language: Haskell2010
+ build-depends: base >= 4.7 && < 5
+ , containers
+
+executable advent11m
+ hs-source-dirs: src/advent11
+ main-is: advent11-map.hs
+ default-language: Haskell2010
+ build-depends: base >= 4.7 && < 5
+ , containers
+
+executable advent11naive
+ hs-source-dirs: src/advent11
+ main-is: advent11-naive.hs
+ default-language: Haskell2010
+ build-depends: base >= 4.7 && < 5
+ , containers
--- /dev/null
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 11 - Advent of Code 2018</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?18"/>
+<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 Google, 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; the easiest ones take 3-4 hours each, but the
+harder ones take 6-8 hours, and a few even longer than that. 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="/2018/about">[About]</a></li><li><a href="/2018/events">[Events]</a></li><li><a href="https://teespring.com/adventofcode" target="_blank">[Shop]</a></li><li><a href="/2018/settings">[Settings]</a></li><li><a href="/2018/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2018/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <span class="star-count">22*</span></div></div><div><h1 class="title-event"> <span class="title-event-wrap">{year=></span><a href="/2018">2018</a><span class="title-event-wrap">}</span></h1><nav><ul><li><a href="/2018">[Calendar]</a></li><li><a href="/2018/support">[AoC++]</a></li><li><a href="/2018/sponsors">[Sponsors]</a></li><li><a href="/2018/leaderboard">[Leaderboard]</a></li><li><a href="/2018/stats">[Stats]</a></li></ul></nav></div></header>
+
+<div id="sidebar">
+<div id="sponsor"><div class="quiet">Our <a href="/2018/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://clubhouse.io/?utm_source=spon&utm_medium=ch&utm_campaign=aoc2018" target="_blank" onclick="if(ga)ga('send','event','sponsor','click',this.href);" rel="noopener">Clubhouse</a> - The first project management platform for software development that brings everyone on every team together to build better products. AoC participants get two free months by signing up at r.clbh.se/mze9q9P Also, we're hiring!</div></div>
+</div><!--/sidebar-->
+
+<main>
+<article class="day-desc"><h2>--- Day 11: Chronal Charge ---</h2><p>You watch the Elves and their sleigh fade into the distance as they head toward the North Pole.</p>
+<p>Actually, you're the one fading. The <span title="wheeeeeeeeeeeeeeeeee">falling sensation</span> returns.</p>
+<p>The low fuel warning light is illuminated on your wrist-mounted device. Tapping it once causes it to project a hologram of the situation: a <em>300x300</em> grid of fuel cells and their current power levels, some negative. You're not sure what negative power means in the context of time travel, but it can't be good.</p>
+<p>Each fuel cell has a coordinate ranging <em>from 1 to 300</em> in both the X (horizontal) and Y (vertical) direction. In <code>X,Y</code> notation, the top-left cell is <code>1,1</code>, and the top-right cell is <code>300,1</code>.</p>
+<p>The interface lets you select <em>any 3x3 square</em> of fuel cells. To increase your chances of getting to your destination, you decide to choose the 3x3 square with the <em>largest total power</em>.</p>
+<p>The power level in a given fuel cell can be found through the following process:</p>
+<ul>
+<li>Find the fuel cell's <em>rack ID</em>, which is its <em>X coordinate plus 10</em>.</li>
+<li>Begin with a power level of the <em>rack ID</em> times the <em>Y coordinate</em>.</li>
+<li>Increase the power level by the value of the <em>grid serial number</em> (your puzzle input).</li>
+<li>Set the power level to itself multiplied by the <em>rack ID</em>.</li>
+<li>Keep only the <em>hundreds digit</em> of the power level (so <code>12<em>3</em>45</code> becomes <code>3</code>; numbers with no hundreds digit become <code>0</code>).</li>
+<li><em>Subtract 5</em> from the power level.</li>
+</ul>
+<p>For example, to find the power level of the fuel cell at <code>3,5</code> in a grid with serial number <code>8</code>:</p>
+<ul>
+<li>The rack ID is <code>3 + 10 = <em>13</em></code>.</li>
+<li>The power level starts at <code>13 * 5 = <em>65</em></code>.</li>
+<li>Adding the serial number produces <code>65 + 8 = <em>73</em></code>.</li>
+<li>Multiplying by the rack ID produces <code>73 * 13 = <em>949</em></code>.</li>
+<li>The hundreds digit of <code><em>9</em>49</code> is <code><em>9</em></code>.</li>
+<li>Subtracting 5 produces <code>9 - 5 = <em>4</em></code>.</li>
+</ul>
+<p>So, the power level of this fuel cell is <code><em>4</em></code>.</p>
+<p>Here are some more example power levels:</p>
+<ul>
+<li>Fuel cell at <code>122,79</code>, grid serial number <code>57</code>: power level <code>-5</code>.</li>
+<li>Fuel cell at <code>217,196</code>, grid serial number <code>39</code>: power level <code>0</code>.</li>
+<li>Fuel cell at <code>101,153</code>, grid serial number <code>71</code>: power level <code>4</code>.</li>
+</ul>
+<p>Your goal is to find the 3x3 square which has the largest total power. The square must be entirely within the 300x300 grid. Identify this square using the <code>X,Y</code> coordinate of its <em>top-left fuel cell</em>. For example:</p>
+<p>For grid serial number <code>18</code>, the largest total 3x3 square has a top-left corner of <code><em>33,45</em></code> (with a total power of <code>29</code>); these fuel cells appear in the middle of this 5x5 region:</p>
+<pre><code>-2 -4 4 4 4
+-4 <em> 4 4 4 </em>-5
+ 4 <em> 3 3 4 </em>-4
+ 1 <em> 1 2 4 </em>-3
+-1 0 2 -5 -2
+</code></pre>
+<p>For grid serial number <code>42</code>, the largest 3x3 square's top-left is <code><em>21,61</em></code> (with a total power of <code>30</code>); they are in the middle of this region:</p>
+<pre><code>-3 4 2 2 2
+-4 <em> 4 3 3 </em> 4
+-5 <em> 3 3 4 </em>-4
+ 4 <em> 3 3 4 </em>-3
+ 3 3 3 -5 -1
+</code></pre>
+<p><em>What is the <code>X,Y</code> coordinate of the top-left fuel cell of the 3x3 square with the largest total power?</em></p>
+</article>
+<p>Your puzzle answer was <code>21,34</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p>You discover a dial on the side of the device; it seems to let you select a square of <em>any size</em>, not just 3x3. Sizes from 1x1 to 300x300 are supported.</p>
+<p>Realizing this, you now must find the <em>square of any size with the largest total power</em>. Identify this square by including its size as a third parameter after the top-left coordinate: a 9x9 square with a top-left corner of <code>3,5</code> is identified as <code>3,5,9</code>.</p>
+<p>For example:</p>
+<ul>
+<li>For grid serial number <code>18</code>, the largest total square (with a total power of <code>113</code>) is 16x16 and has a top-left corner of <code>90,269</code>, so its identifier is <code><em>90,269,16</em></code>.</li>
+<li>For grid serial number <code>42</code>, the largest total square (with a total power of <code>119</code>) is 12x12 and has a top-left corner of <code>232,251</code>, so its identifier is <code><em>232,251,12</em></code>.</li>
+</ul>
+<p><em>What is the <code>X,Y,size</code> identifier of the square with the largest total power?</em></p>
+</article>
+<p>Your puzzle answer was <code>90,244,16</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="/2018">return to your advent calendar</a> and try another puzzle.</p>
+<p>Your puzzle input was <code class="puzzle-input">5719</code>.</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+%22Chronal+Charge%22+%2D+Day+11+%2D+Advent+of+Code+2018&url=https%3A%2F%2Fadventofcode%2Ecom%2F2018%2Fday%2F11&related=ericwastl&hashtags=AdventOfCode" target="_blank">Twitter</a>
+ <a href="http://www.reddit.com/submit?url=https%3A%2F%2Fadventofcode%2Ecom%2F2018%2Fday%2F11&title=I%27ve+completed+%22Chronal+Charge%22+%2D+Day+11+%2D+Advent+of+Code+2018" target="_blank">Reddit</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('send', 'pageview');
+</script>
+<!-- /ga -->
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+{-# LANGUAGE OverloadedStrings #-}
+
+import Data.List
+import qualified Data.Map.Strict as M
+-- import Data.Map.Strict ((!))
+-- import qualified Data.Set as S
+-- import Data.Function (on)
+import Data.Ord (comparing)
+
+type Coord = (Integer, Integer) -- x, y
+type Grid = M.Map Coord Integer
+
+key = 5719
+-- key = 42
+
+main :: IO ()
+main = do
+ let g = makeGrid key
+ print $ part1 g
+ print $ part2 g
+
+
+part1 grid = keyOfMaxValue sg
+ where sg = allSubCellPower 3 grid
+
+
+part2 grid = maximumBy (comparing snd) $ [bestInGrid size grid | size <- [3..300]]
+
+-- bestSubCell size grid =
+
+makeGrid :: Integer -> Grid
+makeGrid key = M.fromList [((x, y), powerLevel x y key) | x <- [1..300], y <- [1..300] ]
+
+powerLevel :: Integer -> Integer -> Integer -> Integer
+powerLevel x y key = ((interim `div` 100) `mod` 10) - 5
+ where rackID = x + 10
+ interim = ((rackID) * y + key) * rackID
+
+subCellPower :: Integer -> Integer -> Integer -> Grid -> Integer
+subCellPower size x y grid = M.foldr (+) 0 subGrid
+ where subGrid = M.filterWithKey inBounds grid
+ inBounds (kx, ky) _ = (kx >= x) && (kx < x+size) && (ky >= y) && (ky < y+size)
+
+allSubCellPower :: Integer -> Grid -> Grid
+allSubCellPower size grid = M.fromList [((x, y), subCellPower size x y grid)| x <- [1..(301-size)], y <- [1..(301-size)]]
+
+
+keyAndMaxValue :: Ord b => M.Map a b -> (a, b)
+keyAndMaxValue m = M.foldrWithKey mergeKV (M.findMin m) m
+ where mergeKV k v (bestK, bestV) =
+ if v > bestV then (k, v) else (bestK, bestV)
+
+keyOfMaxValue :: Ord b => M.Map a b -> a
+keyOfMaxValue m = fst $ keyAndMaxValue m
+
+bestInGrid :: Integer -> Grid -> ((Integer, Integer, Integer), Integer)
+bestInGrid size grid = ((x, y, size), p)
+ where ((x, y), p) = keyAndMaxValue $ allSubCellPower size grid
--- /dev/null
+{-# LANGUAGE OverloadedStrings #-}
+
+import Data.List
+import qualified Data.Map.Strict as M
+import Data.Map.Strict ((!))
+-- import qualified Data.Set as S
+-- import Data.Function (on)
+import Data.Ord (comparing)
+
+type Coord = (Integer, Integer) -- x, y
+type Grid = M.Map Coord Integer
+
+key = 5719
+-- key = 42
+
+main :: IO ()
+main = do
+ let g = makeGrid key
+ print $ part1 g
+ print $ part2 g
+
+
+part1 grid = keyOfMaxValue sg
+ where sg = allSubCellPower 3 grid
+
+
+part2 grid = maximumBy (comparing snd) $ [bestInGrid size grid | size <- [3..300]]
+
+-- bestSubCell size grid =
+
+makeGrid :: Integer -> Grid
+makeGrid key = M.fromList [((x, y), powerLevel x y key) | x <- [1..300], y <- [1..300] ]
+
+powerLevel :: Integer -> Integer -> Integer -> Integer
+powerLevel x y key = ((interim `div` 100) `mod` 10) - 5
+ where rackID = x + 10
+ interim = ((rackID) * y + key) * rackID
+
+subCellPower :: Integer -> Integer -> Integer -> Grid -> Integer
+subCellPower size x y grid = sum [grid!(sx, sy) | sx <- [x..(x+size-1)], sy <- [y..(y+size-1)]]
+
+allSubCellPower :: Integer -> Grid -> Grid
+allSubCellPower size grid = M.fromList [((x, y), subCellPower size x y grid)| x <- [1..(301-size)], y <- [1..(301-size)]]
+
+
+keyAndMaxValue :: Ord b => M.Map a b -> (a, b)
+keyAndMaxValue m = M.foldrWithKey mergeKV (M.findMin m) m
+ where mergeKV k v (bestK, bestV) =
+ if v > bestV then (k, v) else (bestK, bestV)
+
+keyOfMaxValue :: Ord b => M.Map a b -> a
+keyOfMaxValue m = fst $ keyAndMaxValue m
+
+bestInGrid :: Integer -> Grid -> ((Integer, Integer, Integer), Integer)
+bestInGrid size grid = ((x, y, size), p)
+ where ((x, y), p) = keyAndMaxValue $ allSubCellPower size grid
--- /dev/null
+{-# LANGUAGE OverloadedStrings #-}
+
+-- Using a summed-area table, e.g. see https://en.wikipedia.org/wiki/Summed-area_table
+
+import Data.List
+import qualified Data.Map.Strict as M
+import Data.Map.Strict ((!))
+-- import qualified Data.Set as S
+-- import Data.Function (on)
+import Data.Ord (comparing)
+
+type Coord = (Integer, Integer) -- x, y
+type Grid = M.Map Coord Integer
+
+key = 5719
+-- key = 42
+
+main :: IO ()
+main = do
+ let g = makeGrid key
+ print $ part1 g
+ print $ part2 g
+
+
+part1 grid = keyOfMaxValue sg
+ where sg = allSubCellPower 3 grid
+
+
+part2 grid = maximumBy (comparing snd) $ [bestInGrid size grid | size <- [3..300]]
+
+-- bestSubCell size grid =
+
+makeGrid :: Integer -> Grid
+-- makeGrid key = M.fromList [((x, y), powerLevel x y key) | x <- [1..300], y <- [1..300] ]
+makeGrid key = foldl' addSummedArea M.empty [((x, y), powerLevel x y key) | x <- [0..300], y <- [0..300] ]
+
+addSummedArea :: Grid -> ((Integer, Integer), Integer) -> Grid
+addSummedArea grid ((x, y), power) = M.insert (x, y) (power + upper + left - upperLeft) grid
+ where upper = M.findWithDefault 0 (x-1, y) grid
+ left = M.findWithDefault 0 (x, y-1) grid
+ upperLeft = M.findWithDefault 0 (x-1, y-1) grid
+
+
+powerLevel :: Integer -> Integer -> Integer -> Integer
+powerLevel 0 y _ = 0
+powerLevel x 0 _ = 0
+powerLevel x y key = ((interim `div` 100) `mod` 10) - 5
+ where rackID = x + 10
+ interim = ((rackID) * y + key) * rackID
+
+subCellPower :: Integer -> Integer -> Integer -> Grid -> Integer
+-- subCellPower size x y grid = sum [grid!(sx, sy) | sx <- [x..(x+size-1)], sy <- [y..(y+size-1)]]
+subCellPower size x0 y0 grid = grid!(x,y) + grid!(x',y') - grid!(x,y') - grid!(x',y)
+ where x = x0 - 1
+ x' = x + size
+ y = y0 - 1
+ y' = y + size
+
+allSubCellPower :: Integer -> Grid -> Grid
+allSubCellPower size grid = M.fromList [((x, y), subCellPower size x y grid)| x <- [1..(301-size)], y <- [1..(301-size)]]
+
+
+keyAndMaxValue :: Ord b => M.Map a b -> (a, b)
+keyAndMaxValue m = M.foldrWithKey mergeKV (M.findMin m) m
+ where mergeKV k v (bestK, bestV) =
+ if v > bestV then (k, v) else (bestK, bestV)
+
+keyOfMaxValue :: Ord b => M.Map a b -> a
+keyOfMaxValue m = fst $ keyAndMaxValue m
+
+bestInGrid :: Integer -> Grid -> ((Integer, Integer, Integer), Integer)
+bestInGrid size grid = ((x, y, size), p)
+ where ((x, y), p) = keyAndMaxValue $ allSubCellPower size grid