-import Debug.Trace
+-- import Debug.Trace
import qualified Data.Set as S
main :: IO ()
main =
do grid0 <- readGrid
- print grid0
+ -- print grid0
let finalGrid = head $ drop 200 $ iterate update grid0
print $ S.size finalGrid
neighbourSpacesLeft :: Cell -> Grid
neighbourSpacesLeft (Cell {..})
- | column == 4 && row == 3 = S.fromList [ Cell { level = (level + 1), row = r, column = 5} | r <- [1..gridSize] ]
- | column == 1 = S.singleton ( Cell { level = (level - 1), row = 3, column = 2})
- | otherwise = S.singleton ( Cell { level, row, column = (column - 1)})
+ | column == 4 && row == 3 = S.fromList [ Cell { level = (level + 1),
+ row = r, column = 5}
+ | r <- [1..gridSize] ]
+ | column == 1 = S.singleton ( Cell { level = (level - 1),
+ row = 3, column = 2})
+ | otherwise = S.singleton ( Cell { column = (column - 1), ..})
neighbourSpacesRight :: Cell -> Grid
neighbourSpacesRight (Cell {..})
- | column == 2 && row == 3 = S.fromList [ Cell { level = (level + 1), row = r, column = 1} | r <- [1..gridSize] ]
- | column == 5 = S.singleton ( Cell { level = (level - 1), row = 3, column = 4})
- | otherwise = S.singleton ( Cell { level, row, column = (column + 1)})
+ | column == 2 && row == 3 = S.fromList [ Cell { level = (level + 1),
+ row = r, column = 1}
+ | r <- [1..gridSize] ]
+ | column == 5 = S.singleton ( Cell { level = (level - 1),
+ row = 3, column = 4})
+ | otherwise = S.singleton ( Cell { column = (column + 1), ..})
neighbourSpacesAbove :: Cell -> Grid
neighbourSpacesAbove (Cell {..})
- | row == 4 && column == 3 = S.fromList [ Cell { level = (level + 1), row = 5, column = c} | c <- [1..gridSize] ]
- | row == 1 = S.singleton ( Cell { level = (level - 1), row = 2, column = 3})
- | otherwise = S.singleton ( Cell { level, row = (row - 1), column})
+ | row == 4 && column == 3 = S.fromList [ Cell { level = (level + 1),
+ row = 5, column = c}
+ | c <- [1..gridSize] ]
+ | row == 1 = S.singleton ( Cell { level = (level - 1),
+ row = 2, column = 3})
+ | otherwise = S.singleton ( Cell { row = (row - 1), ..})
neighbourSpacesBelow :: Cell -> Grid
neighbourSpacesBelow (Cell {..})
- | row == 2 && column == 3 = S.fromList [ Cell { level = (level + 1), row = 1, column = c} | c <- [1..gridSize] ]
- | row == 5 = S.singleton ( Cell { level = (level - 1), row = 4, column = 3})
- | otherwise = S.singleton ( Cell { level, row = (row + 1), column})
+ | row == 2 && column == 3 = S.fromList [ Cell { level = (level + 1),
+ row = 1, column = c}
+ | c <- [1..gridSize] ]
+ | row == 5 = S.singleton ( Cell { level = (level - 1),
+ row = 4, column = 3})
+ | otherwise = S.singleton ( Cell { row = (row + 1), ..})
countOccupiedNeighbours :: Cell -> Grid -> Int
+++ /dev/null
-
--- import Debug.Trace
-
-
-import Data.Bool (bool)
-import Data.Distributive (Distributive(..))
-import Data.Functor.Rep (Representable(..), distributeRep)
-import Data.Functor.Identity (Identity(..))
-import Control.Comonad.Representable.Store (Store(..), StoreT(..), store, experiment, runStore)
-import Control.Comonad (Comonad(..))
-
-import Data.Maybe
-import Data.List
-import qualified Data.Set as S
-import qualified Data.Map as M
-
-import Control.Concurrent (threadDelay)
-import Control.Monad (forM_)
-
-import Control.Comonad
-import Control.Comonad.Cofree
-import Data.Distributive
-import Data.Functor.Rep
-import qualified Data.Sequence as Q
-import qualified Data.List.NonEmpty as NE
-
-
-data TPossible a = TPossible
- { leftward :: a
- , rightward :: a
- , above :: a
- , below :: a
- } deriving (Show, Eq, Functor)
-
-data TChoice = L | R | U | D
- deriving (Show, Eq)
-
-instance Distributive TPossible where
- distribute :: Functor f => f (TPossible a) -> TPossible (f a)
- distribute fga = TPossible (fmap leftward fga) (fmap rightward fga)
- (fmap above fga) (fmap below fga)
-
-instance Representable TPossible where
- type Rep TPossible = TChoice
-
- index :: TPossible a -> TChoice -> a
- index here L = leftward here
- index here R = rightward here
- index here U = above here
- index here D = below here
-
- tabulate :: (TChoice -> a) -> TPossible a
- tabulate describe = TPossible (describe L) (describe R)
- (describe U) (describe D)
-
-relativePosition :: Q.Seq TChoice -> Int
-relativePosition = sum . fmap valOf
- where
- valOf L = (-1)
- valOf R = 1
- valOf U = (-10)
- valOf D = 10
-
-numberLine :: Cofree TPossible Int
-numberLine = tabulate relativePosition
-
-project :: NE.NonEmpty a -> Cofree TPossible a
-project l = tabulate describe
- where
- describe = (l NE.!!) . foldl go 0
- maxIndex = length l - 1
- minIndex = 0
- go n L = max minIndex (n - 1)
- go n R = min maxIndex (n + 1)
- go n U = max minIndex (n - 1)
- go n D = min maxIndex (n + 1)
-
-elems :: NE.NonEmpty String
-elems = "one" NE.:| ["two", "three"]
-
-path :: Q.Seq TChoice
-path = Q.fromList [R, R, R, R, L]
-
-moveTo :: Q.Seq TChoice -> Cofree TPossible a -> Cofree TPossible a
-moveTo ind = extend (\cfr -> index cfr ind)
-
-main :: IO ()
-main = print $ index (project elems) path
--- main = print elems
+++ /dev/null
-
-
-import Control.Concurrent (threadDelay)
-
-
-import Data.Functor.Compose (Compose(..))
-import Data.Vector (Vector, (!), generate)
-import Data.Bool (bool)
-import Data.Distributive (Distributive(..))
-import Data.Functor.Rep (Representable(..), distributeRep)
-import Data.Functor.Identity (Identity(..))
-import Control.Comonad.Representable.Store (Store(..), StoreT(..), store, experiment)
-import Control.Comonad (Comonad(..))
-import Control.Monad (forM_)
-
-type Coord = (Int, Int)
-type Grid = Store (Compose Vector Vector) Bool
-type Rule = Grid -> Bool
-
-instance Distributive Vector where
- distribute = distributeRep
-
-instance Representable Vector where
- type Rep Vector = Int
- index v i = v ! (i `mod` gridSize)
- tabulate = generate gridSize
-
-gridSize :: Int
-gridSize = 20
-
-neighbourCoords :: [Coord]
-neighbourCoords = [(x, y) | x <- [-1, 0, 1], y <- [-1, 0, 1], (x, y) /= (0, 0)]
-
-addCoords :: Coord -> Coord -> Coord
-addCoords (x, y) (x', y') = (x + x', y + y')
-
-basicRule :: Rule
-basicRule g = numNeighboursAlive == 3 || (alive && numNeighboursAlive == 2)
- where
- alive = extract g
- neighbours = experiment (at neighbourCoords) g
- numNeighboursAlive = length (filter id neighbours)
-
-step :: Rule -> Grid -> Grid
-step = extend
-
-render :: Grid -> String
-render (StoreT (Identity (Compose g)) _) = foldMap ((++ "\n") . foldMap (bool "." "#")) g
-
-mkGrid :: [Coord] -> Grid
-mkGrid xs = store (`elem` xs) (0, 0)
-
-at :: [Coord] -> Coord -> [Coord]
-coords `at` origin = map (addCoords origin) coords
-
-glider, blinker, beacon :: [Coord]
-glider = [(1, 0), (2, 1), (0, 2), (1, 2), (2, 2)]
-blinker = [(0, 0), (1, 0), (2, 0)]
-beacon = [(0, 0), (1, 0), (0, 1), (3, 2), (2, 3), (3, 3)]
-
-
-
-
-
-
-tickTime :: Int
-tickTime = 200000
-
-start :: Grid
-start = mkGrid $
- glider `at` (0, 0)
- ++ beacon `at` (15, 5)
-
-main :: IO ()
-main = forM_ (iterate (step basicRule) start) $ \grid -> do
- putStr "\ESC[2J" -- Clear terminal screen
- putStrLn (render grid)
- threadDelay tickTime
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 24 - 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?25"/>
+<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, 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/stores/advent-of-code" 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">48*</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.twilio.com/quest" target="_blank" onclick="if(ga)ga('send','event','sponsor','sidebar',this.href);" rel="noopener">TwilioQuest</a> - Play Advent of Code and earn rad loot in TwilioQuest, a developer RPG for Mac, Windows, and Linux. Learn JavaScript, Python, git, APIs for SMS, VoIP, or WhatsApp, and much more.</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 24: Planet of Discord ---</h2><p>You land on <a href="https://en.wikipedia.org/wiki/Eris_(dwarf_planet)">Eris</a>, your last stop before reaching Santa. As soon as you do, your sensors start picking up strange life forms moving around: Eris is infested with <a href="https://www.nationalgeographic.org/thisday/sep9/worlds-first-computer-bug/">bugs</a>! With an <span title="For a sad version of this story, look up Voices of a Distant Star.">over 24-hour roundtrip</span> for messages between you and Earth, you'll have to deal with this problem on your own.</p>
+<p>Eris isn't a very large place; a scan of the entire area fits into a 5x5 grid (your puzzle input). The scan shows <em>bugs</em> (<code>#</code>) and <em>empty spaces</em> (<code>.</code>).</p>
+<p>Each <em>minute</em>, The bugs live and die based on the number of bugs in the <em>four adjacent tiles</em>:</p>
+<ul>
+<li>A bug <em>dies</em> (becoming an empty space) unless there is <em>exactly one</em> bug adjacent to it.</li>
+<li>An empty space <em>becomes infested</em> with a bug if <em>exactly one or two</em> bugs are adjacent to it.</li>
+</ul>
+<p>Otherwise, a bug or empty space remains the same. (Tiles on the edges of the grid have fewer than four adjacent tiles; the missing tiles count as empty space.) This process happens in every location <em>simultaneously</em>; that is, within the same minute, the number of adjacent bugs is counted for every tile first, and then the tiles are updated.</p>
+<p>Here are the first few minutes of an example scenario:</p>
+<pre><code>Initial state:
+....#
+#..#.
+#..##
+..#..
+#....
+
+After 1 minute:
+#..#.
+####.
+###.#
+##.##
+.##..
+
+After 2 minutes:
+#####
+....#
+....#
+...#.
+#.###
+
+After 3 minutes:
+#....
+####.
+...##
+#.##.
+.##.#
+
+After 4 minutes:
+####.
+....#
+##..#
+.....
+##...
+</code></pre>
+<p>To understand the nature of the bugs, watch for the first time a layout of bugs and empty spaces <em>matches any previous layout</em>. In the example above, the first layout to appear twice is:</p>
+<pre><code>.....
+.....
+.....
+#....
+.#...
+</code></pre>
+<p>To calculate the <em>biodiversity rating</em> for this layout, consider each tile left-to-right in the top row, then left-to-right in the second row, and so on. Each of these tiles is worth biodiversity points equal to <em>increasing powers of two</em>: 1, 2, 4, 8, 16, 32, and so on. Add up the biodiversity points for tiles with bugs; in this example, the 16th tile (<code>32768</code> points) and 22nd tile (<code>2097152</code> points) have bugs, a total biodiversity rating of <code><em>2129920</em></code>.</p>
+<p><em>What is the biodiversity rating for the first layout that appears twice?</em></p>
+</article>
+<p>Your puzzle answer was <code>17863711</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p>After careful analysis, one thing is certain: <em>you have no idea where all these bugs are coming from</em>.</p>
+<p>Then, you remember: Eris is an old <a href="20">Plutonian</a> settlement! Clearly, the bugs are coming from recursively-folded space.</p>
+<p>This 5x5 grid is <em>only one</em> level in an <em>infinite</em> number of recursion levels. The tile in the middle of the grid is actually another 5x5 grid, the grid in your scan is contained as the middle tile of a larger 5x5 grid, and so on. Two levels of grids look like this:</p>
+<pre><code> | | | |
+ | | | |
+ | | | |
+-----+-----+---------+-----+-----
+ | | | |
+ | | | |
+ | | | |
+-----+-----+---------+-----+-----
+ | | | | | | | |
+ | |-+-+-+-+-| |
+ | | | | | | | |
+ | |-+-+-+-+-| |
+ | | | |?| | | |
+ | |-+-+-+-+-| |
+ | | | | | | | |
+ | |-+-+-+-+-| |
+ | | | | | | | |
+-----+-----+---------+-----+-----
+ | | | |
+ | | | |
+ | | | |
+-----+-----+---------+-----+-----
+ | | | |
+ | | | |
+ | | | |
+</code></pre>
+<p>(To save space, some of the tiles are not drawn to scale.) Remember, this is only a small part of the infinitely recursive grid; there is a 5x5 grid that contains this diagram, and a 5x5 grid that contains that one, and so on. Also, the <code>?</code> in the diagram contains another 5x5 grid, which itself contains another 5x5 grid, and so on.</p>
+<p>The scan you took (your puzzle input) shows where the bugs are <em>on a single level</em> of this structure. The middle tile of your scan is empty to accommodate the recursive grids within it. Initially, no other levels contain bugs.</p>
+<p>Tiles still count as <em>adjacent</em> if they are directly <em>up, down, left, or right</em> of a given tile. Some tiles have adjacent tiles at a recursion level above or below its own level. For example:</p>
+<pre><code> | | | |
+ 1 | 2 | 3 | 4 | 5
+ | | | |
+-----+-----+---------+-----+-----
+ | | | |
+ 6 | 7 | 8 | 9 | 10
+ | | | |
+-----+-----+---------+-----+-----
+ | |A|B|C|D|E| |
+ | |-+-+-+-+-| |
+ | |F|G|H|I|J| |
+ | |-+-+-+-+-| |
+ 11 | 12 |K|L|?|N|O| 14 | 15
+ | |-+-+-+-+-| |
+ | |P|Q|R|S|T| |
+ | |-+-+-+-+-| |
+ | |U|V|W|X|Y| |
+-----+-----+---------+-----+-----
+ | | | |
+ 16 | 17 | 18 | 19 | 20
+ | | | |
+-----+-----+---------+-----+-----
+ | | | |
+ 21 | 22 | 23 | 24 | 25
+ | | | |
+</code></pre>
+<ul>
+<li>Tile 19 has four adjacent tiles: 14, 18, 20, and 24.</li>
+<li>Tile G has four adjacent tiles: B, F, H, and L.</li>
+<li>Tile D has four adjacent tiles: 8, C, E, and I.</li>
+<li>Tile E has four adjacent tiles: 8, D, 14, and J.</li>
+<li>Tile 14 has <em>eight</em> adjacent tiles: 9, E, J, O, T, Y, 15, and 19.</li>
+<li>Tile N has <em>eight</em> adjacent tiles: I, O, S, and five tiles within the sub-grid marked <code>?</code>.</li>
+</ul>
+<p>The rules about bugs living and dying are the same as before.</p>
+<p>For example, consider the same initial state as above:</p>
+<pre><code>....#
+#..#.
+#.?##
+..#..
+#....
+</code></pre>
+<p>The center tile is drawn as <code>?</code> to indicate the next recursive grid. Call this level 0; the grid within this one is level 1, and the grid that contains this one is level -1. Then, after <em>ten</em> minutes, the grid at each level would look like this:</p>
+<pre><code>Depth -5:
+..#..
+.#.#.
+..?.#
+.#.#.
+..#..
+
+Depth -4:
+...#.
+...##
+..?..
+...##
+...#.
+
+Depth -3:
+#.#..
+.#...
+..?..
+.#...
+#.#..
+
+Depth -2:
+.#.##
+....#
+..?.#
+...##
+.###.
+
+Depth -1:
+#..##
+...##
+..?..
+...#.
+.####
+
+Depth 0:
+.#...
+.#.##
+.#?..
+.....
+.....
+
+Depth 1:
+.##..
+#..##
+..?.#
+##.##
+#####
+
+Depth 2:
+###..
+##.#.
+#.?..
+.#.##
+#.#..
+
+Depth 3:
+..###
+.....
+#.?..
+#....
+#...#
+
+Depth 4:
+.###.
+#..#.
+#.?..
+##.#.
+.....
+
+Depth 5:
+####.
+#..#.
+#.?#.
+####.
+.....
+</code></pre>
+<p>In this example, after 10 minutes, a total of <code><em>99</em></code> bugs are present.</p>
+<p>Starting with your scan, <em>how many bugs are present after 200 minutes?</em></p>
+</article>
+<p>Your puzzle answer was <code>1937</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="24/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+%22Planet+of+Discord%22+%2D+Day+24+%2D+Advent+of+Code+2019&url=https%3A%2F%2Fadventofcode%2Ecom%2F2019%2Fday%2F24&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+%22Planet+of+Discord%22+%2D+Day+24+%2D+Advent+of+Code+2019+%23AdventOfCode+https%3A%2F%2Fadventofcode%2Ecom%2F2019%2Fday%2F24'}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