From: Neil Smith <neil.git@njae.me.uk> Date: Thu, 21 Dec 2017 21:41:54 +0000 (+0000) Subject: Done day 21 X-Git-Url: https://git.njae.me.uk/?a=commitdiff_plain;h=5da6dfef190a4e7514c4194ce88e31d1cc96ca49;p=advent-of-code-17.git Done day 21 --- diff --git a/advent-of-code.cabal b/advent-of-code.cabal index e2dd2a8..f9fafce 100644 --- a/advent-of-code.cabal +++ b/advent-of-code.cabal @@ -219,3 +219,12 @@ executable advent20 , text , megaparsec , vector + +executable advent21 + hs-source-dirs: src/advent21 + main-is: advent21.hs + default-language: Haskell2010 + build-depends: base >= 4.7 && < 5 + , containers + , text + , megaparsec diff --git a/data/advent21.txt b/data/advent21.txt new file mode 100644 index 0000000..97f767a --- /dev/null +++ b/data/advent21.txt @@ -0,0 +1,108 @@ +../.. => .../.##/##. +#./.. => .##/.##/#.. +##/.. => ..#/.../### +.#/#. => #.#/..#/##. +##/#. => .#./.#./..# +##/## => #.#/#../### +.../.../... => ..../#.../.##./..#. +#../.../... => ####/#.##/##.#/..#. +.#./.../... => ..##/..##/..##/..## +##./.../... => ..../..#./##../##.# +#.#/.../... => ##.#/..../####/...# +###/.../... => .#.#/.###/.#../.#.# +.#./#../... => .###/#.#./...#/##.. +##./#../... => #.##/#.../####/###. +..#/#../... => ####/...#/...#/#.## +#.#/#../... => .#../##../..##/..#. +.##/#../... => .#../..##/..../.##. +###/#../... => #.../..#./.#.#/#..# +.../.#./... => #.#./.#.#/.###/...# +#../.#./... => ###./.#../...#/.#.. +.#./.#./... => ##.#/.#../#..#/##.. +##./.#./... => #..#/...#/.#.#/###. +#.#/.#./... => .##./#.../#..#/.### +###/.#./... => .#.#/##.#/..../##.# +.#./##./... => ##.#/#.##/.#.#/#.## +##./##./... => #.##/..#./..#./.##. +..#/##./... => ..../#.../..#./..## +#.#/##./... => .##./####/####/#### +.##/##./... => #.##/####/#.##/#..# +###/##./... => .#../.###/##../...# +.../#.#/... => ...#/...#/#.##/#### +#../#.#/... => ..#./..#./###./.##. +.#./#.#/... => .##./##../.###/.#.# +##./#.#/... => #.#./.#../.##./...# +#.#/#.#/... => ##.#/..##/#.../##.# +###/#.#/... => ..##/##../.#.#/..## +.../###/... => .#../#.../.##./.... +#../###/... => ..##/..##/...#/.##. +.#./###/... => #..#/..#./#.#./..## +##./###/... => #.##/.#../##.#/##.# +#.#/###/... => ####/###./.##./...# +###/###/... => #..#/#.##/..../.##. +..#/.../#.. => #.#./.#../##../..#. +#.#/.../#.. => ##.#/####/##../.#.# +.##/.../#.. => ####/##../#..#/..#. +###/.../#.. => ##../..#./####/##.# +.##/#../#.. => ##../#.#./###./..## +###/#../#.. => ..../.#../#..#/...# +..#/.#./#.. => ..#./...#/.###/.#.# +#.#/.#./#.. => ###./..../#.#./###. +.##/.#./#.. => ####/#.##/.#.#/.#.. +###/.#./#.. => ###./#.##/##../#### +.##/##./#.. => ##.#/..##/..#./.#.. +###/##./#.. => ##.#/.##./.###/.##. +#../..#/#.. => #.../###./##.#/#..# +.#./..#/#.. => ..##/.###/...#/..#. +##./..#/#.. => ##../#.#./...#/.#.. +#.#/..#/#.. => ..#./###./##../.### +.##/..#/#.. => #.../.##./..../#.#. +###/..#/#.. => .#.#/#.##/#.##/..#. +#../#.#/#.. => ..##/..##/#.../#### +.#./#.#/#.. => #.../...#/..../..## +##./#.#/#.. => ###./..##/.#../.##. +..#/#.#/#.. => ...#/..##/..#./.#.. +#.#/#.#/#.. => #.#./.#../..../##.. +.##/#.#/#.. => ..#./.###/##.#/.... +###/#.#/#.. => #.##/..##/...#/##.. +#../.##/#.. => #.#./##../###./.#.# +.#./.##/#.. => .###/#..#/.##./.... +##./.##/#.. => .#.#/.#../.###/.##. +#.#/.##/#.. => .#../..##/###./#.## +.##/.##/#.. => ##../.##./..#./.#.. +###/.##/#.. => .#.#/..#./#..#/.### +#../###/#.. => #.##/#..#/.#.#/#.#. +.#./###/#.. => #.../#..#/#.../.#.# +##./###/#.. => ##../####/##../.### +..#/###/#.. => #.../..../####/##.# +#.#/###/#.. => ...#/..../...#/..## +.##/###/#.. => .#../####/#.##/.#.. +###/###/#.. => ###./.#.#/#.../##.. +.#./#.#/.#. => ...#/##../####/...# +##./#.#/.#. => ####/#..#/###./#.## +#.#/#.#/.#. => .###/#..#/..#./...# +###/#.#/.#. => ###./.###/##.#/###. +.#./###/.#. => #..#/#.../..#./#### +##./###/.#. => #.../..../#..#/..## +#.#/###/.#. => #..#/.#.#/#.../##.. +###/###/.#. => .#.#/..../.#.#/#.## +#.#/..#/##. => .#../..##/...#/###. +###/..#/##. => .###/..#./##.#/##.# +.##/#.#/##. => ####/#.##/.##./##.. +###/#.#/##. => #..#/#..#/####/#.## +#.#/.##/##. => .###/#.#./#..#/.#.# +###/.##/##. => #.#./#.#./#.##/..## +.##/###/##. => ####/###./##.#/##.# +###/###/##. => ##../..##/#.#./#... +#.#/.../#.# => .#../###./.###/##.# +###/.../#.# => ..../.#.#/#..#/##.. +###/#../#.# => ..#./#.../.##./...# +#.#/.#./#.# => ...#/#.../##.#/.##. +###/.#./#.# => ..../..../#.#./##.# +###/##./#.# => .#../...#/...#/###. +#.#/#.#/#.# => ...#/#.../##../.### +###/#.#/#.# => #.../...#/.#../#.## +#.#/###/#.# => ..../.##./..../##.. +###/###/#.# => .##./.#.#/#.##/.##. +###/#.#/### => #.#./####/.##./.##. +###/###/### => .#.#/..##/#.##/.##. \ No newline at end of file diff --git a/problems/day21.html b/problems/day21.html new file mode 100644 index 0000000..4d1bc0f --- /dev/null +++ b/problems/day21.html @@ -0,0 +1,195 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> +<meta charset="utf-8"/> +<title>Day 21 - Advent of Code 2017</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?12"/> +<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/> +<link rel="shortcut icon" href="/favicon.ico?2"/> +</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 probably took the longest; the easiest ones took an hour or two +each, but the harder ones took 4-5 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="/2017/about">[About]</a></li><li><a href="/2017/support">[AoC++]</a></li><li><a href="/2017/events">[Events]</a></li><li><a href="/2017/settings">[Settings]</a></li><li><a href="/2017/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <span class="supporter">(AoC++)</span> <span class="star-count">42*</span></div></div><div><h1 class="title-event"> <span class="title-event-wrap"></span><a href="/2017">2017</a><span class="title-event-wrap"></span></h1><nav><ul><li><a href="/2017">[Calendar]</a></li><li><a href="/2017/leaderboard">[Leaderboard]</a></li><li><a href="/2017/stats">[Stats]</a></li><li><a href="/2017/sponsors">[Sponsors]</a></li></ul></nav></div></header> + +<div id="sidebar"> +<div id="sponsor"><div class="quiet">Our <a href="/2017/sponsors">sponsors</a> help make Advent of Code possible:</div><p><a href="http://kx.com/" target="_blank" onclick="if(ga)ga('send','event','sponsor','click',this.href);" rel="noopener">Kx Systems</a> - kdb+, the in-memory time series technology standard</p></div> +<p class="quiet">By popular demand, there are now AoC-themed objects available (until Jan. 3rd)! Get them shipped <a href="https://teespring.com/advent-of-code" target="_blank">from the US</a> or <a href="https://teespring.com/advent-of-code-eu" target="_blank">from Europe</a>.</p> + +</div><!--/sidebar--> + +<main> +<article class="day-desc"><h2>--- Day 21: Fractal Art ---</h2><p>You find a program trying to generate some art. It uses a strange process that involves <span title="This technique is also often used on TV.">repeatedly enhancing</span> the detail of an image through a set of rules.</p> +<p>The image consists of a two-dimensional square grid of pixels that are either on (<code>#</code>) or off (<code>.</code>). The program always begins with this pattern:</p> +<pre><code>.#. +..# +### +</code></pre> +<p>Because the pattern is both <code>3</code> pixels wide and <code>3</code> pixels tall, it is said to have a <em>size</em> of <code>3</code>.</p> +<p>Then, the program repeats the following process:</p> +<ul> +<li>If the size is evenly divisible by <code>2</code>, break the pixels up into <code>2x2</code> squares, and convert each <code>2x2</code> square into a <code>3x3</code> square by following the corresponding <em>enhancement rule</em>.</li> +<li>Otherwise, the size is evenly divisible by <code>3</code>; break the pixels up into <code>3x3</code> squares, and convert each <code>3x3</code> square into a <code>4x4</code> square by following the corresponding <em>enhancement rule</em>.</li> +</ul> +<p>Because each square of pixels is replaced by a larger one, the image gains pixels and so its <em>size</em> increases.</p> +<p>The artist's book of enhancement rules is nearby (your puzzle input); however, it seems to be missing rules. The artist explains that sometimes, one must <em>rotate</em> or <em>flip</em> the input pattern to find a match. (Never rotate or flip the output pattern, though.) Each pattern is written concisely: rows are listed as single units, ordered top-down, and separated by slashes. For example, the following rules correspond to the adjacent patterns:</p> +<pre><code>../.# = .. + .# + + .#. +.#./..#/### = ..# + ### + + #..# +#..#/..../#..#/.##. = .... + #..# + .##. +</code></pre> +<p>When searching for a rule to use, rotate and flip the pattern as necessary. For example, all of the following patterns match the same rule:</p> +<pre><code>.#. .#. #.. ### +..# #.. #.# ..# +### ### ##. .#. +</code></pre> +<p>Suppose the book contained the following two rules:</p> +<pre><code>../.# => ##./#../... +.#./..#/### => #..#/..../..../#..# +</code></pre> +<p>As before, the program begins with this pattern:</p> +<pre><code>.#. +..# +### +</code></pre> +<p>The size of the grid (<code>3</code>) is not divisible by <code>2</code>, but it is divisible by <code>3</code>. It divides evenly into a single square; the square matches the second rule, which produces:</p> +<pre><code>#..# +.... +.... +#..# +</code></pre> +<p>The size of this enhanced grid (<code>4</code>) is evenly divisible by <code>2</code>, so that rule is used. It divides evenly into four squares:</p> +<pre><code>#.|.# +..|.. +--+-- +..|.. +#.|.# +</code></pre> +<p>Each of these squares matches the same rule (<code>../.# => ##./#../...</code>), three of which require some flipping and rotation to line up with the rule. The output for the rule is the same in all four cases:</p> +<pre><code>##.|##. +#..|#.. +...|... +---+--- +##.|##. +#..|#.. +...|... +</code></pre> +<p>Finally, the squares are joined into a new grid:</p> +<pre><code>##.##. +#..#.. +...... +##.##. +#..#.. +...... +</code></pre> +<p>Thus, after <code>2</code> iterations, the grid contains <code>12</code> pixels that are <em>on</em>.</p> +<p><em>How many pixels stay on</em> after <code>5</code> iterations?</p> +</article> +<p>Your puzzle answer was <code>158</code>.</p><article class="day-desc"><h2>--- Part Two ---</h2><p><em>How many pixels stay on</em> after <code>18</code> iterations?</p> +</article> +<p>Your puzzle answer was <code>2301762</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="/2017">return to your advent calendar</a> and try another puzzle.</p> +<p>If you still want to see it, you can <a href="21/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+%22Fractal+Art%22+%2D+Day+21+%2D+Advent+of+Code+2017&url=http%3A%2F%2Fadventofcode%2Ecom%2F2017%2Fday%2F21&related=ericwastl&hashtags=AdventOfCode" target="_blank">Twitter</a> + <a href="https://plus.google.com/share?url=http%3A%2F%2Fadventofcode%2Ecom%2F2017%2Fday%2F21" target="_blank">Google+</a> + <a href="http://www.reddit.com/submit?url=http%3A%2F%2Fadventofcode%2Ecom%2F2017%2Fday%2F21&title=I%27ve+completed+%22Fractal+Art%22+%2D+Day+21+%2D+Advent+of+Code+2017" 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 diff --git a/src/advent21/advent21.hs b/src/advent21/advent21.hs new file mode 100644 index 0000000..62b5b5c --- /dev/null +++ b/src/advent21/advent21.hs @@ -0,0 +1,170 @@ +{-# LANGUAGE NegativeLiterals #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE BangPatterns #-} + +import Data.Text (Text) +import qualified Data.Text as T +import qualified Data.Text.IO as TIO + +import Text.Megaparsec hiding (State) +import qualified Text.Megaparsec.Lexer as L +import Text.Megaparsec.Text (Parser) +import qualified Control.Applicative as CA +-- import qualified Data.Functor as F + +import qualified Data.Map.Strict as M +import Data.Map.Strict ((!)) + +import Data.List + + +type Grid = M.Map (Int, Int) Bool +type ExplodedGrid = M.Map (Int, Int) Grid + +data Rule = Rule Grid Grid deriving (Eq, Show) + +rulePre (Rule g _) = g +rulePost (Rule _ g) = g + + +initialGrid = case parse gridP "" ".#./..#/###" of + Left _ -> M.empty + Right g -> g + + +main :: IO () +main = do + text <- TIO.readFile "data/advent21.txt" + let rules = readRules text + print $ countLit $ nthApplication rules 5 + print $ countLit $ nthApplication rules 18 + + +readRules :: Text -> [Rule] +readRules = expandRules . successfulParse + +expandRules = concatMap expandRule +expandRule rule = [Rule l (rulePost rule) | l <- allArrangements (rulePre rule)] + +reflectH g = M.fromList [((r, c) , M.findWithDefault False (rm - r, c) g) | r <- [0..rm], c <- [0..cm] ] + where (rm, cm) = bounds g + +reflectV g = M.fromList [((r, c) , M.findWithDefault False (r, cm - c) g) | r <- [0..rm], c <- [0..cm] ] + where (rm, cm) = bounds g + +transposeG g = M.fromList [((c, r) , M.findWithDefault False (r, c) g) | r <- [0..rm], c <- [0..cm] ] + where (rm, cm) = bounds g + +allArrangements grid = map (\f -> f grid) [ id + , reflectH + , reflectV + , transposeG + , reflectH . transposeG + , reflectV . transposeG + , reflectH . reflectV . transposeG + , reflectV . reflectH + ] + + + + +countLit = M.size . M.filter id + + +applyOnce rules g = contractExploded $ M.map (apply rules) $ explodeGrid g + +nthApplication rules n = (!! n) $ iterate (applyOnce rules) initialGrid + + + +apply rules grid = rulePost thisRule + where ri = head $ findIndices (\r -> rulePre r == grid) rules + thisRule = rules!!ri + + +explodeGrid :: Grid -> ExplodedGrid +explodeGrid g = if (rm + 1) `rem` 2 == 0 + then explodeGrid' 2 g + else explodeGrid' 3 g + where (rm, cm) = bounds g + +contractExploded :: ExplodedGrid -> Grid +contractExploded gs = foldl1 (>|<) $ map (foldl1 (>-<)) rows + where rows = explodedRows gs + + +explodeGrid' :: Int -> Grid -> ExplodedGrid +explodeGrid' n g = M.fromList [((bigR, bigC), subGrid n g bigR bigC) | bigR <- [0..bigRm], bigC <- [0..bigCm]] + where (rm, cm) = bounds g + bigRm = (rm + 1) `div` n - 1 + bigCm = (cm + 1) `div` n - 1 + + +subGrid :: Int -> Grid -> Int -> Int -> Grid +subGrid n g bigR bigC = M.fromList [ ((r, c), + M.findWithDefault False (r + rStep, c + cStep) g) + | r <- [0..(n - 1)], c <- [0..(n - 1)] + ] + where rStep = bigR * n + cStep = bigC * n + + +explodedRows eg = [M.filterWithKey (\(r, _) _ -> r == row) eg | row <- [0..rowMax] ] + where (rowMax, _) = bounds eg + +(>-<) g1 g2 = M.union g1 g2' + where (_, cm) = bounds g1 + g2' = M.mapKeys (\(r, c) -> (r, c + cm + 1)) g2 + +(>|<) g1 g2 = M.union g1 g2' + where (rm, _) = bounds g1 + g2' = M.mapKeys (\(r, c) -> (r + rm + 1, c)) g2 + + + + + +bounds :: M.Map (Int, Int) a -> (Int, Int) +bounds grid = (maximum $ map fst $ M.keys grid, maximum $ map snd $ M.keys grid) + + +showGrid g = unlines [[showGChar $ M.findWithDefault False (r, c) g | + c <- [0..cm] ] | r <- [0..rm] ] + where (rm, cm) = bounds g + showGChar True = '#' + showGChar False = '.' + + +onlySpace = (char ' ') <|> (char '\t') + +sc :: Parser () +sc = L.space (skipSome onlySpace) CA.empty CA.empty + +lexeme = L.lexeme sc + +symbol = L.symbol sc +rowSep = symbol "/" +ruleJoin = symbol "=>" + +present = id True <$ symbol "#" +absent = id False <$ symbol "." + +rulesP = ruleP `sepBy` space +ruleP = Rule <$> gridP <*> (ruleJoin *> gridP) + +gridP = gridify <$> rowP `sepBy` rowSep + where gridify g = M.fromList $ concat + [map (\(c, v) -> ((r, c), v)) nr | + (r, nr) <- zip [0..] + [zip [0..] r | r <- g]] + + +rowP = some (present <|> absent) + +successfulParse :: Text -> [Rule] +successfulParse input = + case parse rulesP "input" input of + Left _error -> [] + Right instructions -> instructions \ No newline at end of file diff --git a/src/advent21/advent21.ipynb b/src/advent21/advent21.ipynb new file mode 100644 index 0000000..82fb65b --- /dev/null +++ b/src/advent21/advent21.ipynb @@ -0,0 +1,1276 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "{-# LANGUAGE NegativeLiterals #-}\n", + "{-# LANGUAGE FlexibleContexts #-}\n", + "{-# LANGUAGE OverloadedStrings #-}\n", + "{-# LANGUAGE TypeFamilies #-}\n", + "{-# LANGUAGE BangPatterns #-}" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import Data.Text (Text)\n", + "import qualified Data.Text as T\n", + "import qualified Data.Text.IO as TIO\n", + "\n", + "import Text.Megaparsec hiding (State)\n", + "import qualified Text.Megaparsec.Lexer as L\n", + "import Text.Megaparsec.Text (Parser)\n", + "import qualified Control.Applicative as CA\n", + "-- import Data.Functor (void)\n", + "\n", + "import qualified Data.Map.Strict as M\n", + "import Data.Map.Strict ((!))\n", + "\n", + "-- import Data.Vector ((!), (//))\n", + "-- import qualified Data.Vector as V\n", + "\n", + "import Data.List \n", + "import qualified Data.Functor as F" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "type Grid = M.Map (Int, Int) Bool\n", + "-- type Grid = [[Char]]\n", + "-- type Grid = [[Bool]]\n", + "\n", + "type ExplodedGrid = M.Map (Int, Int) Grid\n", + "\n", + "data Rule = Rule Grid Grid deriving (Eq, Show)\n", + "\n", + "rulePre (Rule g _) = g\n", + "rulePost (Rule _ g) = g" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [], + "source": [ + "onlySpace = (char ' ') <|> (char '\\t')\n", + "\n", + "sc :: Parser ()\n", + "sc = L.space (skipSome onlySpace) CA.empty CA.empty" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "lexeme = L.lexeme sc\n", + "\n", + "symbol = L.symbol sc\n", + "rowSep = symbol \"/\"\n", + "ruleJoin = symbol \"=>\"\n", + "\n", + "-- present :: Parser Bool\n", + "present = id True <$ symbol \"#\"\n", + "\n", + "-- absent :: Parser Bool\n", + "absent = id False <$ symbol \".\"\n", + "\n", + "rulesP = ruleP `sepBy` space\n", + "ruleP = Rule <$> gridP <*> (ruleJoin *> gridP)\n", + "\n", + "gridP = gridify <$> rowP `sepBy` rowSep\n", + " where gridify g = M.fromList $ concat \n", + " [map (\\(c, v) -> ((r, c), v)) nr | \n", + " (r, nr) <- zip [0..] \n", + " [zip [0..] r | r <- g]]\n", + "\n", + "\n", + "rowP = some (present <|> absent)\n", + " \n", + "successfulParse :: Text -> [Rule]\n", + "successfulParse input = \n", + " case parse rulesP \"input\" input of\n", + " Left _error -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err\n", + " Right instructions -> instructions" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Rule (fromList [((0,0),True),((0,1),False),((1,0),False),((1,1),False)]) (fromList [((0,0),False),((0,1),True),((0,2),True),((1,0),False),((1,1),True),((1,2),True),((2,0),True),((2,1),False),((2,2),False)])" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "parseTest ruleP \"#./.. => .##/.##/#..\"" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Rule (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),True),((2,0),False),((2,1),False),((2,2),False)]) (fromList [((0,0),True),((0,1),False),((0,2),True),((0,3),False),((1,0),False),((1,1),True),((1,2),False),((1,3),False),((2,0),False),((2,1),True),((2,2),True),((2,3),False),((3,0),False),((3,1),False),((3,2),False),((3,3),True)])" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "parseTest ruleP \"##./#.#/... => #.#./.#../.##./...#\"" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "testRule = head $ successfulParse \"##./#.#/... => #.#./.#../.##./...#\"" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Rule (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),True),((2,0),False),((2,1),False),((2,2),False)]) (fromList [((0,0),True),((0,1),False),((0,2),True),((0,3),False),((1,0),False),((1,1),True),((1,2),False),((1,3),False),((2,0),False),((2,1),True),((2,2),True),((2,3),False),((3,0),False),((3,1),False),((3,2),False),((3,3),True)])" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "testRule" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Rule (fromList [((0,0),True),((0,1),False),((1,0),False),((1,1),False)]) (fromList [((0,0),False),((0,1),True),((0,2),True),((1,0),False),((1,1),True),((1,2),True),((2,0),True),((2,1),False),((2,2),False)]),Rule (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),True),((2,0),False),((2,1),False),((2,2),False)]) (fromList [((0,0),True),((0,1),False),((0,2),True),((0,3),False),((1,0),False),((1,1),True),((1,2),False),((1,3),False),((2,0),False),((2,1),True),((2,2),True),((2,3),False),((3,0),False),((3,1),False),((3,2),False),((3,3),True)])]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "parseTest rulesP \"#./.. => .##/.##/#..\\n##./#.#/... => #.#./.#../.##./...#\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Rule (fromList [((0,0),True),((0,1),False),((1,0),False),((1,1),False)]) \n", + " (fromList [((0,0),False),((0,1),True),((0,2),True),((1,0),False),((1,1),True),((1,2),True),((2,0),True),((2,1),False),((2,2),False),((2,3),True),((2,4),True),((2,5),False),((3,0),True),((3,1),False),((3,2),True),((4,0),False),((4,1),False),((4,2),False)]),\n", + " \n", + "Rule (fromList []) \n", + " (fromList [((0,0),True),((0,1),False),((0,2),True),((0,3),False),((1,0),False),((1,1),True),((1,2),False),((1,3),False),((2,0),False),((2,1),True),((2,2),True),((2,3),False),((3,0),False),((3,1),False),((3,2),False),((3,3),True)])" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "g = [[False,True,True],[False,True,True],[True,False,False]]" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[((0,0),False),((0,1),True),((0,2),True),((1,0),False),((1,1),True),((1,2),True),((2,0),True),((2,1),False),((2,2),False)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "concat [map (\\(c, v) -> ((r, c), v)) nr | (r, nr) <- zip [0..] [zip [0..] r | r <- g]]" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [], + "source": [ + "bounds :: M.Map (Int, Int) a -> (Int, Int)\n", + "bounds grid = (maximum $ map fst $ M.keys grid, maximum $ map snd $ M.keys grid)" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3,3)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "bounds (rulePost testRule)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "showGrid g = unlines [[showChar $ M.findWithDefault False (r, c) g | \n", + " c <- [0..cm] ] | r <- [0..rm] ]\n", + " where (rm, cm) = bounds g\n", + " showChar True = '#'\n", + " showChar False = '.'" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "#.#.\n", + ".#..\n", + ".##.\n", + "...#" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "putStrLn $ showGrid $ rulePost testRule" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "initialGrid = case parse gridP \"\" \".#./..#/###\" of \n", + " Left _ -> M.empty \n", + " Right g -> g" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "fromList [((0,0),False),((0,1),True),((0,2),False),((1,0),False),((1,1),False),((1,2),True),((2,0),True),((2,1),True),((2,2),True)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + ".#.\n", + "..#\n", + "###" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "putStrLn $ showGrid initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "reflectH g = M.fromList [((r, c) , M.findWithDefault False (rm - r, c) g) | r <- [0..rm], c <- [0..cm] ]\n", + " where (rm, cm) = bounds g" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "###\n", + "..#\n", + ".#." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "putStrLn $ showGrid $ reflectH initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "reflectV g = M.fromList [((r, c) , M.findWithDefault False (r, cm - c) g) | r <- [0..rm], c <- [0..cm] ]\n", + " where (rm, cm) = bounds g" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + ".#.\n", + "#..\n", + "###" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "putStrLn $ showGrid $ reflectV initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "transpose g = M.fromList [((c, r) , M.findWithDefault False (r, c) g) | r <- [0..rm], c <- [0..cm] ]\n", + " where (rm, cm) = bounds g" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "..#\n", + "#.#\n", + ".##" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "putStrLn $ showGrid $ transpose initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "allArrangements grid = map (\\f -> f grid) [ id\n", + " , reflectH\n", + " , reflectV\n", + " , transpose\n", + " , reflectH . transpose\n", + " , reflectV . transpose\n", + " , reflectH . reflectV . transpose\n", + " , reflectV . reflectH\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[\".#.\\n..#\\n###\\n\",\"###\\n..#\\n.#.\\n\",\".#.\\n#..\\n###\\n\",\"..#\\n#.#\\n.##\\n\",\".##\\n#.#\\n..#\\n\",\"#..\\n#.#\\n##.\\n\",\"##.\\n#.#\\n#..\\n\",\"###\\n#..\\n.#.\\n\"]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "map showGrid $ allArrangements initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "sampleRulesCompact = successfulParse \"../.# => ##./#../...\\n.#./..#/### => #..#/..../..../#..#\"\n", + "length sampleRulesCompact" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "expandRule rule = [Rule l (rulePost rule) | l <- allArrangements (rulePre rule)]\n", + "expandRules = concatMap expandRule" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[\"##.\\n#.#\\n...\\n=>#.#.\\n.#..\\n.##.\\n...#\\n\",\"...\\n#.#\\n##.\\n=>#.#.\\n.#..\\n.##.\\n...#\\n\",\".##\\n#.#\\n...\\n=>#.#.\\n.#..\\n.##.\\n...#\\n\",\"##.\\n#..\\n.#.\\n=>#.#.\\n.#..\\n.##.\\n...#\\n\",\".#.\\n#..\\n##.\\n=>#.#.\\n.#..\\n.##.\\n...#\\n\",\".##\\n..#\\n.#.\\n=>#.#.\\n.#..\\n.##.\\n...#\\n\",\".#.\\n..#\\n.##\\n=>#.#.\\n.#..\\n.##.\\n...#\\n\",\"...\\n#.#\\n.##\\n=>#.#.\\n.#..\\n.##.\\n...#\\n\"]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "[showGrid (rulePre r) ++ \"=>\" ++ showGrid (rulePost r) | r <- expandRule testRule]" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "16" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "length $ expandRules sampleRulesCompact" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "readRules = expandRules . successfulParse" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[Rule (fromList [((0,0),False),((0,1),False),((1,0),False),((1,1),True)]) (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),False),((2,0),False),((2,1),False),((2,2),False)]),Rule (fromList [((0,0),False),((0,1),True),((1,0),False),((1,1),False)]) (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),False),((2,0),False),((2,1),False),((2,2),False)]),Rule (fromList [((0,0),False),((0,1),False),((1,0),True),((1,1),False)]) (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),False),((2,0),False),((2,1),False),((2,2),False)]),Rule (fromList [((0,0),False),((0,1),False),((1,0),False),((1,1),True)]) (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),False),((2,0),False),((2,1),False),((2,2),False)]),Rule (fromList [((0,0),False),((0,1),True),((1,0),False),((1,1),False)]) (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),False),((2,0),False),((2,1),False),((2,2),False)]),Rule (fromList [((0,0),False),((0,1),False),((1,0),True),((1,1),False)]) (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),False),((2,0),False),((2,1),False),((2,2),False)]),Rule (fromList [((0,0),True),((0,1),False),((1,0),False),((1,1),False)]) (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),False),((2,0),False),((2,1),False),((2,2),False)]),Rule (fromList [((0,0),True),((0,1),False),((1,0),False),((1,1),False)]) (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),False),((2,0),False),((2,1),False),((2,2),False)]),Rule (fromList [((0,0),False),((0,1),True),((0,2),False),((1,0),False),((1,1),False),((1,2),True),((2,0),True),((2,1),True),((2,2),True)]) (fromList [((0,0),True),((0,1),False),((0,2),False),((0,3),True),((1,0),False),((1,1),False),((1,2),False),((1,3),False),((2,0),False),((2,1),False),((2,2),False),((2,3),False),((3,0),True),((3,1),False),((3,2),False),((3,3),True)]),Rule (fromList [((0,0),True),((0,1),True),((0,2),True),((1,0),False),((1,1),False),((1,2),True),((2,0),False),((2,1),True),((2,2),False)]) (fromList [((0,0),True),((0,1),False),((0,2),False),((0,3),True),((1,0),False),((1,1),False),((1,2),False),((1,3),False),((2,0),False),((2,1),False),((2,2),False),((2,3),False),((3,0),True),((3,1),False),((3,2),False),((3,3),True)]),Rule (fromList [((0,0),False),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),False),((2,0),True),((2,1),True),((2,2),True)]) (fromList [((0,0),True),((0,1),False),((0,2),False),((0,3),True),((1,0),False),((1,1),False),((1,2),False),((1,3),False),((2,0),False),((2,1),False),((2,2),False),((2,3),False),((3,0),True),((3,1),False),((3,2),False),((3,3),True)]),Rule (fromList [((0,0),False),((0,1),False),((0,2),True),((1,0),True),((1,1),False),((1,2),True),((2,0),False),((2,1),True),((2,2),True)]) (fromList [((0,0),True),((0,1),False),((0,2),False),((0,3),True),((1,0),False),((1,1),False),((1,2),False),((1,3),False),((2,0),False),((2,1),False),((2,2),False),((2,3),False),((3,0),True),((3,1),False),((3,2),False),((3,3),True)]),Rule (fromList [((0,0),False),((0,1),True),((0,2),True),((1,0),True),((1,1),False),((1,2),True),((2,0),False),((2,1),False),((2,2),True)]) (fromList [((0,0),True),((0,1),False),((0,2),False),((0,3),True),((1,0),False),((1,1),False),((1,2),False),((1,3),False),((2,0),False),((2,1),False),((2,2),False),((2,3),False),((3,0),True),((3,1),False),((3,2),False),((3,3),True)]),Rule (fromList [((0,0),True),((0,1),False),((0,2),False),((1,0),True),((1,1),False),((1,2),True),((2,0),True),((2,1),True),((2,2),False)]) (fromList [((0,0),True),((0,1),False),((0,2),False),((0,3),True),((1,0),False),((1,1),False),((1,2),False),((1,3),False),((2,0),False),((2,1),False),((2,2),False),((2,3),False),((3,0),True),((3,1),False),((3,2),False),((3,3),True)]),Rule (fromList [((0,0),True),((0,1),True),((0,2),False),((1,0),True),((1,1),False),((1,2),True),((2,0),True),((2,1),False),((2,2),False)]) (fromList [((0,0),True),((0,1),False),((0,2),False),((0,3),True),((1,0),False),((1,1),False),((1,2),False),((1,3),False),((2,0),False),((2,1),False),((2,2),False),((2,3),False),((3,0),True),((3,1),False),((3,2),False),((3,3),True)]),Rule (fromList [((0,0),True),((0,1),True),((0,2),True),((1,0),True),((1,1),False),((1,2),False),((2,0),False),((2,1),True),((2,2),False)]) (fromList [((0,0),True),((0,1),False),((0,2),False),((0,3),True),((1,0),False),((1,1),False),((1,2),False),((1,3),False),((2,0),False),((2,1),False),((2,2),False),((2,3),False),((3,0),True),((3,1),False),((3,2),False),((3,3),True)])]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "sampleRules = readRules \"../.# => ##./#../...\\n.#./..#/### => #..#/..../..../#..#\"\n", + "sampleRules" + ] + }, + { + "cell_type": "code", + "execution_count": 125, + "metadata": {}, + "outputs": [], + "source": [ + "text <- TIO.readFile \"../../data/advent21.txt\"\n", + "rules = readRules text" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "864" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "length rules" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "apply rules grid = rulePost thisRule\n", + " where ri = head $ findIndices (\\r -> rulePre r == grid) rules\n", + " thisRule = rules!!ri" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "#..#\n", + "....\n", + "....\n", + "#..#" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "putStrLn $ showGrid $ apply sampleRules initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [], + "source": [ + "subGrid :: Int -> Grid -> Int -> Int -> Grid\n", + "subGrid n g bigR bigC = M.fromList [ ((r, c), \n", + " M.findWithDefault False (r + rStep, c + cStep) g) \n", + " | r <- [0..(n - 1)], c <- [0..(n - 1)]\n", + " ]\n", + " where rStep = bigR * n\n", + " cStep = bigC * n" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [], + "source": [ + "explodeGrid' :: Int -> Grid -> ExplodedGrid\n", + "explodeGrid' n g = M.fromList [((bigR, bigC), subGrid n g bigR bigC) | bigR <- [0..bigRm], bigC <- [0..bigCm]]\n", + " where (rm, cm) = bounds g\n", + " bigRm = (rm + 1) `div` n - 1\n", + " bigCm = (cm + 1) `div` n - 1" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": {}, + "outputs": [], + "source": [ + "explodeGrid :: Grid -> ExplodedGrid\n", + "explodeGrid g = if (rm + 1) `rem` 2 == 0 \n", + " then explodeGrid' 2 g\n", + " else explodeGrid' 3 g\n", + " where (rm, cm) = bounds g" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "fromList [((0,0),\"#.\\n..\\n\"),((0,1),\".#\\n..\\n\"),((1,0),\"..\\n#.\\n\"),((1,1),\"..\\n.#\\n\")]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "testEg = explodeGrid $ apply sampleRules initialGrid\n", + "M.map showGrid testEg" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [], + "source": [ + "explodedRows eg = [M.filterWithKey (\\(r, _) _ -> r == row) eg | row <- [0..rowMax] ]\n", + " where (rowMax, _) = bounds eg" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[fromList [((0,0),fromList [((0,0),True),((0,1),False),((1,0),False),((1,1),False)]),((0,1),fromList [((0,0),False),((0,1),True),((1,0),False),((1,1),False)])],fromList [((1,0),fromList [((0,0),False),((0,1),False),((1,0),True),((1,1),False)]),((1,1),fromList [((0,0),False),((0,1),False),((1,0),False),((1,1),True)])]]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "explodedRows testEg" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [], + "source": [ + "(>-<) g1 g2 = M.union g1 g2'\n", + " where (_, cm) = bounds g1\n", + " g2' = M.mapKeys (\\(r, c) -> (r, c + cm + 1)) g2" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [], + "source": [ + "(>|<) g1 g2 = M.union g1 g2'\n", + " where (rm, _) = bounds g1\n", + " g2' = M.mapKeys (\\(r, c) -> (r + rm + 1, c)) g2" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "fromList [((0,0),True),((0,1),False),((1,0),False),((1,1),False)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "M.findWithDefault M.empty (0, 0) testEg" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<style>/* Styles used for the Hoogle display in the pager */\n", + ".hoogle-doc {\n", + "display: block;\n", + "padding-bottom: 1.3em;\n", + "padding-left: 0.4em;\n", + "}\n", + ".hoogle-code {\n", + "display: block;\n", + "font-family: monospace;\n", + "white-space: pre;\n", + "}\n", + ".hoogle-text {\n", + "display: block;\n", + "}\n", + ".hoogle-name {\n", + "color: green;\n", + "font-weight: bold;\n", + "}\n", + ".hoogle-head {\n", + "font-weight: bold;\n", + "}\n", + ".hoogle-sub {\n", + "display: block;\n", + "margin-left: 0.4em;\n", + "}\n", + ".hoogle-package {\n", + "font-weight: bold;\n", + "font-style: italic;\n", + "}\n", + ".hoogle-module {\n", + "font-weight: bold;\n", + "}\n", + ".hoogle-class {\n", + "font-weight: bold;\n", + "}\n", + ".get-type {\n", + "color: green;\n", + "font-weight: bold;\n", + "font-family: monospace;\n", + "display: block;\n", + "white-space: pre-wrap;\n", + "}\n", + ".show-type {\n", + "color: green;\n", + "font-weight: bold;\n", + "font-family: monospace;\n", + "margin-left: 1em;\n", + "}\n", + ".mono {\n", + "font-family: monospace;\n", + "display: block;\n", + "}\n", + ".err-msg {\n", + "color: red;\n", + "font-style: italic;\n", + "font-family: monospace;\n", + "white-space: pre;\n", + "display: block;\n", + "}\n", + "#unshowable {\n", + "color: red;\n", + "font-weight: bold;\n", + "}\n", + ".err-msg.in.collapse {\n", + "padding-top: 0.7em;\n", + "}\n", + ".highlight-code {\n", + "white-space: pre;\n", + "font-family: monospace;\n", + "}\n", + ".suggestion-warning { \n", + "font-weight: bold;\n", + "color: rgb(200, 130, 0);\n", + "}\n", + ".suggestion-error { \n", + "font-weight: bold;\n", + "color: red;\n", + "}\n", + ".suggestion-name {\n", + "font-weight: bold;\n", + "}\n", + "</style><div class=\"suggestion-name\" style=\"clear:both;\">Redundant bracket</div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Found:</div><div class=\"highlight-code\" id=\"haskell\">(M.findWithDefault M.empty (0, 1) testEg) >-<\n", + " (M.findWithDefault M.empty (0, 0) testEg)</div></div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Why Not:</div><div class=\"highlight-code\" id=\"haskell\">M.findWithDefault M.empty (0, 1) testEg >-<\n", + " (M.findWithDefault M.empty (0, 0) testEg)</div></div><div class=\"suggestion-name\" style=\"clear:both;\">Redundant bracket</div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Found:</div><div class=\"highlight-code\" id=\"haskell\">(M.findWithDefault M.empty (0, 1) testEg) >-<\n", + " (M.findWithDefault M.empty (0, 0) testEg)</div></div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Why Not:</div><div class=\"highlight-code\" id=\"haskell\">(M.findWithDefault M.empty (0, 1) testEg) >-<\n", + " M.findWithDefault M.empty (0, 0) testEg</div></div>" + ], + "text/plain": [ + "Line 1: Redundant bracket\n", + "Found:\n", + "(M.findWithDefault M.empty (0, 1) testEg) >-<\n", + " (M.findWithDefault M.empty (0, 0) testEg)\n", + "Why not:\n", + "M.findWithDefault M.empty (0, 1) testEg >-<\n", + " (M.findWithDefault M.empty (0, 0) testEg)Line 1: Redundant bracket\n", + "Found:\n", + "(M.findWithDefault M.empty (0, 1) testEg) >-<\n", + " (M.findWithDefault M.empty (0, 0) testEg)\n", + "Why not:\n", + "(M.findWithDefault M.empty (0, 1) testEg) >-<\n", + " M.findWithDefault M.empty (0, 0) testEg" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "\".##.\\n....\\n\"" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "showGrid $ (M.findWithDefault M.empty (0, 1) testEg) >-< (M.findWithDefault M.empty (0, 0) testEg)" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<style>/* Styles used for the Hoogle display in the pager */\n", + ".hoogle-doc {\n", + "display: block;\n", + "padding-bottom: 1.3em;\n", + "padding-left: 0.4em;\n", + "}\n", + ".hoogle-code {\n", + "display: block;\n", + "font-family: monospace;\n", + "white-space: pre;\n", + "}\n", + ".hoogle-text {\n", + "display: block;\n", + "}\n", + ".hoogle-name {\n", + "color: green;\n", + "font-weight: bold;\n", + "}\n", + ".hoogle-head {\n", + "font-weight: bold;\n", + "}\n", + ".hoogle-sub {\n", + "display: block;\n", + "margin-left: 0.4em;\n", + "}\n", + ".hoogle-package {\n", + "font-weight: bold;\n", + "font-style: italic;\n", + "}\n", + ".hoogle-module {\n", + "font-weight: bold;\n", + "}\n", + ".hoogle-class {\n", + "font-weight: bold;\n", + "}\n", + ".get-type {\n", + "color: green;\n", + "font-weight: bold;\n", + "font-family: monospace;\n", + "display: block;\n", + "white-space: pre-wrap;\n", + "}\n", + ".show-type {\n", + "color: green;\n", + "font-weight: bold;\n", + "font-family: monospace;\n", + "margin-left: 1em;\n", + "}\n", + ".mono {\n", + "font-family: monospace;\n", + "display: block;\n", + "}\n", + ".err-msg {\n", + "color: red;\n", + "font-style: italic;\n", + "font-family: monospace;\n", + "white-space: pre;\n", + "display: block;\n", + "}\n", + "#unshowable {\n", + "color: red;\n", + "font-weight: bold;\n", + "}\n", + ".err-msg.in.collapse {\n", + "padding-top: 0.7em;\n", + "}\n", + ".highlight-code {\n", + "white-space: pre;\n", + "font-family: monospace;\n", + "}\n", + ".suggestion-warning { \n", + "font-weight: bold;\n", + "color: rgb(200, 130, 0);\n", + "}\n", + ".suggestion-error { \n", + "font-weight: bold;\n", + "color: red;\n", + "}\n", + ".suggestion-name {\n", + "font-weight: bold;\n", + "}\n", + "</style><div class=\"suggestion-name\" style=\"clear:both;\">Redundant bracket</div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Found:</div><div class=\"highlight-code\" id=\"haskell\">(M.findWithDefault M.empty (0, 1) testEg) >|<\n", + " (M.findWithDefault M.empty (0, 0) testEg)</div></div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Why Not:</div><div class=\"highlight-code\" id=\"haskell\">M.findWithDefault M.empty (0, 1) testEg >|<\n", + " (M.findWithDefault M.empty (0, 0) testEg)</div></div><div class=\"suggestion-name\" style=\"clear:both;\">Redundant bracket</div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Found:</div><div class=\"highlight-code\" id=\"haskell\">(M.findWithDefault M.empty (0, 1) testEg) >|<\n", + " (M.findWithDefault M.empty (0, 0) testEg)</div></div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Why Not:</div><div class=\"highlight-code\" id=\"haskell\">(M.findWithDefault M.empty (0, 1) testEg) >|<\n", + " M.findWithDefault M.empty (0, 0) testEg</div></div>" + ], + "text/plain": [ + "Line 1: Redundant bracket\n", + "Found:\n", + "(M.findWithDefault M.empty (0, 1) testEg) >|<\n", + " (M.findWithDefault M.empty (0, 0) testEg)\n", + "Why not:\n", + "M.findWithDefault M.empty (0, 1) testEg >|<\n", + " (M.findWithDefault M.empty (0, 0) testEg)Line 1: Redundant bracket\n", + "Found:\n", + "(M.findWithDefault M.empty (0, 1) testEg) >|<\n", + " (M.findWithDefault M.empty (0, 0) testEg)\n", + "Why not:\n", + "(M.findWithDefault M.empty (0, 1) testEg) >|<\n", + " M.findWithDefault M.empty (0, 0) testEg" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "\".#\\n..\\n#.\\n..\\n\"" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "showGrid $ (M.findWithDefault M.empty (0, 1) testEg) >|< (M.findWithDefault M.empty (0, 0) testEg)" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": {}, + "outputs": [], + "source": [ + "contractExploded :: ExplodedGrid -> Grid\n", + "contractExploded gs = foldl1 (>|<) $ map (foldl1 (>-<)) rows\n", + " where rows = explodedRows gs" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\"#..#\\n....\\n....\\n#..#\\n\"" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "showGrid $ contractExploded testEg" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "##.##.\n", + "#..#..\n", + "......\n", + "##.##.\n", + "#..#..\n", + "......" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "putStrLn $ showGrid $ contractExploded $ M.map (apply sampleRules) testEg" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": {}, + "outputs": [], + "source": [ + "applyOnce rules g = contractExploded $ M.map (apply rules) $ explodeGrid g" + ] + }, + { + "cell_type": "code", + "execution_count": 135, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + ".#.#.#.#..##..#.##\n", + ".#.#...#..##....##\n", + "..####..##..####..\n", + "..#.#..##.###.#.#.\n", + "....#..##.###...#.\n", + "###..##..#..###..#\n", + "..#.##..#.##.##...\n", + "....##....##.##.##\n", + "####..####..#..##.\n", + "#.#.#.#.#.#.....#.\n", + "#...#.#...#..##.#.\n", + "###..####..###...#\n", + "..#.##..#.##..#.##\n", + "....##....##....##\n", + "####..####..####..\n", + "#.#.#.#.#.#.#.#.#.\n", + "#...#.#...#.#...#.\n", + "###..####..####..#" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "putStrLn $ showGrid $ (!! 5) $ iterate (applyOnce rules) initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 131, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + ".#\n", + "##" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "putStrLn $ showGrid $ (!(1, 2)) $ explodeGrid $ last $ take 3 $ iterate (applyOnce rules) initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 136, + "metadata": {}, + "outputs": [], + "source": [ + "countLit = M.size . M.filter id" + ] + }, + { + "cell_type": "code", + "execution_count": 137, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "countLit initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 142, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "##.##.\n", + "#..#..\n", + "......\n", + "##.##.\n", + "#..#..\n", + "......" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "putStrLn $ showGrid $ (!! 2) $ iterate (applyOnce sampleRules) initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 143, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "12" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "countLit $ (!! 2) $ iterate (applyOnce sampleRules) initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 144, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "158" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "countLit $ (!! 5) $ iterate (applyOnce rules) initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2301762" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "countLit $ (!! 18) $ iterate (applyOnce rules) initialGrid" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Haskell", + "language": "haskell", + "name": "haskell" + }, + "language_info": { + "codemirror_mode": "ihaskell", + "file_extension": ".hs", + "name": "haskell", + "version": "8.0.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}