From 8307ab6717ea4ceaff6691cbc3fc5acf70335f79 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Sat, 25 Dec 2021 22:16:37 +0000 Subject: [PATCH 01/16] Done day 21 part 2 --- advent-of-code21.cabal | 2 +- advent21/Main.hs | 90 ++++++++++++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/advent-of-code21.cabal b/advent-of-code21.cabal index 121c742..b760b36 100644 --- a/advent-of-code21.cabal +++ b/advent-of-code21.cabal @@ -210,4 +210,4 @@ executable advent20 executable advent21 import: common-extensions, build-directives main-is: advent21/Main.hs - build-depends: text, attoparsec, mtl, containers, monad-loops + build-depends: text, attoparsec, containers, multiset diff --git a/advent21/Main.hs b/advent21/Main.hs index 5a76130..f187b98 100644 --- a/advent21/Main.hs +++ b/advent21/Main.hs @@ -1,8 +1,11 @@ -- Writeup at https://work.njae.me.uk/2021/12/23/advent-of-code-2021-day-20/ +import Debug.Trace + + import Data.Text () import qualified Data.Text.IO as TIO -import Data.Attoparsec.Text hiding (take, takeWhile, dropWhile) +import Data.Attoparsec.Text hiding (take, takeWhile) import Control.Applicative -- import Control.Monad.State.Strict @@ -13,19 +16,34 @@ import Control.Applicative import qualified Data.Map.Strict as M import Data.Map.Strict ((!)) +import Data.List +import qualified Data.MultiSet as MS data Player = Player1 | Player2 deriving (Eq, Ord, Show) data PlayerState = PlayerState { position :: Int , score :: Int - } deriving (Eq, Show) + } deriving (Eq, Ord, Show) data Game = Game { players :: M.Map Player PlayerState , current :: Player , rolls :: Int - } deriving (Eq, Show) + } deriving (Eq, Ord) + +type Games = MS.MultiSet Game +type Dice = MS.MultiSet Int +type Winners = MS.MultiSet Player + + +instance Show Game where + + show game = "{" ++ (showPlayer Player1) ++ (showActive) ++ (showPlayer Player2) ++ "}" + where showPlayer p = (show $ position $ (players game) ! p) ++ "," ++ (show $ score $ (players game) ! p) + showActive = if (current game) == Player1 then "<" else ">" + + -- type GameState = State Game @@ -35,32 +53,34 @@ main :: IO () main = do text <- TIO.readFile "data/advent21.txt" let game = successfulParse text - print game - print $ gameStep game - print $ take 8 $ iterate gameStep game - print $ finished game print $ part1 game - -- let (enhancement, image) = parse text - -- print $ part1 enhancement image - -- print $ part2 enhancement image + print $ part2 game part1 game = scoreGame finalGame - where finalGame = head $ dropWhile (not . finished) $ iterate gameStep game + where finalGame = head $ dropWhile (not . finished 1000) $ scanl' gameStep game detDice + detDice = map (\n -> sum ([d `mod1` 100 | d <- [n..(n+2)]]::[Int])) [1, 4..] + +part2 game = max (Player1 `MS.occur` winners) (Player2 `MS.occur` winners) + where games0 = MS.singleton game + winners0 = MS.empty + winners = nonDetGameSimulation 21 games0 diracDice winners0 -finished game = any (>= 1000) $ map score $ M.elems (players game) +finished :: Int -> Game -> Bool +finished threshold game = any (>= threshold) $ map score $ M.elems (players game) +scoreGame :: Game -> Int scoreGame game = (rolls game) * losingScore where losingScore = minimum $ map score $ M.elems (players game) +diracDice :: Dice +diracDice = MS.fromList [a + b + c | a <- [1..3], b <- [1..3], c <- [1..3]] -gameStep :: Game -> Game -gameStep game = game' - where rs = rolls game + 1 - theseRolls = [n `mod1` 100 | n <- [rs..(rs + 2)]] :: [Int] - activePlayer = (players game) ! (current game) +gameStep :: Game -> Int -> Game +gameStep game theseRolls = game' + where activePlayer = (players game) ! (current game) pos = position activePlayer sc = score activePlayer - pos' = (pos + (sum theseRolls)) `mod1` 10 + pos' = (pos + theseRolls) `mod1` 10 sc' = sc + pos' activePlayer' = PlayerState {position = pos', score = sc'} current' = nextPlayer (current game) @@ -70,8 +90,36 @@ gameStep game = game' , rolls = rolls game + 3 } - - +nonDetGameSimulation :: Int -> Games -> Dice -> Winners -> Winners +nonDetGameSimulation winThreshold games0 dice winners0 + -- | trace ((show games0) ++ "; " ++ (show winners0)) False = undefined + -- | trace (show winners0) False = undefined + | MS.null games0 = winners0 + | otherwise = nonDetGameSimulation winThreshold games dice winners + where games' = nonDetGameStep games0 dice + (winGames, games) = MS.partition (finished winThreshold) games' + p1Wins = MS.size $ MS.filter (\g -> current g == Player2) winGames + p2Wins = MS.size $ MS.filter (\g -> current g == Player1) winGames + winners = MS.insertMany Player2 p2Wins $ MS.insertMany Player1 p1Wins winners0 + +nonDetGameStep :: Games -> Dice -> Games +nonDetGameStep games dice = MS.foldOccur (nonDetGameStep1 dice) MS.empty games +-- nonDetGameStep games dice + -- | trace ("G0 >" ++ (show games) ++ "-" ++ (show dice)) False = undefined + -- | otherwise = MS.foldOccur (nonDetGameStep1 games) MS.empty dice + +nonDetGameStep1 :: Dice -> Game -> MS.Occur -> Games -> Games +nonDetGameStep1 dice game gnum acc = MS.foldOccur (nonDetGameStep2 game gnum) MS.empty dice +-- nonDetGameStep1 game dice dnum acc + -- | trace ("G1 >" ++ (show game) ++ "-" ++ (show dice) ++ ": " ++ (show gnum)) False = undefined + -- | otherwise = MS.foldOccur (nonDetGameStep2 dice dnum) acc game + +nonDetGameStep2 :: Game -> MS.Occur -> Int -> MS.Occur -> Games -> Games +nonDetGameStep2 game gnum roll dnum acc = MS.insertMany game' (gnum * dnum) acc +-- nonDetGameStep2 dice dnum game gnum acc + -- | trace ("G2 >" ++ (show game) ++ "-" ++ (show dice) ++ ": " ++ (show gnum) ++ "," ++ (show dnum)) False = undefined + -- | otherwise = MS.insertMany game' (gnum * dnum) acc + where game' = gameStep game roll nextPlayer :: Player -> Player @@ -81,6 +129,8 @@ nextPlayer Player2 = Player1 mod1 :: Int -> Int -> Int mod1 a b = ((a - 1) `mod` b) + 1 + + -- Parsing playerP = ("1" *> pure Player1) <|> ("2" *> pure Player2) -- 2.34.1 From 86f61207669563aa3134ec14d52555b12bd7860c Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Sat, 25 Dec 2021 22:20:34 +0000 Subject: [PATCH 02/16] Added day 21 problem --- advent21/Main.hs | 7 +- problems/day21.html | 156 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 problems/day21.html diff --git a/advent21/Main.hs b/advent21/Main.hs index f187b98..536176f 100644 --- a/advent21/Main.hs +++ b/advent21/Main.hs @@ -44,11 +44,6 @@ instance Show Game where showActive = if (current game) == Player1 then "<" else ">" - - --- type GameState = State Game - - main :: IO () main = do text <- TIO.readFile "data/advent21.txt" @@ -109,7 +104,7 @@ nonDetGameStep games dice = MS.foldOccur (nonDetGameStep1 dice) MS.empty games -- | otherwise = MS.foldOccur (nonDetGameStep1 games) MS.empty dice nonDetGameStep1 :: Dice -> Game -> MS.Occur -> Games -> Games -nonDetGameStep1 dice game gnum acc = MS.foldOccur (nonDetGameStep2 game gnum) MS.empty dice +nonDetGameStep1 dice game gnum acc = MS.foldOccur (nonDetGameStep2 game gnum) acc dice -- nonDetGameStep1 game dice dnum acc -- | trace ("G1 >" ++ (show game) ++ "-" ++ (show dice) ++ ": " ++ (show gnum)) False = undefined -- | otherwise = MS.foldOccur (nonDetGameStep2 dice dnum) acc game diff --git a/problems/day21.html b/problems/day21.html new file mode 100644 index 0000000..2dc8837 --- /dev/null +++ b/problems/day21.html @@ -0,0 +1,156 @@ + + + + +Day 21 - Advent of Code 2021 + + + + + + + +

Advent of Code

Neil Smith (AoC++) 42*

  {:year 2021}

+ + + +
+ +

--- Day 21: Dirac Dice ---

There's not much to do as you slowly descend to the bottom of the ocean. The submarine computer challenges you to a nice game of Dirac Dice.

+

This game consists of a single die, two pawns, and a game board with a circular track containing ten spaces marked 1 through 10 clockwise. Each player's starting space is chosen randomly (your puzzle input). Player 1 goes first.

+

Players take turns moving. On each player's turn, the player rolls the die three times and adds up the results. Then, the player moves their pawn that many times forward around the track (that is, moving clockwise on spaces in order of increasing value, wrapping back around to 1 after 10). So, if a player is on space 7 and they roll 2, 2, and 1, they would move forward 5 times, to spaces 8, 9, 10, 1, and finally stopping on 2.

+

After each player moves, they increase their score by the value of the space their pawn stopped on. Players' scores start at 0. So, if the first player starts on space 7 and rolls a total of 5, they would stop on space 2 and add 2 to their score (for a total score of 2). The game immediately ends as a win for any player whose score reaches at least 1000.

+

Since the first game is a practice game, the submarine opens a compartment labeled deterministic dice and a 100-sided die falls out. This die always rolls 1 first, then 2, then 3, and so on up to 100, after which it starts over at 1 again. Play using this die.

+

For example, given these starting positions:

+
Player 1 starting position: 4
+Player 2 starting position: 8
+
+

This is how the game would go:

+
    +
  • Player 1 rolls 1+2+3 and moves to space 10 for a total score of 10.
  • +
  • Player 2 rolls 4+5+6 and moves to space 3 for a total score of 3.
  • +
  • Player 1 rolls 7+8+9 and moves to space 4 for a total score of 14.
  • +
  • Player 2 rolls 10+11+12 and moves to space 6 for a total score of 9.
  • +
  • Player 1 rolls 13+14+15 and moves to space 6 for a total score of 20.
  • +
  • Player 2 rolls 16+17+18 and moves to space 7 for a total score of 16.
  • +
  • Player 1 rolls 19+20+21 and moves to space 6 for a total score of 26.
  • +
  • Player 2 rolls 22+23+24 and moves to space 6 for a total score of 22.
  • +
+

...after many turns...

+
    +
  • Player 2 rolls 82+83+84 and moves to space 6 for a total score of 742.
  • +
  • Player 1 rolls 85+86+87 and moves to space 4 for a total score of 990.
  • +
  • Player 2 rolls 88+89+90 and moves to space 3 for a total score of 745.
  • +
  • Player 1 rolls 91+92+93 and moves to space 10 for a final score, 1000.
  • +
+

Since player 1 has at least 1000 points, player 1 wins and the game ends. At this point, the losing player had 745 points and the die had been rolled a total of 993 times; 745 * 993 = 739785.

+

Play a practice game using the deterministic 100-sided die. The moment either player wins, what do you get if you multiply the score of the losing player by the number of times the die was rolled during the game?

+
+

Your puzzle answer was 734820.

--- Part Two ---

Now that you're warmed up, it's time to play the real game.

+

A second compartment opens, this time labeled Dirac dice. Out of it falls a single three-sided die.

+

As you experiment with the die, you feel a little strange. An informational brochure in the compartment explains that this is a quantum die: when you roll it, the universe splits into multiple copies, one copy for each possible outcome of the die. In this case, rolling the die always splits the universe into three copies: one where the outcome of the roll was 1, one where it was 2, and one where it was 3.

+

The game is played the same as before, although to prevent things from getting too far out of hand, the game now ends when either player's score reaches at least 21.

+

Using the same starting positions as in the example above, player 1 wins in 444356092776315 universes, while player 2 merely wins in 341960390180808 universes.

+

Using your given starting positions, determine every possible outcome. Find the player that wins in more universes; in how many universes does that player win?

+
+

Your puzzle answer was 193170338541590.

Both parts of this puzzle are complete! They provide two gold stars: **

+

At this point, you should return to your Advent calendar and try another puzzle.

+

If you still want to see it, you can get your puzzle input.

+

You can also this puzzle.

+
+ + + + + + \ No newline at end of file -- 2.34.1 From 64b373b65e3acb209038196ee9f2b54b97b306fe Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Mon, 27 Dec 2021 15:25:16 +0000 Subject: [PATCH 03/16] Tweaks --- advent21/Main.hs | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/advent21/Main.hs b/advent21/Main.hs index 536176f..191530e 100644 --- a/advent21/Main.hs +++ b/advent21/Main.hs @@ -1,19 +1,12 @@ --- Writeup at https://work.njae.me.uk/2021/12/23/advent-of-code-2021-day-20/ +-- Writeup at https://work.njae.me.uk/2021/12/26/advent-of-code-2021-day-21/ import Debug.Trace - import Data.Text () import qualified Data.Text.IO as TIO import Data.Attoparsec.Text hiding (take, takeWhile) import Control.Applicative --- import Control.Monad.State.Strict --- import Control.Monad.Reader --- import Control.Monad.Writer --- import Control.Monad.RWS.Strict --- import Control.Monad.Loops - import qualified Data.Map.Strict as M import Data.Map.Strict ((!)) import Data.List @@ -36,9 +29,7 @@ type Games = MS.MultiSet Game type Dice = MS.MultiSet Int type Winners = MS.MultiSet Player - instance Show Game where - show game = "{" ++ (showPlayer Player1) ++ (showActive) ++ (showPlayer Player2) ++ "}" where showPlayer p = (show $ position $ (players game) ! p) ++ "," ++ (show $ score $ (players game) ! p) showActive = if (current game) == Player1 then "<" else ">" @@ -98,22 +89,16 @@ nonDetGameSimulation winThreshold games0 dice winners0 winners = MS.insertMany Player2 p2Wins $ MS.insertMany Player1 p1Wins winners0 nonDetGameStep :: Games -> Dice -> Games +-- nonDetGameStep games dice | trace ("G0 >" ++ (show games) ++ "-" ++ (show dice)) False = undefined nonDetGameStep games dice = MS.foldOccur (nonDetGameStep1 dice) MS.empty games --- nonDetGameStep games dice - -- | trace ("G0 >" ++ (show games) ++ "-" ++ (show dice)) False = undefined - -- | otherwise = MS.foldOccur (nonDetGameStep1 games) MS.empty dice nonDetGameStep1 :: Dice -> Game -> MS.Occur -> Games -> Games +-- nonDetGameStep1 dice game gnum acc | trace ("G1 >" ++ (show game) ++ "-" ++ (show dice) ++ ": " ++ (show gnum)) False = undefined nonDetGameStep1 dice game gnum acc = MS.foldOccur (nonDetGameStep2 game gnum) acc dice --- nonDetGameStep1 game dice dnum acc - -- | trace ("G1 >" ++ (show game) ++ "-" ++ (show dice) ++ ": " ++ (show gnum)) False = undefined - -- | otherwise = MS.foldOccur (nonDetGameStep2 dice dnum) acc game nonDetGameStep2 :: Game -> MS.Occur -> Int -> MS.Occur -> Games -> Games +-- nonDetGameStep2 dice dnum game gnum acc | trace ("G2 >" ++ (show game) ++ "-" ++ (show dice) ++ ": " ++ (show gnum) ++ "," ++ (show dnum)) False = undefined nonDetGameStep2 game gnum roll dnum acc = MS.insertMany game' (gnum * dnum) acc --- nonDetGameStep2 dice dnum game gnum acc - -- | trace ("G2 >" ++ (show game) ++ "-" ++ (show dice) ++ ": " ++ (show gnum) ++ "," ++ (show dnum)) False = undefined - -- | otherwise = MS.insertMany game' (gnum * dnum) acc where game' = gameStep game roll -- 2.34.1 From e2b15781f674220586e860fb9a85b6ad0f278fad Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Wed, 29 Dec 2021 10:56:43 +0000 Subject: [PATCH 04/16] Done day 22 --- advent-of-code21.cabal | 5 + advent22/Main.hs | 112 +++++++++++ data/advent22.txt | 420 +++++++++++++++++++++++++++++++++++++++++ data/advent22a.txt | 4 + data/advent22b.txt | 22 +++ problems/day22.html | 287 ++++++++++++++++++++++++++++ 6 files changed, 850 insertions(+) create mode 100644 advent22/Main.hs create mode 100644 data/advent22.txt create mode 100644 data/advent22a.txt create mode 100644 data/advent22b.txt create mode 100644 problems/day22.html diff --git a/advent-of-code21.cabal b/advent-of-code21.cabal index b760b36..8ba8f78 100644 --- a/advent-of-code21.cabal +++ b/advent-of-code21.cabal @@ -211,3 +211,8 @@ executable advent21 import: common-extensions, build-directives main-is: advent21/Main.hs build-depends: text, attoparsec, containers, multiset + +executable advent22 + import: common-extensions, build-directives + main-is: advent22/Main.hs + build-depends: linear, text, attoparsec, containers, lens diff --git a/advent22/Main.hs b/advent22/Main.hs new file mode 100644 index 0000000..51c7a8e --- /dev/null +++ b/advent22/Main.hs @@ -0,0 +1,112 @@ +-- Writeup at https://work.njae.me.uk/2021/12/21/advent-of-code-2021-day-19/ + +import Data.Text () +import qualified Data.Text.IO as TIO +import Data.Attoparsec.Text -- hiding (take, takeWhile) +import Control.Applicative + +import Linear -- (V3(..), (^+^), (^-^)) +-- import Linear.V3 +-- import Data.Ix +import Control.Lens +import Data.List + +type Coord = V3 Int + +data Parity = On | Off deriving (Eq, Ord, Show) + +data Cuboid = Cuboid + { _bounds :: (Coord, Coord) + , _parity :: Parity + , _time :: Int + } + deriving (Ord, Eq, Show) +makeLenses ''Cuboid + +-- Main + +main :: IO () +main = + do text <- TIO.readFile "data/advent22.txt" + let cuboids = successfulParse text + print $ part1 cuboids + print $ part2 cuboids + -- print $ part2 transScanners + + +part1 cuboids = sweepX (filter isLocal cuboids) +part2 cuboids = sweepX cuboids + +isLocal :: Cuboid -> Bool +isLocal cuboid = all (>= (- 50)) ls && all (<= 50) hs + where ls = [cuboid ^. bounds . _1 . c | c <- [_x, _y, _z]] :: [Int] + hs = [cuboid ^. bounds . _2 . c | c <- [_x, _y, _z]] :: [Int] + +straddles :: (Lens' (V3 Int) Int) -> Int -> Cuboid -> Bool +straddles f here cuboid = + ((cuboid ^. bounds . _1 . f) <= here) && ((cuboid ^. bounds . _2 . f) >= here) + +events :: (Lens' (V3 Int) Int) -> [Cuboid] -> [Int] +events f cuboids = nub $ sort $ ls ++ hs + where ls = map (^. bounds . _1 . f) cuboids + hs = map ((+1) . (^. bounds . _2 . f)) cuboids + +isActive :: [Cuboid] -> Bool +isActive [] = False +isActive cs = ((last scs) ^. parity) == On + where scs = sortOn (^. time) cs + +sweepX :: [Cuboid] -> Int +sweepX cuboids = sum $ map (volumeSize cuboids) segments + where evs = events _x cuboids + segments = if null evs then [] else zip evs $ tail evs + +volumeSize :: [Cuboid] -> (Int, Int) -> Int +volumeSize cuboids (here, there) = (sweepY cuboidsHere) * (there - here) + where cuboidsHere = filter (straddles _x here) cuboids + +sweepY :: [Cuboid] -> Int +sweepY cuboids = sum $ map (areaSize cuboids) segments + where evs = events _y cuboids + segments = if null evs then [] else zip evs $ tail evs + +areaSize :: [Cuboid] -> (Int, Int) -> Int +areaSize cuboids (here, there) = (countActive cuboidsHere) * (there - here) + where cuboidsHere = filter (straddles _y here) cuboids + +-- assume for a given x and y. +countActive :: [Cuboid] -> Int +countActive cuboids = sum $ map (segmentSize cuboids) segments + where evs = events _z cuboids + segments = if null evs then [] else zip evs $ tail evs + +segmentSize :: [Cuboid] -> (Int, Int) -> Int +segmentSize cuboids (here, there) + | isActive $ filter (straddles _z here) cuboids = (there - here) + | otherwise = 0 + + +-- Parse the input file + +cuboidsP = timeify <$> cuboidP `sepBy` endOfLine + where timeify cuboids = map (\(c, n) -> c & time .~ n) $ zip cuboids [0..] + +cuboidP = cubify <$> (partiyP <* " ") <*> (boundsP `sepBy` ",") + where cubify p ranges = + Cuboid { _parity = p + , _bounds = ( vecify (map fst ranges) + , vecify (map snd ranges) + ) + , _time = 0 + } + vecify [c1, c2, c3] = V3 c1 c2 c3 + +partiyP = ("on" *> pure On) <|> ("off" *> pure Off) + +boundsP = (,) <$> (("x" <|> "y" <|> "z") *> "=" *> signed decimal) <*> (".." *> signed decimal) + +-- successfulParse :: Text -> (Integer, [Maybe Integer]) +successfulParse input = + case parseOnly cuboidsP input of + Left _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err + Right cuboids -> cuboids diff --git a/data/advent22.txt b/data/advent22.txt new file mode 100644 index 0000000..67ef470 --- /dev/null +++ b/data/advent22.txt @@ -0,0 +1,420 @@ +on x=-14..32,y=-22..28,z=-25..26 +on x=-20..32,y=-3..46,z=-33..18 +on x=-21..31,y=-37..11,z=-9..43 +on x=-21..25,y=-26..27,z=-25..26 +on x=-23..29,y=-36..13,z=-5..47 +on x=-9..42,y=-6..42,z=-11..38 +on x=-41..11,y=-47..5,z=-6..43 +on x=-21..23,y=-38..13,z=0..46 +on x=-14..30,y=-19..28,z=-47..-2 +on x=-19..25,y=-7..41,z=1..47 +off x=29..42,y=-16..-1,z=-31..-14 +on x=-10..36,y=-17..34,z=-47..-2 +off x=8..22,y=-49..-36,z=-29..-12 +on x=-25..19,y=-18..32,z=-2..45 +off x=5..20,y=-26..-11,z=17..28 +on x=-38..16,y=-11..37,z=-41..8 +off x=36..47,y=-42..-23,z=8..21 +on x=-38..14,y=-2..45,z=-16..34 +off x=10..21,y=21..34,z=-18..-5 +on x=-7..41,y=-20..31,z=-9..39 +on x=-34984..-26543,y=51648..78707,z=2562..28760 +on x=-86882..-76628,y=-3025..23665,z=212..25252 +on x=16968..25727,y=-63916..-50529,z=-66385..-32536 +on x=51240..58676,y=-70513..-53482,z=-5723..-2181 +on x=25522..47536,y=59856..75899,z=-26563..-20675 +on x=-47427..-29230,y=263..15871,z=60551..73934 +on x=-49066..-32558,y=-83794..-57151,z=-12695..9141 +on x=7952..11761,y=-87854..-74674,z=-33510..-18712 +on x=14813..45800,y=-88090..-59749,z=-16138..19384 +on x=54962..82735,y=-51202..-41420,z=-6277..3174 +on x=28570..39632,y=3948..23664,z=59429..92252 +on x=10173..34690,y=54298..71815,z=33766..47516 +on x=-30040..-8528,y=47135..59588,z=53864..79134 +on x=52995..78066,y=34652..67693,z=-1410..11141 +on x=-59744..-30776,y=-69920..-47945,z=-40419..-23586 +on x=-45505..-36193,y=-7591..6204,z=-81897..-56319 +on x=-27185..4367,y=70914..91278,z=-37549..-6146 +on x=68299..85401,y=-2668..18702,z=7949..38736 +on x=-48016..-39417,y=-30061..-131,z=47316..67163 +on x=18922..45171,y=45663..74414,z=29341..45641 +on x=-83234..-54027,y=44109..52468,z=-4481..28200 +on x=11096..21770,y=-29415..3025,z=75030..79682 +on x=-12391..240,y=-82180..-59968,z=-62792..-43281 +on x=-21740..3314,y=-76672..-50745,z=-67582..-45134 +on x=24006..40635,y=-54293..-32906,z=56194..75600 +on x=-64832..-51947,y=36327..54090,z=-31747..-13348 +on x=-5630..3784,y=25936..35775,z=-79445..-55695 +on x=59474..79536,y=11162..20087,z=-43239..-21997 +on x=-42704..-21476,y=42749..67408,z=45494..62514 +on x=-67338..-34016,y=39691..52934,z=23922..46990 +on x=36..29262,y=-66430..-64048,z=-47255..-32882 +on x=-49961..-23854,y=-33575..-17917,z=60474..79383 +on x=-95438..-61587,y=-6573..12719,z=-16659..7687 +on x=48747..57111,y=-45643..-33863,z=-52117..-25721 +on x=-7911..10806,y=69265..78676,z=-43705..-9526 +on x=-33044..-7074,y=-57853..-34320,z=36878..55690 +on x=-28089..-14737,y=-90786..-66686,z=-38515..-12841 +on x=28657..34475,y=51064..66504,z=-44706..-31406 +on x=-38352..-7921,y=-36628..-19091,z=69614..89173 +on x=33444..62541,y=-86297..-62055,z=-25558..3049 +on x=-7893..9364,y=45810..68816,z=-63710..-26796 +on x=-96852..-63618,y=-23272..5127,z=-21228..13510 +on x=49451..80375,y=-17005..5647,z=32766..48164 +on x=1216..23787,y=-79871..-70398,z=-39246..-12428 +on x=8110..28804,y=-23683..-6255,z=-86978..-60413 +on x=-91843..-64794,y=21641..32187,z=-25519..1600 +on x=-84702..-60659,y=24066..41911,z=-2842..13228 +on x=-84116..-50874,y=-2116..24626,z=39105..47345 +on x=-69707..-49086,y=-58246..-33874,z=-49108..-19140 +on x=-80374..-57833,y=-39663..-9105,z=37441..56461 +on x=-65366..-33730,y=43099..59734,z=12904..42440 +on x=-37882..-15459,y=55202..81928,z=29196..57759 +on x=-73714..-66268,y=-42342..-22053,z=-1577..17395 +on x=-45347..-18358,y=-71639..-50205,z=34719..43466 +on x=62119..93299,y=-38373..-6511,z=-19061..-12726 +on x=68788..79926,y=-26182..-6654,z=64..29378 +on x=-3163..19750,y=60505..90174,z=-29340..-4768 +on x=38014..51952,y=-55129..-41022,z=-53465..-43181 +on x=-83575..-54103,y=-38626..-8427,z=-58305..-26823 +on x=57418..75464,y=32685..55142,z=27632..47860 +on x=17409..43096,y=-14819..5247,z=56286..91172 +on x=-57542..-38853,y=-36026..-22716,z=-53467..-44559 +on x=-54395..-40763,y=53537..74971,z=8637..31681 +on x=-83350..-54446,y=-44870..-26661,z=5069..27109 +on x=45158..67479,y=29868..51352,z=-34080..-27306 +on x=-35037..1444,y=-27954..-14736,z=69985..75566 +on x=-48243..-29989,y=48513..72378,z=-846..11192 +on x=16940..34441,y=-23094..-20006,z=55993..84391 +on x=-80060..-74149,y=-19098..-6716,z=-8014..22908 +on x=-35703..-13805,y=-1750..11794,z=-79543..-68729 +on x=19096..49179,y=-19061..6100,z=-90095..-61586 +on x=-5759..12300,y=-24129..1598,z=-78131..-71335 +on x=-80107..-59282,y=18788..28926,z=-32218..-18671 +on x=17906..47185,y=70542..86767,z=-15303..-7410 +on x=-50011..-41176,y=-65664..-47330,z=-31467..145 +on x=-65064..-54780,y=30369..47688,z=-27259..-9116 +on x=-41200..-25966,y=8286..16030,z=-80485..-71406 +on x=-25005..-8465,y=-62425..-39883,z=-73910..-49104 +on x=-90073..-65919,y=-40041..-6842,z=11821..34815 +on x=-9863..5212,y=62942..73336,z=-49611..-32481 +on x=-72450..-53738,y=25669..61019,z=-42767..-33000 +on x=70524..79427,y=11137..21973,z=-33847..-17549 +on x=-33296..-22111,y=38021..42133,z=58536..63703 +on x=40059..62864,y=-31079..-21302,z=-64201..-54154 +on x=-15941..12092,y=7536..15873,z=78034..86183 +on x=-41500..-15959,y=33851..48026,z=-74834..-41086 +on x=-59083..-38668,y=-13350..-2027,z=49484..73174 +on x=-4095..8756,y=-64780..-51492,z=49645..62452 +on x=-31361..-12314,y=-38990..-20332,z=-90545..-56684 +on x=-46362..-38435,y=61213..80598,z=-30242..-4160 +on x=4406..10923,y=39319..59618,z=41980..76407 +on x=42541..67135,y=-62451..-39506,z=16125..24314 +on x=-88856..-63914,y=-41550..-6971,z=-36441..-10957 +on x=-57870..-29367,y=62111..87873,z=346..8417 +on x=25365..57215,y=-51965..-37423,z=-68675..-54847 +on x=-42073..-20908,y=-29544..-2756,z=-79732..-58011 +on x=-91232..-69039,y=-19067..-15167,z=-7422..7651 +on x=-79660..-56222,y=-40850..-16219,z=-53704..-34791 +on x=-28030..-19052,y=54771..59286,z=47770..61473 +on x=4679..8347,y=-68490..-37569,z=-71691..-54025 +on x=-36261..-33968,y=65152..87454,z=15069..23461 +on x=-57397..-32767,y=-26556..-7367,z=-61244..-50883 +on x=6647..43596,y=-65890..-33847,z=-60762..-39595 +on x=44139..81693,y=-18393..3971,z=41751..54896 +on x=58964..89245,y=-29574..-47,z=-37566..-18941 +on x=7903..23182,y=77128..82135,z=-26489..-3834 +on x=-53964..-36089,y=23028..34027,z=49791..71611 +on x=-42773..-30730,y=37521..59454,z=34775..47152 +on x=62682..94006,y=-28953..-20439,z=-2866..11849 +on x=-74328..-48322,y=13265..43861,z=30215..41614 +on x=28122..34699,y=32573..53783,z=64261..71660 +on x=25714..53862,y=32522..40741,z=44640..64380 +on x=5135..26963,y=66487..77359,z=-28927..-5750 +on x=53256..67009,y=42403..62040,z=-18273..3659 +on x=2724..22380,y=-71266..-50543,z=-51153..-23711 +on x=14732..36928,y=69759..80965,z=-14161..-1907 +on x=2221..11122,y=-2798..25790,z=75480..80705 +on x=-8779..12240,y=-52629..-41036,z=-79171..-44613 +on x=-78433..-58051,y=15556..26838,z=-63149..-36913 +on x=47350..65323,y=24442..41722,z=17632..48332 +on x=-87960..-72048,y=10138..40520,z=-28933..-22155 +on x=-70110..-51730,y=-53097..-48326,z=15171..33120 +on x=-42568..-22819,y=43046..63237,z=31102..53381 +on x=30352..42731,y=50048..74026,z=34360..45595 +on x=-75575..-60339,y=-49604..-26199,z=-30633..-26441 +on x=-39156..-11816,y=-7319..31334,z=-78526..-66890 +on x=63486..78527,y=-42319..-24356,z=-28097..5129 +on x=65275..77354,y=25121..50655,z=10107..44272 +on x=-15735..-8751,y=-80245..-59369,z=-45141..-22290 +on x=-22200..-16116,y=2819..20817,z=-92548..-73896 +on x=27288..32028,y=-56404..-45837,z=40665..65602 +on x=-87559..-65472,y=-7140..1719,z=-34450..150 +on x=65413..90229,y=12624..27783,z=-22210..-11015 +on x=52662..68206,y=-2927..12091,z=51623..58483 +on x=449..20528,y=58423..86096,z=-30314..-6386 +on x=28651..54782,y=67421..87042,z=-10822..18948 +on x=-2097..26946,y=55130..71111,z=48439..55954 +on x=-400..28565,y=30492..45291,z=-86975..-68022 +on x=-21933..11975,y=58104..64964,z=-52315..-37205 +on x=24194..42657,y=-8955..10900,z=61373..88513 +on x=-65768..-40461,y=-59729..-45233,z=1323..23698 +on x=44198..65990,y=-8536..10867,z=-62699..-49680 +on x=-92079..-66561,y=-42535..-10970,z=-28894..-6059 +on x=58008..85453,y=-30345..-15668,z=-28123..-16771 +on x=-41605..-10850,y=-89020..-56631,z=-38968..-24180 +on x=1405..24877,y=-8086..5054,z=73018..83807 +on x=57620..79914,y=-44641..-37383,z=11175..28207 +on x=-86076..-54704,y=20502..30827,z=902..30801 +on x=-9203..17788,y=-92465..-75253,z=-41423..-19571 +on x=-45664..-33915,y=-70403..-62505,z=4945..21199 +on x=37619..56309,y=49836..79516,z=-32494..-9948 +on x=-21412..3869,y=-59795..-57282,z=-67147..-47843 +on x=-6408..12811,y=76516..98300,z=-11383..12528 +on x=-11591..-3910,y=55667..65005,z=36361..59408 +on x=31944..43301,y=54028..66235,z=-43324..-9651 +on x=29667..49469,y=37069..52070,z=-65427..-36883 +on x=-47659..-25192,y=26924..37825,z=57768..80653 +on x=54447..87516,y=4450..27816,z=-50280..-19273 +on x=63625..74718,y=-43042..-17884,z=6860..19348 +on x=-37001..-25122,y=-84208..-55034,z=5805..29579 +on x=8593..23288,y=28927..60647,z=-66517..-51182 +on x=56272..86054,y=-35040..-11786,z=-4650..7567 +on x=24182..55820,y=-41430..-27777,z=49216..79902 +on x=53831..60772,y=-11415..12136,z=53987..64682 +on x=14912..30906,y=-72651..-41298,z=43838..63318 +on x=5745..25358,y=18835..35588,z=59119..84625 +on x=-26685..-11191,y=59709..88104,z=-6467..11125 +on x=-28912..3937,y=-15004..8700,z=-98360..-61633 +on x=-12903..2361,y=17..18248,z=-81715..-64855 +on x=45615..72644,y=-71598..-37550,z=-2676..19050 +on x=32929..68025,y=-37995..-23876,z=-58571..-48665 +on x=20720..27000,y=-85746..-62454,z=-42881..-29570 +on x=9751..32735,y=72223..82214,z=-615..26936 +on x=-54778..-31244,y=-51548..-34864,z=51437..67846 +on x=-95867..-62875,y=8059..39412,z=-16075..-8463 +on x=-58617..-29914,y=65524..80535,z=-160..14882 +on x=-97175..-66019,y=6732..13442,z=-5054..-4537 +on x=9909..22956,y=43932..69310,z=49991..62879 +on x=10307..26798,y=-58449..-22603,z=56161..69364 +on x=-52418..-35038,y=20797..32859,z=47367..68176 +on x=50865..70613,y=25950..55232,z=1715..18345 +on x=31261..50752,y=57062..67534,z=-10578..3620 +on x=-30718..-20498,y=-81224..-49610,z=-43224..-27822 +on x=-47016..-42262,y=-17054..3287,z=56582..68954 +on x=65759..75369,y=10302..34231,z=9079..37287 +on x=-81428..-45144,y=-38882..-18217,z=22946..47183 +on x=22364..47688,y=-9944..10518,z=-75657..-58786 +on x=-59323..-27735,y=-40586..-19558,z=48616..61066 +on x=-44355..-21766,y=44377..55344,z=-65666..-54938 +on x=7551..24890,y=-59803..-45594,z=-71713..-53395 +on x=21051..46459,y=-15141..11457,z=-81430..-55097 +on x=28451..40401,y=50600..73922,z=26258..48802 +on x=65359..73866,y=5848..25953,z=-41269..-12089 +on x=50437..79435,y=-12375..-3496,z=-56754..-34377 +on x=42960..71465,y=-50596..-33356,z=38051..53128 +on x=56065..83859,y=-12331..15724,z=-44672..-25006 +on x=43816..61467,y=-27854..3321,z=-66359..-46311 +on x=46419..71959,y=15799..49190,z=19825..42092 +on x=12762..19545,y=35492..53207,z=-76222..-59251 +on x=-29359..8800,y=-40020..-18365,z=59128..91042 +on x=-57633..-35906,y=11786..31613,z=-71153..-45879 +off x=-28805..-17956,y=-59888..-43012,z=42648..74611 +off x=-42643..-19588,y=-78988..-65222,z=-21724..-13301 +off x=-27666..-4093,y=25817..52990,z=-78773..-62002 +on x=-44447..-22010,y=-4350..8087,z=71792..76443 +off x=-52436..-36521,y=58187..60171,z=-30877..-5785 +off x=30949..54850,y=-80253..-51446,z=-42817..-17759 +off x=-12430..2289,y=67850..78580,z=-22187..-9886 +on x=78033..83816,y=-6411..2621,z=-16082..17718 +on x=6033..26840,y=46920..61676,z=-62786..-60371 +on x=41642..68702,y=-31557..-6225,z=-46944..-32045 +off x=42328..54839,y=-36837..-25464,z=44803..67696 +on x=-4696..9727,y=-78316..-61064,z=-43010..-25992 +off x=2577..5831,y=33478..50260,z=-74134..-59334 +off x=44509..59254,y=-46525..-24266,z=-52032..-29431 +on x=-49736..-39595,y=44340..73878,z=14131..27812 +on x=-5708..2717,y=-4707..26547,z=-82128..-73256 +off x=-3861..22852,y=20675..37847,z=62464..82612 +on x=-61797..-34749,y=-69661..-56672,z=-23152..-3146 +off x=-2151..11187,y=11086..15192,z=-98635..-74513 +on x=75566..89896,y=-6282..21295,z=-9410..15219 +on x=-6221..29338,y=-79154..-53916,z=38043..44917 +off x=-58367..-51748,y=44711..51127,z=-48861..-27655 +off x=-70068..-49996,y=-28609..-6512,z=34004..47719 +on x=73203..84184,y=7347..28289,z=25524..44263 +off x=-20438..6097,y=-78991..-53563,z=-62000..-43052 +off x=-74573..-47172,y=-50896..-27703,z=29260..43117 +off x=-64917..-43787,y=-69200..-48743,z=-4493..1817 +off x=-4740..6426,y=-79627..-55329,z=-35575..-19230 +off x=37671..67456,y=-20558..10079,z=-64509..-58127 +on x=-57773..-36494,y=43821..60372,z=-40639..-14709 +off x=42010..54972,y=-58161..-45494,z=13543..22941 +off x=-10472..11730,y=58458..92017,z=-34884..-19062 +on x=42614..70836,y=-58228..-25353,z=9183..41819 +off x=-71437..-59603,y=-18631..-1205,z=42785..55274 +on x=-11633..11598,y=-88188..-70416,z=-45039..-15775 +off x=-34786..-18384,y=48292..76994,z=27707..41300 +off x=67987..91582,y=-24892..-6216,z=-27519..-4073 +off x=-95863..-71402,y=-12803..-5538,z=-18344..-6375 +off x=-48801..-32636,y=-28613..-11153,z=-89670..-63018 +off x=-71768..-40216,y=26550..36989,z=30142..63385 +on x=37884..68214,y=39248..55995,z=25722..49328 +on x=70565..75222,y=-20619..-3412,z=27935..52930 +off x=-21598..2011,y=74781..81100,z=-25987..-3855 +on x=-75036..-61874,y=-32562..-5327,z=-50998..-41765 +off x=-63523..-41725,y=5688..29199,z=44858..71165 +off x=61744..82331,y=19706..33500,z=-8681..23550 +on x=-13018..1939,y=-85134..-70690,z=21016..26881 +off x=46091..63616,y=-9027..9805,z=47979..67694 +on x=-43168..-23185,y=38140..73548,z=-70403..-45064 +on x=-21826..-15877,y=-4769..2487,z=-88364..-72521 +on x=-45604..-19621,y=-42328..-27813,z=41716..64795 +off x=-37807..-6478,y=62634..81953,z=21871..40083 +off x=-86239..-52437,y=-34061..-24158,z=6635..22285 +off x=-10046..8212,y=-57826..-42350,z=-64233..-50000 +off x=-23400..-15200,y=20821..46657,z=-69259..-61044 +off x=63800..85169,y=25545..36274,z=1181..9243 +off x=34365..46983,y=60399..70159,z=-9350..10407 +off x=75052..91805,y=-6284..14904,z=-12646..5614 +off x=-12868..17859,y=26208..52846,z=69112..89483 +on x=-76644..-57162,y=-7449..5409,z=44619..49339 +on x=-80361..-62758,y=-39442..-4968,z=-22736..3121 +off x=-13708..17868,y=-84516..-60741,z=28313..59460 +on x=-61365..-27022,y=60283..79040,z=12734..34211 +on x=59390..88366,y=3645..19175,z=10089..27184 +on x=64326..76729,y=-41855..-20943,z=-15727..12390 +on x=-35669..-15225,y=-75232..-71544,z=14793..22177 +on x=1446..19605,y=30027..41625,z=-90629..-64444 +on x=-15642..-2359,y=-37513..-9009,z=60067..77543 +off x=42909..63915,y=42085..55920,z=26312..61750 +off x=68237..77060,y=-8177..10878,z=22063..39904 +on x=-79592..-61745,y=-43270..-22274,z=-15365..-7259 +on x=-26948..-1541,y=-70070..-35808,z=34287..67722 +off x=-1759..21632,y=51902..66240,z=-58961..-38669 +off x=62017..99124,y=8399..25845,z=-6825..4625 +on x=-81423..-45456,y=37042..58320,z=5711..35366 +on x=-82431..-70294,y=30267..46149,z=-21442..-8817 +on x=-50291..-18766,y=62669..89780,z=13362..37144 +on x=-57455..-30808,y=-33781..-25716,z=-62288..-49278 +off x=69408..77145,y=-30227..-3558,z=-8412..13712 +on x=61933..69888,y=-12888..12859,z=27164..54531 +off x=-72176..-58281,y=-30439..-3646,z=33760..57845 +on x=7054..12401,y=16053..38787,z=71624..93039 +on x=-82557..-56975,y=-9661..7083,z=-49481..-37495 +off x=-63291..-52165,y=38518..66467,z=-21283..-6110 +off x=16118..33266,y=14334..21585,z=-83237..-54922 +on x=-83749..-57908,y=-4258..16963,z=-39970..-37018 +off x=-40166..-19345,y=31883..67052,z=37110..67786 +off x=53380..67985,y=30237..59055,z=10510..26125 +on x=63305..68408,y=40812..49109,z=-19691..-270 +on x=7857..29425,y=-67019..-30697,z=-66136..-49059 +on x=-6691..14066,y=8113..20816,z=68185..83416 +off x=56395..68976,y=-41328..-8083,z=29277..56422 +off x=42604..60191,y=-46774..-17713,z=-70387..-40480 +on x=44483..57415,y=22283..48790,z=32064..54994 +on x=17474..35769,y=-66687..-45930,z=-58457..-49847 +off x=15183..27040,y=77008..79727,z=5346..23053 +on x=57382..83244,y=-1506..16227,z=-42975..-26600 +off x=-76269..-59043,y=-39996..-15892,z=-5245..9633 +off x=-48720..-38320,y=-82501..-50743,z=-30445..3452 +off x=44165..72746,y=-56976..-44779,z=20590..51329 +off x=31202..50559,y=-76566..-68717,z=1071..25360 +off x=48638..68694,y=39421..47200,z=-54744..-25005 +on x=-14094..4575,y=-83328..-65186,z=-34311..-29606 +off x=-19001..4040,y=-81894..-59810,z=-36960..-18967 +on x=30791..52076,y=-25832..-4223,z=-73089..-56794 +off x=-93615..-62412,y=-19037..11194,z=-14911..-3294 +on x=-25222..7078,y=-71358..-40442,z=49313..70622 +off x=34344..62044,y=6210..11031,z=60071..75518 +off x=-36155..-19629,y=-67617..-54197,z=-36930..-25462 +off x=14784..49665,y=56247..79695,z=-40721..-10725 +off x=45116..56902,y=-57539..-36970,z=-38837..-6838 +off x=-74240..-58205,y=40561..53888,z=-36015..-10174 +on x=-20339..7554,y=-96016..-65717,z=3050..11613 +on x=11773..47908,y=-81962..-63309,z=4806..34070 +off x=30557..49760,y=-58795..-43120,z=35993..53984 +off x=-52744..-19296,y=9807..25934,z=-79649..-49636 +on x=50803..83487,y=5479..33026,z=38339..61575 +on x=-70483..-50069,y=-49499..-47847,z=19537..32373 +on x=22443..26988,y=12955..44140,z=-79590..-63366 +on x=66174..78169,y=22686..40038,z=-8573..13730 +off x=62989..80551,y=-37830..-4601,z=-43297..-12723 +on x=53257..56713,y=34533..53556,z=26835..31575 +off x=-4031..7654,y=8509..39962,z=-81694..-67518 +off x=57233..71094,y=27227..54883,z=10536..37871 +on x=-70015..-61633,y=25435..48517,z=-49774..-30793 +off x=-93287..-56846,y=-43238..-6705,z=-755..14291 +on x=46390..75500,y=48598..66176,z=11222..19821 +off x=-33580..-11644,y=66170..90004,z=-34066..-6888 +on x=-52264..-22145,y=-59771..-39731,z=-48084..-35038 +on x=27471..41952,y=21493..51568,z=63607..68568 +off x=35677..61663,y=-38988..-27710,z=-59698..-34034 +on x=-12750..7828,y=76570..89565,z=-9478..-2925 +on x=-83435..-59885,y=9514..27522,z=-32652..-7881 +on x=44111..55856,y=-15541..11579,z=50997..67817 +on x=-22587..7924,y=-47534..-25646,z=56797..91101 +on x=-49141..-19337,y=-4798..4186,z=-80631..-56013 +off x=42136..65030,y=-16965..-1971,z=40298..60536 +on x=-42229..-34266,y=-69343..-51015,z=9907..27353 +on x=10687..25863,y=-43246..-37990,z=-80771..-54026 +off x=-76786..-59333,y=-34403..-28720,z=21847..36652 +off x=-30992..-13228,y=-2730..11499,z=-80125..-58916 +off x=65153..93773,y=18808..27693,z=-3847..9938 +off x=-2776..20701,y=28706..54514,z=-73135..-60817 +on x=60981..91265,y=-38749..-27891,z=-411..17743 +off x=-54774..-33840,y=-50944..-31833,z=36016..68503 +on x=-56457..-42433,y=-31957..-17376,z=-67116..-39975 +on x=-66548..-58154,y=6529..38361,z=-43401..-33610 +on x=-86989..-63673,y=1246..25535,z=-29251..-13027 +off x=-63939..-36393,y=58956..74942,z=14817..20781 +on x=8693..22260,y=-40321..-24946,z=-79188..-50768 +on x=41600..58375,y=-42108..-14086,z=51334..72807 +off x=23909..36369,y=-88428..-69824,z=4151..21692 +off x=39444..56689,y=38940..48175,z=-54864..-34971 +off x=-1029..21273,y=-52735..-43901,z=-74676..-47912 +on x=39722..48576,y=-47808..-36179,z=-54647..-33662 +on x=-46883..-23410,y=-75362..-58864,z=-49691..-14864 +on x=-45647..-11809,y=-80750..-61164,z=-58949..-35240 +on x=-65456..-42409,y=-24374..-17014,z=54398..75575 +on x=39202..51304,y=42703..59340,z=16019..36596 +off x=-57900..-42577,y=36780..51719,z=-53715..-32242 +on x=32591..58935,y=52680..81095,z=-11789..17287 +on x=-59966..-41440,y=-66646..-35336,z=-23770..-2743 +on x=19804..29351,y=-48957..-37599,z=-81246..-53109 +off x=-36..17904,y=-5338..21145,z=-79404..-61902 +on x=-39881..-31460,y=-86863..-57518,z=4307..22680 +off x=-25806..-11126,y=56665..87855,z=-26783..-4947 +on x=-25407..-17465,y=8784..45426,z=-80441..-63533 +off x=46122..78812,y=-64720..-41608,z=-20340..-3282 +on x=-21418..-6135,y=28527..45821,z=-74932..-63067 +off x=23344..47538,y=57629..72961,z=-15693..8596 +off x=-11839..6967,y=19341..34049,z=-89713..-60630 +on x=-45928..-37032,y=32356..52368,z=-66659..-40545 +on x=-86673..-53256,y=-44328..-16315,z=14485..35041 +on x=2034..20139,y=53326..81029,z=39047..50387 +off x=-81855..-73071,y=-10471..3245,z=-14114..-3707 +on x=70037..76368,y=12668..35400,z=-35982..-8580 +off x=32997..62535,y=-27698..-14203,z=-61911..-36153 +on x=-29767..-15210,y=63013..73940,z=-37989..-4125 +off x=-42214..-34753,y=-31073..-18734,z=-75221..-58111 +on x=-51293..-37459,y=-65903..-40128,z=30775..47506 +on x=-28933..-18510,y=-35296..-4760,z=54010..82629 +off x=55947..81197,y=-52157..-15817,z=15934..45009 +on x=-54644..-35512,y=-89321..-61207,z=-26266..3023 +on x=51084..75115,y=-46798..-32970,z=12847..16751 +on x=-31877..-1755,y=-16518..6949,z=76605..84122 +off x=-12076..20354,y=23633..59717,z=50871..78154 +on x=7581..23640,y=-85279..-54514,z=-49510..-19917 +on x=-79844..-68838,y=-49312..-17949,z=-7165..25085 +on x=-24243..3171,y=9716..31566,z=-81170..-65766 +off x=-74462..-58771,y=-3480..26616,z=-42553..-23900 +off x=-48143..-38553,y=42767..59814,z=30402..48166 +off x=33860..48294,y=-54872..-43212,z=34467..49090 +off x=40140..46896,y=-15654..9520,z=51719..87495 +off x=-69166..-61577,y=28458..40680,z=16037..37970 +off x=14225..35212,y=-86212..-67164,z=-34232..-24202 +off x=58187..73377,y=33943..39219,z=-18273..-5694 +on x=-42848..-21135,y=-52454..-36140,z=50130..82337 +on x=-80976..-60546,y=1460..28768,z=-4463..32217 +on x=-47037..-29197,y=63702..92015,z=-7785..16238 \ No newline at end of file diff --git a/data/advent22a.txt b/data/advent22a.txt new file mode 100644 index 0000000..4d036d6 --- /dev/null +++ b/data/advent22a.txt @@ -0,0 +1,4 @@ +on x=10..12,y=10..12,z=10..12 +on x=11..13,y=11..13,z=11..13 +off x=9..11,y=9..11,z=9..11 +on x=10..10,y=10..10,z=10..10 \ No newline at end of file diff --git a/data/advent22b.txt b/data/advent22b.txt new file mode 100644 index 0000000..8c68bc7 --- /dev/null +++ b/data/advent22b.txt @@ -0,0 +1,22 @@ +on x=-20..26,y=-36..17,z=-47..7 +on x=-20..33,y=-21..23,z=-26..28 +on x=-22..28,y=-29..23,z=-38..16 +on x=-46..7,y=-6..46,z=-50..-1 +on x=-49..1,y=-3..46,z=-24..28 +on x=2..47,y=-22..22,z=-23..27 +on x=-27..23,y=-28..26,z=-21..29 +on x=-39..5,y=-6..47,z=-3..44 +on x=-30..21,y=-8..43,z=-13..34 +on x=-22..26,y=-27..20,z=-29..19 +off x=-48..-32,y=26..41,z=-47..-37 +on x=-12..35,y=6..50,z=-50..-2 +off x=-48..-32,y=-32..-16,z=-15..-5 +on x=-18..26,y=-33..15,z=-7..46 +off x=-40..-22,y=-38..-28,z=23..41 +on x=-16..35,y=-41..10,z=-47..6 +off x=-32..-23,y=11..30,z=-14..3 +on x=-49..-5,y=-3..45,z=-29..18 +off x=18..30,y=-20..-8,z=-3..13 +on x=-41..9,y=-7..43,z=-33..15 +on x=-54112..-39298,y=-85059..-49293,z=-27449..7877 +on x=967..23432,y=45373..81175,z=27513..53682 \ No newline at end of file diff --git a/problems/day22.html b/problems/day22.html new file mode 100644 index 0000000..5a3bc45 --- /dev/null +++ b/problems/day22.html @@ -0,0 +1,287 @@ + + + + +Day 22 - Advent of Code 2021 + + + + + + + +
+ + + +
+ +

--- Day 22: Reactor Reboot ---

Operating at these extreme ocean depths has overloaded the submarine's reactor; it needs to be rebooted.

+

The reactor core is made up of a large 3-dimensional grid made up entirely of cubes, one cube per integer 3-dimensional coordinate (x,y,z). Each cube can be either on or off; at the start of the reboot process, they are all off. (Could it be an old model of a reactor you've seen before?)

+

To reboot the reactor, you just need to set all of the cubes to either on or off by following a list of reboot steps (your puzzle input). Each step specifies a cuboid (the set of all cubes that have coordinates which fall within ranges for x, y, and z) and whether to turn all of the cubes in that cuboid on or off.

+

For example, given these reboot steps:

+
on x=10..12,y=10..12,z=10..12
+on x=11..13,y=11..13,z=11..13
+off x=9..11,y=9..11,z=9..11
+on x=10..10,y=10..10,z=10..10
+
+

The first step (on x=10..12,y=10..12,z=10..12) turns on a 3x3x3 cuboid consisting of 27 cubes:

+
    +
  • 10,10,10
  • +
  • 10,10,11
  • +
  • 10,10,12
  • +
  • 10,11,10
  • +
  • 10,11,11
  • +
  • 10,11,12
  • +
  • 10,12,10
  • +
  • 10,12,11
  • +
  • 10,12,12
  • +
  • 11,10,10
  • +
  • 11,10,11
  • +
  • 11,10,12
  • +
  • 11,11,10
  • +
  • 11,11,11
  • +
  • 11,11,12
  • +
  • 11,12,10
  • +
  • 11,12,11
  • +
  • 11,12,12
  • +
  • 12,10,10
  • +
  • 12,10,11
  • +
  • 12,10,12
  • +
  • 12,11,10
  • +
  • 12,11,11
  • +
  • 12,11,12
  • +
  • 12,12,10
  • +
  • 12,12,11
  • +
  • 12,12,12
  • +
+

The second step (on x=11..13,y=11..13,z=11..13) turns on a 3x3x3 cuboid that overlaps with the first. As a result, only 19 additional cubes turn on; the rest are already on from the previous step:

+
    +
  • 11,11,13
  • +
  • 11,12,13
  • +
  • 11,13,11
  • +
  • 11,13,12
  • +
  • 11,13,13
  • +
  • 12,11,13
  • +
  • 12,12,13
  • +
  • 12,13,11
  • +
  • 12,13,12
  • +
  • 12,13,13
  • +
  • 13,11,11
  • +
  • 13,11,12
  • +
  • 13,11,13
  • +
  • 13,12,11
  • +
  • 13,12,12
  • +
  • 13,12,13
  • +
  • 13,13,11
  • +
  • 13,13,12
  • +
  • 13,13,13
  • +
+

The third step (off x=9..11,y=9..11,z=9..11) turns off a 3x3x3 cuboid that overlaps partially with some cubes that are on, ultimately turning off 8 cubes:

+
    +
  • 10,10,10
  • +
  • 10,10,11
  • +
  • 10,11,10
  • +
  • 10,11,11
  • +
  • 11,10,10
  • +
  • 11,10,11
  • +
  • 11,11,10
  • +
  • 11,11,11
  • +
+

The final step (on x=10..10,y=10..10,z=10..10) turns on a single cube, 10,10,10. After this last step, 39 cubes are on.

+

The initialization procedure only uses cubes that have x, y, and z positions of at least -50 and at most 50. For now, ignore cubes outside this region.

+

Here is a larger example:

+
on x=-20..26,y=-36..17,z=-47..7
+on x=-20..33,y=-21..23,z=-26..28
+on x=-22..28,y=-29..23,z=-38..16
+on x=-46..7,y=-6..46,z=-50..-1
+on x=-49..1,y=-3..46,z=-24..28
+on x=2..47,y=-22..22,z=-23..27
+on x=-27..23,y=-28..26,z=-21..29
+on x=-39..5,y=-6..47,z=-3..44
+on x=-30..21,y=-8..43,z=-13..34
+on x=-22..26,y=-27..20,z=-29..19
+off x=-48..-32,y=26..41,z=-47..-37
+on x=-12..35,y=6..50,z=-50..-2
+off x=-48..-32,y=-32..-16,z=-15..-5
+on x=-18..26,y=-33..15,z=-7..46
+off x=-40..-22,y=-38..-28,z=23..41
+on x=-16..35,y=-41..10,z=-47..6
+off x=-32..-23,y=11..30,z=-14..3
+on x=-49..-5,y=-3..45,z=-29..18
+off x=18..30,y=-20..-8,z=-3..13
+on x=-41..9,y=-7..43,z=-33..15
+on x=-54112..-39298,y=-85059..-49293,z=-27449..7877
+on x=967..23432,y=45373..81175,z=27513..53682
+
+

The last two steps are fully outside the initialization procedure area; all other steps are fully within it. After executing these steps in the initialization procedure region, 590784 cubes are on.

+

Execute the reboot steps. Afterward, considering only cubes in the region x=-50..50,y=-50..50,z=-50..50, how many cubes are on?

+
+

Your puzzle answer was 545118.

--- Part Two ---

Now that the initialization procedure is complete, you can reboot the reactor.

+

Starting with all cubes off, run all of the reboot steps for all cubes in the reactor.

+

Consider the following reboot steps:

+
on x=-5..47,y=-31..22,z=-19..33
+on x=-44..5,y=-27..21,z=-14..35
+on x=-49..-1,y=-11..42,z=-10..38
+on x=-20..34,y=-40..6,z=-44..1
+off x=26..39,y=40..50,z=-2..11
+on x=-41..5,y=-41..6,z=-36..8
+off x=-43..-33,y=-45..-28,z=7..25
+on x=-33..15,y=-32..19,z=-34..11
+off x=35..47,y=-46..-34,z=-11..5
+on x=-14..36,y=-6..44,z=-16..29
+on x=-57795..-6158,y=29564..72030,z=20435..90618
+on x=36731..105352,y=-21140..28532,z=16094..90401
+on x=30999..107136,y=-53464..15513,z=8553..71215
+on x=13528..83982,y=-99403..-27377,z=-24141..23996
+on x=-72682..-12347,y=18159..111354,z=7391..80950
+on x=-1060..80757,y=-65301..-20884,z=-103788..-16709
+on x=-83015..-9461,y=-72160..-8347,z=-81239..-26856
+on x=-52752..22273,y=-49450..9096,z=54442..119054
+on x=-29982..40483,y=-108474..-28371,z=-24328..38471
+on x=-4958..62750,y=40422..118853,z=-7672..65583
+on x=55694..108686,y=-43367..46958,z=-26781..48729
+on x=-98497..-18186,y=-63569..3412,z=1232..88485
+on x=-726..56291,y=-62629..13224,z=18033..85226
+on x=-110886..-34664,y=-81338..-8658,z=8914..63723
+on x=-55829..24974,y=-16897..54165,z=-121762..-28058
+on x=-65152..-11147,y=22489..91432,z=-58782..1780
+on x=-120100..-32970,y=-46592..27473,z=-11695..61039
+on x=-18631..37533,y=-124565..-50804,z=-35667..28308
+on x=-57817..18248,y=49321..117703,z=5745..55881
+on x=14781..98692,y=-1341..70827,z=15753..70151
+on x=-34419..55919,y=-19626..40991,z=39015..114138
+on x=-60785..11593,y=-56135..2999,z=-95368..-26915
+on x=-32178..58085,y=17647..101866,z=-91405..-8878
+on x=-53655..12091,y=50097..105568,z=-75335..-4862
+on x=-111166..-40997,y=-71714..2688,z=5609..50954
+on x=-16602..70118,y=-98693..-44401,z=5197..76897
+on x=16383..101554,y=4615..83635,z=-44907..18747
+off x=-95822..-15171,y=-19987..48940,z=10804..104439
+on x=-89813..-14614,y=16069..88491,z=-3297..45228
+on x=41075..99376,y=-20427..49978,z=-52012..13762
+on x=-21330..50085,y=-17944..62733,z=-112280..-30197
+on x=-16478..35915,y=36008..118594,z=-7885..47086
+off x=-98156..-27851,y=-49952..43171,z=-99005..-8456
+off x=2032..69770,y=-71013..4824,z=7471..94418
+on x=43670..120875,y=-42068..12382,z=-24787..38892
+off x=37514..111226,y=-45862..25743,z=-16714..54663
+off x=25699..97951,y=-30668..59918,z=-15349..69697
+off x=-44271..17935,y=-9516..60759,z=49131..112598
+on x=-61695..-5813,y=40978..94975,z=8655..80240
+off x=-101086..-9439,y=-7088..67543,z=33935..83858
+off x=18020..114017,y=-48931..32606,z=21474..89843
+off x=-77139..10506,y=-89994..-18797,z=-80..59318
+off x=8476..79288,y=-75520..11602,z=-96624..-24783
+on x=-47488..-1262,y=24338..100707,z=16292..72967
+off x=-84341..13987,y=2429..92914,z=-90671..-1318
+off x=-37810..49457,y=-71013..-7894,z=-105357..-13188
+off x=-27365..46395,y=31009..98017,z=15428..76570
+off x=-70369..-16548,y=22648..78696,z=-1892..86821
+on x=-53470..21291,y=-120233..-33476,z=-44150..38147
+off x=-93533..-4276,y=-16170..68771,z=-104985..-24507
+
+

After running the above reboot steps, 2758514936282235 cubes are on. (Just for fun, 474140 of those are also in the initialization procedure region.)

+

Starting again with all cubes off, execute all reboot steps. Afterward, considering all cubes, how many cubes are on?

+
+

Your puzzle answer was 1227298136842375.

Both parts of this puzzle are complete! They provide two gold stars: **

+

At this point, you should return to your Advent calendar and try another puzzle.

+

If you still want to see it, you can get your puzzle input.

+

You can also this puzzle.

+
+ + + + + + \ No newline at end of file -- 2.34.1 From 063d9534648f286c83f6f26ae619cd670acfcc4a Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Wed, 29 Dec 2021 16:46:28 +0000 Subject: [PATCH 05/16] Tidyied day 22 --- advent22/Main.hs | 24 +- problems/day21-x10.svg | 5455 +++++++++++++++++++++++++++++++++++++++ problems/day21-x11.svg | 5457 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 10922 insertions(+), 14 deletions(-) create mode 100644 problems/day21-x10.svg create mode 100644 problems/day21-x11.svg diff --git a/advent22/Main.hs b/advent22/Main.hs index 51c7a8e..3712b67 100644 --- a/advent22/Main.hs +++ b/advent22/Main.hs @@ -1,13 +1,11 @@ --- Writeup at https://work.njae.me.uk/2021/12/21/advent-of-code-2021-day-19/ +-- Writeup at https://work.njae.me.uk/2021/12/29/advent-of-code-2021-day-22/ import Data.Text () import qualified Data.Text.IO as TIO import Data.Attoparsec.Text -- hiding (take, takeWhile) import Control.Applicative -import Linear -- (V3(..), (^+^), (^-^)) --- import Linear.V3 --- import Data.Ix +import Linear import Control.Lens import Data.List @@ -31,8 +29,6 @@ main = let cuboids = successfulParse text print $ part1 cuboids print $ part2 cuboids - -- print $ part2 transScanners - part1 cuboids = sweepX (filter isLocal cuboids) part2 cuboids = sweepX cuboids @@ -57,34 +53,34 @@ isActive cs = ((last scs) ^. parity) == On where scs = sortOn (^. time) cs sweepX :: [Cuboid] -> Int -sweepX cuboids = sum $ map (volumeSize cuboids) segments +sweepX cuboids = sum $ map (volumeSize cuboids) $ segment evs where evs = events _x cuboids - segments = if null evs then [] else zip evs $ tail evs volumeSize :: [Cuboid] -> (Int, Int) -> Int volumeSize cuboids (here, there) = (sweepY cuboidsHere) * (there - here) where cuboidsHere = filter (straddles _x here) cuboids +-- assume for a given x sweepY :: [Cuboid] -> Int -sweepY cuboids = sum $ map (areaSize cuboids) segments +sweepY cuboids = sum $ map (areaSize cuboids) $ segment evs where evs = events _y cuboids - segments = if null evs then [] else zip evs $ tail evs areaSize :: [Cuboid] -> (Int, Int) -> Int -areaSize cuboids (here, there) = (countActive cuboidsHere) * (there - here) +areaSize cuboids (here, there) = (sweepZ cuboidsHere) * (there - here) where cuboidsHere = filter (straddles _y here) cuboids -- assume for a given x and y. -countActive :: [Cuboid] -> Int -countActive cuboids = sum $ map (segmentSize cuboids) segments +sweepZ :: [Cuboid] -> Int +sweepZ cuboids = sum $ map (segmentSize cuboids) $ segment evs where evs = events _z cuboids - segments = if null evs then [] else zip evs $ tail evs segmentSize :: [Cuboid] -> (Int, Int) -> Int segmentSize cuboids (here, there) | isActive $ filter (straddles _z here) cuboids = (there - here) | otherwise = 0 +segment :: [Int] -> [(Int, Int)] +segment evs = if null evs then [] else zip evs $ tail evs -- Parse the input file diff --git a/problems/day21-x10.svg b/problems/day21-x10.svg new file mode 100644 index 0000000..3e2e3e9 --- /dev/null +++ b/problems/day21-x10.svg @@ -0,0 +1,5455 @@ + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + y + + + + + + z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + + + + + + 9 + + + + + + 10 + + + + + + 11 + + + + + + 13 + + + + + + 14 + + + + + + 12 + + + + + + 8 + + + + + + 9 + + + + + + 10 + + + + + + 11 + + + + + + 12 + + + + + + 13 + + + + + + 14 + + + + + + x = 10 + + + + + + + + diff --git a/problems/day21-x11.svg b/problems/day21-x11.svg new file mode 100644 index 0000000..0827324 --- /dev/null +++ b/problems/day21-x11.svg @@ -0,0 +1,5457 @@ + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + y + + + + + + z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + + + + + + 9 + + + + + + 10 + + + + + + 11 + + + + + + 13 + + + + + + 14 + + + + + + 12 + + + + + + 8 + + + + + + 9 + + + + + + 10 + + + + + + 11 + + + + + + 12 + + + + + + 13 + + + + + + 14 + + + + + + x = 11 + + + + + + + + -- 2.34.1 From de1fcea0ec1190169209dc5be726b66f1be14afe Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Sun, 2 Jan 2022 18:37:04 +0000 Subject: [PATCH 06/16] Done day 23 --- advent-of-code21.cabal | 7 +- advent23/Main.hs | 343 +++++++++++++++++++++++++++++++++ data/advent23.txt | 5 + data/advent23a.txt | 5 + problems/day23.html | 420 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 779 insertions(+), 1 deletion(-) create mode 100644 advent23/Main.hs create mode 100644 data/advent23.txt create mode 100644 data/advent23a.txt create mode 100644 problems/day23.html diff --git a/advent-of-code21.cabal b/advent-of-code21.cabal index 8ba8f78..6fd1c09 100644 --- a/advent-of-code21.cabal +++ b/advent-of-code21.cabal @@ -43,7 +43,7 @@ common common-extensions , NamedFieldPuns , NegativeLiterals , NumDecimals - , OverloadedLists + -- , OverloadedLists , OverloadedStrings , PartialTypeSignatures , PatternGuards @@ -216,3 +216,8 @@ executable advent22 import: common-extensions, build-directives main-is: advent22/Main.hs build-depends: linear, text, attoparsec, containers, lens + +executable advent23 + import: common-extensions, build-directives + main-is: advent23/Main.hs + build-depends: containers, linear, pqueue, mtl, lens diff --git a/advent23/Main.hs b/advent23/Main.hs new file mode 100644 index 0000000..2666769 --- /dev/null +++ b/advent23/Main.hs @@ -0,0 +1,343 @@ +-- Writeup at https://work.njae.me.uk/2021/12/16/advent-of-code-2021-day-15/ + +import Debug.Trace + + +import qualified Data.PQueue.Prio.Min as P +import qualified Data.Set as S +import qualified Data.Sequence as Q +import Data.Sequence ((<|), (|>), (><)) --, ViewR( (:>) ), ViewL( (:<) )) +import qualified Data.Map.Strict as M +import Data.Map.Strict ((!)) +import Data.Foldable (foldl', sum) -- (toList, foldr', foldl', all) +-- import Data.Char +import Control.Monad.Reader +import Control.Lens hiding ((<|), (|>), (:>), (:<)) +import Data.Maybe -- (fromMaybe) +-- import Linear (V2(..), (^+^)) --, (^-^), (*^), (^*)) +import Linear hiding (trace) + + + +pattern Empty <- (Q.viewl -> Q.EmptyL) where Empty = Q.empty +pattern x :< xs <- (Q.viewl -> x Q.:< xs) where (:<) = (Q.<|) +pattern xs :> x <- (Q.viewr -> xs Q.:> x) where (:>) = (Q.|>) + + +data Amphipod = A | B | C | D deriving (Show, Read, Eq, Ord, Enum) + +type Coord = V2 Int -- r, c +_r :: Lens' (V2 Int) Int +_r = _x +_c :: Lens' (V2 Int) Int +_c = _y + +data Step = Step + { _destination :: Coord + , _distance :: Int + , _transits :: S.Set Coord + , _entryRequirement :: Maybe Amphipod + } deriving (Show, Eq, Ord) +makeLenses ''Step + +type Steps = M.Map Coord (S.Set Step) + +data Burrow = Burrow + { _possibleSteps :: Steps + , _roomColumns :: M.Map Amphipod Int + , _hallRow :: Int + } deriving (Show, Eq) +makeLenses ''Burrow + +type BurrowContext = Reader Burrow + +type MoveState = M.Map Coord Amphipod + +data AppliedMove = AppliedMove + { _afterMove :: MoveState + , _appliedStep :: Step + } + deriving (Show, Eq, Ord) +makeLenses ''AppliedMove + +data Agendum = + Agendum { _current :: MoveState + , _trail :: Q.Seq MoveState + , _trailCost :: Int + , _cost :: Int + } deriving (Show, Eq) +makeLenses ''Agendum + +type Agenda = P.MinPQueue Int Agendum + +type ExploredStates = S.Set MoveState + + + +main :: IO () +main = + do text <- readFile "data/advent23.txt" + -- let (burrow, initState) = mkBurrow text + -- print burrow + -- print initState + print $ part1 text + print $ part2 text + + +-- part1 :: Burrow -> MoveState -> Int +part1 text = maybe 0 _cost result + where + (burrow, initState) = mkBurrow text + result = runReader (searchBurrow initState) burrow + +part2 text = maybe 0 _cost result + where + rows = lines text + extraRows = [(" #D#C#B#A# " :: String), (" #D#B#A#C# " :: String)] + modifiedRows = (take 3 rows) ++ extraRows ++ (drop 3 rows) + modifiedText = unlines modifiedRows + (burrow, initState) = mkBurrow modifiedText + result = runReader (searchBurrow initState) burrow + + +searchBurrow :: MoveState -> BurrowContext (Maybe Agendum) +searchBurrow initState = + do agenda <- initAgenda initState + aStar agenda S.empty + +initAgenda :: MoveState -> BurrowContext Agenda +initAgenda initState = + do c <- estimateCost initState + return $ P.singleton c Agendum { _current = initState + , _trail = Q.empty, _trailCost = 0, _cost = c} + + +aStar :: Agenda -> ExploredStates -> BurrowContext (Maybe Agendum) +aStar agenda closed + -- | trace ("Peeping " ++ (show $ fst $ P.findMin agenda) ++ ": " ++ (show reached) ++ " <- " ++ (show $ toList $ Q.take 1 $ _trail $ currentAgendum) ++ " :: " ++ (show newAgenda)) False = undefined + -- | trace ("Peeping " ++ (show $ _current $ snd $ P.findMin agenda) ) False = undefined + | P.null agenda = return Nothing + | otherwise = + do let (_, currentAgendum) = P.findMin agenda + let reached = currentAgendum ^. current + nexts <- candidates currentAgendum closed + let newAgenda = foldl' (\q a -> P.insert (_cost a) a q) (P.deleteMin agenda) nexts + reachedGoal <- isGoal reached + if reachedGoal + then return (Just currentAgendum) + else if reached `S.member` closed + then aStar (P.deleteMin agenda) closed + else aStar newAgenda (S.insert reached closed) + + +candidates :: Agendum -> ExploredStates -> BurrowContext (Q.Seq Agendum) +candidates agendum closed = + do let candidate = agendum ^. current + let previous = agendum ^. trail + let prevCost = agendum ^. trailCost + succs <- successors candidate + let nonloops = S.filter (\s -> (s ^. afterMove) `S.notMember` closed) succs + let nonloopsQ = Q.fromList $ S.toList nonloops + mapM (makeAgendum previous prevCost) nonloopsQ + + +makeAgendum :: Q.Seq MoveState -> Int -> AppliedMove -> BurrowContext Agendum +makeAgendum previous prevCost newPosition = + do predicted <- estimateCost (newPosition ^. afterMove) + -- grid <- asks _grid + let newTrail = previous |> (newPosition ^. afterMove) + let newPositionCost = stepCost newPosition + let incurred = prevCost + newPositionCost + return Agendum { _current = newPosition ^. afterMove + , _trail = newTrail + , _trailCost = incurred + , _cost = incurred + predicted + } + +-- class (Eq s, Ord s, Show s) => SearchState s where +-- emptySearchState :: MoveState +-- successors :: MoveState -> BurrowContext (Q.Seq MoveState) +-- estimateCost :: MoveState -> BurrowContext Int +-- isGoal :: MoveState -> BurrowContext Bool +-- entryCost :: MoveState -> BurrowContext Int + + +-- instance SearchState Position where + +-- emptySearchState = Position (V2 0 0) + +successors :: MoveState -> BurrowContext (S.Set AppliedMove) +successors moveState = + do steps <- asks _possibleSteps + let succs = M.foldrWithKey' (legalSteps steps moveState) S.empty moveState + return succs + +legalSteps :: Steps -> MoveState -> Coord -> Amphipod -> S.Set AppliedMove -> S.Set AppliedMove +legalSteps steps state here amphipod acc = S.union appliedSteps acc + where allSteps = steps ! here + freeSteps = S.filter freeSpaces allSteps + freeSpaces st = S.null $ S.intersection (M.keysSet state) (st ^. transits) + validTargetSteps = S.filter (\st -> fromMaybe amphipod (st ^. entryRequirement) == amphipod) freeSteps + openRoomSteps = S.filter (openRoom state) validTargetSteps + appliedSteps = S.map (\s -> AppliedMove + { _afterMove = (applyStep state here s) + , _appliedStep = s + } + ) openRoomSteps + +openRoom :: MoveState -> Step -> Bool +openRoom state step + | isNothing e = True + | otherwise = M.null roomBlockers + where e = step ^. entryRequirement + je = fromJust e + tc = step ^. destination . _c + roomBlockers = M.filterWithKey (\(V2 _ ac) a -> a /= je && ac == tc) state + +applyStep :: MoveState -> Coord -> Step -> MoveState +applyStep moveState here step = moveState'' + where moveState' = M.delete here moveState + moveState'' = M.insert (step ^. destination) (moveState ! here) moveState' + +singleStepCost :: Amphipod -> Int +singleStepCost A = 1 +singleStepCost B = 10 +singleStepCost C = 100 +singleStepCost D = 1000 + +estimateCost :: MoveState -> BurrowContext Int +estimateCost state = + do rCols <- asks _roomColumns + hRow <- asks _hallRow + let amphipodCosts = M.mapWithKey (estimateACost rCols hRow) state + return $ sum $ M.elems amphipodCosts + +estimateACost :: M.Map Amphipod Int -> Int -> Coord -> Amphipod -> Int +estimateACost rCols hRow (V2 r c) amphipod = (singleStepCost amphipod) * dist + where targetCol = rCols ! amphipod + dist = if c == targetCol + then 0 + else (r - hRow) + (abs (c - targetCol)) + 1 + +stepCost :: AppliedMove -> Int +stepCost aStep = (singleStepCost amphipod) * (S.size $ aStep ^. appliedStep . transits) + where dest = aStep ^. appliedStep . destination + amphipod = (aStep ^. afterMove) ! dest + +isGoal :: MoveState -> BurrowContext Bool +isGoal state = + do rCols <- asks _roomColumns + let misplaced = M.filterWithKey (inWrongRoom rCols) state + return $ M.null misplaced + +inWrongRoom rCols (V2 _ c) amphipod = c /= rightCol + where rightCol = rCols ! amphipod + + +------------------------------ + + +mkBurrow :: String -> (Burrow, MoveState) +-- mkBurrow :: String -> ((S.Set Coord, M.Map Coord Amphipod), MoveState) +mkBurrow text = (burrow, initState) -- (burrow, initState) + where rows = lines text + hall = mkHall (rows!!1) + rooms = mkRooms $ drop 2 rows + roomCols = S.map (^. _c) $ M.keysSet rooms + hall' = S.filter ((`S.notMember` roomCols) . (^. _c)) hall + routes = mkRoutes hall' rooms + roomColMap = M.fromList $ zip [A .. D] $ S.toAscList roomCols + burrow = Burrow { _possibleSteps = routes, _roomColumns = roomColMap, _hallRow = 1} + initState = mkInitialState rows + + +mkHall :: String -> S.Set Coord +mkHall text = S.fromList hallCoords + where hallCols = filter ((/= '#') . snd) $ zip [0..] text + hallCoords = map ((V2 1) . fst) hallCols + +mkRooms :: [String] -> M.Map Coord Amphipod +mkRooms text = M.unions rooms + where rooms = map mkRoom $ zip [2..] text + +mkRoom :: (Int, String) -> M.Map Coord Amphipod +mkRoom (r, text) = M.fromList roomCoords + where roomCols = filter ((`elem` ("ABCD." :: String)) . snd) $ zip [0..] text + roomCoords = zip (map ((V2 r) . fst) roomCols) [A .. D] + +-- invertRooms rooms = M.fromList [(a, M.keysSet $ M.filter (== a) rooms) | a <- [A .. D]] + +mkRoutes :: S.Set Coord -> M.Map Coord Amphipod -> Steps +mkRoutes halls rooms = M.unionsWith (S.union) [hallRoutes, roomHallRoutes, roomRoomRoutes] + where hallRoutes = S.foldr' (mkHallRoute rooms) M.empty halls + roomHallRoutes = S.foldr' (mkRoomHallRoute halls) M.empty (M.keysSet rooms) + roomRoomRoutes = S.foldr' (mkRoomRoomRoute hallRow rooms) M.empty (M.keysSet rooms) + hallRow = (S.findMin halls) ^. _r + +mkHallRoute :: M.Map Coord Amphipod -> Coord -> Steps -> Steps +-- mkHallRoute rooms here routes | trace ("mkHR " ++ (show here) ++ " " ++ (show routes)) False = undefined +mkHallRoute rooms here routes = M.foldrWithKey' (mkHallRoute1 here) routes rooms + +mkHallRoute1 :: Coord -> Coord -> Amphipod -> Steps -> Steps +-- mkHallRoute1 here there entry routes | trace ("mkHR1 " ++ (show here) ++ " " ++ (show there) ++ (show routes)) False = undefined +mkHallRoute1 here@(V2 hr hc) there@(V2 tr tc) entry routes = M.insert here (S.insert step existingRoutes) routes + -- | trace ("mkHR1 " ++ (show here) ++ " " ++ (show there) ++ (show routes) ++ " > " ++ show res) False = undefined + -- | otherwise = res + where step = Step { _destination = there + , _distance = (S.size transits) + , _transits = transits + , _entryRequirement = Just entry + } + cMin = min hc tc + cMax = max hc tc + transits = S.delete here $ S.fromList $ [V2 hr c | c <- [cMin..cMax]] ++ [V2 r tc | r <- [hr..tr]] + existingRoutes = M.findWithDefault S.empty here routes + -- res = M.insert here (S.insert step existingRoutes) routes + +mkRoomHallRoute :: S.Set Coord -> Coord -> Steps -> Steps +mkRoomHallRoute halls here routes = S.foldr' (mkRoomHallRoute1 here) routes halls + +mkRoomHallRoute1 :: Coord -> Coord -> Steps -> Steps +mkRoomHallRoute1 here@(V2 hr hc) there@(V2 tr tc) routes = M.insert here (S.insert step existingRoutes) routes + where step = Step { _destination = there + , _distance = (S.size transits) + , _transits = transits + , _entryRequirement = Nothing + } + cMin = min hc tc + cMax = max hc tc + transits = S.delete here $ S.fromList $ [V2 r hc | r <- [tr..hr]] ++ [V2 tr c | c <- [cMin..cMax]] + existingRoutes = M.findWithDefault S.empty here routes + +mkRoomRoomRoute :: Int -> M.Map Coord Amphipod -> Coord -> Steps -> Steps +mkRoomRoomRoute hallRow rooms here routes = M.foldrWithKey' (mkRoomRoomRoute1 hallRow here) routes rooms + +mkRoomRoomRoute1 :: Int -> Coord -> Coord -> Amphipod -> Steps -> Steps +-- mkRoomRoomRoute1 _hallRow here there entry routes | trace ("mkRR1 " ++ (show here) ++ " " ++ (show there) ++ (show routes)) False = undefined +mkRoomRoomRoute1 hallRow here@(V2 hr hc) there@(V2 tr tc) entry routes + | here == there = routes + | otherwise = M.insert here (S.insert step existingRoutes) routes + where step = Step { _destination = there + , _distance = (S.size transits) + , _transits = transits + , _entryRequirement = Just entry + } + cMin = min hc tc + cMax = max hc tc + transitUp = S.fromList [V2 r hc | r <- [hallRow..hr]] + transitAcross = S.fromList [V2 hallRow c | c <- [cMin..cMax]] + transitDown = S.fromList [V2 r tc | r <- [hallRow..tr]] + transits = S.delete here $ S.unions [transitUp, transitAcross, transitDown] + existingRoutes = M.findWithDefault S.empty here routes + + +mkInitialState :: [String] -> MoveState +mkInitialState rows = + M.fromList [ (V2 r c, read [(rows!!r)!!c]) + | r <- [0..maxR], c <- [0..maxC] + , isAmphipod ((rows!!r)!!c) + ] + where maxR = length rows - 1 + maxC = (length $ head rows) - 1 + isAmphipod c = c `elem` ("ABCD" :: String) + diff --git a/data/advent23.txt b/data/advent23.txt new file mode 100644 index 0000000..0b327f0 --- /dev/null +++ b/data/advent23.txt @@ -0,0 +1,5 @@ +############# +#...........# +###D#B#D#A### + #C#C#A#B# + ######### \ No newline at end of file diff --git a/data/advent23a.txt b/data/advent23a.txt new file mode 100644 index 0000000..e59b374 --- /dev/null +++ b/data/advent23a.txt @@ -0,0 +1,5 @@ +############# +#...........# +###B#C#B#D### + #A#D#C#A# + ######### \ No newline at end of file diff --git a/problems/day23.html b/problems/day23.html new file mode 100644 index 0000000..b663d78 --- /dev/null +++ b/problems/day23.html @@ -0,0 +1,420 @@ + + + + +Day 23 - Advent of Code 2021 + + + + + + + +
+ + + +
+ +

--- Day 23: Amphipod ---

A group of amphipods notice your fancy submarine and flag you down. "With such an impressive shell," one amphipod says, "surely you can help us with a question that has stumped our best scientists."

+

They go on to explain that a group of timid, stubborn amphipods live in a nearby burrow. Four types of amphipods live there: Amber (A), Bronze (B), Copper (C), and Desert (D). They live in a burrow that consists of a hallway and four side rooms. The side rooms are initially full of amphipods, and the hallway is initially empty.

+

They give you a diagram of the situation (your puzzle input), including locations of each amphipod (A, B, C, or D, each of which is occupying an otherwise open space), walls (#), and open space (.).

+

For example:

+
#############
+#...........#
+###B#C#B#D###
+  #A#D#C#A#
+  #########
+
+

The amphipods would like a method to organize every amphipod into side rooms so that each side room contains one type of amphipod and the types are sorted A-D going left to right, like this:

+
#############
+#...........#
+###A#B#C#D###
+  #A#B#C#D#
+  #########
+
+

Amphipods can move up, down, left, or right so long as they are moving into an unoccupied open space. Each type of amphipod requires a different amount of energy to move one step: Amber amphipods require 1 energy per step, Bronze amphipods require 10 energy, Copper amphipods require 100, and Desert ones require 1000. The amphipods would like you to find a way to organize the amphipods that requires the least total energy.

+

However, because they are timid and stubborn, the amphipods have some extra rules:

+
    +
  • Amphipods will never stop on the space immediately outside any room. They can move into that space so long as they immediately continue moving. (Specifically, this refers to the four open spaces in the hallway that are directly above an amphipod starting position.)
  • +
  • Amphipods will never move from the hallway into a room unless that room is their destination room and that room contains no amphipods which do not also have that room as their own destination. If an amphipod's starting room is not its destination room, it can stay in that room until it leaves the room. (For example, an Amber amphipod will not move from the hallway into the right three rooms, and will only move into the leftmost room if that room is empty or if it only contains other Amber amphipods.)
  • +
  • Once an amphipod stops moving in the hallway, it will stay in that spot until it can move into a room. (That is, once any amphipod starts moving, any other amphipods currently in the hallway are locked in place and will not move again until they can move fully into a room.)
  • +
+

In the above example, the amphipods can be organized using a minimum of 12521 energy. One way to do this is shown below.

+

Starting configuration:

+
#############
+#...........#
+###B#C#B#D###
+  #A#D#C#A#
+  #########
+
+

One Bronze amphipod moves into the hallway, taking 4 steps and using 40 energy:

+
#############
+#...B.......#
+###B#C#.#D###
+  #A#D#C#A#
+  #########
+
+

The only Copper amphipod not in its side room moves there, taking 4 steps and using 400 energy:

+
#############
+#...B.......#
+###B#.#C#D###
+  #A#D#C#A#
+  #########
+
+

A Desert amphipod moves out of the way, taking 3 steps and using 3000 energy, and then the Bronze amphipod takes its place, taking 3 steps and using 30 energy:

+
#############
+#.....D.....#
+###B#.#C#D###
+  #A#B#C#A#
+  #########
+
+

The leftmost Bronze amphipod moves to its room using 40 energy:

+
#############
+#.....D.....#
+###.#B#C#D###
+  #A#B#C#A#
+  #########
+
+

Both amphipods in the rightmost room move into the hallway, using 2003 energy in total:

+
#############
+#.....D.D.A.#
+###.#B#C#.###
+  #A#B#C#.#
+  #########
+
+

Both Desert amphipods move into the rightmost room using 7000 energy:

+
#############
+#.........A.#
+###.#B#C#D###
+  #A#B#C#D#
+  #########
+
+

Finally, the last Amber amphipod moves into its room, using 8 energy:

+
#############
+#...........#
+###A#B#C#D###
+  #A#B#C#D#
+  #########
+
+

What is the least energy required to organize the amphipods?

+
+

Your puzzle answer was 14460.

--- Part Two ---

As you prepare to give the amphipods your solution, you notice that the diagram they handed you was actually folded up. As you unfold it, you discover an extra part of the diagram.

+

Between the first and second lines of text that contain amphipod starting positions, insert the following lines:

+
  #D#C#B#A#
+  #D#B#A#C#
+
+

So, the above example now becomes:

+
#############
+#...........#
+###B#C#B#D###
+  #D#C#B#A#
+  #D#B#A#C#
+  #A#D#C#A#
+  #########
+
+

The amphipods still want to be organized into rooms similar to before:

+
#############
+#...........#
+###A#B#C#D###
+  #A#B#C#D#
+  #A#B#C#D#
+  #A#B#C#D#
+  #########
+
+

In this updated example, the least energy required to organize these amphipods is 44169:

+
#############
+#...........#
+###B#C#B#D###
+  #D#C#B#A#
+  #D#B#A#C#
+  #A#D#C#A#
+  #########
+
+#############
+#..........D#
+###B#C#B#.###
+  #D#C#B#A#
+  #D#B#A#C#
+  #A#D#C#A#
+  #########
+
+#############
+#A.........D#
+###B#C#B#.###
+  #D#C#B#.#
+  #D#B#A#C#
+  #A#D#C#A#
+  #########
+
+#############
+#A........BD#
+###B#C#.#.###
+  #D#C#B#.#
+  #D#B#A#C#
+  #A#D#C#A#
+  #########
+
+#############
+#A......B.BD#
+###B#C#.#.###
+  #D#C#.#.#
+  #D#B#A#C#
+  #A#D#C#A#
+  #########
+
+#############
+#AA.....B.BD#
+###B#C#.#.###
+  #D#C#.#.#
+  #D#B#.#C#
+  #A#D#C#A#
+  #########
+
+#############
+#AA.....B.BD#
+###B#.#.#.###
+  #D#C#.#.#
+  #D#B#C#C#
+  #A#D#C#A#
+  #########
+
+#############
+#AA.....B.BD#
+###B#.#.#.###
+  #D#.#C#.#
+  #D#B#C#C#
+  #A#D#C#A#
+  #########
+
+#############
+#AA...B.B.BD#
+###B#.#.#.###
+  #D#.#C#.#
+  #D#.#C#C#
+  #A#D#C#A#
+  #########
+
+#############
+#AA.D.B.B.BD#
+###B#.#.#.###
+  #D#.#C#.#
+  #D#.#C#C#
+  #A#.#C#A#
+  #########
+
+#############
+#AA.D...B.BD#
+###B#.#.#.###
+  #D#.#C#.#
+  #D#.#C#C#
+  #A#B#C#A#
+  #########
+
+#############
+#AA.D.....BD#
+###B#.#.#.###
+  #D#.#C#.#
+  #D#B#C#C#
+  #A#B#C#A#
+  #########
+
+#############
+#AA.D......D#
+###B#.#.#.###
+  #D#B#C#.#
+  #D#B#C#C#
+  #A#B#C#A#
+  #########
+
+#############
+#AA.D......D#
+###B#.#C#.###
+  #D#B#C#.#
+  #D#B#C#.#
+  #A#B#C#A#
+  #########
+
+#############
+#AA.D.....AD#
+###B#.#C#.###
+  #D#B#C#.#
+  #D#B#C#.#
+  #A#B#C#.#
+  #########
+
+#############
+#AA.......AD#
+###B#.#C#.###
+  #D#B#C#.#
+  #D#B#C#.#
+  #A#B#C#D#
+  #########
+
+#############
+#AA.......AD#
+###.#B#C#.###
+  #D#B#C#.#
+  #D#B#C#.#
+  #A#B#C#D#
+  #########
+
+#############
+#AA.......AD#
+###.#B#C#.###
+  #.#B#C#.#
+  #D#B#C#D#
+  #A#B#C#D#
+  #########
+
+#############
+#AA.D.....AD#
+###.#B#C#.###
+  #.#B#C#.#
+  #.#B#C#D#
+  #A#B#C#D#
+  #########
+
+#############
+#A..D.....AD#
+###.#B#C#.###
+  #.#B#C#.#
+  #A#B#C#D#
+  #A#B#C#D#
+  #########
+
+#############
+#...D.....AD#
+###.#B#C#.###
+  #A#B#C#.#
+  #A#B#C#D#
+  #A#B#C#D#
+  #########
+
+#############
+#.........AD#
+###.#B#C#.###
+  #A#B#C#D#
+  #A#B#C#D#
+  #A#B#C#D#
+  #########
+
+#############
+#..........D#
+###A#B#C#.###
+  #A#B#C#D#
+  #A#B#C#D#
+  #A#B#C#D#
+  #########
+
+#############
+#...........#
+###A#B#C#D###
+  #A#B#C#D#
+  #A#B#C#D#
+  #A#B#C#D#
+  #########
+
+

Using the initial configuration from the full diagram, what is the least energy required to organize the amphipods?

+
+

Your puzzle answer was 41366.

Both parts of this puzzle are complete! They provide two gold stars: **

+

At this point, you should return to your Advent calendar and try another puzzle.

+

If you still want to see it, you can get your puzzle input.

+

You can also this puzzle.

+
+ + + + + + \ No newline at end of file -- 2.34.1 From 7a460170e89b445166e009bcb29232812b4b7527 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Mon, 3 Jan 2022 16:42:27 +0000 Subject: [PATCH 07/16] Tidying --- advent-of-code21.cabal | 10 +++++ advent23/Main.hs | 100 +++++++++++++++-------------------------- 2 files changed, 47 insertions(+), 63 deletions(-) diff --git a/advent-of-code21.cabal b/advent-of-code21.cabal index 6fd1c09..351c77a 100644 --- a/advent-of-code21.cabal +++ b/advent-of-code21.cabal @@ -221,3 +221,13 @@ executable advent23 import: common-extensions, build-directives main-is: advent23/Main.hs build-depends: containers, linear, pqueue, mtl, lens + +executable advent23prof + import: common-extensions, build-directives + main-is: advent23/Main.hs + build-depends: containers, linear, pqueue, mtl, lens + ghc-options: -O2 + -Wall + -threaded + -rtsopts "-with-rtsopts=-N -p -s -hT" + \ No newline at end of file diff --git a/advent23/Main.hs b/advent23/Main.hs index 2666769..0d3955f 100644 --- a/advent23/Main.hs +++ b/advent23/Main.hs @@ -1,23 +1,19 @@ --- Writeup at https://work.njae.me.uk/2021/12/16/advent-of-code-2021-day-15/ - -import Debug.Trace +-- Writeup at https://work.njae.me.uk/2022/01/03/advent-of-code-2021-day-23/ +-- import Debug.Trace import qualified Data.PQueue.Prio.Min as P import qualified Data.Set as S import qualified Data.Sequence as Q -import Data.Sequence ((<|), (|>), (><)) --, ViewR( (:>) ), ViewL( (:<) )) +-- import Data.Sequence ((<|), (|>), (><)) --, ViewR( (:>) ), ViewL( (:<) )) +import Data.Sequence ((|>)) import qualified Data.Map.Strict as M import Data.Map.Strict ((!)) -import Data.Foldable (foldl', sum) -- (toList, foldr', foldl', all) --- import Data.Char +import Data.Foldable (foldl') -- , sum, toList, foldr', foldl', all) import Control.Monad.Reader import Control.Lens hiding ((<|), (|>), (:>), (:<)) -import Data.Maybe -- (fromMaybe) --- import Linear (V2(..), (^+^)) --, (^-^), (*^), (^*)) -import Linear hiding (trace) - - +import Data.Maybe +import Linear hiding (trace, distance) pattern Empty <- (Q.viewl -> Q.EmptyL) where Empty = Q.empty pattern x :< xs <- (Q.viewl -> x Q.:< xs) where (:<) = (Q.<|) @@ -26,6 +22,12 @@ pattern xs :> x <- (Q.viewr -> xs Q.:> x) where (:>) = (Q.|>) data Amphipod = A | B | C | D deriving (Show, Read, Eq, Ord, Enum) +singleStepCost :: Amphipod -> Int +singleStepCost A = 1 +singleStepCost B = 10 +singleStepCost C = 100 +singleStepCost D = 1000 + type Coord = V2 Int -- r, c _r :: Lens' (V2 Int) Int _r = _x @@ -73,7 +75,6 @@ type Agenda = P.MinPQueue Int Agendum type ExploredStates = S.Set MoveState - main :: IO () main = do text <- readFile "data/advent23.txt" @@ -84,12 +85,13 @@ main = print $ part2 text --- part1 :: Burrow -> MoveState -> Int +part1 :: String -> Int part1 text = maybe 0 _cost result where (burrow, initState) = mkBurrow text result = runReader (searchBurrow initState) burrow +part2 :: String -> Int part2 text = maybe 0 _cost result where rows = lines text @@ -111,17 +113,14 @@ initAgenda initState = return $ P.singleton c Agendum { _current = initState , _trail = Q.empty, _trailCost = 0, _cost = c} - aStar :: Agenda -> ExploredStates -> BurrowContext (Maybe Agendum) aStar agenda closed - -- | trace ("Peeping " ++ (show $ fst $ P.findMin agenda) ++ ": " ++ (show reached) ++ " <- " ++ (show $ toList $ Q.take 1 $ _trail $ currentAgendum) ++ " :: " ++ (show newAgenda)) False = undefined - -- | trace ("Peeping " ++ (show $ _current $ snd $ P.findMin agenda) ) False = undefined | P.null agenda = return Nothing | otherwise = do let (_, currentAgendum) = P.findMin agenda let reached = currentAgendum ^. current nexts <- candidates currentAgendum closed - let newAgenda = foldl' (\q a -> P.insert (_cost a) a q) (P.deleteMin agenda) nexts + let newAgenda = foldl' (\q a -> P.insert (a ^. cost) a q) (P.deleteMin agenda) nexts reachedGoal <- isGoal reached if reachedGoal then return (Just currentAgendum) @@ -129,22 +128,18 @@ aStar agenda closed then aStar (P.deleteMin agenda) closed else aStar newAgenda (S.insert reached closed) - candidates :: Agendum -> ExploredStates -> BurrowContext (Q.Seq Agendum) candidates agendum closed = - do let candidate = agendum ^. current - let previous = agendum ^. trail + do let previous = agendum ^. trail let prevCost = agendum ^. trailCost - succs <- successors candidate + succs <- successors (agendum ^. current) let nonloops = S.filter (\s -> (s ^. afterMove) `S.notMember` closed) succs let nonloopsQ = Q.fromList $ S.toList nonloops mapM (makeAgendum previous prevCost) nonloopsQ - makeAgendum :: Q.Seq MoveState -> Int -> AppliedMove -> BurrowContext Agendum makeAgendum previous prevCost newPosition = do predicted <- estimateCost (newPosition ^. afterMove) - -- grid <- asks _grid let newTrail = previous |> (newPosition ^. afterMove) let newPositionCost = stepCost newPosition let incurred = prevCost + newPositionCost @@ -154,36 +149,26 @@ makeAgendum previous prevCost newPosition = , _cost = incurred + predicted } --- class (Eq s, Ord s, Show s) => SearchState s where --- emptySearchState :: MoveState --- successors :: MoveState -> BurrowContext (Q.Seq MoveState) --- estimateCost :: MoveState -> BurrowContext Int --- isGoal :: MoveState -> BurrowContext Bool --- entryCost :: MoveState -> BurrowContext Int - - --- instance SearchState Position where - --- emptySearchState = Position (V2 0 0) - successors :: MoveState -> BurrowContext (S.Set AppliedMove) successors moveState = - do steps <- asks _possibleSteps + do steps <- asks (^. possibleSteps) let succs = M.foldrWithKey' (legalSteps steps moveState) S.empty moveState return succs legalSteps :: Steps -> MoveState -> Coord -> Amphipod -> S.Set AppliedMove -> S.Set AppliedMove legalSteps steps state here amphipod acc = S.union appliedSteps acc where allSteps = steps ! here - freeSteps = S.filter freeSpaces allSteps - freeSpaces st = S.null $ S.intersection (M.keysSet state) (st ^. transits) - validTargetSteps = S.filter (\st -> fromMaybe amphipod (st ^. entryRequirement) == amphipod) freeSteps - openRoomSteps = S.filter (openRoom state) validTargetSteps + occupiedSpaces = M.keysSet state + freeSpaces st = S.null $ S.intersection occupiedSpaces (st ^. transits) + freeSteps = {-# SCC freeSteps #-} S.filter freeSpaces allSteps + validTargetSteps = {-# SCC validTargetSteps #-} S.filter (\st -> fromMaybe amphipod (st ^. entryRequirement) == amphipod) freeSteps + openRoomSteps = {-# SCC openRoomSteps #-} S.filter (openRoom state) validTargetSteps + highestRowSteps = {-# SCC highestRowSteps #-} S.filter (highestRow (S.map (^. destination) openRoomSteps)) openRoomSteps appliedSteps = S.map (\s -> AppliedMove { _afterMove = (applyStep state here s) , _appliedStep = s } - ) openRoomSteps + ) highestRowSteps openRoom :: MoveState -> Step -> Bool openRoom state step @@ -194,21 +179,19 @@ openRoom state step tc = step ^. destination . _c roomBlockers = M.filterWithKey (\(V2 _ ac) a -> a /= je && ac == tc) state +highestRow :: S.Set Coord -> Step -> Bool +highestRow others step = higherRow `S.notMember` others + where higherRow = (step ^. destination) & _r +~ 1 + applyStep :: MoveState -> Coord -> Step -> MoveState applyStep moveState here step = moveState'' where moveState' = M.delete here moveState moveState'' = M.insert (step ^. destination) (moveState ! here) moveState' -singleStepCost :: Amphipod -> Int -singleStepCost A = 1 -singleStepCost B = 10 -singleStepCost C = 100 -singleStepCost D = 1000 - estimateCost :: MoveState -> BurrowContext Int estimateCost state = - do rCols <- asks _roomColumns - hRow <- asks _hallRow + do rCols <- asks (^. roomColumns) + hRow <- asks (^. hallRow) let amphipodCosts = M.mapWithKey (estimateACost rCols hRow) state return $ sum $ M.elems amphipodCosts @@ -220,25 +203,23 @@ estimateACost rCols hRow (V2 r c) amphipod = (singleStepCost amphipod) * dist else (r - hRow) + (abs (c - targetCol)) + 1 stepCost :: AppliedMove -> Int -stepCost aStep = (singleStepCost amphipod) * (S.size $ aStep ^. appliedStep . transits) +stepCost aStep = (singleStepCost amphipod) * (aStep ^. appliedStep . distance) where dest = aStep ^. appliedStep . destination amphipod = (aStep ^. afterMove) ! dest isGoal :: MoveState -> BurrowContext Bool isGoal state = - do rCols <- asks _roomColumns + do rCols <- asks (^. roomColumns) let misplaced = M.filterWithKey (inWrongRoom rCols) state return $ M.null misplaced +inWrongRoom :: M.Map Amphipod Int -> Coord -> Amphipod -> Bool inWrongRoom rCols (V2 _ c) amphipod = c /= rightCol where rightCol = rCols ! amphipod - ------------------------------ - mkBurrow :: String -> (Burrow, MoveState) --- mkBurrow :: String -> ((S.Set Coord, M.Map Coord Amphipod), MoveState) mkBurrow text = (burrow, initState) -- (burrow, initState) where rows = lines text hall = mkHall (rows!!1) @@ -250,7 +231,6 @@ mkBurrow text = (burrow, initState) -- (burrow, initState) burrow = Burrow { _possibleSteps = routes, _roomColumns = roomColMap, _hallRow = 1} initState = mkInitialState rows - mkHall :: String -> S.Set Coord mkHall text = S.fromList hallCoords where hallCols = filter ((/= '#') . snd) $ zip [0..] text @@ -265,14 +245,12 @@ mkRoom (r, text) = M.fromList roomCoords where roomCols = filter ((`elem` ("ABCD." :: String)) . snd) $ zip [0..] text roomCoords = zip (map ((V2 r) . fst) roomCols) [A .. D] --- invertRooms rooms = M.fromList [(a, M.keysSet $ M.filter (== a) rooms) | a <- [A .. D]] - mkRoutes :: S.Set Coord -> M.Map Coord Amphipod -> Steps mkRoutes halls rooms = M.unionsWith (S.union) [hallRoutes, roomHallRoutes, roomRoomRoutes] where hallRoutes = S.foldr' (mkHallRoute rooms) M.empty halls roomHallRoutes = S.foldr' (mkRoomHallRoute halls) M.empty (M.keysSet rooms) roomRoomRoutes = S.foldr' (mkRoomRoomRoute hallRow rooms) M.empty (M.keysSet rooms) - hallRow = (S.findMin halls) ^. _r + hallRow = S.findMin $ S.map (^. _r) halls mkHallRoute :: M.Map Coord Amphipod -> Coord -> Steps -> Steps -- mkHallRoute rooms here routes | trace ("mkHR " ++ (show here) ++ " " ++ (show routes)) False = undefined @@ -281,8 +259,6 @@ mkHallRoute rooms here routes = M.foldrWithKey' (mkHallRoute1 here) routes rooms mkHallRoute1 :: Coord -> Coord -> Amphipod -> Steps -> Steps -- mkHallRoute1 here there entry routes | trace ("mkHR1 " ++ (show here) ++ " " ++ (show there) ++ (show routes)) False = undefined mkHallRoute1 here@(V2 hr hc) there@(V2 tr tc) entry routes = M.insert here (S.insert step existingRoutes) routes - -- | trace ("mkHR1 " ++ (show here) ++ " " ++ (show there) ++ (show routes) ++ " > " ++ show res) False = undefined - -- | otherwise = res where step = Step { _destination = there , _distance = (S.size transits) , _transits = transits @@ -292,7 +268,6 @@ mkHallRoute1 here@(V2 hr hc) there@(V2 tr tc) entry routes = M.insert here (S.in cMax = max hc tc transits = S.delete here $ S.fromList $ [V2 hr c | c <- [cMin..cMax]] ++ [V2 r tc | r <- [hr..tr]] existingRoutes = M.findWithDefault S.empty here routes - -- res = M.insert here (S.insert step existingRoutes) routes mkRoomHallRoute :: S.Set Coord -> Coord -> Steps -> Steps mkRoomHallRoute halls here routes = S.foldr' (mkRoomHallRoute1 here) routes halls @@ -315,7 +290,7 @@ mkRoomRoomRoute hallRow rooms here routes = M.foldrWithKey' (mkRoomRoomRoute1 h mkRoomRoomRoute1 :: Int -> Coord -> Coord -> Amphipod -> Steps -> Steps -- mkRoomRoomRoute1 _hallRow here there entry routes | trace ("mkRR1 " ++ (show here) ++ " " ++ (show there) ++ (show routes)) False = undefined mkRoomRoomRoute1 hallRow here@(V2 hr hc) there@(V2 tr tc) entry routes - | here == there = routes + | hc == tc = routes | otherwise = M.insert here (S.insert step existingRoutes) routes where step = Step { _destination = there , _distance = (S.size transits) @@ -340,4 +315,3 @@ mkInitialState rows = where maxR = length rows - 1 maxC = (length $ head rows) - 1 isAmphipod c = c `elem` ("ABCD" :: String) - -- 2.34.1 From e6bc0a0ceb66599693a69d21b85ce95762fa4314 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Tue, 4 Jan 2022 12:26:36 +0000 Subject: [PATCH 08/16] Updated readme --- README.html | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.html b/README.html index ddd45d3..64114cd 100644 --- a/README.html +++ b/README.html @@ -115,6 +115,7 @@

or

stack ghci advent01:exe:advent01

if the first form is ambiguous.

+

Profiling

To profile, use

cabal run advent01 --enable-profiling -- +RTS -N -p -s -hT

Or, you can simplify the RTS options by adding them to a new stanza in the cabal file:

@@ -130,7 +131,6 @@
cabal run advent01prof --enable-profiling

Generate the profile graph with

hp2ps -M advent01.hp
-

For Cabal, look at profiling with Cabal sandboxes

Packages

Packages I used a lot:

    diff --git a/README.md b/README.md index 7b831f2..17a2902 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,8 @@ stack ghci advent01:exe:advent01 ``` if the first form is ambiguous. +## Profiling + To profile, use ``` @@ -99,8 +101,6 @@ Generate the profile graph with hp2ps -M advent01.hp ``` -For Cabal, look at [profiling with Cabal sandboxes](https://nikita-volkov.github.io/profiling-cabal-projects/) - # Packages -- 2.34.1 From 8f8a643512f241b116b6da3cc43d2a9cd7360a42 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Tue, 19 Apr 2022 10:40:34 +0100 Subject: [PATCH 09/16] Done day 24 --- advent-of-code21.cabal | 16 ++- advent24/Main.hs | 232 +++++++++++++++++++++++++++++++++++++ advent24/MainDelay.hs | 214 ++++++++++++++++++++++++++++++++++ advent24/MainLax.hs | 212 ++++++++++++++++++++++++++++++++++ data/advent24.txt | 252 +++++++++++++++++++++++++++++++++++++++++ data/advent24a.txt | 5 + data/advent24b.txt | 5 + problems/day24.html | 167 +++++++++++++++++++++++++++ 8 files changed, 1102 insertions(+), 1 deletion(-) create mode 100644 advent24/Main.hs create mode 100644 advent24/MainDelay.hs create mode 100644 advent24/MainLax.hs create mode 100644 data/advent24.txt create mode 100644 data/advent24a.txt create mode 100644 data/advent24b.txt create mode 100644 problems/day24.html diff --git a/advent-of-code21.cabal b/advent-of-code21.cabal index 351c77a..5727015 100644 --- a/advent-of-code21.cabal +++ b/advent-of-code21.cabal @@ -230,4 +230,18 @@ executable advent23prof -Wall -threaded -rtsopts "-with-rtsopts=-N -p -s -hT" - \ No newline at end of file + +executable advent24 + import: common-extensions, build-directives + main-is: advent24/Main.hs + build-depends: text, attoparsec, containers + +executable advent24l + import: common-extensions, build-directives + main-is: advent24/MainLax.hs + build-depends: text, attoparsec, containers + +executable advent24d + import: common-extensions, build-directives + main-is: advent24/MainDelay.hs + build-depends: text, attoparsec, containers diff --git a/advent24/Main.hs b/advent24/Main.hs new file mode 100644 index 0000000..2b85e46 --- /dev/null +++ b/advent24/Main.hs @@ -0,0 +1,232 @@ +-- Writeup at https://work.njae.me.uk/2021/12/29/advent-of-code-2021-day-24/ +-- Based on ideas by Daniel Lin, +-- taken from https://github.com/ephemient/aoc2021/blob/main/hs/src/Day24.hs + +import Debug.Trace + +import Data.Text (Text) +import qualified Data.Text.IO as TIO +import Data.Attoparsec.Text -- hiding (take, takeWhile) +import Control.Applicative +import qualified Data.Map as M +import Data.Map ((!)) +import Data.List +import Control.Monad +import Data.Maybe + +data Register = W | X | Y | Z deriving (Eq, Ord, Show, Enum) + +data Interval = Interval Integer Integer + deriving (Eq, Ord, Show) + +data Argument = Reg Register | Lit Integer + deriving (Eq, Ord, Show) + +data Instruction + = Inp Register + | Add Register Argument + | Mul Register Argument + | Div Register Argument + | Mod Register Argument + | Eql Register Argument + deriving (Eq, Ord, Show) + +type LitMachine = M.Map Register Integer +type IntMachine = M.Map Register (Maybe Interval) + +data ModelMachine = ModelMachine + { mCode :: [Integer] + , mMachine :: LitMachine + } deriving (Show) + +-- Main + +main :: IO () +main = + do text <- TIO.readFile "data/advent24.txt" + let instrs = successfulParse text + let m0 = ModelMachine {mCode = [], mMachine = emptyMachine} + putStrLn $ part1 m0 instrs + putStrLn $ part2 m0 instrs + +part1 :: ModelMachine -> [Instruction] -> String +part1 = findCode [9, 8..1] + +part2 :: ModelMachine -> [Instruction] -> String +part2 = findCode [1..9] + +findCode :: [Integer] -> ModelMachine -> [Instruction] -> String +findCode digits machine instrs = concatMap show $ mCode $ head $ runLit instrs digits machine + +plausible :: [Instruction] -> LitMachine -> Bool +plausible instrs litMachine = feasible ranMachine + where intMachine = intervalify litMachine + ranMachine = runInt instrs intMachine + +feasible :: Maybe IntMachine -> Bool +feasible Nothing = False +feasible (Just machine) = isJust z && a <= 0 && b >= 0 + where z = machine ! Z + Just (Interval a b) = z + + + +-- feasible :: IntMachine -> Bool +-- -- feasible machine | trace ("Feasible " ++ (show machine)) False = undefined +-- feasible machine +-- | (w && x && y && isJust z) = a <= 0 && b >= 0 +-- | otherwise = False +-- where w = isJust $ machine ! W +-- x = isJust $ machine ! X +-- y = isJust $ machine ! Y +-- z = machine ! Z +-- Just (Interval a b) = z + +valid :: ModelMachine -> Bool +valid (ModelMachine{..}) = (mMachine ! Z) == 0 + + +emptyMachine :: LitMachine +emptyMachine = M.fromList [(r, 0) | r <- [W .. Z]] + +intervalify :: LitMachine -> IntMachine +intervalify = M.map (\i -> Just (Interval i i)) + + +runLit :: [Instruction] -> [Integer] -> ModelMachine -> [ModelMachine] +-- runLit instrs _digits m0 | trace ((show $ length instrs) ++ " " ++ (show m0)) False = undefined +-- runLit [] _digits machine | trace (show machine) True = [machine] +runLit [] _ machine = [machine] +runLit (Inp reg : instrs) digits (ModelMachine {..}) = + do guard (plausible (Inp reg : instrs) mMachine) + i <- digits + let m1 = M.insert reg i mMachine + mm2 <- runLit instrs digits (ModelMachine { mCode = mCode ++ [i], mMachine = m1}) + guard (valid mm2) + return mm2 +runLit (Add reg arg : instrs) digits (ModelMachine {..}) = + runLit instrs digits (ModelMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a + b +runLit (Mul reg arg : instrs) digits (ModelMachine {..}) = + runLit instrs digits (ModelMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a * b +runLit (Div reg arg : instrs) digits (ModelMachine {..}) = + runLit instrs digits (ModelMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a `quot` b +runLit (Mod reg arg : instrs) digits (ModelMachine {..}) = + runLit instrs digits (ModelMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a `rem` b +runLit (Eql reg arg : instrs) digits (ModelMachine {..}) = + runLit instrs digits (ModelMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = if a == b then 1 else 0 + + +runInt :: [Instruction] -> IntMachine -> Maybe IntMachine +runInt instrs machine = foldl' interpretInt (Just machine) instrs + +interpretInt :: Maybe IntMachine -> Instruction -> Maybe IntMachine +-- interpretInt machine instr | trace ("iInt " ++ (show instr) ++ " " ++ (show machine)) False = undefined +interpretInt Nothing _ = Nothing +interpretInt (Just machine) (Inp reg) = Just $ M.insert reg (Just (Interval 1 9)) machine +interpretInt (Just machine) (Add reg arg) + | isJust a && isJust b = Just $ M.insert reg c machine + | otherwise = Nothing + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (+:) <$> a <*> b +interpretInt (Just machine) (Mul reg arg) + | isJust a && isJust b = Just $ M.insert reg c machine + | otherwise = Nothing + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (*:) <$> a <*> b +interpretInt (Just machine) (Div reg arg) + | isJust a && isJust b = Just $ M.insert reg c machine + | otherwise = Nothing + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (/:) <$> a <*> b +interpretInt (Just machine) (Mod reg arg) + | isJust a && isJust b = Just $ M.insert reg c machine + | otherwise = Nothing + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (%:) <$> a <*> b +interpretInt (Just machine) (Eql reg arg) + | isJust a && isJust b = Just $ M.insert reg c machine + | otherwise = Nothing + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (=:) <$> a <*> b + +(+:), (*:), (/:), (%:), (=:) :: Interval -> Interval -> Maybe Interval +(Interval a b) +: (Interval c d) = Just (Interval (a + c) (b + d)) +(Interval a b) *: (Interval c d) + | a >= 0 && c >= 0 = Just ( Interval (a * c) (b * d) ) + | b <= 0 && d <= 0 = Just ( Interval (b * d) (a * c) ) + | a >= 0 && d <= 0 = Just ( Interval (a * d) (b * c) ) + | b <= 0 && c >= 0 = Just ( Interval (b * c) (a * d) ) +(Interval a b) /: (Interval c d) + | c > 0 = Just ( Interval (a `quot` d) (b `quot` c) ) + | d < 0 = Just ( Interval (a `quot` c) (b `quot` d) ) + | otherwise = Nothing +(Interval _a _b) %: (Interval c d) + | c > 0 = Just ( Interval 0 (d - 1)) + | otherwise = Nothing +(Interval a b) =: (Interval c d) + | b < c = Just (Interval 0 0) + | a > d = Just (Interval 0 0) + | a == b && a == c && a == d = Just (Interval 1 1) + | otherwise = Just (Interval 0 1) + + +evaluateLit :: Argument -> LitMachine -> Integer +evaluateLit (Reg reg) machine = machine ! reg +evaluateLit (Lit n) _ = n + +evaluateInt :: Argument -> IntMachine -> Maybe Interval +evaluateInt (Reg reg) machine = machine ! reg +evaluateInt (Lit n) _ = Just (Interval n n) + + +-- Parse the input file + +instructionsP:: Parser [Instruction] +instructionsP = instructionP `sepBy` endOfLine + +instructionP:: Parser Instruction +instructionP = choice [inpP, addP, mulP, divP, modP, eqlP] + +inpP, addP, mulP, divP, modP, eqlP :: Parser Instruction +inpP = Inp <$> ("inp " *> registerP) +addP = Add <$> ("add " *> registerP) <*> (" " *> argumentP) +mulP = Mul <$> ("mul " *> registerP) <*> (" " *> argumentP) +divP = Div <$> ("div " *> registerP) <*> (" " *> argumentP) +modP = Mod <$> ("mod " *> registerP) <*> (" " *> argumentP) +eqlP = Eql <$> ("eql " *> registerP) <*> (" " *> argumentP) + +registerP, wP, xP, yP, zP :: Parser Register +registerP = choice [wP, xP, yP, zP] +wP = "w" *> pure W +xP = "x" *> pure X +yP = "y" *> pure Y +zP = "z" *> pure Z + +argumentP :: Parser Argument +argumentP = (Reg <$> registerP) <|> (Lit <$> signed decimal) + +successfulParse :: Text -> [Instruction] +successfulParse input = + case parseOnly instructionsP input of + Left _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err + Right instrs -> instrs diff --git a/advent24/MainDelay.hs b/advent24/MainDelay.hs new file mode 100644 index 0000000..fc65f3c --- /dev/null +++ b/advent24/MainDelay.hs @@ -0,0 +1,214 @@ +-- Writeup at https://work.njae.me.uk/2021/12/29/advent-of-code-2021-day-24/ +-- Based on ideas by Daniel Lin, +-- taken from https://github.com/ephemient/aoc2021/blob/main/hs/src/Day24.hs + +import Debug.Trace + +import Data.Text (Text) +import qualified Data.Text.IO as TIO +import Data.Attoparsec.Text -- hiding (take, takeWhile) +import Control.Applicative +import qualified Data.Map as M +import Data.Map ((!)) +import Data.List +import Control.Monad +import Data.Maybe + +data Register = W | X | Y | Z deriving (Eq, Ord, Show, Enum) + +data Interval = Interval Integer Integer + deriving (Eq, Ord, Show) + +data Argument = Reg Register | Lit Integer + deriving (Eq, Ord, Show) + +data Instruction + = Inp Register + | Add Register Argument + | Mul Register Argument + | Div Register Argument + | Mod Register Argument + | Eql Register Argument + deriving (Eq, Ord, Show) + +type LiteralMachine = M.Map Register Integer +type IntervalMachine = M.Map Register (Maybe Interval) + +data CodeMachine = CodeMachine + { mCode :: [Integer] + , mMachine :: LiteralMachine + } deriving (Show) + +-- Main + +main :: IO () +main = + do text <- TIO.readFile "data/advent24.txt" + let instrs = successfulParse text + let m0 = CodeMachine {mCode = [], mMachine = emptyMachine} + putStrLn $ part1 m0 instrs + putStrLn $ part2 m0 instrs + +part1 :: CodeMachine -> [Instruction] -> String +part1 = findCode [9, 8..1] + +part2 :: CodeMachine -> [Instruction] -> String +part2 = findCode [1..9] + +findCode :: [Integer] -> CodeMachine -> [Instruction] -> String +findCode digits machine instrs = concatMap show $ mCode $ head $ runLit instrs digits machine + +plausible :: [Instruction] -> LiteralMachine -> Bool +plausible instrs litMachine = feasible ranMachine + where intMachine = intervalify litMachine + ranMachine = runInt instrs intMachine + +feasible :: IntervalMachine -> Bool +-- feasible machine | trace ("Feasible " ++ (show machine)) False = undefined +feasible machine + | (w && x && y && isJust z) = a <= 0 && b >= 0 + | otherwise = False + where w = isJust $ machine ! W + x = isJust $ machine ! X + y = isJust $ machine ! Y + z = machine ! Z + Just (Interval a b) = z + +valid :: CodeMachine -> Bool +valid (CodeMachine{..}) = (mMachine ! Z) == 0 + + +emptyMachine :: LiteralMachine +emptyMachine = M.fromList [(r, 0) | r <- [W .. Z]] + +intervalify :: LiteralMachine -> IntervalMachine +intervalify = M.map (\i -> Just (Interval i i)) + + +runLit :: [Instruction] -> [Integer] -> CodeMachine -> [CodeMachine] +-- runLit instrs _digits m0 | trace ((show $ length instrs) ++ " " ++ (show m0)) False = undefined +runLit [] _ machine = [machine] +runLit (Inp reg : instrs) digits (CodeMachine {..}) = + do -- guard (plausible (Inp reg : instrs) mMachine) + i <- digits + let m1 = M.insert reg i mMachine + guard (plausible instrs m1) + mm2 <- runLit instrs digits (CodeMachine { mCode = mCode ++ [i], mMachine = m1}) + guard (valid mm2) + return mm2 +runLit (Add reg arg : instrs) digits (CodeMachine {..}) = + runLit instrs digits (CodeMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a + b +runLit (Mul reg arg : instrs) digits (CodeMachine {..}) = + runLit instrs digits (CodeMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a * b +runLit (Div reg arg : instrs) digits (CodeMachine {..}) = + runLit instrs digits (CodeMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a `quot` b +runLit (Mod reg arg : instrs) digits (CodeMachine {..}) = + runLit instrs digits (CodeMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a `rem` b +runLit (Eql reg arg : instrs) digits (CodeMachine {..}) = + runLit instrs digits (CodeMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = if a == b then 1 else 0 + + +runInt :: [Instruction] -> IntervalMachine -> IntervalMachine +runInt instrs machine = foldl' interpretInt machine instrs + +interpretInt :: IntervalMachine -> Instruction -> IntervalMachine +-- interpretInt machine instr | trace ("iInt " ++ (show instr) ++ " " ++ (show machine)) False = undefined +interpretInt machine (Inp reg) = M.insert reg (Just (Interval 1 9)) machine +interpretInt machine (Add reg arg) = M.insert reg c machine + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (+:) <$> a <*> b + -- c = join $ (liftM2 (+:)) a b +interpretInt machine (Mul reg arg) = M.insert reg c machine + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (*:) <$> a <*> b +interpretInt machine (Div reg arg) = M.insert reg c machine + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (/:) <$> a <*> b +interpretInt machine (Mod reg arg) = M.insert reg c machine + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (%:) <$> a <*> b +interpretInt machine (Eql reg arg) = M.insert reg c machine + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (=:) <$> a <*> b + +(+:), (*:), (/:), (%:), (=:) :: Interval -> Interval -> Maybe Interval +(Interval a b) +: (Interval c d) = Just (Interval (a + c) (b + d)) +(Interval a b) *: (Interval c d) + | a >= 0 && c >= 0 = Just ( Interval (a * c) (b * d) ) + | b <= 0 && d <= 0 = Just ( Interval (b * d) (a * c) ) + | a >= 0 && d <= 0 = Just ( Interval (a * d) (b * c) ) + | b <= 0 && c >= 0 = Just ( Interval (b * c) (a * d) ) +(Interval a b) /: (Interval c d) + | c > 0 = Just ( Interval (a `quot` d) (b `quot` c) ) + | d < 0 = Just ( Interval (a `quot` c) (b `quot` d) ) + | otherwise = Nothing +(Interval _a _b) %: (Interval c d) + | c > 0 && c == d = Just ( Interval 0 (c - 1)) + | c > 0 && c /= d = Just ( Interval 0 (max (c - 1) (d - 1))) + | otherwise = Nothing +(Interval a b) =: (Interval c d) + | b < c = Just (Interval 0 0) + | a > d = Just (Interval 0 0) + | a == b && a == c && a == d = Just (Interval 1 1) + | otherwise = Just (Interval 0 1) + +evaluateLit :: Argument -> LiteralMachine -> Integer +evaluateLit (Reg reg) machine = machine ! reg +evaluateLit (Lit n) _ = n + +evaluateInt :: Argument -> IntervalMachine -> Maybe Interval +evaluateInt (Reg reg) machine = machine ! reg +evaluateInt (Lit n) _ = Just (Interval n n) + + +-- Parse the input file + +instructionsP:: Parser [Instruction] +instructionsP = instructionP `sepBy` endOfLine + +instructionP:: Parser Instruction +instructionP = choice [inpP, addP, mulP, divP, modP, eqlP] + +inpP, addP, mulP, divP, modP, eqlP :: Parser Instruction +inpP = Inp <$> ("inp " *> registerP) +addP = Add <$> ("add " *> registerP) <*> (" " *> argumentP) +mulP = Mul <$> ("mul " *> registerP) <*> (" " *> argumentP) +divP = Div <$> ("div " *> registerP) <*> (" " *> argumentP) +modP = Mod <$> ("mod " *> registerP) <*> (" " *> argumentP) +eqlP = Eql <$> ("eql " *> registerP) <*> (" " *> argumentP) + +registerP, wP, xP, yP, zP :: Parser Register +registerP = choice [wP, xP, yP, zP] +wP = "w" *> pure W +xP = "x" *> pure X +yP = "y" *> pure Y +zP = "z" *> pure Z + +argumentP :: Parser Argument +argumentP = (Reg <$> registerP) <|> (Lit <$> signed decimal) + +successfulParse :: Text -> [Instruction] +successfulParse input = + case parseOnly instructionsP input of + Left _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err + Right instrs -> instrs diff --git a/advent24/MainLax.hs b/advent24/MainLax.hs new file mode 100644 index 0000000..2dc91cd --- /dev/null +++ b/advent24/MainLax.hs @@ -0,0 +1,212 @@ +-- Writeup at https://work.njae.me.uk/2021/12/29/advent-of-code-2021-day-24/ +-- Based on ideas by Daniel Lin, +-- taken from https://github.com/ephemient/aoc2021/blob/main/hs/src/Day24.hs + +import Debug.Trace + +import Data.Text (Text) +import qualified Data.Text.IO as TIO +import Data.Attoparsec.Text -- hiding (take, takeWhile) +import Control.Applicative +import qualified Data.Map as M +import Data.Map ((!)) +import Data.List +import Control.Monad +import Data.Maybe + +data Register = W | X | Y | Z deriving (Eq, Ord, Show, Enum) + +data Interval = Interval Integer Integer + deriving (Eq, Ord, Show) + +data Argument = Reg Register | Lit Integer + deriving (Eq, Ord, Show) + +data Instruction + = Inp Register + | Add Register Argument + | Mul Register Argument + | Div Register Argument + | Mod Register Argument + | Eql Register Argument + deriving (Eq, Ord, Show) + +type LiteralMachine = M.Map Register Integer +type IntervalMachine = M.Map Register (Maybe Interval) + +data CodeMachine = CodeMachine + { mCode :: [Integer] + , mMachine :: LiteralMachine + } deriving (Show) + +-- Main + +main :: IO () +main = + do text <- TIO.readFile "data/advent24.txt" + let instrs = successfulParse text + let m0 = CodeMachine {mCode = [], mMachine = emptyMachine} + putStrLn $ part1 m0 instrs + putStrLn $ part2 m0 instrs + +part1 :: CodeMachine -> [Instruction] -> String +part1 = findCode [9, 8..1] + +part2 :: CodeMachine -> [Instruction] -> String +part2 = findCode [1..9] + +findCode :: [Integer] -> CodeMachine -> [Instruction] -> String +findCode digits machine instrs = concatMap show $ mCode $ head $ runLit instrs digits machine + +plausible :: [Instruction] -> LiteralMachine -> Bool +plausible instrs litMachine = feasible ranMachine + where intMachine = intervalify litMachine + ranMachine = runInt instrs intMachine + +feasible :: IntervalMachine -> Bool +-- feasible machine | trace ("Feasible " ++ (show machine)) False = undefined +feasible machine + | (w && x && y && isJust z) = a <= 0 && b >= 0 + | otherwise = False + where w = isJust $ machine ! W + x = isJust $ machine ! X + y = isJust $ machine ! Y + z = machine ! Z + Just (Interval a b) = z + +valid :: CodeMachine -> Bool +valid (CodeMachine{..}) = (mMachine ! Z) == 0 + + +emptyMachine :: LiteralMachine +emptyMachine = M.fromList [(r, 0) | r <- [W .. Z]] + +intervalify :: LiteralMachine -> IntervalMachine +intervalify = M.map (\i -> Just (Interval i i)) + + +runLit :: [Instruction] -> [Integer] -> CodeMachine -> [CodeMachine] +-- runLit instrs _digits m0 | trace ((show $ length instrs) ++ " " ++ (show m0)) False = undefined +runLit [] _ machine = [machine] +runLit (Inp reg : instrs) digits (CodeMachine {..}) = + do guard (plausible (Inp reg : instrs) mMachine) + i <- digits + let m1 = M.insert reg i mMachine + mm2 <- runLit instrs digits (CodeMachine { mCode = mCode ++ [i], mMachine = m1}) + guard (valid mm2) + return mm2 +runLit (Add reg arg : instrs) digits (CodeMachine {..}) = + runLit instrs digits (CodeMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a + b +runLit (Mul reg arg : instrs) digits (CodeMachine {..}) = + runLit instrs digits (CodeMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a * b +runLit (Div reg arg : instrs) digits (CodeMachine {..}) = + runLit instrs digits (CodeMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a `quot` b +runLit (Mod reg arg : instrs) digits (CodeMachine {..}) = + runLit instrs digits (CodeMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = a `rem` b +runLit (Eql reg arg : instrs) digits (CodeMachine {..}) = + runLit instrs digits (CodeMachine{mMachine = M.insert reg c mMachine, ..}) + where a = mMachine ! reg + b = evaluateLit arg mMachine + c = if a == b then 1 else 0 + + +runInt :: [Instruction] -> IntervalMachine -> IntervalMachine +runInt instrs machine = foldl' interpretInt machine instrs + +interpretInt :: IntervalMachine -> Instruction -> IntervalMachine +-- interpretInt machine instr | trace ("iInt " ++ (show instr) ++ " " ++ (show machine)) False = undefined +interpretInt machine (Inp reg) = M.insert reg (Just (Interval 1 9)) machine +interpretInt machine (Add reg arg) = M.insert reg c machine + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (+:) <$> a <*> b + -- c = join $ (liftM2 (+:)) a b +interpretInt machine (Mul reg arg) = M.insert reg c machine + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (*:) <$> a <*> b +interpretInt machine (Div reg arg) = M.insert reg c machine + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (/:) <$> a <*> b +interpretInt machine (Mod reg arg) = M.insert reg c machine + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (%:) <$> a <*> b +interpretInt machine (Eql reg arg) = M.insert reg c machine + where a = machine ! reg + b = evaluateInt arg machine + c = join $ (=:) <$> a <*> b + +(+:), (*:), (/:), (%:), (=:) :: Interval -> Interval -> Maybe Interval +(Interval a b) +: (Interval c d) = Just (Interval (a + c) (b + d)) +(Interval a b) *: (Interval c d) + | a >= 0 && c >= 0 = Just ( Interval (a * c) (b * d) ) + | b <= 0 && d <= 0 = Just ( Interval (b * d) (a * c) ) + | a >= 0 && d <= 0 = Just ( Interval (a * d) (b * c) ) + | b <= 0 && c >= 0 = Just ( Interval (b * c) (a * d) ) +(Interval a b) /: (Interval c d) + | c > 0 = Just ( Interval (a `quot` d) (b `quot` c) ) + | d < 0 = Just ( Interval (a `quot` c) (b `quot` d) ) + | otherwise = Nothing +(Interval _a _b) %: (Interval c d) + | c > 0 = Just ( Interval 0 (d - 1)) + | otherwise = Nothing +(Interval a b) =: (Interval c d) + | b < c = Just (Interval 0 0) + | a > d = Just (Interval 0 0) + | a == b && a == c && a == d = Just (Interval 1 1) + | otherwise = Just (Interval 0 1) + +evaluateLit :: Argument -> LiteralMachine -> Integer +evaluateLit (Reg reg) machine = machine ! reg +evaluateLit (Lit n) _ = n + +evaluateInt :: Argument -> IntervalMachine -> Maybe Interval +evaluateInt (Reg reg) machine = machine ! reg +evaluateInt (Lit n) _ = Just (Interval n n) + + +-- Parse the input file + +instructionsP:: Parser [Instruction] +instructionsP = instructionP `sepBy` endOfLine + +instructionP:: Parser Instruction +instructionP = choice [inpP, addP, mulP, divP, modP, eqlP] + +inpP, addP, mulP, divP, modP, eqlP :: Parser Instruction +inpP = Inp <$> ("inp " *> registerP) +addP = Add <$> ("add " *> registerP) <*> (" " *> argumentP) +mulP = Mul <$> ("mul " *> registerP) <*> (" " *> argumentP) +divP = Div <$> ("div " *> registerP) <*> (" " *> argumentP) +modP = Mod <$> ("mod " *> registerP) <*> (" " *> argumentP) +eqlP = Eql <$> ("eql " *> registerP) <*> (" " *> argumentP) + +registerP, wP, xP, yP, zP :: Parser Register +registerP = choice [wP, xP, yP, zP] +wP = "w" *> pure W +xP = "x" *> pure X +yP = "y" *> pure Y +zP = "z" *> pure Z + +argumentP :: Parser Argument +argumentP = (Reg <$> registerP) <|> (Lit <$> signed decimal) + +successfulParse :: Text -> [Instruction] +successfulParse input = + case parseOnly instructionsP input of + Left _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err + Right instrs -> instrs diff --git a/data/advent24.txt b/data/advent24.txt new file mode 100644 index 0000000..baaee40 --- /dev/null +++ b/data/advent24.txt @@ -0,0 +1,252 @@ +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 12 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 4 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 11 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 10 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 14 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 12 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -6 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 14 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 15 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 6 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 12 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 16 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -9 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 1 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 14 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 7 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 14 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 8 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -5 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 11 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -9 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 8 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -5 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 3 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -2 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 1 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -7 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 8 +mul y x +add z y \ No newline at end of file diff --git a/data/advent24a.txt b/data/advent24a.txt new file mode 100644 index 0000000..844ab0d --- /dev/null +++ b/data/advent24a.txt @@ -0,0 +1,5 @@ +inp w +add z w +add z 2 +mod z 3 +add z -1 diff --git a/data/advent24b.txt b/data/advent24b.txt new file mode 100644 index 0000000..b60d5e0 --- /dev/null +++ b/data/advent24b.txt @@ -0,0 +1,5 @@ +inp z +mod z 4 +inp w +sub w 3 +eql z w diff --git a/problems/day24.html b/problems/day24.html new file mode 100644 index 0000000..d5aeec8 --- /dev/null +++ b/problems/day24.html @@ -0,0 +1,167 @@ + + + + +Day 24 - Advent of Code 2021 + + + + + + + + +
    + + + +
    +

    --- Day 24: Arithmetic Logic Unit ---

    Magic smoke starts leaking from the submarine's arithmetic logic unit (ALU). Without the ability to perform basic arithmetic and logic functions, the submarine can't produce cool patterns with its Christmas lights!

    +

    It also can't navigate. Or run the oxygen system.

    +

    Don't worry, though - you probably have enough oxygen left to give you enough time to build a new ALU.

    +

    The ALU is a four-dimensional processing unit: it has integer variables w, x, y, and z. These variables all start with the value 0. The ALU also supports six instructions:

    +
      +
    • inp a - Read an input value and write it to variable a.
    • +
    • add a b - Add the value of a to the value of b, then store the result in variable a.
    • +
    • mul a b - Multiply the value of a by the value of b, then store the result in variable a.
    • +
    • div a b - Divide the value of a by the value of b, truncate the result to an integer, then store the result in variable a. (Here, "truncate" means to round the value toward zero.)
    • +
    • mod a b - Divide the value of a by the value of b, then store the remainder in variable a. (This is also called the modulo operation.)
    • +
    • eql a b - If the value of a and b are equal, then store the value 1 in variable a. Otherwise, store the value 0 in variable a.
    • +
    +

    In all of these instructions, a and b are placeholders; a will always be the variable where the result of the operation is stored (one of w, x, y, or z), while b can be either a variable or a number. Numbers can be positive or negative, but will always be integers.

    +

    The ALU has no jump instructions; in an ALU program, every instruction is run exactly once in order from top to bottom. The program halts after the last instruction has finished executing.

    +

    (Program authors should be especially cautious; attempting to execute div with b=0 or attempting to execute mod with a<0 or b<=0 will cause the program to crash and might even damage the ALU. These operations are never intended in any serious ALU program.)

    +

    For example, here is an ALU program which takes an input number, negates it, and stores it in x:

    +
    inp x
    +mul x -1
    +
    +

    Here is an ALU program which takes two input numbers, then sets z to 1 if the second input number is three times larger than the first input number, or sets z to 0 otherwise:

    +
    inp z
    +inp x
    +mul z 3
    +eql z x
    +
    +

    Here is an ALU program which takes a non-negative integer as input, converts it into binary, and stores the lowest (1's) bit in z, the second-lowest (2's) bit in y, the third-lowest (4's) bit in x, and the fourth-lowest (8's) bit in w:

    +
    inp w
    +add z w
    +mod z 2
    +div w 2
    +add y w
    +mod y 2
    +div w 2
    +add x w
    +mod x 2
    +div w 2
    +mod w 2
    +
    +

    Once you have built a replacement ALU, you can install it in the submarine, which will immediately resume what it was doing when the ALU failed: validating the submarine's model number. To do this, the ALU will run the MOdel Number Automatic Detector program (MONAD, your puzzle input).

    +

    Submarine model numbers are always fourteen-digit numbers consisting only of digits 1 through 9. The digit 0 cannot appear in a model number.

    +

    When MONAD checks a hypothetical fourteen-digit model number, it uses fourteen separate inp instructions, each expecting a single digit of the model number in order of most to least significant. (So, to check the model number 13579246899999, you would give 1 to the first inp instruction, 3 to the second inp instruction, 5 to the third inp instruction, and so on.) This means that when operating MONAD, each input instruction should only ever be given an integer value of at least 1 and at most 9.

    +

    Then, after MONAD has finished running all of its instructions, it will indicate that the model number was valid by leaving a 0 in variable z. However, if the model number was invalid, it will leave some other non-zero value in z.

    +

    MONAD imposes additional, mysterious restrictions on model numbers, and legend says the last copy of the MONAD documentation was eaten by a tanuki. You'll need to figure out what MONAD does some other way.

    +

    To enable as many submarine features as possible, find the largest valid fourteen-digit model number that contains no 0 digits. What is the largest model number accepted by MONAD?

    +
    +

    Your puzzle answer was 91398299697996.

    --- Part Two ---

    As the submarine starts booting up things like the Retro Encabulator, you realize that maybe you don't need all these submarine features after all.

    +

    What is the smallest model number accepted by MONAD?

    +
    +

    Your puzzle answer was 41171183141291.

    Both parts of this puzzle are complete! They provide two gold stars: **

    +

    At this point, you should return to your Advent calendar and try another puzzle.

    +

    If you still want to see it, you can get your puzzle input.

    +

    You can also this puzzle.

    +
    + + + + + + \ No newline at end of file -- 2.34.1 From f961efa630553f9630649481bc6380ec70949720 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Sat, 23 Apr 2022 17:57:57 +0100 Subject: [PATCH 10/16] Updated blog link --- advent24/Main.hs | 2 +- advent24/MainDelay.hs | 2 +- advent24/MainLax.hs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/advent24/Main.hs b/advent24/Main.hs index 2b85e46..b1ca376 100644 --- a/advent24/Main.hs +++ b/advent24/Main.hs @@ -1,4 +1,4 @@ --- Writeup at https://work.njae.me.uk/2021/12/29/advent-of-code-2021-day-24/ +-- Writeup at https://work.njae.me.uk/2022/04/23/advent-of-code-2021-day-24/ -- Based on ideas by Daniel Lin, -- taken from https://github.com/ephemient/aoc2021/blob/main/hs/src/Day24.hs diff --git a/advent24/MainDelay.hs b/advent24/MainDelay.hs index fc65f3c..223b813 100644 --- a/advent24/MainDelay.hs +++ b/advent24/MainDelay.hs @@ -1,4 +1,4 @@ --- Writeup at https://work.njae.me.uk/2021/12/29/advent-of-code-2021-day-24/ +-- Writeup at https://work.njae.me.uk/2022/04/23/advent-of-code-2021-day-24/ -- Based on ideas by Daniel Lin, -- taken from https://github.com/ephemient/aoc2021/blob/main/hs/src/Day24.hs diff --git a/advent24/MainLax.hs b/advent24/MainLax.hs index 2dc91cd..e8e984f 100644 --- a/advent24/MainLax.hs +++ b/advent24/MainLax.hs @@ -1,4 +1,4 @@ --- Writeup at https://work.njae.me.uk/2021/12/29/advent-of-code-2021-day-24/ +-- Writeup at https://work.njae.me.uk/2022/04/23/advent-of-code-2021-day-24/ -- Based on ideas by Daniel Lin, -- taken from https://github.com/ephemient/aoc2021/blob/main/hs/src/Day24.hs -- 2.34.1 From f0646e388035b9b0f712b4ebd87790dd041f037a Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Sun, 24 Apr 2022 15:13:49 +0100 Subject: [PATCH 11/16] Done day 25 --- advent-of-code21.cabal | 6 + advent25/Main.hs | 96 ++++++++++ data/advent25.txt | 137 ++++++++++++++ data/advent25a.txt | 9 + problems/day25.html | 397 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 645 insertions(+) create mode 100644 advent25/Main.hs create mode 100644 data/advent25.txt create mode 100644 data/advent25a.txt create mode 100644 problems/day25.html diff --git a/advent-of-code21.cabal b/advent-of-code21.cabal index 5727015..d97a3b0 100644 --- a/advent-of-code21.cabal +++ b/advent-of-code21.cabal @@ -245,3 +245,9 @@ executable advent24d import: common-extensions, build-directives main-is: advent24/MainDelay.hs build-depends: text, attoparsec, containers + +executable advent25 + import: common-extensions, build-directives + main-is: advent25/Main.hs + build-depends: linear, containers + \ No newline at end of file diff --git a/advent25/Main.hs b/advent25/Main.hs new file mode 100644 index 0000000..5c9d005 --- /dev/null +++ b/advent25/Main.hs @@ -0,0 +1,96 @@ +-- Writeup at https://work.njae.me.uk/2021/12/12/advent-of-code-2021-day-11/ + +import qualified Data.Map as M +import Data.Map.Strict ((!), (\\), (!?)) +import Linear (V2(..), (^+^)) +import Data.List (unfoldr) + +type Coord = V2 Int -- r, c +data Grid = Grid (Coord, Coord) (M.Map Coord Cucumber) + deriving (Eq, Show) + +data Cucumber = Eastwards | Southwards + deriving (Eq) + +instance Show Cucumber where + show Eastwards = ">" + show Southwards = "v" + +main :: IO () +main = + do text <- readFile "data/advent25.txt" + let grid = mkGrid text + print $ (1 +) $ length $ simulate grid + +mkGrid :: String -> Grid +mkGrid text = Grid (V2 0 0, V2 maxR maxC) + ( M.fromList + [ (V2 r c, mkCucubmer r c) + | r <- [0..maxR], c <- [0..maxC] + , isCucumber r c + ] + ) + where rows = lines text + maxR = length rows - 1 + maxC = (length $ head rows) - 1 + isCucumber r c = ((rows !! r) !! c) `elem` (">v" :: String) + mkCucubmer r c = if (rows !! r) !! c == '>' then Eastwards else Southwards + +delta :: Cucumber -> Coord +delta Eastwards = V2 0 1 +delta Southwards = V2 1 0 + +wrap :: (Coord, Coord) -> Coord -> Coord +wrap bounds@(V2 r0 c0, V2 r1 c1) (V2 r c) + | r > r1 = wrap bounds $ V2 r0 c + | r < r0 = wrap bounds $ V2 r1 c + | c > c1 = wrap bounds $ V2 r c0 + | c < c0 = wrap bounds $ V2 r c1 + | otherwise = V2 r c + +ahead :: Grid -> Coord -> Coord +ahead (Grid bounds cucumbers) here = wrap bounds (here ^+^ (delta c)) + where c = cucumbers ! here + +vacant :: Grid -> Coord -> Bool +vacant (Grid _ cucumbers) here = M.notMember here cucumbers + +canMove :: Grid -> Grid +canMove grid@(Grid bounds cucumbers) = Grid bounds $ M.filterWithKey openAhead cucumbers + where openAhead here _ = vacant grid $ ahead grid here + +blocked :: Grid -> Bool +blocked grid = M.null cucumbers + where Grid _ cucumbers = canMove grid + +eastFacing, southFacing :: Grid -> Grid +eastFacing (Grid bounds cucumbers) = Grid bounds $ M.filter (== Eastwards) cucumbers +southFacing (Grid bounds cucumbers) = Grid bounds $ M.filter (== Southwards) cucumbers + +advanceEastwards, advanceSouthwards :: Grid -> Grid +advanceEastwards = advance eastFacing +advanceSouthwards = advance southFacing + +advance :: (Grid -> Grid) -> Grid -> Grid +advance facing grid@(Grid bounds cucumbers) = Grid bounds $ M.union cannotMove advanced + where Grid _ advancing = facing $ canMove grid + cannotMove = cucumbers \\ advancing + advanced = M.fromList $ map advanceOne $ M.toAscList advancing + advanceOne (here, c) = (ahead grid here, c) + +step :: Grid -> Grid +step = advanceSouthwards . advanceEastwards + +maybeStep :: Grid -> Maybe (Grid, Grid) +maybeStep grid + | blocked grid = Nothing + | otherwise = Just (grid', grid') + where grid' = step grid + +simulate :: Grid -> [Grid] +simulate grid = unfoldr maybeStep grid + +showGrid :: Grid -> String +showGrid (Grid (V2 minR minC, V2 maxR maxC) cucumbers) = + unlines $ [ concat [showCucumber (V2 r c) | c <- [minC..maxC] ] | r <- [minR..maxR] ] + where showCucumber here = maybe "." show $ cucumbers !? here diff --git a/data/advent25.txt b/data/advent25.txt new file mode 100644 index 0000000..09a45d9 --- /dev/null +++ b/data/advent25.txt @@ -0,0 +1,137 @@ +v>>>.v..v.>.>.....>>.vv>v.v>...vv>>...vv...>..>.vv.>>vvv..vv.>v..vvv>.>.v..>.>....>..vv>.>v..v>v>v.v....>v..>..>..>..v..v>.v...v>v.v>v.v>.> +.>.v..>>>.v....>.>...v.>>.>v..v.v...>.....>.>....>.>>>.vv>.>.>..>..vv..>vvv...v.....v....>....>>vv>.vv.>.>.v>....v.>>v.>.>v..>>>..v>.v.>... +.v..>>....v>v..>>.>.v>.>..v>>>v>.v..v.>>vv.v....>.>>>.>>>.>.>.v>..>.>...vv..>>...>.>v>vv>.v>......>v...>v.>>.v>v>...>v...v...v...vvvv>..v.. +v.>...v>..vv.>..v>>....>.>v>>vv>>v>>v>v>..vv>..>.>.vv>.>.v>...>.vv>.v>.vv..v.>...>.v>.vvvv>.>>....v>...>v>.>v>>>.vv.v>.>v>.v.>>v...vvv..>>. +.vv>.v....>.v>.v.v..>>..v>vv>>v..>v...>..vvv.>v.>v.v..>.v.v.v.>.>>.>>>...>.v>v>>>.vv>..>v.v.>v.>...>....vv>.>.>......vv>v.v>>.vvv.vv.vv>.v. +>.>.v>.v>v.v.v.>.v>v...v>>..>>>>.v>.....v.v>>v.vv.vvv.v.v......v..>.v.v.....v.v..>v..>>>v.v..>v....v>..>v>v..vv...v.v.v.>>..v.>v>>..>v.v... +vvvvvv.>>.v>.v.v.>..vvv..v.v.>..v.>>>vv...v...>vv>..v.>vvv>v...v>>..v.v>...v.>v....v>.vv..>v>v...v.....v..>v.v.....v...>.vv.v..vv.>>v>>>... +.vv>.>.v..>.>vv.vvv>..>...v...>..>...>>>>v>..>>.v..>>...v.v>>>>.>.>.>.>v.vvv...>.>.v>>>.>>v.>>..>..v....v.>>......v..v.>.>vvv....>..v.vv>>> +.>v....vv>v>v..>v>.v..v>v..v>v>.>.vv>v>vv.>v>...>>.v.>>v.v>.>>.>>....>>v>.>v..vv..vvvv..v>v>v.v>....>.v.>.v.>.....>>vv>>.v..v>>>..v.v...>v. +.>.>.>>v.v..>>.>.>>...v.v.>...v.>v>>>..>.>.v.>..>>v>>vv.v.>>>.>>.>.>>>>v..v>>v..>....>....>.....>.>..v...>vvv>v.v...vv.v..v..>>vv>>.>v..>>> +>..v....>>...v....>....v.>>>..>.v..>..vv>>v>.v>vv..>.v>v>v.v....>.vv.>>v...>v.>v>...v>..vv.v.v.v>v>>.v...>>..v>.v...v.vv...>v...vv...vv>v.v +v>v..>v>v..v.>.>>..v..v>v>>..v..v..v..>>.v.>..v.v.v>v>..>.>v..>vv>.v.>..v.v.v....vvv.v.v.>.v....v.>..>v.......>>v>>.v.......v.vv.>....>.>>. +v..vv.vvv>>v>.>v..v>.v>.v.v>>v.....v.vv.vvv.>v>..>..>.v....>>>.v>>.>v>.v..v..>>.v..vv>.v.vv..v.....v..>.>>v.v>.>.v....>..v>..>..v....v..v.> +.>.>>v>..v.>.......>>vvv.vvv.v>..>.v>vvv..vvvv..vv..v...>...vv.v.>.v.>..v.>v>v>vv......>..>v.v....>.v.v>.>>..v>.>>.>...v>..v>>.vv>v...>v..> +.>..v...v....v.>vv.vv..v>.v.v>>..vvv>>>..v>>.>v.v.v..>.....v.vv>>.v...v..v...v>...>.v....v>v.vv.v.>.>.>..vv..>>vvv..v.>.>.>.>v>.v>v...>>... +..v..........>.v>>..v...v.>..>..v...v.v.v>.>v..>v.....v>.v>>>>v.vv.>.>.>>>.v.>v>.....v.v>.v>.>....>..>v.>v.v..vv>..>vv>>>v.>..v>v.>v>....vv +.>>>..v.>>v>>....>.>.>v..v..>v.>.>.v.v..>...>>v>..v>..v>.....>..v.v......vv....>.>>.v>>.>vvvv..>v..>..v>>v>.....>vv>vv>.>>.v..v>v.v...>>.>. +....>.>...vv.>>.>.>>.v..>.>>.>.v>.v>v....v..v>....>....>vv...>>.>v.v.>>v.v>v.>..>v>.>v.vv.>>>>.v..v>..>>v.v.v..v.v...>>>>>..>v.v>>v.>v>v.v. +>>>v.>.v......>.>..>........>>.>v>v>v..v.>..vv>..v>.vv>>.v>.>..vvv.v...v.v>.v>.....v...>..v.>.v...v..>.v...v>>.v>..v.v...>v...v..v.v>v>..>. +vvv.v>.>>>..v>..vv.vv.>>v.>>..>.>v>>>>vv..v.>...>v>....>v>.v>.>>>.>v.>.>.vv.v>..v...>>>...>v.>...>>...>.>..>.v.>v.v..>.v>..>...v.>.>.>...>. +.v..v.....>..vv.>.v.>>.>>>v.vv>...>..v.....>.v..>.>>..vv>>>...vv>v.>v..>>v.v.v>.v.>>v.vvv....>>.>vvvvv.>>>.>..>v>.>>.>.>.....>>.>...>.v..>> +>..v...v>...>v.>....vv>.vv...vv...v>v>v.vv.v>vv.vv.>>vv>>...>.v>..>v...v......>..>.v......>.>v>>vv.v...v.>.......>v>.v>.v...v.>....v.>>..v. +.>v>.vv...>..>..v.vv.>.>.......v.>>>>>.>>.>>.v.v.>>...>.>...v...>.v.>>.>v>>......vv.>v.>.>>>.v..v........>.>.....>....>>.>>.>.>vv...v..vv>> +..>..v>..v.v.>vvv>.......>.vvv.>..>..>.v.v.>......>......>>..v.>v.>>vv>vvv.v...vvv.>v..>vv.v..v>.v>.>>....>..>..>..v..vv.v>>.v...>.v..vvv.v +>..vv..vv..v..v...v..>v>>v>.v....>....>..>vvv.v.v...v..v.v>..>v.v.v.v.v>v..>vv...>.>v..v>.>>...>..>..>v.v..v..>.>......>>>.v>...v.v>>v>.... +v.v>v.>>>.v...>.vv>v>.vvv>..>..v>.v.>.v>...>>..vvv>>...>....v.v..>.v.....>v..>.v.vv..vv>.>.>..>...vv...v.>>>>..>>..v.v>>...>.vv>.vvv.>...>v +v>.>>.>..v.......v..vvv>v.>....v..>...v.v.v>>.v...>...>..>....v.v.>.v...>...v.v>.v.....>v.>......>...v.vv.v>..v>...v>.....>v..v>.v....v...> +>v..>v....v>....>vv>>v>...........v>>v...>.v.>..>v.vv>>.v>.vvvv.v..v.>>v>.>.>...v..v.v>...>.>vvv>>>.v.>.>.v>vv.v.v..>....>.v.>>.>vv..v.>.v. +>.v.v>v>>v>v..v..v..vv>v>v..>>>.>.vv....vv>v..>.>>...>>...>..v.>......v...>.>.v.vv>.vvv...>.>.v>....>>..>>..v.v....vv...v.v>>.>.>.>.vvvv>v. +....>.v.>v..>....v..>..v..v....>.vv.....>.>>.v.>>.....vvv.v.>..>v.vv>..>..>v.....>vvvvv>.v.v>>..v.>.v.>..v.>.v.>...>...v.vv>.>.v>v....v...v +>v>...v..vv..v>.>v>>>>.>>...v>.>>..vv.>>...>v..vv.>..>...v.>v.>..>..v..>..vv.>..>v..>.>..>..v.>.>>>...........>v>v>v.>vv>....>..>vv.vv>v>>. +>v.v.v>>>.>.>..>.>vv...v>>>...>vv..>...vv..>v>.v..v.>..>>>.>v.>v.>..>.vv..>v.v>.>.v>...>>.......>>.vv...v.>v.>v...vv..>.v>>..>v.>..>>>..v.. +..>.v>...v....vv>...>..vvv.>vv>v...vv.>.v...v...>.>v...>.v.v.>.v>v..v.>v>..v.v...vvv>..>...v.v.v......>v.v...>v.>.v.>v.v.....v>.>..v...v.>. +....v.>vv>.v.>....>vv>.....v.>....>.v..>>....v.>v.v..>...v..>...>v..>.v..v.>.v.v>v>v>...vv>..>vv>.v>.>...>.v.>v.........v>.>v.v.....v>>v.v> +vv..>..>.>.>...vv..>v.vv>...v..>v..>v>>.>..>.>.>>>.>....>...>v...>..>.v..>.>>...v..>>v>.>.v.v..v..>>>>.>>.v>>>..>vv..v>.>..>.>v..>.vv...v.v +.....>>....>v.vv..v.>v>..>......vvv>...>>.v...>...v.v.>..>vvv.vvv.v.>..vv.>..>.vvvv>v>..>>...v.vv.....>v..v...v>.v....>..>>.v>.....v..v>..> +..>.>......vvv.v>v.>.vv..v..vvv>vvvv>>.vv.>..>v>..vvvv..vvv..>>v...>v..>..>.....>v.vv>v>.v>>.....vv...v..>..>..>v...vv.vv.>vv.>..>.v>..>v.. +.vv...>..v.v....>.........v...>.>vv..>>>v.>v..>.>v>....v>.>...v...>...v.>v.v......v>vv.>.>...v>..>>vv>>v.v.>v>.v>.........>.>>..>v>..v..v.. +vv..>.>.>v>>...vvvv..v>vvvvv.vv..vv.v.v>.>v...>.>v....>...vv>.....>.v..>.v>>..>.>v..>vv...>v..>>...>.....>.>..v>.>>v>>..>v>>v.v...>....vv.. +>>..v>..v.v..v>v>v>>v.>...>.>....vv.>..v.v.>vv.....vv>vv.>...>..>vv.>v.....v..v...vv..v...vv.v>..v.>v.>vv>.>>.>..>.v>..v>...>vvv.v>..v.>.>. +>.>..v.>>....>.vvv.v..>v.....v>.>.>v..v..v>>v.v>..v>>vv...>...v.>v....vv.....v>....v.>...vvvv..>.....v>v>......v>..>v....v>.......>>..vv>.> +.>.v..v>>.>..>>>>.v>.vv.v.v..v....>>>>.>.>v.v>>v>..>.v.>.>.v>v.>v...vv.v>.>>v..v....>>>..v>.vv>>>.>.v...>>.>....v..>>..v>..>..>..>v>v>>.vv. +>>v>v>.>v.>>...>.>...>>..>>..v......v>>vv.vvv.>..>...v>>..vv>...vvvvv>.v.>v.>..>>>>.v>..>.v.vv.>.v......>>.....v.>vv.v.vv..>..>.>...>>..>>. +..>v...>v..>..>.v..v....v>vvv.>>v..v>>>..v>>...>.v>...>......vv.v..v>>v>.....>vv.v.>.v.>.>...vvv....v...>....v.>..v..v..v>.>.>>>>..v...v... +v..vv..v>>......v..v..>....v.v>>.>..v>.>..v....>.>..v.v>...>>>>..>.>v.v>.....v>v>..v...>..>.>...>>...>>..>v.>>v...>>.v....vv.>.v....v..>v>v +..>>v>>..v.>>.>v>.>v.>.>v>vv.>>.>>>v...>.v.>>>..>..>..v.vv>.>.v...vv..v>>v..>.>vv.>.vv.>>>.vv....vvv>..>>>v......v...>v.vvv>.v....v...v.>.v +..>..vvv...>>...>....v...>v>>v>>.>vv..>>.v>.....v....v>.....>>v...>v>..v.v.v>....>.>...>..>...>..>>v.v>v>>>..>v.vvv>.>.>.>>v>>>v>.v>>.v>.vv +....>..v>vv.>>..>.v.vv..v...>.>..v>v>....>>..v.>....>.....v.vv.v>>>vv..>>>vv>..v.>...v.v.v...>...v....v.....v..v.>v.....>v.v.>.v..v>v>>.>.> +v.>vvv.vv>.>vv>.>.>...>....>.v>.>v>..>v>>vv>....v>.v.>..>>.>>..>>>...v>...v.....v..v.v....>.>.vv>vvv.>.v..v>..v>.>.>>v.v.>v>v.>.>..>>.>>..> +.v>.....>.v>..>>...>v.>vvv>...vvvv...>>>>>v>.v.>..vvv>v..v......>>>vv.vvv>.......>.v.v.v.>>.....>.v.v..v>....v.>.vv.>..v.>>.v>....>.vvv.v>. +v.vvvv>.>.>..>vv>......>>v>v.>......vv>.v.v..>vv..v....>.>>.>v.......>.>..vv>.v.v..>.>v.>>v>.>>>>v.>v..v...>..v.v>.v.>>v>>.v.v.v.v>v..vvv.. +>.>.>.v..v.v.v>>.vv.v.>..>>>.>.v.>.>....v.>v.>..>..vv...v..v...>>..>>..v>vv>..>.v....vv.>..v>.>.v.>....>.>...vv...v>.v>..>.....>>>.>>>>v>>. +>.v....>...>..>..>v>>.>v>v....vv.v>>vvv.v.>>v>vvvv>.vv>>..vv>.v....>>>.>vv>vv..v.>v.>..>......v.v.v>.vvv.>...>>...>>.....v>.v>...>v..v>...> +.>.>>.>.>.....>>>v..v>..v>....>v>>.>.v.v...v>vv>.v....v.>v.>.vv....v>v..>>v.v.v.>vv>.vvv.>....>.v.....v>v.vv.v>vv..v>.v..>..v>v.......v..>. +>v.vv>.>>.>>.>>>....>vv.vv>vv>v.>v.>.v.>>>v..v>vv.>..v>...>.v...>>.vv.>>v.v>..>>>..>.v.>>.v..v>.v>v>.v..v...>v.......vv.vvv.v.v>.......vv.. +v.v...v.>>v...v.>v.vvv>>v>v.>>...v>>>>v.v>.v>vv..>>>>v.>.vv>..v>v>...>>>v..v...>..>v.....v.>>..>.v.>.vv....>>..v...>..vv>.v.vv.v.v>.>.v.v.. +.>.>.>v...>>.>..vv.v..v>>....v...>..>>>.v>>>...vv..v....>v..v...>...vv.v.v..v.>.>>vv.vv.v>vvv..>.v>..>>...v.vvv..v>>...>..v.>vv>.>...v>..>v +>..v..>v>.v>.v.v>>vv>.vv...v....v.>>v>>v>.v....v>>v..>..>>v.vvv.vv.>>..>v>>.v..vv..>vvv..v...vvv..vv......vvv..>v>>>....>vv>....>.v..v>v>>. +.>>v.>>..>.>>v.>>....v.v>>.>..v.v.v..v....v>vv>v>..>.>>...>v.vvv.v..>.>..v>.>v>..v.>.v.v.v.>.>......v>.>>..v>>>>>v.vv>..>vvv>v>>>>>.>..v>vv +v..v...vv..v.vv>....vv..v.v>>v..>>>>.v...v.>>..>...>>......v.v.vv..vv.>>vv...vv.>.vv.>.>..v>>vvv...>v.>v>v.>v.v>.v>v.>>v.>.v.v.vv..v..v>.>. +.....>>.v..>.v..vvv..>..>.....v.v..>>....>v>vv>.>..>v.v...>v.>..v...>..vv>v.>>..v.>.>.vv>v..>.>.>.......v.>..>......v.vv>.>.vv.>v....v.>... +v..>>v>>>.....>v.>.v.>v..>...>v.>>.vv>vv>.v>....>.............>.>>>.>.>.v.>v>>..vv>>v.v>vv..v.v..v.>.>..v..>>...v.>.....>.>...vvv..>v..>.>> +..>...v>...v...v.>.v.>.>..v...>v..vv>>..v.vv.>.>.......v.>.>..vvvv>......>.>..v>>...>>....vvv...>.v>>>...v...v..>v..v>.>.>v..>...v>v.>...>. +.>v>>>.>>v..v..>.>..........v.>>.>.v.v.>...vv>v.>....>>v.v..v>..>..>.>.>>>v..>.vv.vv>>..v..v...>...>.>..vv.v.>v..>..>...>v.v>vv>v.>>>>>...> +>.>.>......>>vv>>>..>>>.>..v....v..>......>.>v..v>.>vv....>....v........v>.>v..vv...>>>.vv>>v.v>..vv.>v.v....>v.>.vvv.v>>.vv>.......>.>>>>. +...>.....vv>...>....v>v>>.v.v.>.v..>.v>.v.>>.....vv.>>.vv.........>.v..>>>.v....v...v.v.v....>vv.v.>.v....vv...v.vv.....>>.......v.v.v...v. +>.vv>..>v...v..>.v.>>.v.....vv.v.>v..v>.>..v.>>vv.....v>>....>v>....v>vvv...vv...>......v..>......v.v>v.v>.>.v.>v..v>vv..v.>v>>v>v..v.v>>.. +>v.........>v>....v.v.>.v..>>..>>v.>..vv.vv.>v....v.>v>v.>...v.>>...v>>v..v..>..v.>v>v>..v.....>.v..v...v...>..>v>.>vv.....vv>>v.vv>v>v.... +v.>.........>.>v..>.....>...v.>.v.v.>..>.....>..>.v.......v.v.vv........v.>.v.>...v...>>>.>..vv>v..vvv>>..vvv.>>v>.vvv.vv.v.v>.v..>.>v.>>.. +v.v...v.v.>.>.v.>>>vv...>vv...>>>>>..vvv....>>.>....v>v..vv....v.v>>.>>.>v>>..>.>..v..v>.v.....>.>v>v..>...v.vv.....>>..>>>>v.>>>...>..>.>. +>.v.v>>v.vvv>v....vvvvvv.>.>>>.>...>v>.>v>....>..>.....v..>v>..>.>..v>v.v>..v>.>vv.>...>v..>v.v..>>>>>....vv.vv>vv.>vv.vv.>...>v....v..>>vv +.>..>..v.>.vv...vvvv..>v.....>.>vvv.v>...v>.>v..>>...v..v>.vv.v.v.>>vv>>..>v>.>v.>v....>.>>.>...>.v.>>.>.v.>>>>.>...>v.>v>.v.vvvv>.vv..>>.. +.>.>.>v..v>....v>vv...>.....v>..>v>v>..v>v.v>..>>>.>.>>>...>v..vv>v>>.v>v>...>.v.>v..>>.>..>....v..>.vv>.>..v..>.>....>v>..>...>vv.>...>v.. +..>.>v.>....v>v>v>..>..>v.v.>.v.>>.>v.vv>v..>.v.v.>.....>..v..v....>...>...>v.>..vv.v.vvv>.v........v.v.>v..v.v.>vv....>v.>.>>.>...>>..>>vv +>....>>.vvv....v..v.v..>..v>.>v>..v>v.>..v..v....v..>..>...>.>v>v.>.>.vv.>.v>.v..>.>>...v>v.v>>..>>>.vv>.>.>v>>>>v...>.v.vv..v>..>..v>..... +...>>.v..>.v.v.>.>.>v.v>v.>>v..>.>v...v.v..vvv.....vvvv>....v.vv>..>...vvvv>v.>vv...v.v.>>.>.>v.>v>vvvv.>vv..>>..v.vvv.v...>>>>>>v...>v.>.v +vv>v.vv..>..v>.v.>>....>..v.....v..>v.vv..>vv>vv>>>v.v.>...vv.v>v..v.>..v...v>.>>..v>..>>vv...v..>>....v.....vv.>..>>..>..>>>>.>......>>v>> +..>>...v.vv>>..>...v>.v>v..>>>..>v>.v>v.>..>...>>...>>>..v.>v........>...>>..>....>.v.v..>v..vv>>.>vv.vvvv>v.v.vv>>>>.v.v..vv>......vv.v>vv +v..vv.>v..>.>..>....v>.>.>.>>...>>.v>>v.v.>.>>v>.vvvvvv.v.vvv>.vv>..>....>vv.vv>>>v>.vvv>.....vv...v>..v.v......vv.>.v..vv.>.v.v......v..>> +vv.v>..>.>v....v...>>>.>..v.v>..v>vv.>>.>..>.>vv.v.v...>v.v>>..........v.v>>>.v.v...>..v..>>.v..>.>.>v>..>>vv.>>v>.v..>.....v...v..v>.>v>v. +>.>>.....vvv.v>vvvvv.>>..v.v>>v.v..v..vvvv..v....v>>v.v...>.....vv..vv...v>.v.v.vv.vv>v..v.v.>.v.....>....>>....>.v.>>v..vvv.>>>v>.vv>..... +>>vv>...v>v.v>.>>.>.......v.v>.v..vv>v>v..v.>..>.>.>v...vv.v.vvv>.....v>.>..>.>v..>.>>vv>>.v.v...>.>.>>.v..>...>..>..>.v>.vv.....>.v.>..... +...>>v.v.vv.v..>.>..>.v.....v.v...vv..>.>>>.>.v>v.>....>v>.v.v...v.>.>v....>v...>v..>>...vv..>>..>>v>>v.v>vv.>....>.>>v.v..>..v..>v..vv>... +.v.>>v..v>>vv..v>v.vv>....>v>..v...vv>.>.v>>>...vv..>...>...v..v....v.v>.>..>.>....v.v>v..v.>.>.v>.>..>>>>v.v>.v>..>.......v>vv....vvv.>... +v..>.....>v.>vv.>>...>>...>...v.>...>v.v..v>.v..>.>.vv.vv>v.v....>>..>vv>..>.v>vv.v>.>>.>>.v..vv>.>.vv.>.>..>..v>.>v.......vvvv>.v.>..v>v.> +>v>>.>.....>......>..>..>v.....v......vvv...v>.v.>....>.vv..>v.>..v..>>>.>..v.......>..>>.>.>v..v..>v.v>v>....>.>.........>vv...>>v..>v.>.. +>.v.....v......v.>.>v.>..>.>>...>..vv..vv.>......>vv.>.>v>v....>>.>.>v.>v>.vv.v.>..v.>.v.>..v.>>v..........>>.v..v>>.v.v.vv...v.vvvv.>.v>v> +>.v..>v>.....>...>>v.>.>>>>>>vv>vv>.>.v..>..v..>....>>..>...>...v.v.>>.v.>v.v...v>.v...v>v...>.vv.>.>>>>>>>.v>v>v..>..>v..v.vvv>...>.>..vv. +.>.>>>.vv...>.v....v..v>.vv.vv>.v.>>v....vv>>v>>v>.....>.>..v>>...vv>>>v>v>v>...v.>v.......vvv.vv.>...>v....vv.>>>......v.>..vvv.>...>...>v +...>..v...vv.>>>.>>.>..vv..v.>>v.>..>.vv>.....v.>>.v...v>>...>>.>vvv.>>>>>>v.v>vvv..v...v.....>.v......>.>.v.>.v..>>>>v..vv...>..v>>..>.>.. +.>vv..vv>>>.>....>vv.v....v.vv..v.>v.v.v...>.v>..v.>.v.>v.v.v.>vv...>v.v.>>..>>.>>vv...>...>.v>vvv>v>...v..v.v>v.v>.>vvv>>.>.>...v>.>.>.... +.....>vv...>.>>.vv>vv.v.vv.v.....v>..>.v.....>..>vv..>..v........>.>v....>.>v>v..v>v.>.>>..>vv..v>.>.vvv..v.>>v>v.v>.>>>>>...vv.>......vv>v +>vv.v.....v..>>v.>>..v>>.>..vv.....v.v...>v.v...vv>.vvv.>..v.>..v..v>.v.v>v>.v.>>..>vv.>vv.>....vv>vvv.v..v..>vv.vvv...v>v..v.v.v.>....v>.v +.>....v......v..vv.>.v>v.v...v.v>...v.>..>v...>.v...>.>v...v>.>..v.v.>>>vv.>.v>v>vv..>>.v.v..>vv.>..v>v..v>vvv....>vv.......v.>v>..>vv.>v.. +>...v>v.v.....v....>>.v.v..v>..........>.>v>.....v>>v>v.v>.....v>......>.>>...v>>v.>v..>>..v.v>>>v...>.>vv.v.>v>v...v>..vvv>....v>.>>.>v..v +vv.vv.vv>.>>>>>v>>>....>.vvv.>..v.>...v>>.>..vv..>>v...>.v..>v>.v...v..>..>>v>>>...>.v.>v...vv..vv..>v.>..>vvv.>..vvv.v..>>>..v>v.v.>.v>>>. +.v...>..v.v>......vvvv>vv>.v>..v...>.>.v>..v..........>vv.>v..>.v>.v...>.v.v..v.....vv>..v..v.v.v..v>.v.>>..>>..vv>>.vvv>...>v>.v>vv.v..>.. +>v...>>v>v..>.>..>.....>>.v....v.>.>vv..>.>.vv.>..>...>....v>.>v>v...>v..>.>>.v>.>.>vvvv>>....v.>.......>..v>v>.>.v..>.....v>..>>..>>>>v.v. +>>..v.....>.>>v..>v..>>>v>v....vv...vvvv..>.>..>.>v.vvv>>v..>...v..vv...>..v......v>v>.v.v>..v>v>v.>>.>.v.>v.v.>v.>>>.>...v>>.v.>v.vvv>>>.v +..v>>>..>.>v..vv>.>>.vv..v..v.>>>>vv>vvv..>>v.>>>..>v.vv.>v.>...>....v..>..>>..v>.v..v.v..vv>..>.>v...v>>v>>.>.>...v.v>.>v.v.v.v.vv>v>.v.v> +..>>.v>.>>.vv......>.>>v>.>>v>..v....>v>v.>>vv....vv.v>.v.>.......>vv.....v.v..v>>..>v...v..>>>...>v..>..v.>>..v....>.>.>.....>..v>v..vvv>> +....v..v.vv>.v.>.v..vvvvv>.v>.v.>>..>....>.>>..>..v.>.vv...............>vv>..>..>.>>v..>>>..>...>..>vv.>>...>..>.>...v>v.>vvvv....>>.v..>v> +.v.vv.v.v>>v..vvv>...vv..>..>>..>v>>..>.>....v>v.vv.v.....v.vv.v.>.>..>>.>.v>v.vv>.v...>>..>.>>...vv>v....v...>.>v>v.>v>>..v..>..>.>.vv.v.> +.>>..v>..v>..v..v..>.>.>.....vvv.v..vv.>..>.v>>.>.v>vv>v......v>..>>>.>>>.>v>.>>>.v>.v.>>.vvv.>.>.vv>>.>vvv..vvv......v>..v.....>.v.v>.vv.v +...>>>>....v.v.>....>>v>v.>.....>>>>v....>.vv.>.>>>..>>>.>v>....v.v...v...>..>.....>.>.v.vv.v.>vvvv>.>>>...v.>>>v.>>..v.>...>v.v.>....>.>v> +>>.v.>>>.....>.v>>>.>..v.>>vv..>v......v>v.>v.>v>>>>>>.>..>v.>.>..>.v.vv..>....>vv.vv.vv.v>..vvv.>>>....vv>..>v.>>>.>.v.>.>vv.>v.v..v..>>.. +.>.v.vvvv..>.>vvv>.v.vv.vv..v......>>..v>.v>.vv>.>>v.>v.>v.v>.v.>....>>.>..>v.v>...>>....>vvvv>.>>.>>v>.v.vv.>.>..v.>.v..v.v.vv>>..v....>v. +>....v..v.>.v.>.>>......>..>v..v.v.vv.v..v.>.v..vv..v>.>.>>>v>.>>...>>.vv...v...v.>>v.>.v>v>.v>.vv...>v>.>v...>..v>..>........vv>v.>>....v. +>v.v>.v.....>>....>...>.v>v.v.>.v>>...v.v...v...>..v>>>..v..>vv.v...vv.>.>...>>v>v..>v>..v.v>.....>..v..vvv.v.....>>...>.>>>v>.>>.v.v>.>>.v +v>v.>.vv>.v>...>...v>v>.>>.>.v>v>vv....>vv..>.vv.>>vv.>....>.v.v..>.>vv.....>.>.>v.>vv>>v>..>>vv..v..>>.>.>...>>.>v..vv..>.vvv>.v.....>.vv. +>..v.>v....v>.>v...v.>>vvv>.vv>v>v.>.>...>..>v.....v..v...v..v>v.>.v..v>..vvv...vv..vv>.>v.vv>...v....>>.>.>>>v.v..>.>v.....>.....v.vv.v>v. +>..vv........>>v>v.v...v.....vv..v...v..........vvv.....>....vv>v..vvv.v.v>.>v>v.v......>.v..>..v.....vv.>v.>...>....>....v...v>v.......... +...vv...v>>.v>vv...vvv..v>>.v>..v.v>>v..>...>vvv.>...>.>vv.v.v.>.v....>.v.v..v.>>....>..>vv>...>v...>.v..v..vv.>.>vv>vv>>..vvv..>vv....vv.v +v..>>..v..vv...>v.v.>>vv>>>.>...>...>...>.>.......vvv.>..>vv>>...>vv..v>>>...>>v>v>>..v.>..>.vv.>vv>>.>..>...vvv..v.vvv..v.>.v.v>...vvvvv.. +>>.....vv...>>.>>.v.v.v.>v.v.>.>v..v..>.>....v..>..>>>v.v...>v>v.>v...v>.v..v.v>v..v>......v.v>.>.>.v.....>>>>>.vv.v>>v..v..>>.>...>v>vv... +.>>>...v.v.>>.vvv..>.>...>v>v.>vv...v.>.>v.>>..>>vv.v.......>>.>>..>..v.>..vvv>..v..>v>>....>.>.v>.vv.v..v>.....>.v>.vv.>>...v>>v>.vv...>.> +.>.>..v.v.vv>..>.>.v.vv..vv..>v.>..v.>>>>..v>.v.v>v.vv.>>v...>v.>.>>.>.vvv.>.>v...v>.>.>...v.>v....>..v.>.>>v.>.>..v..>>vv..vvvv>v>>.v>>..> +..v..>vvv..>>...>>>>v.v.vv.....>.v.>>vv..v.>.>vvv.>>.v.>.v..>..>>>...v.>v>>>...>>...>>>...vv...vvv...>v>....v...v...>..v>..>.>>>>vvvv...v.v +.v.v.>v>v>.>>..v...>.v>>.>..>.v.vvv>v.>>v>...v>.vvv.>vv>>.>..>.v.v.v.vv...>....vv....vv>v>v.>..>.v.v.>..vv.....v.>.>..vvv.vvvv>>v...v>.v.v> +v>.v.v...>...>vv..v...vv.vv>..vv>..vv...>>.v.v>.v>...v.v...vv>>.....v>.>v>>.v...vvv.v.vvv..>>>.vv..v>v>..vv......v>>v.>...>vv.>..vv....>>.. +.v.>.v.>.v..v>.>.>...>...>>>...v.>>...vv.v....vv.>v.>v.>.>.>v>v>.>..>>v.>>....v..v...v.>>.>v.........>..>.>.v>vvvv.vv.>v.v>..>..vv.>>>..>>> +v..>.v.>.v>v.vv...v>>.v.>...>>>v.v.>...>>.>>.>..v....>.>v.>>vv>........v..v.>...v>>>..vv..vv>vv.>v.....v....v.>..>.v...v.vv...vv.vv>....... +.v..>.>>.>.>>>v>..v>..v.>>>v>...v>>v.>.vv>..vv..v.>>.>.v.>.v..>......>vv.>v.vv>..v>>v........vv.>.v....>vv....>.v....>...v..vv...v.>v.>v>.. +v>...>..v.>..>.>..>v.v.vv.............>.v.>..>...v>v.v>..>vvv.>.v.vv>vv.>v.v>.v..>vv.v>>vv.v..v>..>vv.>.v....v.>>v>.>...vvv.vv>v>..>vvvvv>. +>v...v..v>v....>v...>v...>.>.>..v.v...v>.>>>.v.v...>.>....>.v..v.>.>..>.>>v.vv.>v...>..v...v...vv...>.>.v.>vv>.>>..>v....>>v.>v.......vv... +v>.vv>>..v>.>..>...v.>>v.v.>.>>..>.>v.v>>......vv.v..>.vv.>v.v.vv.vvv>v>>.v.>>>....>..v..>.v..>...vv>v.>.v>v.>.>vv..vv.>>.v...>....v>v...>> +.v...vv...>v.v.v.>.v>vv..vv..v.>>.vvv...>v.vvv.v..vv.>>.>>v>.>v...vvvv>.>.......v>>>>.>..v.>.>v...>v.....>.>>>.>.v.....>..>v....>.>v.vv.v.> +...v>>.>..v>>v.vv.....>>.>..vv.v>>>......v..>>.>vv>.......v....vv.>>>.vvv.>...>v..>>....vv>.>vv.>>v...>vv.vvv....v....>v>.>..vv>v....v.v.>. +..>>..v.....>vv.>>.vv>v>..v>vv>..>.>.>v>>.>.>..v...>vvv...>v>.v.>..vv.....v>.v..>.>>.>.vvv>...>v.v.>.>..>.v.>>>.....>v>.>>..>>vv...v.v...v> +>.v..vv...>v>..vv.>.vv>>.>>.>.>....v...>..vvv....v>....v>.v>..>>.v>>>.v>....>>.>...v...v.>>v.v>...v>>..>v>..v.v..v>...v.v..v.v.>>v..>.vvv.v +>>>......vvv..v>>.v.....v.v>>...>v>>>>>vv...v.>....>...>>.vvv>>.v.....v...>>.vv...v....v>...v..v>>v..v..>..vv....>>..v..vv>v.>.>vv..v.v.v>. +>v.>v>v>vv.v>.v.v..vv..>v.>>.>..>...>>...>..>....>..>.v......>>>v.>>>..v.v.v>.v..>..>.vv.v>...>.vv>...v>>.>>....>vv>....v.>...v>.>.v>.>..v. +.>v....vv....v>.v.>>v.v>....>..v.>..>..vv..vv>..vv>...>>>v.v..>..v.>..vv.vv.>..>...v.>v.>.>v..v.>..vvv>.vv.v>v>.v.v...v....>>>>....vv>>...> +>..>v>.v.vv..>.v>..vv..v>..v......vv.vv..>......>v.>>....v>>v>>..vv.>.>v..>.v.>>.>...>...vvvv>v>v>..>.v>v>.>>v>.v..vv..>.>v....>>>..>.vv>v. +...vvv>.v.>v...v.v.>>>v>...vvv..v>....>v..>>..v.v.v>>.v>......v.v.v>vvv>.>..v.v.>>.>.v..vv>v>>v>.vv>v...>v...>.>>....v>>..v.vvv........>.v. +>..>...>...vv..>.vv>......vv>...v>vv>vvvvv.>>>..........v>.....>..>>.>.>v.v..>.>...>...vvv>>v...>...v.v.v.>.>.>>...>v.v>.vvv>v>....vv.v.v.. +..v>v>>....v..vvv.>...v>..>v..v..v..v.v....>.....>v.>>..vv..>..>vv>...v.....vvv...vv..>.v>vv......>..>.v>>......>v..>.>..>.......v.v.v.vv>. diff --git a/data/advent25a.txt b/data/advent25a.txt new file mode 100644 index 0000000..0f3c0cd --- /dev/null +++ b/data/advent25a.txt @@ -0,0 +1,9 @@ +v...>>.vv> +.vv>>.vv.. +>>.>v>...v +>>v>>.>.v. +v>v.vv.v.. +>.>>..v... +.vv..>.>v. +v.v..>>v.v +....v..v.> diff --git a/problems/day25.html b/problems/day25.html new file mode 100644 index 0000000..c187a2b --- /dev/null +++ b/problems/day25.html @@ -0,0 +1,397 @@ + + + + +Day 25 - Advent of Code 2021 + + + + + + + + +
    + + + +
    +

    --- Day 25: Sea Cucumber ---

    This is it: the bottom of the ocean trench, the last place the sleigh keys could be. Your submarine's experimental antenna still isn't boosted enough to detect the keys, but they must be here. All you need to do is reach the seafloor and find them.

    +

    At least, you'd touch down on the seafloor if you could; unfortunately, it's completely covered by two large herds of sea cucumbers, and there isn't an open space large enough for your submarine.

    +

    You suspect that the Elves must have done this before, because just then you discover the phone number of a deep-sea marine biologist on a handwritten note taped to the wall of the submarine's cockpit.

    +

    "Sea cucumbers? Yeah, they're probably hunting for food. But don't worry, they're predictable critters: they move in perfectly straight lines, only moving forward when there's space to do so. They're actually quite polite!"

    +

    You explain that you'd like to predict when you could land your submarine.

    +

    "Oh that's easy, they'll eventually pile up and leave enough space for-- wait, did you say submarine? And the only place with that many sea cucumbers would be at the very bottom of the Mariana--" You hang up the phone.

    +

    There are two herds of sea cucumbers sharing the same region; one always moves east (>), while the other always moves south (v). Each location can contain at most one sea cucumber; the remaining locations are empty (.). The submarine helpfully generates a map of the situation (your puzzle input). For example:

    +
    v...>>.vv>
    +.vv>>.vv..
    +>>.>v>...v
    +>>v>>.>.v.
    +v>v.vv.v..
    +>.>>..v...
    +.vv..>.>v.
    +v.v..>>v.v
    +....v..v.>
    +
    +

    Every step, the sea cucumbers in the east-facing herd attempt to move forward one location, then the sea cucumbers in the south-facing herd attempt to move forward one location. When a herd moves forward, every sea cucumber in the herd first simultaneously considers whether there is a sea cucumber in the adjacent location it's facing (even another sea cucumber facing the same direction), and then every sea cucumber facing an empty location simultaneously moves into that location.

    +

    So, in a situation like this:

    +
    ...>>>>>...
    +

    After one step, only the rightmost sea cucumber would have moved:

    +
    ...>>>>.>..
    +

    After the next step, two sea cucumbers move:

    +
    ...>>>.>.>.
    +

    During a single step, the east-facing herd moves first, then the south-facing herd moves. So, given this situation:

    +
    ..........
    +.>v....v..
    +.......>..
    +..........
    +
    +

    After a single step, of the sea cucumbers on the left, only the south-facing sea cucumber has moved (as it wasn't out of the way in time for the east-facing cucumber on the left to move), but both sea cucumbers on the right have moved (as the east-facing sea cucumber moved out of the way of the south-facing sea cucumber):

    +
    ..........
    +.>........
    +..v....v>.
    +..........
    +
    +

    Due to strong water currents in the area, sea cucumbers that move off the right edge of the map appear on the left edge, and sea cucumbers that move off the bottom edge of the map appear on the top edge. Sea cucumbers always check whether their destination location is empty before moving, even if that destination is on the opposite side of the map:

    +
    Initial state:
    +...>...
    +.......
    +......>
    +v.....>
    +......>
    +.......
    +..vvv..
    +
    +After 1 step:
    +..vv>..
    +.......
    +>......
    +v.....>
    +>......
    +.......
    +....v..
    +
    +After 2 steps:
    +....v>.
    +..vv...
    +.>.....
    +......>
    +v>.....
    +.......
    +.......
    +
    +After 3 steps:
    +......>
    +..v.v..
    +..>v...
    +>......
    +..>....
    +v......
    +.......
    +
    +After 4 steps:
    +>......
    +..v....
    +..>.v..
    +.>.v...
    +...>...
    +.......
    +v......
    +
    +

    To find a safe place to land your submarine, the sea cucumbers need to stop moving. Again consider the first example:

    +
    Initial state:
    +v...>>.vv>
    +.vv>>.vv..
    +>>.>v>...v
    +>>v>>.>.v.
    +v>v.vv.v..
    +>.>>..v...
    +.vv..>.>v.
    +v.v..>>v.v
    +....v..v.>
    +
    +After 1 step:
    +....>.>v.>
    +v.v>.>v.v.
    +>v>>..>v..
    +>>v>v>.>.v
    +.>v.v...v.
    +v>>.>vvv..
    +..v...>>..
    +vv...>>vv.
    +>.v.v..v.v
    +
    +After 2 steps:
    +>.v.v>>..v
    +v.v.>>vv..
    +>v>.>.>.v.
    +>>v>v.>v>.
    +.>..v....v
    +.>v>>.v.v.
    +v....v>v>.
    +.vv..>>v..
    +v>.....vv.
    +
    +After 3 steps:
    +v>v.v>.>v.
    +v...>>.v.v
    +>vv>.>v>..
    +>>v>v.>.v>
    +..>....v..
    +.>.>v>v..v
    +..v..v>vv>
    +v.v..>>v..
    +.v>....v..
    +
    +After 4 steps:
    +v>..v.>>..
    +v.v.>.>.v.
    +>vv.>>.v>v
    +>>.>..v>.>
    +..v>v...v.
    +..>>.>vv..
    +>.v.vv>v.v
    +.....>>vv.
    +vvv>...v..
    +
    +After 5 steps:
    +vv>...>v>.
    +v.v.v>.>v.
    +>.v.>.>.>v
    +>v>.>..v>>
    +..v>v.v...
    +..>.>>vvv.
    +.>...v>v..
    +..v.v>>v.v
    +v.v.>...v.
    +
    +...
    +
    +After 10 steps:
    +..>..>>vv.
    +v.....>>.v
    +..v.v>>>v>
    +v>.>v.>>>.
    +..v>v.vv.v
    +.v.>>>.v..
    +v.v..>v>..
    +..v...>v.>
    +.vv..v>vv.
    +
    +...
    +
    +After 20 steps:
    +v>.....>>.
    +>vv>.....v
    +.>v>v.vv>>
    +v>>>v.>v.>
    +....vv>v..
    +.v.>>>vvv.
    +..v..>>vv.
    +v.v...>>.v
    +..v.....v>
    +
    +...
    +
    +After 30 steps:
    +.vv.v..>>>
    +v>...v...>
    +>.v>.>vv.>
    +>v>.>.>v.>
    +.>..v.vv..
    +..v>..>>v.
    +....v>..>v
    +v.v...>vv>
    +v.v...>vvv
    +
    +...
    +
    +After 40 steps:
    +>>v>v..v..
    +..>>v..vv.
    +..>>>v.>.v
    +..>>>>vvv>
    +v.....>...
    +v.v...>v>>
    +>vv.....v>
    +.>v...v.>v
    +vvv.v..v.>
    +
    +...
    +
    +After 50 steps:
    +..>>v>vv.v
    +..v.>>vv..
    +v.>>v>>v..
    +..>>>>>vv.
    +vvv....>vv
    +..v....>>>
    +v>.......>
    +.vv>....v>
    +.>v.vv.v..
    +
    +...
    +
    +After 55 steps:
    +..>>v>vv..
    +..v.>>vv..
    +..>>v>>vv.
    +..>>>>>vv.
    +v......>vv
    +v>v....>>v
    +vvv...>..>
    +>vv.....>.
    +.>v.vv.v..
    +
    +After 56 steps:
    +..>>v>vv..
    +..v.>>vv..
    +..>>v>>vv.
    +..>>>>>vv.
    +v......>vv
    +v>v....>>v
    +vvv....>.>
    +>vv......>
    +.>v.vv.v..
    +
    +After 57 steps:
    +..>>v>vv..
    +..v.>>vv..
    +..>>v>>vv.
    +..>>>>>vv.
    +v......>vv
    +v>v....>>v
    +vvv.....>>
    +>vv......>
    +.>v.vv.v..
    +
    +After 58 steps:
    +..>>v>vv..
    +..v.>>vv..
    +..>>v>>vv.
    +..>>>>>vv.
    +v......>vv
    +v>v....>>v
    +vvv.....>>
    +>vv......>
    +.>v.vv.v..
    +
    +

    In this example, the sea cucumbers stop moving after 58 steps.

    +

    Find somewhere safe to land your submarine. What is the first step on which no sea cucumbers move?

    +
    +

    Your puzzle answer was 435.

    --- Part Two ---

    Suddenly, the experimental antenna control console lights up:

    +
    Sleigh keys detected!
    +

    According to the console, the keys are directly under the submarine. You landed right on them! Using a robotic arm on the submarine, you move the sleigh keys into the airlock.

    +

    Now, you just need to get them to Santa in time to save Christmas! You check your clock - it is Christmas. There's no way you can get them back to the surface in time.

    +

    Just as you start to lose hope, you notice a button on the sleigh keys: remote start. You can start the sleigh from the bottom of the ocean! You just need some way to boost the signal from the keys so it actually reaches the sleigh. Good thing the submarine has that experimental antenna! You'll definitely need 50 stars to boost it that far, though.

    +

    The experimental antenna control console lights up again:

    +
    Energy source detected.
    +Integrating energy source from device "sleigh keys"...done.
    +Installing device drivers...done.
    +Recalibrating experimental antenna...done.
    +Boost strength due to matching signal phase: 1 star
    +
    +

    Only 49 stars to go.

    +
    +

    If you like, you can .

    +

    Both parts of this puzzle are complete! They provide two gold stars: **

    +

    At this point, all that is left is for you to admire your Advent calendar.

    +

    If you still want to see it, you can get your puzzle input.

    +

    You can also this puzzle.

    +
    + + + + + + \ No newline at end of file -- 2.34.1 From 8047349a74fcf277f58f6f7d84d3c4be5f4bb6da Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Sun, 24 Apr 2022 15:52:03 +0100 Subject: [PATCH 12/16] Updated blog link --- advent25/Main.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advent25/Main.hs b/advent25/Main.hs index 5c9d005..9b6b704 100644 --- a/advent25/Main.hs +++ b/advent25/Main.hs @@ -1,4 +1,4 @@ --- Writeup at https://work.njae.me.uk/2021/12/12/advent-of-code-2021-day-11/ +-- Writeup at https://work.njae.me.uk/2022/04/24/advent-of-code-2021-day-25/ import qualified Data.Map as M import Data.Map.Strict ((!), (\\), (!?)) -- 2.34.1 From 4506b761e9bc00ea63e0dbc93f6b619b02895e15 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Tue, 10 May 2022 16:07:08 +0100 Subject: [PATCH 13/16] Some analysis of code and performance --- advent-of-code21.cabal | 7 +- advent14/Main.hs | 4 +- advent15/Main.hs | 4 +- advent16/Main.hs | 3 +- advent21/Main.hs | 2 +- advent24/Main.hs | 6 +- advent25/Main.hs | 2 +- profiling/modules.ipynb | 2581 ++++++++++++++++++++ profiling/modules.md | 184 ++ profiling/profiling.ipynb | 4664 +++++++++++++++++++++++++++++++++++++ profiling/profiling.md | 292 +++ 11 files changed, 7733 insertions(+), 16 deletions(-) create mode 100644 profiling/modules.ipynb create mode 100644 profiling/modules.md create mode 100644 profiling/profiling.ipynb create mode 100644 profiling/profiling.md diff --git a/advent-of-code21.cabal b/advent-of-code21.cabal index d97a3b0..1d50e30 100644 --- a/advent-of-code21.cabal +++ b/advent-of-code21.cabal @@ -158,7 +158,7 @@ executable advent14 executable advent15 import: common-extensions, build-directives main-is: advent15/Main.hs - build-depends: text, containers, linear, array, pqueue, mtl, lens + build-depends: containers, linear, array, pqueue, mtl, lens executable advent15slow import: common-extensions, build-directives @@ -177,11 +177,6 @@ executable advent15prof -threaded -rtsopts "-with-rtsopts=-N -p -s -hT" --- executable advent16 - -- import: common-extensions, build-directives - -- main-is: advent16/Main.hs - -- build-depends: binary, bytestring, bitstring, mtl - executable advent16 import: common-extensions, build-directives main-is: advent16/Main.hs diff --git a/advent14/Main.hs b/advent14/Main.hs index 436f3d2..865db7b 100644 --- a/advent14/Main.hs +++ b/advent14/Main.hs @@ -7,8 +7,8 @@ import Data.Attoparsec.Text import Control.Applicative import Data.List -import qualified Data.Map as M -import Data.Map ((!)) +import qualified Data.Map.Strict as M +import Data.Map.Strict ((!)) import qualified Data.MultiSet as MS import qualified Data.Set as S diff --git a/advent15/Main.hs b/advent15/Main.hs index 40a152a..e9242f9 100644 --- a/advent15/Main.hs +++ b/advent15/Main.hs @@ -1,6 +1,6 @@ -- Writeup at https://work.njae.me.uk/2021/12/16/advent-of-code-2021-day-15/ -import Debug.Trace +-- import Debug.Trace -- import qualified Data.Text.IO as TIO @@ -12,7 +12,7 @@ import Data.Foldable (foldl', sum) -- (toList, foldr', foldl', all) import Data.Char import Control.Monad.Reader import Control.Lens hiding ((<|), (|>), (:>), (:<)) -import Data.Maybe (fromMaybe) +-- import Data.Maybe (fromMaybe) import Linear (V2(..), (^+^), (^-^), (*^), (^*)) import Data.Array.IArray diff --git a/advent16/Main.hs b/advent16/Main.hs index ab14272..98e7879 100644 --- a/advent16/Main.hs +++ b/advent16/Main.hs @@ -5,7 +5,8 @@ import Data.Bits import Data.Char import Data.Int -import Control.Monad.State.Lazy +-- import Control.Monad.State.Lazy +import Control.Monad.State.Strict import qualified Data.ByteString as BYS import qualified Data.Bitstream as BS diff --git a/advent21/Main.hs b/advent21/Main.hs index 191530e..01d23e7 100644 --- a/advent21/Main.hs +++ b/advent21/Main.hs @@ -1,6 +1,6 @@ -- Writeup at https://work.njae.me.uk/2021/12/26/advent-of-code-2021-day-21/ -import Debug.Trace +-- import Debug.Trace import Data.Text () import qualified Data.Text.IO as TIO diff --git a/advent24/Main.hs b/advent24/Main.hs index b1ca376..ae03fac 100644 --- a/advent24/Main.hs +++ b/advent24/Main.hs @@ -2,14 +2,14 @@ -- Based on ideas by Daniel Lin, -- taken from https://github.com/ephemient/aoc2021/blob/main/hs/src/Day24.hs -import Debug.Trace +-- import Debug.Trace import Data.Text (Text) import qualified Data.Text.IO as TIO import Data.Attoparsec.Text -- hiding (take, takeWhile) import Control.Applicative -import qualified Data.Map as M -import Data.Map ((!)) +import qualified Data.Map.Strict as M +import Data.Map.Strict ((!)) import Data.List import Control.Monad import Data.Maybe diff --git a/advent25/Main.hs b/advent25/Main.hs index 9b6b704..9e30cbc 100644 --- a/advent25/Main.hs +++ b/advent25/Main.hs @@ -1,6 +1,6 @@ -- Writeup at https://work.njae.me.uk/2022/04/24/advent-of-code-2021-day-25/ -import qualified Data.Map as M +import qualified Data.Map.Strict as M import Data.Map.Strict ((!), (\\), (!?)) import Linear (V2(..), (^+^)) import Data.List (unfoldr) diff --git a/profiling/modules.ipynb b/profiling/modules.ipynb new file mode 100644 index 0000000..6626344 --- /dev/null +++ b/profiling/modules.ipynb @@ -0,0 +1,2581 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 202, + "id": "09b5b05d-ae4f-4ec4-bebf-5824274e4631", + "metadata": {}, + "outputs": [], + "source": [ + "import os, glob\n", + "import collections\n", + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "import matplotlib as mpl\n", + "import matplotlib.pyplot as plt\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 203, + "id": "7bd3fc71-cd3b-4218-8912-c35bdc2584bf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[' build-depends: base >=4.15\\n',\n", + " ' build-depends: base >=4.15\\n',\n", + " ' -- build-depends: base >=4.13 && < 4.15\\n',\n", + " ' build-depends: text, attoparsec\\n',\n", + " ' build-depends: text, attoparsec\\n',\n", + " ' build-depends: text, attoparsec, linear, containers\\n',\n", + " ' build-depends: split, containers\\n',\n", + " ' build-depends: split\\n',\n", + " ' build-depends: text, attoparsec, containers\\n',\n", + " ' build-depends: text, attoparsec, containers\\n',\n", + " ' build-depends: array, containers, linear\\n',\n", + " ' build-depends: containers\\n',\n", + " ' build-depends: array, containers, linear\\n',\n", + " ' build-depends: text, attoparsec, containers\\n',\n", + " ' build-depends: text, attoparsec, containers, linear\\n',\n", + " ' build-depends: text, attoparsec, containers, multiset\\n',\n", + " ' build-depends: containers, linear, array, pqueue, mtl, lens\\n',\n", + " ' build-depends: text, containers, linear, array, pqueue, mtl, lens\\n',\n", + " ' build-depends: text, containers, linear, array, pqueue, mtl, lens\\n',\n", + " ' build-depends: binary, bytestring, bitstream, mtl\\n',\n", + " ' build-depends: linear, text, attoparsec, lens\\n',\n", + " ' build-depends: text, attoparsec\\n',\n", + " ' build-depends: linear, text, attoparsec, containers, multiset\\n',\n", + " ' build-depends: linear, mtl, containers\\n',\n", + " ' build-depends: text, attoparsec, containers, multiset\\n',\n", + " ' build-depends: linear, text, attoparsec, containers, lens\\n',\n", + " ' build-depends: containers, linear, pqueue, mtl, lens\\n',\n", + " ' build-depends: containers, linear, pqueue, mtl, lens\\n',\n", + " ' build-depends: text, attoparsec, containers\\n',\n", + " ' build-depends: text, attoparsec, containers\\n',\n", + " ' build-depends: text, attoparsec, containers\\n',\n", + " ' build-depends: linear, containers\\n']" + ] + }, + "execution_count": 203, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "with open('../advent-of-code21.cabal') as f:\n", + " build_depends = [l for l in f.readlines() if 'build-depends' in l]\n", + "build_depends" + ] + }, + { + "cell_type": "code", + "execution_count": 204, + "id": "d0e0655a-2fad-47c9-afe1-8ae4c44949ab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[' advent01\\n import: common-extensions, build-directives\\n main-is: advent01/Main.hs\\n -- other-modules:\\n -- other-extensions:\\n -- build-depends: base >=4.13 && < 4.15\\n -- hs-source-dirs:\\n -- default-language: Haskell2010\\n\\n',\n", + " ' advent02\\n import: common-extensions, build-directives\\n main-is: advent02/Main.hs\\n build-depends: text, attoparsec\\n\\n',\n", + " ' advent03\\n import: common-extensions, build-directives\\n main-is: advent03/Main.hs\\n\\n']" + ] + }, + "execution_count": 204, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cabal_file = open('../advent-of-code21.cabal').read()\n", + "executables = cabal_file.split('executable')[2:]\n", + "executables[:3]" + ] + }, + { + "cell_type": "code", + "execution_count": 205, + "id": "62a719db-b264-4b95-8dd0-80ab08b3622a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['text', ' attoparsec']" + ] + }, + "execution_count": 205, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "e = executables[1]\n", + "e.strip().split('build-depends: ')[1].split(',')" + ] + }, + { + "cell_type": "code", + "execution_count": 206, + "id": "5f5e51ea-4457-4701-99d2-844edcec721e", + "metadata": {}, + "outputs": [], + "source": [ + "def extract(line):\n", + " parts = line.strip().split('build-depends: ')\n", + " name = parts[0].split()[0]\n", + " if len(parts) > 1:\n", + " depends = [p.strip() for p in parts[1].split('\\n')[0].split(',') if 'base' not in p]\n", + " else:\n", + " depends = []\n", + " return name, depends " + ] + }, + { + "cell_type": "code", + "execution_count": 207, + "id": "a852a10b-ee9a-46d5-a390-04f218424760", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'advent01': [],\n", + " 'advent02': ['text', 'attoparsec'],\n", + " 'advent03': [],\n", + " 'advent04': ['text', 'attoparsec'],\n", + " 'advent05': ['text', 'attoparsec', 'linear', 'containers'],\n", + " 'advent06': ['split', 'containers'],\n", + " 'advent07': ['split'],\n", + " 'advent08': ['text', 'attoparsec', 'containers'],\n", + " 'advent09': ['array', 'containers', 'linear'],\n", + " 'advent10': ['containers'],\n", + " 'advent11': ['array', 'containers', 'linear'],\n", + " 'advent12': ['text', 'attoparsec', 'containers'],\n", + " 'advent13': ['text', 'attoparsec', 'containers', 'linear'],\n", + " 'advent14': ['text', 'attoparsec', 'containers', 'multiset'],\n", + " 'advent15': ['containers', 'linear', 'array', 'pqueue', 'mtl', 'lens'],\n", + " 'advent16': ['binary', 'bytestring', 'bitstream', 'mtl'],\n", + " 'advent17': ['linear', 'text', 'attoparsec', 'lens'],\n", + " 'advent18': ['text', 'attoparsec'],\n", + " 'advent19': ['linear', 'text', 'attoparsec', 'containers', 'multiset'],\n", + " 'advent20': ['linear', 'mtl', 'containers'],\n", + " 'advent21': ['text', 'attoparsec', 'containers', 'multiset'],\n", + " 'advent22': ['linear', 'text', 'attoparsec', 'containers', 'lens'],\n", + " 'advent23': ['containers', 'linear', 'pqueue', 'mtl', 'lens'],\n", + " 'advent24': ['text', 'attoparsec', 'containers'],\n", + " 'advent25': ['linear', 'containers']}" + ] + }, + "execution_count": 207, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "modules = {e: ms for e, ms in [extract(e) for e in executables] if e.endswith(tuple(str(i) for i in range(10)))}\n", + "modules" + ] + }, + { + "cell_type": "code", + "execution_count": 208, + "id": "57036fc2-db73-4c5b-b3bc-b7e8f9bbccda", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    \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", + " \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", + " \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", + " \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", + " \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", + " \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", + " \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", + " \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", + "
    arrayattoparsecbinarybitstreambytestringcontainerslenslinearmtlmultisetpqueuesplittext
    advent01FalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
    advent02FalseTrueFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseTrue
    advent03FalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
    advent04FalseTrueFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseTrue
    advent05FalseTrueFalseFalseFalseTrueFalseTrueFalseFalseFalseFalseTrue
    advent06FalseFalseFalseFalseFalseTrueFalseFalseFalseFalseFalseTrueFalse
    advent07FalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseTrueFalse
    advent08FalseTrueFalseFalseFalseTrueFalseFalseFalseFalseFalseFalseTrue
    advent09TrueFalseFalseFalseFalseTrueFalseTrueFalseFalseFalseFalseFalse
    advent10FalseFalseFalseFalseFalseTrueFalseFalseFalseFalseFalseFalseFalse
    advent11TrueFalseFalseFalseFalseTrueFalseTrueFalseFalseFalseFalseFalse
    advent12FalseTrueFalseFalseFalseTrueFalseFalseFalseFalseFalseFalseTrue
    advent13FalseTrueFalseFalseFalseTrueFalseTrueFalseFalseFalseFalseTrue
    advent14FalseTrueFalseFalseFalseTrueFalseFalseFalseTrueFalseFalseTrue
    advent15TrueFalseFalseFalseFalseTrueTrueTrueTrueFalseTrueFalseFalse
    advent16FalseFalseTrueTrueTrueFalseFalseFalseTrueFalseFalseFalseFalse
    advent17FalseTrueFalseFalseFalseFalseTrueTrueFalseFalseFalseFalseTrue
    advent18FalseTrueFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseTrue
    advent19FalseTrueFalseFalseFalseTrueFalseTrueFalseTrueFalseFalseTrue
    advent20FalseFalseFalseFalseFalseTrueFalseTrueTrueFalseFalseFalseFalse
    advent21FalseTrueFalseFalseFalseTrueFalseFalseFalseTrueFalseFalseTrue
    advent22FalseTrueFalseFalseFalseTrueTrueTrueFalseFalseFalseFalseTrue
    advent23FalseFalseFalseFalseFalseTrueTrueTrueTrueFalseTrueFalseFalse
    advent24FalseTrueFalseFalseFalseTrueFalseFalseFalseFalseFalseFalseTrue
    advent25FalseFalseFalseFalseFalseTrueFalseTrueFalseFalseFalseFalseFalse
    \n", + "
    " + ], + "text/plain": [ + " array attoparsec binary bitstream bytestring containers lens \\\n", + "advent01 False False False False False False False \n", + "advent02 False True False False False False False \n", + "advent03 False False False False False False False \n", + "advent04 False True False False False False False \n", + "advent05 False True False False False True False \n", + "advent06 False False False False False True False \n", + "advent07 False False False False False False False \n", + "advent08 False True False False False True False \n", + "advent09 True False False False False True False \n", + "advent10 False False False False False True False \n", + "advent11 True False False False False True False \n", + "advent12 False True False False False True False \n", + "advent13 False True False False False True False \n", + "advent14 False True False False False True False \n", + "advent15 True False False False False True True \n", + "advent16 False False True True True False False \n", + "advent17 False True False False False False True \n", + "advent18 False True False False False False False \n", + "advent19 False True False False False True False \n", + "advent20 False False False False False True False \n", + "advent21 False True False False False True False \n", + "advent22 False True False False False True True \n", + "advent23 False False False False False True True \n", + "advent24 False True False False False True False \n", + "advent25 False False False False False True False \n", + "\n", + " linear mtl multiset pqueue split text \n", + "advent01 False False False False False False \n", + "advent02 False False False False False True \n", + "advent03 False False False False False False \n", + "advent04 False False False False False True \n", + "advent05 True False False False False True \n", + "advent06 False False False False True False \n", + "advent07 False False False False True False \n", + "advent08 False False False False False True \n", + "advent09 True False False False False False \n", + "advent10 False False False False False False \n", + "advent11 True False False False False False \n", + "advent12 False False False False False True \n", + "advent13 True False False False False True \n", + "advent14 False False True False False True \n", + "advent15 True True False True False False \n", + "advent16 False True False False False False \n", + "advent17 True False False False False True \n", + "advent18 False False False False False True \n", + "advent19 True False True False False True \n", + "advent20 True True False False False False \n", + "advent21 False False True False False True \n", + "advent22 True False False False False True \n", + "advent23 True True False True False False \n", + "advent24 False False False False False True \n", + "advent25 True False False False False False " + ] + }, + "execution_count": 208, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "all_modules = set(m for p in modules for m in modules[p])\n", + "modules_df = pd.DataFrame.from_dict({p: {m: m in modules[p] for m in sorted(all_modules)} for p in modules}, orient='index').sort_index()\n", + "modules_df" + ] + }, + { + "cell_type": "code", + "execution_count": 209, + "id": "2eec3a74-e533-4d59-b495-9e774ca470e5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "| | 0 |\n", + "|:-----------|----:|\n", + "| containers | 17 |\n", + "| attoparsec | 13 |\n", + "| text | 13 |\n", + "| linear | 11 |\n", + "| lens | 4 |\n", + "| mtl | 4 |\n", + "| array | 3 |\n", + "| multiset | 3 |\n", + "| pqueue | 2 |\n", + "| split | 2 |\n", + "| binary | 1 |\n", + "| bitstream | 1 |\n", + "| bytestring | 1 |\n" + ] + } + ], + "source": [ + "print(modules_df.sum().sort_values(ascending=False).to_markdown())" + ] + }, + { + "cell_type": "code", + "execution_count": 210, + "id": "da22ede4-ac7c-4d32-9396-4cf585f97ba7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    \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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    programmodulepresent
    14advent02attoparsecTrue
    25advent02textTrue
    40advent04attoparsecTrue
    51advent04textTrue
    53advent05attoparsecTrue
    ............
    300advent24attoparsecTrue
    304advent24containersTrue
    311advent24textTrue
    317advent25containersTrue
    319advent25linearTrue
    \n", + "

    75 rows × 3 columns

    \n", + "
    " + ], + "text/plain": [ + " program module present\n", + "14 advent02 attoparsec True\n", + "25 advent02 text True\n", + "40 advent04 attoparsec True\n", + "51 advent04 text True\n", + "53 advent05 attoparsec True\n", + ".. ... ... ...\n", + "300 advent24 attoparsec True\n", + "304 advent24 containers True\n", + "311 advent24 text True\n", + "317 advent25 containers True\n", + "319 advent25 linear True\n", + "\n", + "[75 rows x 3 columns]" + ] + }, + "execution_count": 210, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "modules_scatter = modules_df.stack().reset_index()\n", + "modules_scatter.columns = ['program', 'module', 'present']\n", + "modules_scatter = modules_scatter[modules_scatter.present]\n", + "modules_scatter" + ] + }, + { + "cell_type": "code", + "execution_count": 211, + "id": "fa6a99a2-749a-48d5-9009-11a45eb2722a", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 211, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "modules_scatter.plot.scatter(x='program', y='module', s=80, rot=45, figsize=(10, 6))" + ] + }, + { + "cell_type": "code", + "execution_count": 212, + "id": "0e1cb390-cfce-41aa-b18f-b3d9fee57ae0", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "cmap = mpl.colors.ListedColormap(['white', 'blue'])\n", + "\n", + "fig, ax = plt.subplots(figsize=(10, 10))\n", + "ax.imshow(modules_df.to_numpy().T, cmap=cmap)\n", + "plt.xticks(range(modules_df.index.size), labels=modules_df.index.values, rotation=90);\n", + "plt.yticks(range(modules_df.columns.size), labels=modules_df.columns.values);\n", + "\n", + "ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5))\n", + "ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5))\n", + "ax.grid(which='minor', axis='both', linestyle='-', color='silver', linewidth=1.5);\n", + "plt.savefig('packages.png');" + ] + }, + { + "cell_type": "code", + "execution_count": 213, + "id": "d79246cc-4471-43ac-ba76-d720acbb7435", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['../advent01/Main.hs',\n", + " '../advent02/Main.hs',\n", + " '../advent03/Main.hs',\n", + " '../advent04/Main.hs',\n", + " '../advent05/Main.hs',\n", + " '../advent06/Main.hs',\n", + " '../advent07/Main.hs',\n", + " '../advent08/Main.hs',\n", + " '../advent09/Main.hs',\n", + " '../advent10/Main.hs',\n", + " '../advent11/Main.hs',\n", + " '../advent12/Main.hs',\n", + " '../advent13/Main.hs',\n", + " '../advent14/Main.hs',\n", + " '../advent15/Main.hs',\n", + " '../advent16/Main.hs',\n", + " '../advent17/Main.hs',\n", + " '../advent18/Main.hs',\n", + " '../advent19/Main.hs',\n", + " '../advent20/Main.hs',\n", + " '../advent21/Main.hs',\n", + " '../advent22/Main.hs',\n", + " '../advent23/Main.hs',\n", + " '../advent24/Main.hs',\n", + " '../advent25/Main.hs']" + ] + }, + "execution_count": 213, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mains = list(sorted(f for f in glob.glob('../advent*/Main.hs')))\n", + "mains" + ] + }, + { + "cell_type": "code", + "execution_count": 214, + "id": "f9076c9f-fc86-435b-9471-99726bfbfb87", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'advent01': [('Data.List', False)],\n", + " 'advent02': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Control.Applicative', False)],\n", + " 'advent03': [('Data.List', False), ('Data.Char', False)],\n", + " 'advent04': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Control.Applicative', False),\n", + " ('Data.List', False)],\n", + " 'advent05': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Control.Applicative', False),\n", + " ('Data.Map.Strict', True),\n", + " ('Linear', False)],\n", + " 'advent06': [('Data.List', False),\n", + " ('Data.List.Split', False),\n", + " ('Data.IntMap.Strict', True)],\n", + " 'advent07': [('Data.List.Split', False)],\n", + " 'advent08': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Data.List', False),\n", + " ('Data.Map.Strict', True),\n", + " ('Data.Map.Strict', False),\n", + " ('Data.Set', True)],\n", + " 'advent09': [('Data.Array', False),\n", + " ('Data.Char', False),\n", + " ('Data.List', False),\n", + " ('Data.Set', True),\n", + " ('Data.Set', False),\n", + " ('Linear', False)],\n", + " 'advent10': [('Data.Map.Strict', True), ('Data.List', False)],\n", + " 'advent11': [('Data.Array.IArray', False),\n", + " ('Data.Char', False),\n", + " ('Linear', False)],\n", + " 'advent12': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Data.Tuple', False),\n", + " ('Data.Char', False),\n", + " ('Data.Map.Strict', True),\n", + " ('Data.Map.Strict', False),\n", + " ('Data.Set', True),\n", + " ('Data.Set', False)],\n", + " 'advent13': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Control.Applicative', False),\n", + " ('Data.Set', True),\n", + " ('Linear', False),\n", + " ('Data.List', False)],\n", + " 'advent14': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Control.Applicative', False),\n", + " ('Data.List', False),\n", + " ('Data.Map.Strict', True),\n", + " ('Data.Map.Strict', False),\n", + " ('Data.MultiSet', True),\n", + " ('Data.Set', True)],\n", + " 'advent15': [('Data.PQueue.Prio.Min', True),\n", + " ('Data.Set', True),\n", + " ('Data.Sequence', True),\n", + " ('Data.Sequence', False),\n", + " ('Data.Foldable', False),\n", + " ('Data.Char', False),\n", + " ('Control.Monad.Reader', False),\n", + " ('Control.Lens', False),\n", + " ('Linear', False),\n", + " ('Data.Array.IArray', False)],\n", + " 'advent16': [('Data.Word', False),\n", + " ('Data.Bits', False),\n", + " ('Data.Char', False),\n", + " ('Data.Int', False),\n", + " ('Control.Monad.State.Strict', False),\n", + " ('Data.ByteString', True),\n", + " ('Data.Bitstream', True)],\n", + " 'advent17': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Control.Lens', False),\n", + " ('Linear', False),\n", + " ('Data.Ix', False)],\n", + " 'advent18': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Control.Applicative', False),\n", + " ('Data.Maybe', False),\n", + " ('Data.List', False)],\n", + " 'advent19': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Linear', False),\n", + " ('Data.Set', True),\n", + " ('Data.MultiSet', True),\n", + " ('Data.Monoid', False),\n", + " ('Data.Maybe', False),\n", + " ('Data.List', False),\n", + " ('Control.Monad', False)],\n", + " 'advent20': [('Control.Monad.State.Strict', False),\n", + " ('Control.Monad.Reader', False),\n", + " ('Control.Monad.RWS.Strict', False),\n", + " ('Data.List', False),\n", + " ('Data.Ix', False),\n", + " ('Data.Maybe', False),\n", + " ('Data.Set', True),\n", + " ('Linear', False)],\n", + " 'advent21': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Control.Applicative', False),\n", + " ('Data.Map.Strict', True),\n", + " ('Data.Map.Strict', False),\n", + " ('Data.List', False),\n", + " ('Data.MultiSet', True)],\n", + " 'advent22': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Control.Applicative', False),\n", + " ('Linear', False),\n", + " ('Control.Lens', False),\n", + " ('Data.List', False)],\n", + " 'advent23': [('Data.PQueue.Prio.Min', True),\n", + " ('Data.Set', True),\n", + " ('Data.Sequence', True),\n", + " ('Data.Sequence', False),\n", + " ('Data.Map.Strict', True),\n", + " ('Data.Map.Strict', False),\n", + " ('Data.Foldable', False),\n", + " ('Control.Monad.Reader', False),\n", + " ('Control.Lens', False),\n", + " ('Data.Maybe', False),\n", + " ('Linear', False)],\n", + " 'advent24': [('Data.Text', False),\n", + " ('Data.Text.IO', True),\n", + " ('Data.Attoparsec.Text', False),\n", + " ('Control.Applicative', False),\n", + " ('Data.Map.Strict', True),\n", + " ('Data.Map.Strict', False),\n", + " ('Data.List', False),\n", + " ('Control.Monad', False),\n", + " ('Data.Maybe', False)],\n", + " 'advent25': [('Data.Map.Strict', True),\n", + " ('Data.Map.Strict', False),\n", + " ('Linear', False),\n", + " ('Data.List', False)]}" + ] + }, + "execution_count": 214, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "main_imports = {}\n", + "\n", + "for m in mains:\n", + " with open(m) as f:\n", + " lines = f.readlines()\n", + " import_lines = [l for l in lines if l.strip().startswith('import') if 'Debug.Trace' not in l]\n", + " imports = []\n", + " for i in import_lines:\n", + " words = i.strip().split()\n", + " if 'qualified' in i:\n", + " imports.append((words[2], True))\n", + " else:\n", + " imports.append((words[1], False))\n", + " main_imports[m.split('/')[1]] = imports\n", + "\n", + "main_imports" + ] + }, + { + "cell_type": "code", + "execution_count": 215, + "id": "3260db91-68df-47d3-b4c3-8745ea974033", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(('Data.List', False), 16),\n", + " (('Data.Text', False), 13),\n", + " (('Data.Text.IO', True), 13),\n", + " (('Data.Attoparsec.Text', False), 13),\n", + " (('Linear', False), 11),\n", + " (('Control.Applicative', False), 9),\n", + " (('Data.Map.Strict', True), 9),\n", + " (('Data.Set', True), 9),\n", + " (('Data.Map.Strict', False), 7),\n", + " (('Data.Char', False), 6),\n", + " (('Data.Maybe', False), 5),\n", + " (('Control.Lens', False), 4),\n", + " (('Data.MultiSet', True), 3),\n", + " (('Control.Monad.Reader', False), 3),\n", + " (('Data.List.Split', False), 2),\n", + " (('Data.Set', False), 2),\n", + " (('Data.Array.IArray', False), 2),\n", + " (('Data.PQueue.Prio.Min', True), 2),\n", + " (('Data.Sequence', True), 2),\n", + " (('Data.Sequence', False), 2),\n", + " (('Data.Foldable', False), 2),\n", + " (('Control.Monad.State.Strict', False), 2),\n", + " (('Data.Ix', False), 2),\n", + " (('Control.Monad', False), 2),\n", + " (('Data.IntMap.Strict', True), 1),\n", + " (('Data.Array', False), 1),\n", + " (('Data.Tuple', False), 1),\n", + " (('Data.Word', False), 1),\n", + " (('Data.Bits', False), 1),\n", + " (('Data.Int', False), 1),\n", + " (('Data.ByteString', True), 1),\n", + " (('Data.Bitstream', True), 1),\n", + " (('Data.Monoid', False), 1),\n", + " (('Control.Monad.RWS.Strict', False), 1)]" + ] + }, + "execution_count": 215, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import_counts = collections.Counter(l for ls in main_imports.values() for l in ls)\n", + "import_counts.most_common()" + ] + }, + { + "cell_type": "code", + "execution_count": 216, + "id": "3f683faa-4d1d-4269-a66e-0ea848804e03", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'advent01': {'Data.List'},\n", + " 'advent02': {'Control.Applicative',\n", + " 'Data.Attoparsec.Text',\n", + " 'Data.Text',\n", + " 'Data.Text.IO'},\n", + " 'advent03': {'Data.Char', 'Data.List'},\n", + " 'advent04': {'Control.Applicative',\n", + " 'Data.Attoparsec.Text',\n", + " 'Data.List',\n", + " 'Data.Text',\n", + " 'Data.Text.IO'},\n", + " 'advent05': {'Control.Applicative',\n", + " 'Data.Attoparsec.Text',\n", + " 'Data.Map.Strict',\n", + " 'Data.Text',\n", + " 'Data.Text.IO',\n", + " 'Linear'},\n", + " 'advent06': {'Data.IntMap.Strict', 'Data.List', 'Data.List.Split'},\n", + " 'advent07': {'Data.List.Split'},\n", + " 'advent08': {'Data.Attoparsec.Text',\n", + " 'Data.List',\n", + " 'Data.Map.Strict',\n", + " 'Data.Set',\n", + " 'Data.Text',\n", + " 'Data.Text.IO'},\n", + " 'advent09': {'Data.Array', 'Data.Char', 'Data.List', 'Data.Set', 'Linear'},\n", + " 'advent10': {'Data.List', 'Data.Map.Strict'},\n", + " 'advent11': {'Data.Array.IArray', 'Data.Char', 'Linear'},\n", + " 'advent12': {'Data.Attoparsec.Text',\n", + " 'Data.Char',\n", + " 'Data.Map.Strict',\n", + " 'Data.Set',\n", + " 'Data.Text',\n", + " 'Data.Text.IO',\n", + " 'Data.Tuple'},\n", + " 'advent13': {'Control.Applicative',\n", + " 'Data.Attoparsec.Text',\n", + " 'Data.List',\n", + " 'Data.Set',\n", + " 'Data.Text',\n", + " 'Data.Text.IO',\n", + " 'Linear'},\n", + " 'advent14': {'Control.Applicative',\n", + " 'Data.Attoparsec.Text',\n", + " 'Data.List',\n", + " 'Data.Map.Strict',\n", + " 'Data.MultiSet',\n", + " 'Data.Set',\n", + " 'Data.Text',\n", + " 'Data.Text.IO'},\n", + " 'advent15': {'Control.Lens',\n", + " 'Control.Monad.Reader',\n", + " 'Data.Array.IArray',\n", + " 'Data.Char',\n", + " 'Data.Foldable',\n", + " 'Data.PQueue.Prio.Min',\n", + " 'Data.Sequence',\n", + " 'Data.Set',\n", + " 'Linear'},\n", + " 'advent16': {'Control.Monad.State.Strict',\n", + " 'Data.Bits',\n", + " 'Data.Bitstream',\n", + " 'Data.ByteString',\n", + " 'Data.Char',\n", + " 'Data.Int',\n", + " 'Data.Word'},\n", + " 'advent17': {'Control.Lens',\n", + " 'Data.Attoparsec.Text',\n", + " 'Data.Ix',\n", + " 'Data.Text',\n", + " 'Data.Text.IO',\n", + " 'Linear'},\n", + " 'advent18': {'Control.Applicative',\n", + " 'Data.Attoparsec.Text',\n", + " 'Data.List',\n", + " 'Data.Maybe',\n", + " 'Data.Text',\n", + " 'Data.Text.IO'},\n", + " 'advent19': {'Control.Monad',\n", + " 'Data.Attoparsec.Text',\n", + " 'Data.List',\n", + " 'Data.Maybe',\n", + " 'Data.Monoid',\n", + " 'Data.MultiSet',\n", + " 'Data.Set',\n", + " 'Data.Text',\n", + " 'Data.Text.IO',\n", + " 'Linear'},\n", + " 'advent20': {'Control.Monad.RWS.Strict',\n", + " 'Control.Monad.Reader',\n", + " 'Control.Monad.State.Strict',\n", + " 'Data.Ix',\n", + " 'Data.List',\n", + " 'Data.Maybe',\n", + " 'Data.Set',\n", + " 'Linear'},\n", + " 'advent21': {'Control.Applicative',\n", + " 'Data.Attoparsec.Text',\n", + " 'Data.List',\n", + " 'Data.Map.Strict',\n", + " 'Data.MultiSet',\n", + " 'Data.Text',\n", + " 'Data.Text.IO'},\n", + " 'advent22': {'Control.Applicative',\n", + " 'Control.Lens',\n", + " 'Data.Attoparsec.Text',\n", + " 'Data.List',\n", + " 'Data.Text',\n", + " 'Data.Text.IO',\n", + " 'Linear'},\n", + " 'advent23': {'Control.Lens',\n", + " 'Control.Monad.Reader',\n", + " 'Data.Foldable',\n", + " 'Data.Map.Strict',\n", + " 'Data.Maybe',\n", + " 'Data.PQueue.Prio.Min',\n", + " 'Data.Sequence',\n", + " 'Data.Set',\n", + " 'Linear'},\n", + " 'advent24': {'Control.Applicative',\n", + " 'Control.Monad',\n", + " 'Data.Attoparsec.Text',\n", + " 'Data.List',\n", + " 'Data.Map.Strict',\n", + " 'Data.Maybe',\n", + " 'Data.Text',\n", + " 'Data.Text.IO'},\n", + " 'advent25': {'Data.List', 'Data.Map.Strict', 'Linear'}}" + ] + }, + "execution_count": 216, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "main_imports_unqualified = {m: set(i[0] for i in main_imports[m]) for m in main_imports}\n", + "main_imports_unqualified" + ] + }, + { + "cell_type": "code", + "execution_count": 217, + "id": "e5ff5780-e511-41ab-9207-0cc6bdaecb64", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[('Data.List', 16),\n", + " ('Data.Text', 13),\n", + " ('Data.Attoparsec.Text', 13),\n", + " ('Data.Text.IO', 13),\n", + " ('Linear', 11),\n", + " ('Control.Applicative', 9),\n", + " ('Data.Map.Strict', 9),\n", + " ('Data.Set', 9),\n", + " ('Data.Char', 6),\n", + " ('Data.Maybe', 5),\n", + " ('Control.Lens', 4),\n", + " ('Data.MultiSet', 3),\n", + " ('Control.Monad.Reader', 3),\n", + " ('Data.List.Split', 2),\n", + " ('Data.Array.IArray', 2),\n", + " ('Data.PQueue.Prio.Min', 2),\n", + " ('Data.Foldable', 2),\n", + " ('Data.Sequence', 2),\n", + " ('Control.Monad.State.Strict', 2),\n", + " ('Data.Ix', 2),\n", + " ('Control.Monad', 2),\n", + " ('Data.IntMap.Strict', 1),\n", + " ('Data.Array', 1),\n", + " ('Data.Tuple', 1),\n", + " ('Data.Int', 1),\n", + " ('Data.ByteString', 1),\n", + " ('Data.Bits', 1),\n", + " ('Data.Bitstream', 1),\n", + " ('Data.Word', 1),\n", + " ('Data.Monoid', 1),\n", + " ('Control.Monad.RWS.Strict', 1)]" + ] + }, + "execution_count": 217, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import_counts_unqualified = collections.Counter(l for ls in main_imports_unqualified.values() for l in ls)\n", + "import_counts_unqualified.most_common()" + ] + }, + { + "cell_type": "code", + "execution_count": 218, + "id": "e0580f26-9f6d-49f9-83ff-92dbd190aad6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    \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", + " \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", + " \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", + " \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", + " \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", + " \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", + " \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", + " \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", + " \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", + " \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", + " \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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    Control.ApplicativeControl.LensControl.MonadControl.Monad.RWS.StrictControl.Monad.ReaderControl.Monad.State.StrictData.ArrayData.Array.IArrayData.Attoparsec.TextData.Bits...Data.MonoidData.MultiSetData.PQueue.Prio.MinData.SequenceData.SetData.TextData.Text.IOData.TupleData.WordLinear
    advent01FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
    advent02TrueFalseFalseFalseFalseFalseFalseFalseTrueFalse...FalseFalseFalseFalseFalseTrueTrueFalseFalseFalse
    advent03FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
    advent04TrueFalseFalseFalseFalseFalseFalseFalseTrueFalse...FalseFalseFalseFalseFalseTrueTrueFalseFalseFalse
    advent05TrueFalseFalseFalseFalseFalseFalseFalseTrueFalse...FalseFalseFalseFalseFalseTrueTrueFalseFalseTrue
    advent06FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
    advent07FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
    advent08FalseFalseFalseFalseFalseFalseFalseFalseTrueFalse...FalseFalseFalseFalseTrueTrueTrueFalseFalseFalse
    advent09FalseFalseFalseFalseFalseFalseTrueFalseFalseFalse...FalseFalseFalseFalseTrueFalseFalseFalseFalseTrue
    advent10FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
    advent11FalseFalseFalseFalseFalseFalseFalseTrueFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseTrue
    advent12FalseFalseFalseFalseFalseFalseFalseFalseTrueFalse...FalseFalseFalseFalseTrueTrueTrueTrueFalseFalse
    advent13TrueFalseFalseFalseFalseFalseFalseFalseTrueFalse...FalseFalseFalseFalseTrueTrueTrueFalseFalseTrue
    advent14TrueFalseFalseFalseFalseFalseFalseFalseTrueFalse...FalseTrueFalseFalseTrueTrueTrueFalseFalseFalse
    advent15FalseTrueFalseFalseTrueFalseFalseTrueFalseFalse...FalseFalseTrueTrueTrueFalseFalseFalseFalseTrue
    advent16FalseFalseFalseFalseFalseTrueFalseFalseFalseTrue...FalseFalseFalseFalseFalseFalseFalseFalseTrueFalse
    advent17FalseTrueFalseFalseFalseFalseFalseFalseTrueFalse...FalseFalseFalseFalseFalseTrueTrueFalseFalseTrue
    advent18TrueFalseFalseFalseFalseFalseFalseFalseTrueFalse...FalseFalseFalseFalseFalseTrueTrueFalseFalseFalse
    advent19FalseFalseTrueFalseFalseFalseFalseFalseTrueFalse...TrueTrueFalseFalseTrueTrueTrueFalseFalseTrue
    advent20FalseFalseFalseTrueTrueTrueFalseFalseFalseFalse...FalseFalseFalseFalseTrueFalseFalseFalseFalseTrue
    advent21TrueFalseFalseFalseFalseFalseFalseFalseTrueFalse...FalseTrueFalseFalseFalseTrueTrueFalseFalseFalse
    advent22TrueTrueFalseFalseFalseFalseFalseFalseTrueFalse...FalseFalseFalseFalseFalseTrueTrueFalseFalseTrue
    advent23FalseTrueFalseFalseTrueFalseFalseFalseFalseFalse...FalseFalseTrueTrueTrueFalseFalseFalseFalseTrue
    advent24TrueFalseTrueFalseFalseFalseFalseFalseTrueFalse...FalseFalseFalseFalseFalseTrueTrueFalseFalseFalse
    advent25FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseTrue
    \n", + "

    25 rows × 31 columns

    \n", + "
    " + ], + "text/plain": [ + " Control.Applicative Control.Lens Control.Monad \\\n", + "advent01 False False False \n", + "advent02 True False False \n", + "advent03 False False False \n", + "advent04 True False False \n", + "advent05 True False False \n", + "advent06 False False False \n", + "advent07 False False False \n", + "advent08 False False False \n", + "advent09 False False False \n", + "advent10 False False False \n", + "advent11 False False False \n", + "advent12 False False False \n", + "advent13 True False False \n", + "advent14 True False False \n", + "advent15 False True False \n", + "advent16 False False False \n", + "advent17 False True False \n", + "advent18 True False False \n", + "advent19 False False True \n", + "advent20 False False False \n", + "advent21 True False False \n", + "advent22 True True False \n", + "advent23 False True False \n", + "advent24 True False True \n", + "advent25 False False False \n", + "\n", + " Control.Monad.RWS.Strict Control.Monad.Reader \\\n", + "advent01 False False \n", + "advent02 False False \n", + "advent03 False False \n", + "advent04 False False \n", + "advent05 False False \n", + "advent06 False False \n", + "advent07 False False \n", + "advent08 False False \n", + "advent09 False False \n", + "advent10 False False \n", + "advent11 False False \n", + "advent12 False False \n", + "advent13 False False \n", + "advent14 False False \n", + "advent15 False True \n", + "advent16 False False \n", + "advent17 False False \n", + "advent18 False False \n", + "advent19 False False \n", + "advent20 True True \n", + "advent21 False False \n", + "advent22 False False \n", + "advent23 False True \n", + "advent24 False False \n", + "advent25 False False \n", + "\n", + " Control.Monad.State.Strict Data.Array Data.Array.IArray \\\n", + "advent01 False False False \n", + "advent02 False False False \n", + "advent03 False False False \n", + "advent04 False False False \n", + "advent05 False False False \n", + "advent06 False False False \n", + "advent07 False False False \n", + "advent08 False False False \n", + "advent09 False True False \n", + "advent10 False False False \n", + "advent11 False False True \n", + "advent12 False False False \n", + "advent13 False False False \n", + "advent14 False False False \n", + "advent15 False False True \n", + "advent16 True False False \n", + "advent17 False False False \n", + "advent18 False False False \n", + "advent19 False False False \n", + "advent20 True False False \n", + "advent21 False False False \n", + "advent22 False False False \n", + "advent23 False False False \n", + "advent24 False False False \n", + "advent25 False False False \n", + "\n", + " Data.Attoparsec.Text Data.Bits ... Data.Monoid Data.MultiSet \\\n", + "advent01 False False ... False False \n", + "advent02 True False ... False False \n", + "advent03 False False ... False False \n", + "advent04 True False ... False False \n", + "advent05 True False ... False False \n", + "advent06 False False ... False False \n", + "advent07 False False ... False False \n", + "advent08 True False ... False False \n", + "advent09 False False ... False False \n", + "advent10 False False ... False False \n", + "advent11 False False ... False False \n", + "advent12 True False ... False False \n", + "advent13 True False ... False False \n", + "advent14 True False ... False True \n", + "advent15 False False ... False False \n", + "advent16 False True ... False False \n", + "advent17 True False ... False False \n", + "advent18 True False ... False False \n", + "advent19 True False ... True True \n", + "advent20 False False ... False False \n", + "advent21 True False ... False True \n", + "advent22 True False ... False False \n", + "advent23 False False ... False False \n", + "advent24 True False ... False False \n", + "advent25 False False ... False False \n", + "\n", + " Data.PQueue.Prio.Min Data.Sequence Data.Set Data.Text \\\n", + "advent01 False False False False \n", + "advent02 False False False True \n", + "advent03 False False False False \n", + "advent04 False False False True \n", + "advent05 False False False True \n", + "advent06 False False False False \n", + "advent07 False False False False \n", + "advent08 False False True True \n", + "advent09 False False True False \n", + "advent10 False False False False \n", + "advent11 False False False False \n", + "advent12 False False True True \n", + "advent13 False False True True \n", + "advent14 False False True True \n", + "advent15 True True True False \n", + "advent16 False False False False \n", + "advent17 False False False True \n", + "advent18 False False False True \n", + "advent19 False False True True \n", + "advent20 False False True False \n", + "advent21 False False False True \n", + "advent22 False False False True \n", + "advent23 True True True False \n", + "advent24 False False False True \n", + "advent25 False False False False \n", + "\n", + " Data.Text.IO Data.Tuple Data.Word Linear \n", + "advent01 False False False False \n", + "advent02 True False False False \n", + "advent03 False False False False \n", + "advent04 True False False False \n", + "advent05 True False False True \n", + "advent06 False False False False \n", + "advent07 False False False False \n", + "advent08 True False False False \n", + "advent09 False False False True \n", + "advent10 False False False False \n", + "advent11 False False False True \n", + "advent12 True True False False \n", + "advent13 True False False True \n", + "advent14 True False False False \n", + "advent15 False False False True \n", + "advent16 False False True False \n", + "advent17 True False False True \n", + "advent18 True False False False \n", + "advent19 True False False True \n", + "advent20 False False False True \n", + "advent21 True False False False \n", + "advent22 True False False True \n", + "advent23 False False False True \n", + "advent24 True False False False \n", + "advent25 False False False True \n", + "\n", + "[25 rows x 31 columns]" + ] + }, + "execution_count": 218, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "all_imports = set(m for p in main_imports_unqualified for m in main_imports_unqualified[p])\n", + "imports_df = pd.DataFrame.from_dict(\n", + " {p: {m: m in main_imports_unqualified[p] \n", + " for m in sorted(all_imports)} \n", + " for p in main_imports_unqualified}, \n", + " orient='index').sort_index()\n", + "imports_df" + ] + }, + { + "cell_type": "code", + "execution_count": 219, + "id": "3668bdab-5b8f-4ab0-b788-002f0ced7b8c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "| | 0 |\n", + "|:---------------------------|----:|\n", + "| Data.List | 16 |\n", + "| Data.Attoparsec.Text | 13 |\n", + "| Data.Text.IO | 13 |\n", + "| Data.Text | 13 |\n", + "| Linear | 11 |\n", + "| Data.Set | 9 |\n", + "| Data.Map.Strict | 9 |\n", + "| Control.Applicative | 9 |\n", + "| Data.Char | 6 |\n", + "| Data.Maybe | 5 |\n", + "| Control.Lens | 4 |\n", + "| Control.Monad.Reader | 3 |\n", + "| Data.MultiSet | 3 |\n", + "| Data.Array.IArray | 2 |\n", + "| Data.List.Split | 2 |\n", + "| Control.Monad | 2 |\n", + "| Data.Sequence | 2 |\n", + "| Data.PQueue.Prio.Min | 2 |\n", + "| Control.Monad.State.Strict | 2 |\n", + "| Data.Ix | 2 |\n", + "| Data.Foldable | 2 |\n", + "| Data.Bits | 1 |\n", + "| Data.Array | 1 |\n", + "| Data.Monoid | 1 |\n", + "| Data.Int | 1 |\n", + "| Data.ByteString | 1 |\n", + "| Control.Monad.RWS.Strict | 1 |\n", + "| Data.Bitstream | 1 |\n", + "| Data.Tuple | 1 |\n", + "| Data.Word | 1 |\n", + "| Data.IntMap.Strict | 1 |\n" + ] + } + ], + "source": [ + "print(imports_df.sum().sort_values(ascending=False).to_markdown())" + ] + }, + { + "cell_type": "code", + "execution_count": 220, + "id": "3f3e9d52-87b4-4a2d-889d-0bd925f967b0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    \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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    programmodulepresent
    17advent01Data.ListTrue
    31advent02Control.ApplicativeTrue
    39advent02Data.Attoparsec.TextTrue
    57advent02Data.TextTrue
    58advent02Data.Text.IOTrue
    ............
    739advent24Data.TextTrue
    740advent24Data.Text.IOTrue
    761advent25Data.ListTrue
    763advent25Data.Map.StrictTrue
    774advent25LinearTrue
    \n", + "

    140 rows × 3 columns

    \n", + "
    " + ], + "text/plain": [ + " program module present\n", + "17 advent01 Data.List True\n", + "31 advent02 Control.Applicative True\n", + "39 advent02 Data.Attoparsec.Text True\n", + "57 advent02 Data.Text True\n", + "58 advent02 Data.Text.IO True\n", + ".. ... ... ...\n", + "739 advent24 Data.Text True\n", + "740 advent24 Data.Text.IO True\n", + "761 advent25 Data.List True\n", + "763 advent25 Data.Map.Strict True\n", + "774 advent25 Linear True\n", + "\n", + "[140 rows x 3 columns]" + ] + }, + "execution_count": 220, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "imports_scatter = imports_df.stack().reset_index()\n", + "imports_scatter.columns = ['program', 'module', 'present']\n", + "imports_scatter = imports_scatter[imports_scatter.present]\n", + "imports_scatter" + ] + }, + { + "cell_type": "code", + "execution_count": 221, + "id": "1b22b8c9-a14f-406d-bd77-ba7d7b3c3ffa", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 221, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "imports_scatter.plot.scatter(x='program', y='module', s=80, rot=45, figsize=(10, 10))" + ] + }, + { + "cell_type": "code", + "execution_count": 222, + "id": "9552d5f9-cc44-4d49-b97e-8961556878c5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "31" + ] + }, + "execution_count": 222, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "imports_df.columns.size" + ] + }, + { + "cell_type": "code", + "execution_count": 223, + "id": "4b70002e-f12e-4067-b8b8-119504e4d86b", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "cmap = mpl.colors.ListedColormap(['white', 'blue'])\n", + "\n", + "fig, ax = plt.subplots(figsize=(10, 10))\n", + "ax.imshow(imports_df.to_numpy().T, cmap=cmap)\n", + "plt.xticks(range(imports_df.index.size), labels=imports_df.index.values, rotation=90);\n", + "plt.yticks(range(imports_df.columns.size), labels=imports_df.columns.values);\n", + "\n", + "ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5))\n", + "ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5))\n", + "ax.grid(which='minor', axis='both', linestyle='-', color='silver', linewidth=1.5);\n", + "plt.savefig('imports.png');" + ] + }, + { + "cell_type": "code", + "execution_count": 224, + "id": "684eb890-3729-4d68-a862-798c9ca152ce", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'3.4.2'" + ] + }, + "execution_count": 224, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import matplotlib as mpl\n", + "mpl.__version__" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c6ccc03-f87d-437f-aecf-e6cf1fcd0698", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "jupytext": { + "formats": "ipynb,md" + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/profiling/modules.md b/profiling/modules.md new file mode 100644 index 0000000..3cc0a1b --- /dev/null +++ b/profiling/modules.md @@ -0,0 +1,184 @@ +--- +jupyter: + jupytext: + formats: ipynb,md + text_representation: + extension: .md + format_name: markdown + format_version: '1.3' + jupytext_version: 1.11.1 + kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + +```python +import os, glob +import collections +import pandas as pd +import numpy as np + +import matplotlib as mpl +import matplotlib.pyplot as plt +%matplotlib inline +``` + +```python +with open('../advent-of-code21.cabal') as f: + build_depends = [l for l in f.readlines() if 'build-depends' in l] +build_depends +``` + +```python +cabal_file = open('../advent-of-code21.cabal').read() +executables = cabal_file.split('executable')[2:] +executables[:3] +``` + +```python +e = executables[1] +e.strip().split('build-depends: ')[1].split(',') +``` + +```python +def extract(line): + parts = line.strip().split('build-depends: ') + name = parts[0].split()[0] + if len(parts) > 1: + depends = [p.strip() for p in parts[1].split('\n')[0].split(',') if 'base' not in p] + else: + depends = [] + return name, depends +``` + +```python +modules = {e: ms for e, ms in [extract(e) for e in executables] if e.endswith(tuple(str(i) for i in range(10)))} +modules +``` + +```python +all_modules = set(m for p in modules for m in modules[p]) +modules_df = pd.DataFrame.from_dict({p: {m: m in modules[p] for m in sorted(all_modules)} for p in modules}, orient='index').sort_index() +modules_df +``` + +```python +print(modules_df.sum().sort_values(ascending=False).to_markdown()) +``` + +```python +modules_scatter = modules_df.stack().reset_index() +modules_scatter.columns = ['program', 'module', 'present'] +modules_scatter = modules_scatter[modules_scatter.present] +modules_scatter +``` + +```python tags=[] +modules_scatter.plot.scatter(x='program', y='module', s=80, rot=45, figsize=(10, 6)) +``` + +```python +cmap = mpl.colors.ListedColormap(['white', 'blue']) + +fig, ax = plt.subplots(figsize=(10, 10)) +ax.imshow(modules_df.to_numpy().T, cmap=cmap) +plt.xticks(range(modules_df.index.size), labels=modules_df.index.values, rotation=90); +plt.yticks(range(modules_df.columns.size), labels=modules_df.columns.values); + +ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5)) +ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5)) +ax.grid(which='minor', axis='both', linestyle='-', color='silver', linewidth=1.5); +plt.savefig('packages.png'); +``` + +```python +mains = list(sorted(f for f in glob.glob('../advent*/Main.hs'))) +mains +``` + +```python +main_imports = {} + +for m in mains: + with open(m) as f: + lines = f.readlines() + import_lines = [l for l in lines if l.strip().startswith('import') if 'Debug.Trace' not in l] + imports = [] + for i in import_lines: + words = i.strip().split() + if 'qualified' in i: + imports.append((words[2], True)) + else: + imports.append((words[1], False)) + main_imports[m.split('/')[1]] = imports + +main_imports +``` + +```python +import_counts = collections.Counter(l for ls in main_imports.values() for l in ls) +import_counts.most_common() +``` + +```python +main_imports_unqualified = {m: set(i[0] for i in main_imports[m]) for m in main_imports} +main_imports_unqualified +``` + +```python +import_counts_unqualified = collections.Counter(l for ls in main_imports_unqualified.values() for l in ls) +import_counts_unqualified.most_common() +``` + +```python +all_imports = set(m for p in main_imports_unqualified for m in main_imports_unqualified[p]) +imports_df = pd.DataFrame.from_dict( + {p: {m: m in main_imports_unqualified[p] + for m in sorted(all_imports)} + for p in main_imports_unqualified}, + orient='index').sort_index() +imports_df +``` + +```python +print(imports_df.sum().sort_values(ascending=False).to_markdown()) +``` + +```python +imports_scatter = imports_df.stack().reset_index() +imports_scatter.columns = ['program', 'module', 'present'] +imports_scatter = imports_scatter[imports_scatter.present] +imports_scatter +``` + +```python tags=[] +imports_scatter.plot.scatter(x='program', y='module', s=80, rot=45, figsize=(10, 10)) +``` + +```python +imports_df.columns.size +``` + +```python +cmap = mpl.colors.ListedColormap(['white', 'blue']) + +fig, ax = plt.subplots(figsize=(10, 10)) +ax.imshow(imports_df.to_numpy().T, cmap=cmap) +plt.xticks(range(imports_df.index.size), labels=imports_df.index.values, rotation=90); +plt.yticks(range(imports_df.columns.size), labels=imports_df.columns.values); + +ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5)) +ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(0.5)) +ax.grid(which='minor', axis='both', linestyle='-', color='silver', linewidth=1.5); +plt.savefig('imports.png'); +``` + +```python +import matplotlib as mpl +mpl.__version__ +``` + +```python + +``` diff --git a/profiling/profiling.ipynb b/profiling/profiling.ipynb new file mode 100644 index 0000000..cf7c87f --- /dev/null +++ b/profiling/profiling.ipynb @@ -0,0 +1,4664 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 274, + "metadata": { + "Collapsed": "false" + }, + "outputs": [], + "source": [ + "import glob\n", + "import json\n", + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "import matplotlib.pyplot as plt\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 275, + "metadata": { + "Collapsed": "false", + "scrolled": true, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent01) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent01' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent01' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent01' for advent-of-code21-0.1.0.0..\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent01/build/advent01/advent01 ...\n", + "1521\n", + "1543\n", + " 20,426,624 bytes allocated in the heap\n", + " 1,552,136 bytes copied during GC\n", + " 412,104 bytes maximum residency (2 sample(s))\n", + " 136,760 bytes maximum slop\n", + " 62 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 3 colls, 3 par 0.002s 0.001s 0.0003s 0.0003s\n", + " Gen 1 2 colls, 1 par 0.002s 0.001s 0.0004s 0.0004s\n", + "\n", + " Parallel GC work balance: 29.88% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.013s ( 0.012s elapsed)\n", + " GC time 0.004s ( 0.001s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.023s ( 0.017s elapsed)\n", + "\n", + " Alloc rate 1,561,715,663 bytes per MUT second\n", + "\n", + " Productivity 57.8% of total user, 71.1% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent02) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent02' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent02' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent02' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent02/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent02/build/advent02/advent02-tmp/Main.dyn_o ) [Data.Attoparsec.Text changed]\n", + "\n", + "\u001b[;1madvent02/Main.hs:55:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " courseP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [Command]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m55 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mcourseP\u001b[0m\u001b[0m = commandP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent02/Main.hs:56:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " commandP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Command\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m56 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mcommandP\u001b[0m\u001b[0m = forwardP <|> upP <|> downP\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent02/Main.hs:58:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " forwardP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Command\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m58 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mforwardP\u001b[0m\u001b[0m = Forward <$> (\"forward \" *> decimal)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent02/Main.hs:59:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " upP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Command\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m59 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mupP\u001b[0m\u001b[0m = Up <$> (\"up \" *> decimal)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent02/Main.hs:60:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " downP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Command\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m60 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mdownP\u001b[0m\u001b[0m = Down <$> (\"down \" *> decimal)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent02/Main.hs:63:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text -> [Command]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m63 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent02/build/advent02/advent02 ...\n", + "2039912\n", + "1942068080\n", + " 2,701,328 bytes allocated in the heap\n", + " 64 bytes copied during GC\n", + " 223,280 bytes maximum residency (1 sample(s))\n", + " 124,880 bytes maximum slop\n", + " 62 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 0 colls, 0 par 0.000s 0.000s 0.0000s 0.0000s\n", + " Gen 1 1 colls, 0 par 0.000s 0.000s 0.0003s 0.0003s\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.003s elapsed)\n", + " MUT time 0.003s ( 0.003s elapsed)\n", + " GC time 0.000s ( 0.000s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.002s elapsed)\n", + " Total time 0.009s ( 0.007s elapsed)\n", + "\n", + " Alloc rate 975,508,007 bytes per MUT second\n", + "\n", + " Productivity 29.6% of total user, 39.3% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent03) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent03' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent03' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent03' for advent-of-code21-0.1.0.0..\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent03/build/advent03/advent03 ...\n", + "2724524\n", + "2775870\n", + " 12,725,280 bytes allocated in the heap\n", + " 3,135,472 bytes copied during GC\n", + " 214,088 bytes maximum residency (1 sample(s))\n", + " 125,880 bytes maximum slop\n", + " 63 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 2 colls, 2 par 0.005s 0.004s 0.0021s 0.0024s\n", + " Gen 1 1 colls, 0 par 0.000s 0.000s 0.0004s 0.0004s\n", + "\n", + " Parallel GC work balance: 8.64% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.008s ( 0.007s elapsed)\n", + " GC time 0.006s ( 0.005s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.019s ( 0.015s elapsed)\n", + "\n", + " Alloc rate 1,635,549,285 bytes per MUT second\n", + "\n", + " Productivity 40.4% of total user, 47.5% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent04) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent04' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent04' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent04' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent04/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent04/build/advent04/advent04-tmp/Main.dyn_o ) [Data.Attoparsec.Text changed]\n", + "\n", + "\u001b[;1madvent04/Main.hs:72:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘forceCall’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m72 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mforceCall\u001b[0m\u001b[0m (BingoNum n _) = BingoNum n True\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent04/Main.hs:99:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " bingoP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text ([Int], [[[Int]]])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m99 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mbingoP\u001b[0m\u001b[0m = (,) <$> calledP <*> (blankLines *> squaresP)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent04/Main.hs:101:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " calledP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [Int]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m101 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mcalledP\u001b[0m\u001b[0m = decimal `sepBy` \",\"\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent04/Main.hs:103:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " squaresP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [[[Int]]]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m103 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msquaresP\u001b[0m\u001b[0m = squareP `sepBy` blankLines\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent04/Main.hs:104:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " squareP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [[Int]]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m104 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msquareP\u001b[0m\u001b[0m = rowP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent04/Main.hs:105:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " rowP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [Int]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m105 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mrowP\u001b[0m\u001b[0m = paddedDecimal `sepBy1` \" \"\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent04/Main.hs:108:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " paddedDecimal :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m108 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpaddedDecimal\u001b[0m\u001b[0m = (many \" \") *> decimal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent04/Main.hs:110:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " blankLines :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [()]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m110 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mblankLines\u001b[0m\u001b[0m = many1 endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent04/Main.hs:113:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text -> ([Int], [[[Int]]])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m113 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent04/build/advent04/advent04 ...\n", + "82440\n", + "20774\n", + " 87,851,256 bytes allocated in the heap\n", + " 15,993,040 bytes copied during GC\n", + " 2,460,448 bytes maximum residency (4 sample(s))\n", + " 153,864 bytes maximum slop\n", + " 65 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 18 colls, 18 par 0.016s 0.012s 0.0007s 0.0010s\n", + " Gen 1 4 colls, 3 par 0.040s 0.006s 0.0015s 0.0037s\n", + "\n", + " Parallel GC work balance: 28.31% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.038s ( 0.033s elapsed)\n", + " GC time 0.057s ( 0.018s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.100s ( 0.054s elapsed)\n", + "\n", + " Alloc rate 2,339,122,861 bytes per MUT second\n", + "\n", + " Productivity 37.5% of total user, 60.6% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent05) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent05' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent05' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent05' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent05/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent05/build/advent05/advent05-tmp/Main.dyn_o ) [Linear changed]\n", + "\n", + "\u001b[;1madvent05/Main.hs:7:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-imports\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " The import of ‘Control.Applicative’ is redundant\n", + " except perhaps to import instances from ‘Control.Applicative’\n", + " To import instances alone, use: import Control.Applicative()\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m7 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mimport Control.Applicative\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent05/Main.hs:26:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: part1 :: [Line] -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m26 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart1\u001b[0m\u001b[0m trace = M.size $ M.filter (> 1) diagram\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent05/Main.hs:30:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: part2 :: [Line] -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m30 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart2\u001b[0m\u001b[0m trace = M.size $ M.filter (> 1) diagram\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent05/Main.hs:66:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " traceP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [Line]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m66 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mtraceP\u001b[0m\u001b[0m = lineP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent05/Main.hs:67:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " lineP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Line\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m67 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mlineP\u001b[0m\u001b[0m = Line <$> (pointP <* \" -> \") <*> pointP\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent05/Main.hs:68:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " pointP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (V2 Int)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m68 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpointP\u001b[0m\u001b[0m = V2 <$> (decimal <* \",\") <*> decimal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent05/Main.hs:71:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text -> [Line]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m71 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent05/build/advent05/advent05 ...\n", + "5092\n", + "20484\n", + " 575,260,608 bytes allocated in the heap\n", + " 446,639,040 bytes copied during GC\n", + " 24,474,608 bytes maximum residency (14 sample(s))\n", + " 367,632 bytes maximum slop\n", + " 115 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 106 colls, 106 par 0.208s 0.183s 0.0017s 0.0045s\n", + " Gen 1 14 colls, 13 par 0.528s 0.105s 0.0075s 0.0152s\n", + "\n", + " Parallel GC work balance: 25.86% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.393s ( 0.353s elapsed)\n", + " GC time 0.716s ( 0.268s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.020s ( 0.020s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 1.135s ( 0.644s elapsed)\n", + "\n", + " Alloc rate 1,464,438,774 bytes per MUT second\n", + "\n", + " Productivity 36.4% of total user, 58.0% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent06) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent06' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent06' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent06' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent06/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent06/build/advent06/advent06-tmp/Main.dyn_o ) [Data.List.Split changed]\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent06/build/advent06/advent06 ...\n", + "352195\n", + "1600306001288\n", + " 3,994,656 bytes allocated in the heap\n", + " 64 bytes copied during GC\n", + " 223,184 bytes maximum residency (1 sample(s))\n", + " 124,976 bytes maximum slop\n", + " 62 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 0 colls, 0 par 0.000s 0.000s 0.0000s 0.0000s\n", + " Gen 1 1 colls, 0 par 0.000s 0.000s 0.0004s 0.0004s\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.004s ( 0.004s elapsed)\n", + " GC time 0.000s ( 0.000s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.009s ( 0.007s elapsed)\n", + "\n", + " Alloc rate 1,117,434,116 bytes per MUT second\n", + "\n", + " Productivity 38.0% of total user, 50.0% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent07) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent07' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent07' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent07' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent07/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent07/build/advent07/advent07-tmp/Main.dyn_o ) [Data.List.Split changed]\n", + "\n", + "\u001b[;1madvent07/Main.hs:12:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: part1 :: [Int] -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m12 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart1\u001b[0m\u001b[0m = bestFuel loss1\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent07/Main.hs:13:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: part2 :: [Int] -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m13 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart2\u001b[0m\u001b[0m = bestFuel loss2\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent07/build/advent07/advent07 ...\n", + "336721\n", + "91638945\n", + " 9,374,760 bytes allocated in the heap\n", + " 532,856 bytes copied during GC\n", + " 318,896 bytes maximum residency (2 sample(s))\n", + " 135,760 bytes maximum slop\n", + " 62 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 1 colls, 1 par 0.001s 0.000s 0.0002s 0.0002s\n", + " Gen 1 2 colls, 1 par 0.002s 0.001s 0.0003s 0.0004s\n", + "\n", + " Parallel GC work balance: 55.07% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.009s ( 0.009s elapsed)\n", + " GC time 0.002s ( 0.001s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.017s ( 0.012s elapsed)\n", + "\n", + " Alloc rate 1,025,488,891 bytes per MUT second\n", + "\n", + " Productivity 53.8% of total user, 70.2% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent08) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent08' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent08' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent08' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent08/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent08/build/advent08/advent08-tmp/Main.dyn_o ) [Data.Attoparsec.Text changed]\n", + "\n", + "\u001b[;1madvent08/Main.hs:99:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " displaysP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [Display]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m99 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mdisplaysP\u001b[0m\u001b[0m = displayP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent08/Main.hs:100:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " displayP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Display\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m100 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mdisplayP\u001b[0m\u001b[0m = Display <$> (patternsP <* \" | \") <*> patternsP\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent08/Main.hs:102:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " patternsP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [[Char]]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m102 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpatternsP\u001b[0m\u001b[0m = patternP `sepBy` \" \"\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent08/Main.hs:103:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " patternP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [Char]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m103 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpatternP\u001b[0m\u001b[0m = many1 letter\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent08/Main.hs:106:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text -> [Display]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m106 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent08/build/advent08/advent08 ...\n", + "255\n", + "982158\n", + " 3,831,978,128 bytes allocated in the heap\n", + " 41,889,816 bytes copied during GC\n", + " 2,251,264 bytes maximum residency (19 sample(s))\n", + " 162,616 bytes maximum slop\n", + " 63 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 906 colls, 906 par 0.240s 0.062s 0.0001s 0.0012s\n", + " Gen 1 19 colls, 18 par 0.078s 0.031s 0.0016s 0.0025s\n", + "\n", + " Parallel GC work balance: 32.00% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 1.966s ( 1.771s elapsed)\n", + " GC time 0.304s ( 0.080s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.014s ( 0.014s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 2.290s ( 1.868s elapsed)\n", + "\n", + " Alloc rate 1,949,274,255 bytes per MUT second\n", + "\n", + " Productivity 86.5% of total user, 95.5% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent09) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent09' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent09' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent09' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent09/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent09/build/advent09/advent09-tmp/Main.dyn_o ) [Linear changed]\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent09/build/advent09/advent09 ...\n", + "15\n", + "1134\n", + " 632,576 bytes allocated in the heap\n", + " 64 bytes copied during GC\n", + " 223,184 bytes maximum residency (1 sample(s))\n", + " 124,976 bytes maximum slop\n", + " 62 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 0 colls, 0 par 0.000s 0.000s 0.0000s 0.0000s\n", + " Gen 1 1 colls, 0 par 0.000s 0.000s 0.0003s 0.0003s\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.001s ( 0.001s elapsed)\n", + " GC time 0.000s ( 0.000s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.007s ( 0.004s elapsed)\n", + "\n", + " Alloc rate 1,193,744,586 bytes per MUT second\n", + "\n", + " Productivity 8.1% of total user, 14.0% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent10) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent10' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent10' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent10' for advent-of-code21-0.1.0.0..\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent10/build/advent10/advent10 ...\n", + "339537\n", + "2412013412\n", + " 3,868,496 bytes allocated in the heap\n", + " 64 bytes copied during GC\n", + " 223,184 bytes maximum residency (1 sample(s))\n", + " 124,976 bytes maximum slop\n", + " 62 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 0 colls, 0 par 0.000s 0.000s 0.0000s 0.0000s\n", + " Gen 1 1 colls, 0 par 0.000s 0.000s 0.0003s 0.0003s\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.003s ( 0.003s elapsed)\n", + " GC time 0.000s ( 0.000s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.009s ( 0.006s elapsed)\n", + "\n", + " Alloc rate 1,516,570,168 bytes per MUT second\n", + "\n", + " Productivity 29.7% of total user, 42.9% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent11) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent11' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent11' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent11' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent11/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent11/build/advent11/advent11-tmp/Main.dyn_o ) [Linear changed]\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent11/build/advent11/advent11 ...\n", + "1627\n", + "329\n", + " 54,909,424 bytes allocated in the heap\n", + " 1,785,512 bytes copied during GC\n", + " 268,416 bytes maximum residency (2 sample(s))\n", + " 141,184 bytes maximum slop\n", + " 63 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 12 colls, 12 par 0.005s 0.002s 0.0001s 0.0002s\n", + " Gen 1 2 colls, 1 par 0.002s 0.001s 0.0003s 0.0004s\n", + "\n", + " Parallel GC work balance: 20.48% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.031s ( 0.028s elapsed)\n", + " GC time 0.006s ( 0.002s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.044s ( 0.034s elapsed)\n", + "\n", + " Alloc rate 1,758,386,456 bytes per MUT second\n", + "\n", + " Productivity 71.4% of total user, 83.2% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent12) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent12' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent12' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent12' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent12/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent12/build/advent12/advent12-tmp/Main.dyn_o ) [Data.Attoparsec.Text changed]\n", + "\n", + "\u001b[;1madvent12/Main.hs:85:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " graphP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [([Char], [Char])]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m85 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mgraphP\u001b[0m\u001b[0m = edgeP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent12/Main.hs:86:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " edgeP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text ([Char], [Char])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m86 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35medgeP\u001b[0m\u001b[0m = (,) <$> many1 letter <* \"-\" <*> many1 letter\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent12/Main.hs:89:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text -> [([Char], [Char])]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m89 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent12/build/advent12/advent12 ...\n", + "4495\n", + "131254\n", + " 1,018,073,152 bytes allocated in the heap\n", + " 457,994,984 bytes copied during GC\n", + " 38,962,240 bytes maximum residency (19 sample(s))\n", + " 366,016 bytes maximum slop\n", + " 129 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 227 colls, 227 par 0.234s 0.181s 0.0008s 0.0049s\n", + " Gen 1 19 colls, 18 par 1.223s 0.291s 0.0153s 0.0553s\n", + "\n", + " Parallel GC work balance: 57.92% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 1.524s ( 1.436s elapsed)\n", + " GC time 1.323s ( 0.338s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.135s ( 0.134s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 2.987s ( 1.911s elapsed)\n", + "\n", + " Alloc rate 668,225,062 bytes per MUT second\n", + "\n", + " Productivity 55.5% of total user, 82.1% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent13) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent13' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent13' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent13' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent13/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent13/build/advent13/advent13-tmp/Main.dyn_o ) [Linear changed]\n", + "\n", + "\u001b[;1madvent13/Main.hs:11:24: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-imports\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " The import of ‘^+^’ from module ‘Linear’ is redundant\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m11 |\u001b[0m\u001b[0m import Linear (V2(..), \u001b[;1m\u001b[35m(^+^)\u001b[0m\u001b[0m)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent13/Main.hs:66:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " inputP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (S.Set (V2 Int), [Fold])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m66 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35minputP\u001b[0m\u001b[0m = (,) <$> sheetP <* many1 endOfLine <*> foldsP\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent13/Main.hs:68:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " sheetP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (S.Set (V2 Int))\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m68 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msheetP\u001b[0m\u001b[0m = S.fromList <$> dotP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent13/Main.hs:69:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " dotP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (V2 Int)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m69 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mdotP\u001b[0m\u001b[0m = V2 <$> decimal <* \",\" <*> decimal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent13/Main.hs:71:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " foldsP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [Fold]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m71 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mfoldsP\u001b[0m\u001b[0m = foldP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent13/Main.hs:72:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " foldP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Fold\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m72 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mfoldP\u001b[0m\u001b[0m = Fold <$> (\"fold along \" *> axisP) <* \"=\" <*> decimal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent13/Main.hs:74:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " axisP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Axis\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m74 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35maxisP\u001b[0m\u001b[0m = (\"x\" *> pure X) <|> (\"y\" *> pure Y)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent13/Main.hs:77:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text\n", + " -> (S.Set (V2 Int), [Fold])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m77 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent13/build/advent13/advent13 ...\n", + "763\n", + "███ █ █ ██ █ ███ ██ ███ ██ \n", + "█ █ █ █ █ █ █ █ █ █ █ █ █ █ █\n", + "█ █ ████ █ █ █ █ █ █ █ █ █ █\n", + "███ █ █ ████ █ ███ █ ███ ████\n", + "█ █ █ █ █ █ █ █ █ █ █ █ █ █ █\n", + "█ █ █ █ █ █ ████ █ █ ██ █ █ █ █\n", + "\n", + " 6,531,504 bytes allocated in the heap\n", + " 354,392 bytes copied during GC\n", + " 214,088 bytes maximum residency (1 sample(s))\n", + " 125,880 bytes maximum slop\n", + " 62 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 1 colls, 1 par 0.001s 0.000s 0.0002s 0.0002s\n", + " Gen 1 1 colls, 0 par 0.000s 0.000s 0.0003s 0.0003s\n", + "\n", + " Parallel GC work balance: 31.97% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.006s ( 0.006s elapsed)\n", + " GC time 0.001s ( 0.001s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.013s ( 0.009s elapsed)\n", + "\n", + " Alloc rate 1,104,134,445 bytes per MUT second\n", + "\n", + " Productivity 46.5% of total user, 62.0% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent14) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent14' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent14' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent14' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent14/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent14/build/advent14/advent14-tmp/Main.dyn_o ) [Data.MultiSet changed]\n", + "\n", + "\u001b[;1madvent14/Main.hs:7:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-imports\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " The import of ‘Control.Applicative’ is redundant\n", + " except perhaps to import instances from ‘Control.Applicative’\n", + " To import instances alone, use: import Control.Applicative()\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m7 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mimport Control.Applicative\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:67:9: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-local-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘elems’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m67 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35melems\u001b[0m\u001b[0m = S.union (MS.toSet firsts) (MS.toSet seconds)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:73:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " stringify :: (a, a) -> [a]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m73 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mstringify\u001b[0m\u001b[0m (a, b) = [a, b]\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:81:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " inputP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text ([Char], M.Map [Char] [Char])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m81 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35minputP\u001b[0m\u001b[0m = (,) <$> (many1 letter) <* many1 endOfLine <*> rulesP\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:83:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " rulesP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (M.Map [Char] [Char])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m83 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mrulesP\u001b[0m\u001b[0m = M.fromList <$> ruleP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:84:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " ruleP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text ([Char], [Char])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m84 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mruleP\u001b[0m\u001b[0m = (,) <$> many1 letter <* \" -> \" <*> many1 letter\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:87:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text\n", + " -> ([Char], M.Map [Char] [Char])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m87 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "[1 of 1] Compiling Main ( advent14/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent14/build/advent14/advent14-tmp/Main.p_o )\n", + "\n", + "\u001b[;1madvent14/Main.hs:7:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-imports\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " The import of ‘Control.Applicative’ is redundant\n", + " except perhaps to import instances from ‘Control.Applicative’\n", + " To import instances alone, use: import Control.Applicative()\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m7 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mimport Control.Applicative\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:67:9: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-local-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘elems’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m67 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35melems\u001b[0m\u001b[0m = S.union (MS.toSet firsts) (MS.toSet seconds)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:73:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " stringify :: (a, a) -> [a]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m73 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mstringify\u001b[0m\u001b[0m (a, b) = [a, b]\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:81:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " inputP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text ([Char], M.Map [Char] [Char])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m81 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35minputP\u001b[0m\u001b[0m = (,) <$> (many1 letter) <* many1 endOfLine <*> rulesP\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:83:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " rulesP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (M.Map [Char] [Char])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m83 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mrulesP\u001b[0m\u001b[0m = M.fromList <$> ruleP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:84:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " ruleP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text ([Char], [Char])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m84 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mruleP\u001b[0m\u001b[0m = (,) <$> many1 letter <* \" -> \" <*> many1 letter\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent14/Main.hs:87:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text\n", + " -> ([Char], M.Map [Char] [Char])\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m87 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent14/build/advent14/advent14 ...\n", + "2712\n", + "8336623059567\n", + " 23,386,192 bytes allocated in the heap\n", + " 469,768 bytes copied during GC\n", + " 265,168 bytes maximum residency (2 sample(s))\n", + " 140,336 bytes maximum slop\n", + " 62 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 4 colls, 4 par 0.002s 0.000s 0.0001s 0.0002s\n", + " Gen 1 2 colls, 1 par 0.002s 0.001s 0.0003s 0.0003s\n", + "\n", + " Parallel GC work balance: 57.81% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.014s ( 0.012s elapsed)\n", + " GC time 0.003s ( 0.001s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.023s ( 0.016s elapsed)\n", + "\n", + " Alloc rate 1,717,613,851 bytes per MUT second\n", + "\n", + " Productivity 60.5% of total user, 75.8% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent15) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent15' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent15' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent15' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent15/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent15/build/advent15/advent15-tmp/Main.dyn_o ) [Linear changed]\n", + "\n", + "\u001b[;1madvent15/Main.hs:10:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-imports\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " The import of ‘<|, ><’ from module ‘Data.Sequence’ is redundant\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m10 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mimport Data.Sequence ((<|), (|>), (><))\u001b[0m\u001b[0m --, ViewR( (:>) ), ViewL( (:<) ))\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:11:31: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-imports\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " The import of ‘sum’ from module ‘Data.Foldable’ is redundant\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m11 |\u001b[0m\u001b[0m import Data.Foldable (foldl', \u001b[;1m\u001b[35msum\u001b[0m\u001b[0m) -- (toList, foldr', foldl', all)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:16:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-imports\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " The import of ‘*^, ^*’ from module ‘Linear’ is redundant\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m16 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mimport Linear (V2(..), (^+^), (^-^), (*^), (^*))\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:19:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: data constructor ‘Empty’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m19 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern Empty <- (Q.viewl -> Q.EmptyL) where Empty = Q.empty\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:19:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern synonym with no type signature:\n", + " pattern Main.Empty :: forall {a}. Q.Seq a\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m19 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern Empty <- (Q.viewl -> Q.EmptyL) where Empty = Q.empty\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:20:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: data constructor ‘:<’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m20 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern x :< xs <- (Q.viewl -> x Q.:< xs) where (:<) = (Q.<|)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:20:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern synonym with no type signature:\n", + " pattern (:<) :: forall {a}. a -> Q.Seq a -> Q.Seq a\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m20 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern x :< xs <- (Q.viewl -> x Q.:< xs) where (:<) = (Q.<|)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:21:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: data constructor ‘:>’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m21 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern xs :> x <- (Q.viewr -> xs Q.:> x) where (:>) = (Q.|>)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:21:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern synonym with no type signature:\n", + " pattern (:>) :: forall {a}. Q.Seq a -> a -> Q.Seq a\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m21 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern xs :> x <- (Q.viewr -> xs Q.:> x) where (:>) = (Q.|>)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:34:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘grid’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m34 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mmakeLenses ''Cave\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:34:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘goal’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m34 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mmakeLenses ''Cave\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:44:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘cost’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m44 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mmakeLenses ''Agendum\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:51:5: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘unwrapPos’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m51 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35munwrapPos :: s -> BasePosition\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:67:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m67 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:78:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘goal’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m78 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgoal\u001b[0m\u001b[0m <- asks _goal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:84:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘goal’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m84 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgoal\u001b[0m\u001b[0m <- asks _goal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:88:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m88 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:99:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m99 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:114:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘goal’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m114 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgoal\u001b[0m\u001b[0m <- asks _goal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:120:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘goal’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m120 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgoal\u001b[0m\u001b[0m <- asks _goal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:124:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m124 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:129:13: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘cost’ shadows the existing binding\n", + " defined at advent15/Main.hs:44:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m129 |\u001b[0m\u001b[0m let !\u001b[;1m\u001b[35mcost\u001b[0m\u001b[0m = (gridCost - 1 + tileR + tileC) `mod` 9 + 1\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:151:9: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m151 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m = listArray ((V2 0 0), (V2 r c)) $ map mkCell $ concat rows\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:207:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m207 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:207:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-matches\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘grid’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m207 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "[1 of 1] Compiling Main ( advent15/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent15/build/advent15/advent15-tmp/Main.p_o )\n", + "\n", + "\u001b[;1madvent15/Main.hs:10:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-imports\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " The import of ‘<|, ><’ from module ‘Data.Sequence’ is redundant\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m10 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mimport Data.Sequence ((<|), (|>), (><))\u001b[0m\u001b[0m --, ViewR( (:>) ), ViewL( (:<) ))\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:11:31: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-imports\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " The import of ‘sum’ from module ‘Data.Foldable’ is redundant\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m11 |\u001b[0m\u001b[0m import Data.Foldable (foldl', \u001b[;1m\u001b[35msum\u001b[0m\u001b[0m) -- (toList, foldr', foldl', all)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:16:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-imports\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " The import of ‘*^, ^*’ from module ‘Linear’ is redundant\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m16 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mimport Linear (V2(..), (^+^), (^-^), (*^), (^*))\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:19:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: data constructor ‘Empty’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m19 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern Empty <- (Q.viewl -> Q.EmptyL) where Empty = Q.empty\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:19:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern synonym with no type signature:\n", + " pattern Main.Empty :: forall {a}. Q.Seq a\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m19 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern Empty <- (Q.viewl -> Q.EmptyL) where Empty = Q.empty\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:20:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: data constructor ‘:<’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m20 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern x :< xs <- (Q.viewl -> x Q.:< xs) where (:<) = (Q.<|)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:20:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern synonym with no type signature:\n", + " pattern (:<) :: forall {a}. a -> Q.Seq a -> Q.Seq a\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m20 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern x :< xs <- (Q.viewl -> x Q.:< xs) where (:<) = (Q.<|)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:21:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: data constructor ‘:>’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m21 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern xs :> x <- (Q.viewr -> xs Q.:> x) where (:>) = (Q.|>)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:21:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern synonym with no type signature:\n", + " pattern (:>) :: forall {a}. Q.Seq a -> a -> Q.Seq a\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m21 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern xs :> x <- (Q.viewr -> xs Q.:> x) where (:>) = (Q.|>)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:34:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘grid’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m34 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mmakeLenses ''Cave\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:34:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘goal’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m34 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mmakeLenses ''Cave\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:44:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘cost’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m44 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mmakeLenses ''Agendum\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:51:5: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘unwrapPos’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m51 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35munwrapPos :: s -> BasePosition\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:67:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m67 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:78:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘goal’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m78 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgoal\u001b[0m\u001b[0m <- asks _goal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:84:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘goal’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m84 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgoal\u001b[0m\u001b[0m <- asks _goal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:88:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m88 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:99:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m99 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:114:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘goal’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m114 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgoal\u001b[0m\u001b[0m <- asks _goal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:120:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘goal’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m120 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgoal\u001b[0m\u001b[0m <- asks _goal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:124:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m124 |\u001b[0m\u001b[0m do \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:129:13: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘cost’ shadows the existing binding\n", + " defined at advent15/Main.hs:44:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m129 |\u001b[0m\u001b[0m let !\u001b[;1m\u001b[35mcost\u001b[0m\u001b[0m = (gridCost - 1 + tileR + tileC) `mod` 9 + 1\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:151:9: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m151 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m = listArray ((V2 0 0), (V2 r c)) $ map mkCell $ concat rows\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:207:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘grid’ shadows the existing binding\n", + " defined at advent15/Main.hs:34:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m207 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent15/Main.hs:207:8: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-matches\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘grid’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m207 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mgrid\u001b[0m\u001b[0m <- asks _grid\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent15/build/advent15/advent15 ...\n", + "503\n", + "2853\n", + " 3,777,538,616 bytes allocated in the heap\n", + " 924,751,680 bytes copied during GC\n", + " 28,278,080 bytes maximum residency (39 sample(s))\n", + " 904,040 bytes maximum slop\n", + " 111 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 873 colls, 873 par 0.879s 0.676s 0.0008s 0.0016s\n", + " Gen 1 39 colls, 38 par 1.118s 0.304s 0.0078s 0.0202s\n", + "\n", + " Parallel GC work balance: 39.64% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 3.163s ( 2.865s elapsed)\n", + " GC time 1.823s ( 0.808s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.173s ( 0.172s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 5.165s ( 3.848s elapsed)\n", + "\n", + " Alloc rate 1,194,300,602 bytes per MUT second\n", + "\n", + " Productivity 64.6% of total user, 78.9% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent16) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent16' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent16' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent16' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent16/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent16/build/advent16/advent16-tmp/Main.dyn_o ) [Data.Bitstream changed]\n", + "\n", + "\u001b[;1madvent16/Main.hs:58:38: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wtype-defaults\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " • Defaulting the following constraints to type ‘Integer’\n", + " (Integral n0)\n", + " arising from a use of ‘BS.take’ at advent16/Main.hs:58:38-44\n", + " (Num n0) arising from the literal ‘1’ at advent16/Main.hs:58:46\n", + " • In the second argument of ‘($)’, namely ‘BS.take 1 bs’\n", + " In the second argument of ‘($)’, namely ‘BS.unpack $ BS.take 1 bs’\n", + " In the expression: head $ BS.unpack $ BS.take 1 bs\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m58 |\u001b[0m\u001b[0m let value = head $ BS.unpack $ \u001b[;1m\u001b[35mBS.take\u001b[0m\u001b[0m 1 bs\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent16/Main.hs:59:13: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wtype-defaults\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " • Defaulting the following constraints to type ‘Integer’\n", + " (Integral n0)\n", + " arising from a use of ‘BS.drop’ at advent16/Main.hs:59:13-19\n", + " (Num n0) arising from the literal ‘1’ at advent16/Main.hs:59:21\n", + " • In the second argument of ‘($)’, namely ‘BS.drop 1 bs’\n", + " In a stmt of a 'do' block: _ <- put $ BS.drop 1 bs\n", + " In the expression:\n", + " do bs <- get\n", + " let value = head $ BS.unpack $ BS.take 1 bs\n", + " put $ BS.drop 1 bs\n", + " return value\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m59 |\u001b[0m\u001b[0m put $ \u001b[;1m\u001b[35mBS.drop\u001b[0m\u001b[0m 1 bs\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent16/Main.hs:123:29: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In a case alternative:\n", + " Patterns of type ‘Integer’ not matched:\n", + " p where p is not one of {7, 6, 5, ...}\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m123 |\u001b[0m\u001b[0m mkOperator pType contents = \u001b[;1m\u001b[35mcase pType of\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^...\u001b[0m\u001b[0m\n", + "[1 of 1] Compiling Main ( advent16/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent16/build/advent16/advent16-tmp/Main.p_o )\n", + "\n", + "\u001b[;1madvent16/Main.hs:58:38: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wtype-defaults\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " • Defaulting the following constraints to type ‘Integer’\n", + " (Integral n0)\n", + " arising from a use of ‘BS.take’ at advent16/Main.hs:58:38-44\n", + " (Num n0) arising from the literal ‘1’ at advent16/Main.hs:58:46\n", + " • In the second argument of ‘($)’, namely ‘BS.take 1 bs’\n", + " In the second argument of ‘($)’, namely ‘BS.unpack $ BS.take 1 bs’\n", + " In the expression: head $ BS.unpack $ BS.take 1 bs\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m58 |\u001b[0m\u001b[0m let value = head $ BS.unpack $ \u001b[;1m\u001b[35mBS.take\u001b[0m\u001b[0m 1 bs\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent16/Main.hs:59:13: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wtype-defaults\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " • Defaulting the following constraints to type ‘Integer’\n", + " (Integral n0)\n", + " arising from a use of ‘BS.drop’ at advent16/Main.hs:59:13-19\n", + " (Num n0) arising from the literal ‘1’ at advent16/Main.hs:59:21\n", + " • In the second argument of ‘($)’, namely ‘BS.drop 1 bs’\n", + " In a stmt of a 'do' block: _ <- put $ BS.drop 1 bs\n", + " In the expression:\n", + " do bs <- get\n", + " let value = head $ BS.unpack $ BS.take 1 bs\n", + " put $ BS.drop 1 bs\n", + " return value\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m59 |\u001b[0m\u001b[0m put $ \u001b[;1m\u001b[35mBS.drop\u001b[0m\u001b[0m 1 bs\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent16/Main.hs:123:29: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In a case alternative:\n", + " Patterns of type ‘Integer’ not matched:\n", + " p where p is not one of {7, 6, 5, ...}\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m123 |\u001b[0m\u001b[0m mkOperator pType contents = \u001b[;1m\u001b[35mcase pType of\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^...\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent16/build/advent16/advent16 ...\n", + "852\n", + "19348959966392\n", + " 13,136,984 bytes allocated in the heap\n", + " 719,248 bytes copied during GC\n", + " 995,112 bytes maximum residency (2 sample(s))\n", + " 217,304 bytes maximum slop\n", + " 63 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 2 colls, 2 par 0.001s 0.001s 0.0003s 0.0003s\n", + " Gen 1 2 colls, 1 par 0.003s 0.001s 0.0005s 0.0006s\n", + "\n", + " Parallel GC work balance: 40.78% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.003s elapsed)\n", + " MUT time 0.012s ( 0.011s elapsed)\n", + " GC time 0.004s ( 0.002s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.023s ( 0.016s elapsed)\n", + "\n", + " Alloc rate 1,086,681,415 bytes per MUT second\n", + "\n", + " Productivity 52.3% of total user, 68.8% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent17) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent17' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent17' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent17' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent17/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent17/build/advent17/advent17-tmp/Main.dyn_o ) [Linear changed]\n", + "\n", + "\u001b[;1madvent17/Main.hs:8:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-imports\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " The import of ‘_x, _y’ from module ‘Linear’ is redundant\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m8 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mimport Linear (V2(..), (^+^), _x, _y)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent17/Main.hs:63:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " targetP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (V2 Int, V2 Int)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m63 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mtargetP\u001b[0m\u001b[0m = boundify <$> (\"target area: x=\" *> regionP) <*> (\", y=\" *> regionP)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent17/Main.hs:66:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " regionP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (Int, Int)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m66 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mregionP\u001b[0m\u001b[0m = (,) <$> (signed decimal <* \"..\") <*> signed decimal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent17/Main.hs:69:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text -> (V2 Int, V2 Int)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m69 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent17/build/advent17/advent17 ...\n", + "5995\n", + "3202\n", + " 142,847,576 bytes allocated in the heap\n", + " 15,235,936 bytes copied during GC\n", + " 264,784 bytes maximum residency (5 sample(s))\n", + " 133,288 bytes maximum slop\n", + " 63 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 30 colls, 30 par 0.014s 0.007s 0.0002s 0.0020s\n", + " Gen 1 5 colls, 4 par 0.005s 0.001s 0.0002s 0.0003s\n", + "\n", + " Parallel GC work balance: 4.59% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.052s ( 0.045s elapsed)\n", + " GC time 0.019s ( 0.009s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.000s ( 0.000s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.077s ( 0.057s elapsed)\n", + "\n", + " Alloc rate 2,728,607,274 bytes per MUT second\n", + "\n", + " Productivity 68.0% of total user, 78.6% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent18) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent18' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent18' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent18' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent18/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent18/build/advent18/advent18-tmp/Main.dyn_o ) [Data.Attoparsec.Text changed]\n", + "\n", + "\u001b[;1madvent18/Main.hs:33:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: part1 :: [Tree] -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m33 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart1\u001b[0m\u001b[0m numbers = magnitude total\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:36:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " part2 :: (Foldable t, Monad t) => t Tree -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m36 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart2\u001b[0m\u001b[0m numbers = maximum [ magnitude $ snailAdd a b \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:45:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In an equation for ‘left’:\n", + " Patterns of type ‘(Tree, Cxt)’ not matched:\n", + " ((Leaf _), Top)\n", + " ((Leaf _), (L _ _))\n", + " ((Leaf _), (R _ _))\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m45 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mleft (Pair l r, c) = (l, L c r)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:48:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In an equation for ‘right’:\n", + " Patterns of type ‘(Tree, Cxt)’ not matched:\n", + " ((Leaf _), Top)\n", + " ((Leaf _), (L _ _))\n", + " ((Leaf _), (R _ _))\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m48 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mright (Pair l r, c) = (r, R l c)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:59:11: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-matches\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘t’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m59 |\u001b[0m\u001b[0m upmost l@(\u001b[;1m\u001b[35mt\u001b[0m\u001b[0m, Top) = l\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:74:5: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-uni-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In a pattern binding:\n", + " Patterns of type ‘Loc’ not matched:\n", + " ((Leaf _), Top)\n", + " ((Leaf _), (L _ _))\n", + " ((Leaf _), (R _ _))\n", + " ((Pair (Pair _ _) (Pair _ _)), Top)\n", + " ...\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m74 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35m((Pair (Leaf nl) (Leaf nr)), _) = p0\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:77:39: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-uni-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In a lambda abstraction:\n", + " Patterns of type ‘Tree’ not matched: Pair _ _\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m77 |\u001b[0m\u001b[0m Just leftReg -> modify leftReg (\u001b[;1m\u001b[35m\\(Leaf n) -> Leaf (n + nl)\u001b[0m\u001b[0m)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:80:41: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-uni-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In a lambda abstraction:\n", + " Patterns of type ‘Tree’ not matched: Pair _ _\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m80 |\u001b[0m\u001b[0m Just rightReg -> modify rightReg (\u001b[;1m\u001b[35m\\(Leaf n) -> Leaf (n + nr)\u001b[0m\u001b[0m)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:97:25: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-matches\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘c’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m97 |\u001b[0m\u001b[0m rightmostOnLeft t@(_, L \u001b[;1m\u001b[35mc\u001b[0m\u001b[0m r) = rightmostOnLeft $ up t\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:97:27: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-matches\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘r’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m97 |\u001b[0m\u001b[0m rightmostOnLeft t@(_, L c \u001b[;1m\u001b[35mr\u001b[0m\u001b[0m) = rightmostOnLeft $ up t\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:98:25: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-matches\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘l’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m98 |\u001b[0m\u001b[0m rightmostOnLeft t@(_, R \u001b[;1m\u001b[35ml\u001b[0m\u001b[0m c) = Just $ rightmostNum $ left $ up t\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:98:27: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-matches\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘c’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m98 |\u001b[0m\u001b[0m rightmostOnLeft t@(_, R l \u001b[;1m\u001b[35mc\u001b[0m\u001b[0m) = Just $ rightmostNum $ left $ up t\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:106:25: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-matches\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘l’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m106 |\u001b[0m\u001b[0m leftmostOnRight t@(_, R \u001b[;1m\u001b[35ml\u001b[0m\u001b[0m c) = leftmostOnRight $ up t\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:106:27: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-matches\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘c’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m106 |\u001b[0m\u001b[0m leftmostOnRight t@(_, R l \u001b[;1m\u001b[35mc\u001b[0m\u001b[0m) = leftmostOnRight $ up t\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:107:25: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-matches\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘c’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m107 |\u001b[0m\u001b[0m leftmostOnRight t@(_, L \u001b[;1m\u001b[35mc\u001b[0m\u001b[0m r) = Just $ leftmostNum $ right $ up t\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:107:27: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-matches\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘r’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m107 |\u001b[0m\u001b[0m leftmostOnRight t@(_, L c \u001b[;1m\u001b[35mr\u001b[0m\u001b[0m) = Just $ leftmostNum $ right $ up t\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:121:5: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-uni-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In a pattern binding:\n", + " Patterns of type ‘Loc’ not matched:\n", + " ((Pair _ _), Top)\n", + " ((Pair _ _), (L _ _))\n", + " ((Pair _ _), (R _ _))\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m121 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35m((Leaf sn), _) = n0\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:147:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " sfNumbersP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [Tree]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m147 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msfNumbersP\u001b[0m\u001b[0m = sfNumberP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:149:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " sfNumberP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Tree\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m149 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msfNumberP\u001b[0m\u001b[0m = regularP <|> pairP\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:151:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " regularP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Tree\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m151 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mregularP\u001b[0m\u001b[0m = Leaf <$> decimal\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:152:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " pairP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Tree\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m152 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpairP\u001b[0m\u001b[0m = Pair <$> (\"[\" *> sfNumberP) <*> (\",\" *> sfNumberP) <* \"]\"\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent18/Main.hs:155:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text -> [Tree]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m155 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent18/build/advent18/advent18 ...\n", + "2501\n", + "4935\n", + " 985,731,848 bytes allocated in the heap\n", + " 4,292,096 bytes copied during GC\n", + " 362,792 bytes maximum residency (6 sample(s))\n", + " 136,920 bytes maximum slop\n", + " 62 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 231 colls, 231 par 0.062s 0.018s 0.0001s 0.0022s\n", + " Gen 1 6 colls, 5 par 0.008s 0.002s 0.0004s 0.0006s\n", + "\n", + " Parallel GC work balance: 27.31% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 0.521s ( 0.471s elapsed)\n", + " GC time 0.069s ( 0.019s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.001s ( 0.001s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 0.597s ( 0.494s elapsed)\n", + "\n", + " Alloc rate 1,892,803,172 bytes per MUT second\n", + "\n", + " Productivity 87.4% of total user, 95.5% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent19) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent19' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent19' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent19' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent19/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent19/build/advent19/advent19-tmp/Main.dyn_o ) [Data.MultiSet changed]\n", + "\n", + "\u001b[;1madvent19/Main.hs:40:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Worphans\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Orphan instance: instance Show Transform\n", + " To avoid this\n", + " move the instance declaration to the module of the class or of the type, or\n", + " wrap the type with a newtype and declare the instance on the new type.\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m40 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35minstance Show Transform where\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:44:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: nullTrans :: Endo a\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m44 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mnullTrans\u001b[0m\u001b[0m = Endo id\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:45:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: rotX :: Endo (V3 Int)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m45 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mrotX\u001b[0m\u001b[0m = Endo \\(V3 x y z) -> V3 x (- z) y\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:46:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: rotY :: Endo (V3 Int)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m46 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mrotY\u001b[0m\u001b[0m = Endo \\(V3 x y z) -> V3 z y (- x)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:47:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: rotZ :: Endo (V3 Int)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m47 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mrotZ\u001b[0m\u001b[0m = Endo \\(V3 x y z) -> V3 (- y) x z\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:48:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " translate :: (Linear.Vector.Additive f, Num a) => f a -> Endo (f a)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m48 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mtranslate\u001b[0m\u001b[0m v = Endo (v ^+^)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:79:30: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wtype-defaults\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " • Defaulting the following constraints to type ‘Integer’\n", + " (Integral b0) arising from a use of ‘^’ at advent19/Main.hs:79:30\n", + " (Num b0) arising from the literal ‘2’ at advent19/Main.hs:79:31\n", + " • In the first argument of ‘(+)’, namely ‘x ^ 2’\n", + " In the first argument of ‘(+)’, namely ‘x ^ 2 + y ^ 2’\n", + " In the expression: x ^ 2 + y ^ 2 + z ^ 2\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m79 |\u001b[0m\u001b[0m where pythag (V3 x y z) = x\u001b[;1m\u001b[35m^\u001b[0m\u001b[0m2 + y^2 + z^2\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:79:36: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wtype-defaults\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " • Defaulting the following constraints to type ‘Integer’\n", + " (Integral b0) arising from a use of ‘^’ at advent19/Main.hs:79:36\n", + " (Num b0) arising from the literal ‘2’ at advent19/Main.hs:79:37\n", + " • In the second argument of ‘(+)’, namely ‘y ^ 2’\n", + " In the first argument of ‘(+)’, namely ‘x ^ 2 + y ^ 2’\n", + " In the expression: x ^ 2 + y ^ 2 + z ^ 2\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m79 |\u001b[0m\u001b[0m where pythag (V3 x y z) = x^2 + y\u001b[;1m\u001b[35m^\u001b[0m\u001b[0m2 + z^2\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:79:42: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wtype-defaults\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " • Defaulting the following constraints to type ‘Integer’\n", + " (Integral b0) arising from a use of ‘^’ at advent19/Main.hs:79:42\n", + " (Num b0) arising from the literal ‘2’ at advent19/Main.hs:79:43\n", + " • In the second argument of ‘(+)’, namely ‘z ^ 2’\n", + " In the expression: x ^ 2 + y ^ 2 + z ^ 2\n", + " In an equation for ‘pythag’:\n", + " pythag (V3 x y z) = x ^ 2 + y ^ 2 + z ^ 2\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m79 |\u001b[0m\u001b[0m where pythag (V3 x y z) = x^2 + y^2 + z\u001b[;1m\u001b[35m^\u001b[0m\u001b[0m2\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:103:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In an equation for ‘mkReconstruction’:\n", + " Patterns of type ‘[Scanner]’ not matched: []\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m103 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mmkReconstruction (s:ss) = Reconstruction {found = [], working = [s], waiting = ss}\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:117:9: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-uni-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In a pattern binding: Patterns of type ‘[Scanner]’ not matched: []\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m117 |\u001b[0m\u001b[0m where \u001b[;1m\u001b[35m(current:workers) = working\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:132:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " scannersP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [Scanner]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m132 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mscannersP\u001b[0m\u001b[0m = scannerP `sepBy` blankLines\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:133:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " scannerP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Scanner\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m133 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mscannerP\u001b[0m\u001b[0m = scannerify <$> nameP <*> beaconsP\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:142:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " nameP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m142 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mnameP\u001b[0m\u001b[0m = (\"--- scanner \" *>) decimal <* \" ---\" <* endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:144:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " beaconsP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [V3 Int]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m144 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mbeaconsP\u001b[0m\u001b[0m = beaconP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:145:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " beaconP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (V3 Int)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m145 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mbeaconP\u001b[0m\u001b[0m = V3 <$> (signed decimal <* \",\") <*> (signed decimal <* \",\") <*> (signed decimal)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:147:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " blankLines :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [()]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m147 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mblankLines\u001b[0m\u001b[0m = many1 endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent19/Main.hs:150:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text -> [Scanner]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m150 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent19/build/advent19/advent19 ...\n", + "355\n", + "10842\n", + " 4,266,547,304 bytes allocated in the heap\n", + " 79,835,392 bytes copied during GC\n", + " 1,228,664 bytes maximum residency (61 sample(s))\n", + " 175,576 bytes maximum slop\n", + " 63 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 967 colls, 967 par 0.296s 0.075s 0.0001s 0.0015s\n", + " Gen 1 61 colls, 60 par 0.177s 0.055s 0.0009s 0.0012s\n", + "\n", + " Parallel GC work balance: 66.48% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 6.359s ( 6.048s elapsed)\n", + " GC time 0.443s ( 0.100s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.030s ( 0.029s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 6.838s ( 6.181s elapsed)\n", + "\n", + " Alloc rate 670,893,811 bytes per MUT second\n", + "\n", + " Productivity 93.4% of total user, 98.3% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent20) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent20' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent20' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent20' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent20/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent20/build/advent20/advent20-tmp/Main.dyn_o ) [Linear changed]\n", + "\n", + "\u001b[;1madvent20/Main.hs:36:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " part1 :: Enhancement -> Image -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m36 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart1\u001b[0m\u001b[0m enhancement image = fst $ evalRWS (enhanceImage 2) enhancement image\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent20/Main.hs:38:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " part2 :: Enhancement -> Image -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m38 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart2\u001b[0m\u001b[0m enhancement image = fst $ evalRWS (enhanceImage 50) enhancement image\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent20/Main.hs:60:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘showImage’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m60 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mshowImage\u001b[0m\u001b[0m image = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent20/build/advent20/advent20 ...\n", + "5225\n", + "18131\n", + " 4,967,912,192 bytes allocated in the heap\n", + " 6,829,295,704 bytes copied during GC\n", + " 196,918,408 bytes maximum residency (55 sample(s))\n", + " 2,929,528 bytes maximum slop\n", + " 486 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 1148 colls, 1148 par 2.151s 1.658s 0.0014s 0.0090s\n", + " Gen 1 55 colls, 54 par 9.083s 3.698s 0.0672s 0.1647s\n", + "\n", + " Parallel GC work balance: 44.36% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 5.140s ( 4.701s elapsed)\n", + " GC time 9.075s ( 3.216s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 2.159s ( 2.141s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 16.380s ( 10.061s elapsed)\n", + "\n", + " Alloc rate 966,567,938 bytes per MUT second\n", + "\n", + " Productivity 44.6% of total user, 68.0% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent21) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent21' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent21' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent21' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent21/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent21/build/advent21/advent21-tmp/Main.dyn_o ) [Data.MultiSet changed]\n", + "\n", + "\u001b[;1madvent21/Main.hs:45:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: part1 :: Game -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m45 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart1\u001b[0m\u001b[0m game = scoreGame finalGame\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent21/Main.hs:49:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: part2 :: Game -> MS.Occur\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m49 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart2\u001b[0m\u001b[0m game = max (Player1 `MS.occur` winners) (Player2 `MS.occur` winners)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent21/Main.hs:116:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " playerP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Player\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m116 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mplayerP\u001b[0m\u001b[0m = (\"1\" *> pure Player1) <|> (\"2\" *> pure Player2)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent21/Main.hs:118:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " playerStateP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (Player, PlayerState)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m118 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mplayerStateP\u001b[0m\u001b[0m = playerify <$> (\"Player \" *> playerP) <*> (\" starting position: \" *> decimal)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent21/Main.hs:121:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " gameP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Game\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m121 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mgameP\u001b[0m\u001b[0m = gamify <$> playerStateP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent21/Main.hs:126:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text -> Game\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m126 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "[1 of 1] Compiling Main ( advent21/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent21/build/advent21/advent21-tmp/Main.p_o )\n", + "\n", + "\u001b[;1madvent21/Main.hs:45:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: part1 :: Game -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m45 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart1\u001b[0m\u001b[0m game = scoreGame finalGame\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent21/Main.hs:49:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: part2 :: Game -> MS.Occur\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m49 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart2\u001b[0m\u001b[0m game = max (Player1 `MS.occur` winners) (Player2 `MS.occur` winners)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent21/Main.hs:116:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " playerP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Player\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m116 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mplayerP\u001b[0m\u001b[0m = (\"1\" *> pure Player1) <|> (\"2\" *> pure Player2)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent21/Main.hs:118:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " playerStateP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (Player, PlayerState)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m118 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mplayerStateP\u001b[0m\u001b[0m = playerify <$> (\"Player \" *> playerP) <*> (\" starting position: \" *> decimal)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent21/Main.hs:121:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " gameP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Game\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m121 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mgameP\u001b[0m\u001b[0m = gamify <$> playerStateP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent21/Main.hs:126:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text -> Game\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m126 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent21/build/advent21/advent21 ...\n", + "734820\n", + "193170338541590\n", + " 3,812,461,008 bytes allocated in the heap\n", + " 292,492,272 bytes copied during GC\n", + " 6,362,032 bytes maximum residency (38 sample(s))\n", + " 197,344 bytes maximum slop\n", + " 70 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 882 colls, 882 par 0.491s 0.277s 0.0003s 0.0021s\n", + " Gen 1 38 colls, 37 par 0.589s 0.125s 0.0033s 0.0176s\n", + "\n", + " Parallel GC work balance: 29.68% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 2.493s ( 2.275s elapsed)\n", + " GC time 1.041s ( 0.364s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.038s ( 0.038s elapsed)\n", + " EXIT time 0.003s ( 0.001s elapsed)\n", + " Total time 3.579s ( 2.681s elapsed)\n", + "\n", + " Alloc rate 1,529,157,497 bytes per MUT second\n", + "\n", + " Productivity 70.7% of total user, 86.3% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent22) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent22' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent22' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent22' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent22/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent22/build/advent22/advent22-tmp/Main.dyn_o ) [Control.Lens changed]\n", + "\n", + "\u001b[;1madvent22/Main.hs:33:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: part1 :: [Cuboid] -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m33 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart1\u001b[0m\u001b[0m cuboids = sweepX (filter isLocal cuboids)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent22/Main.hs:34:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature: part2 :: [Cuboid] -> Int\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m34 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpart2\u001b[0m\u001b[0m cuboids = sweepX cuboids\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent22/Main.hs:87:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " cuboidsP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text [Cuboid]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m87 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mcuboidsP\u001b[0m\u001b[0m = timeify <$> cuboidP `sepBy` endOfLine\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent22/Main.hs:90:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " cuboidP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Cuboid\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m90 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mcuboidP\u001b[0m\u001b[0m = cubify <$> (partiyP <* \" \") <*> (boundsP `sepBy` \",\")\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent22/Main.hs:98:9: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In an equation for ‘vecify’:\n", + " Patterns of type ‘[a]’ not matched:\n", + " []\n", + " [_]\n", + " [_, _]\n", + " (_:_:_:_:_)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m98 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mvecify [c1, c2, c3] = V3 c1 c2 c3\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent22/Main.hs:100:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " partiyP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text Parity\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m100 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpartiyP\u001b[0m\u001b[0m = (\"on\" *> pure On) <|> (\"off\" *> pure Off)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent22/Main.hs:102:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " boundsP :: Data.Attoparsec.Internal.Types.Parser\n", + " Data.Text.Internal.Text (Int, Int)\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m102 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mboundsP\u001b[0m\u001b[0m = (,) <$> ((\"x\" <|> \"y\" <|> \"z\") *> \"=\" *> signed decimal) <*> (\"..\" *> signed decimal)\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent22/Main.hs:105:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Top-level binding with no type signature:\n", + " successfulParse :: Data.Text.Internal.Text -> [Cuboid]\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m105 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35msuccessfulParse\u001b[0m\u001b[0m input = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent22/build/advent22/advent22 ...\n", + "545118\n", + "1227298136842375\n", + " 2,191,299,168 bytes allocated in the heap\n", + " 15,263,592 bytes copied during GC\n", + " 600,320 bytes maximum residency (16 sample(s))\n", + " 136,960 bytes maximum slop\n", + " 63 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 513 colls, 513 par 0.172s 0.051s 0.0001s 0.0044s\n", + " Gen 1 16 colls, 15 par 0.025s 0.010s 0.0006s 0.0012s\n", + "\n", + " Parallel GC work balance: 22.36% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 1.635s ( 1.511s elapsed)\n", + " GC time 0.194s ( 0.058s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.003s ( 0.003s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 1.838s ( 1.575s elapsed)\n", + "\n", + " Alloc rate 1,340,478,006 bytes per MUT second\n", + "\n", + " Productivity 89.1% of total user, 96.1% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent23) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent23' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent23' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent23' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent23/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent23/build/advent23/advent23-tmp/Main.dyn_o ) [Linear changed]\n", + "\n", + "\u001b[;1madvent23/Main.hs:18:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: data constructor ‘Empty’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m18 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern Empty <- (Q.viewl -> Q.EmptyL) where Empty = Q.empty\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent23/Main.hs:18:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern synonym with no type signature:\n", + " pattern Main.Empty :: forall {a}. Q.Seq a\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m18 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern Empty <- (Q.viewl -> Q.EmptyL) where Empty = Q.empty\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent23/Main.hs:19:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: data constructor ‘:<’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m19 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern x :< xs <- (Q.viewl -> x Q.:< xs) where (:<) = (Q.<|)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent23/Main.hs:19:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern synonym with no type signature:\n", + " pattern (:<) :: forall {a}. a -> Q.Seq a -> Q.Seq a\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m19 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern x :< xs <- (Q.viewl -> x Q.:< xs) where (:<) = (Q.<|)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent23/Main.hs:20:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: data constructor ‘:>’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m20 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern xs :> x <- (Q.viewr -> xs Q.:> x) where (:>) = (Q.|>)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent23/Main.hs:20:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wmissing-signatures\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern synonym with no type signature:\n", + " pattern (:>) :: forall {a}. Q.Seq a -> a -> Q.Seq a\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m20 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mpattern xs :> x <- (Q.viewr -> xs Q.:> x) where (:>) = (Q.|>)\u001b[0m\u001b[0m \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent23/Main.hs:253:9: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘hallRow’ shadows the existing binding\n", + " defined at advent23/Main.hs:52:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m253 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mhallRow\u001b[0m\u001b[0m = S.findMin $ S.map (^. _r) halls\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent23/Main.hs:269:9: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘transits’ shadows the existing binding\n", + " defined at advent23/Main.hs:43:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m269 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mtransits\u001b[0m\u001b[0m = S.delete here $ S.fromList $ [V2 hr c | c <- [cMin..cMax]] ++ [V2 r tc | r <- [hr..tr]]\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent23/Main.hs:284:11: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘transits’ shadows the existing binding\n", + " defined at advent23/Main.hs:43:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m284 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mtransits\u001b[0m\u001b[0m = S.delete here $ S.fromList $ [V2 r hc | r <- [tr..hr]] ++ [V2 tr c | c <- [cMin..cMax]]\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent23/Main.hs:288:17: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘hallRow’ shadows the existing binding\n", + " defined at advent23/Main.hs:52:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m288 |\u001b[0m\u001b[0m mkRoomRoomRoute \u001b[;1m\u001b[35mhallRow\u001b[0m\u001b[0m rooms here routes = M.foldrWithKey' (mkRoomRoomRoute1 hallRow here) routes rooms\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent23/Main.hs:292:18: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘hallRow’ shadows the existing binding\n", + " defined at advent23/Main.hs:52:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m292 |\u001b[0m\u001b[0m mkRoomRoomRoute1 \u001b[;1m\u001b[35mhallRow\u001b[0m\u001b[0m here@(V2 hr hc) there@(V2 tr tc) entry routes \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent23/Main.hs:305:9: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wname-shadowing\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " This binding for ‘transits’ shadows the existing binding\n", + " defined at advent23/Main.hs:43:1\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m305 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mtransits\u001b[0m\u001b[0m = S.delete here $ S.unions [transitUp, transitAcross, transitDown]\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent23/build/advent23/advent23 ...\n", + "14460\n", + "41366\n", + " 57,573,004,072 bytes allocated in the heap\n", + " 12,620,236,792 bytes copied during GC\n", + " 46,724,816 bytes maximum residency (395 sample(s))\n", + " 538,976 bytes maximum slop\n", + " 144 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 13463 colls, 13463 par 4.934s 1.756s 0.0001s 0.0292s\n", + " Gen 1 395 colls, 394 par 25.652s 6.850s 0.0173s 0.0706s\n", + "\n", + " Parallel GC work balance: 70.59% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 44.219s ( 40.856s elapsed)\n", + " GC time 26.684s ( 4.728s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 3.902s ( 3.877s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 74.811s ( 49.464s elapsed)\n", + "\n", + " Alloc rate 1,302,001,880 bytes per MUT second\n", + "\n", + " Productivity 64.3% of total user, 90.4% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent24) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent24' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent24' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent24' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent24/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent24/build/advent24/advent24-tmp/Main.dyn_o ) [Data.Attoparsec.Text changed]\n", + "\n", + "\u001b[;1madvent24/Main.hs:70:9: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-uni-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In a pattern binding:\n", + " Patterns of type ‘Maybe Interval’ not matched: Nothing\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m70 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mJust (Interval a b) = z\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent24/Main.hs:174:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In an equation for ‘*:’:\n", + " Patterns of type ‘Interval’, ‘Interval’ not matched:\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IS _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IS _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IS _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IP _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IS _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IN _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IS _))\n", + " (Interval (GHC.Num.Integer.IP _) (GHC.Num.Integer.IS _))\n", + " ...\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m174 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35m(Interval a b) *: (Interval c d) \u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...\u001b[0m\u001b[0m\n", + "[1 of 1] Compiling Main ( advent24/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent24/build/advent24/advent24-tmp/Main.p_o )\n", + "\n", + "\u001b[;1madvent24/Main.hs:70:9: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-uni-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In a pattern binding:\n", + " Patterns of type ‘Maybe Interval’ not matched: Nothing\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m70 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mJust (Interval a b) = z\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\u001b[0m\n", + "\n", + "\u001b[;1madvent24/Main.hs:174:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wincomplete-patterns\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Pattern match(es) are non-exhaustive\n", + " In an equation for ‘*:’:\n", + " Patterns of type ‘Interval’, ‘Interval’ not matched:\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IS _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IS _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IS _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IP _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IS _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IN _))\n", + " (Interval (GHC.Num.Integer.IS _) (GHC.Num.Integer.IS _))\n", + " (Interval (GHC.Num.Integer.IP _) (GHC.Num.Integer.IS _))\n", + " ...\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m174 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35m(Interval a b) *: (Interval c d) \u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent24/build/advent24/advent24 ...\n", + "91398299697996\n", + "41171183141291\n", + " 98,300,706,304 bytes allocated in the heap\n", + " 344,957,792 bytes copied during GC\n", + " 280,672 bytes maximum residency (924 sample(s))\n", + " 163,968 bytes maximum slop\n", + " 62 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 22855 colls, 22855 par 6.658s 1.697s 0.0001s 0.0043s\n", + " Gen 1 924 colls, 923 par 1.111s 0.361s 0.0004s 0.0015s\n", + "\n", + " Parallel GC work balance: 40.37% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.002s elapsed)\n", + " MUT time 101.104s ( 94.732s elapsed)\n", + " GC time 7.619s ( 1.910s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.150s ( 0.149s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 108.879s ( 96.794s elapsed)\n", + "\n", + " Alloc rate 972,276,847 bytes per MUT second\n", + "\n", + " Productivity 93.0% of total user, 98.0% of total elapsed\n", + "\n", + "Build profile: -w ghc-9.2.2 -O1\n", + "In order, the following will be built (use -v for more details):\n", + " - advent-of-code21-0.1.0.0 (exe:advent25) --enable-profiling (configuration changed)\n", + "Configuring executable 'advent25' for advent-of-code21-0.1.0.0..\n", + "Preprocessing executable 'advent25' for advent-of-code21-0.1.0.0..\n", + "Building executable 'advent25' for advent-of-code21-0.1.0.0..\n", + "[1 of 1] Compiling Main ( advent25/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent25/build/advent25/advent25-tmp/Main.dyn_o ) [Linear changed]\n", + "\n", + "\u001b[;1madvent25/Main.hs:94:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘showGrid’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m94 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mshowGrid\u001b[0m\u001b[0m (Grid (V2 minR minC, V2 maxR maxC) cucumbers) = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "[1 of 1] Compiling Main ( advent25/Main.hs, /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent25/build/advent25/advent25-tmp/Main.p_o )\n", + "\n", + "\u001b[;1madvent25/Main.hs:94:1: \u001b[;1m\u001b[35mwarning:\u001b[0m\u001b[0m\u001b[;1m [\u001b[;1m\u001b[35m-Wunused-top-binds\u001b[0m\u001b[0m\u001b[;1m]\u001b[0m\u001b[0m\u001b[;1m\n", + " Defined but not used: ‘showGrid’\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\n", + "\u001b[;1m\u001b[34m94 |\u001b[0m\u001b[0m \u001b[;1m\u001b[35mshowGrid\u001b[0m\u001b[0m (Grid (V2 minR minC, V2 maxR maxC) cucumbers) = \n", + "\u001b[;1m\u001b[34m |\u001b[0m\u001b[0m\u001b[;1m\u001b[35m ^^^^^^^^\u001b[0m\u001b[0m\n", + "Linking /home/neil/Programming/advent-of-code-21/dist-newstyle/build/x86_64-linux/ghc-9.2.2/advent-of-code21-0.1.0.0/x/advent25/build/advent25/advent25 ...\n", + "435\n", + " 2,884,443,392 bytes allocated in the heap\n", + " 771,632,904 bytes copied during GC\n", + " 1,740,216 bytes maximum residency (204 sample(s))\n", + " 181,984 bytes maximum slop\n", + " 63 MiB total memory in use (0 MB lost due to fragmentation)\n", + "\n", + " Tot time (elapsed) Avg pause Max pause\n", + " Gen 0 500 colls, 500 par 0.585s 0.361s 0.0007s 0.0022s\n", + " Gen 1 204 colls, 203 par 0.705s 0.144s 0.0007s 0.0043s\n", + "\n", + " Parallel GC work balance: 30.44% (serial 0%, perfect 100%)\n", + "\n", + " TASKS: 26 (1 bound, 25 peak workers (25 total), using -N12)\n", + "\n", + " SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)\n", + "\n", + " INIT time 0.004s ( 0.003s elapsed)\n", + " MUT time 7.067s ( 6.800s elapsed)\n", + " GC time 1.257s ( 0.473s elapsed)\n", + " RP time 0.000s ( 0.000s elapsed)\n", + " PROF time 0.032s ( 0.032s elapsed)\n", + " EXIT time 0.002s ( 0.001s elapsed)\n", + " Total time 8.363s ( 7.309s elapsed)\n", + "\n", + " Alloc rate 408,156,917 bytes per MUT second\n", + "\n", + " Productivity 84.9% of total user, 93.5% of total elapsed\n", + "\n" + ] + } + ], + "source": [ + "! cd .. && for i in {01..25}; do cabal run advent${i} --enable-profiling -- +RTS -N -pj -s -hT ; done" + ] + }, + { + "cell_type": "code", + "execution_count": 316, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "rm: cannot remove '../times_raw.csv': No such file or directory\n" + ] + } + ], + "source": [ + "! rm ../times.csv\n", + "! rm ../times_raw.csv" + ] + }, + { + "cell_type": "code", + "execution_count": 317, + "metadata": { + "Collapsed": "false", + "scrolled": true, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Warning: The package list for 'hackage.haskell.org' is 24 days old.\n", + "Run 'cabal update' to get the latest list of available packages.\n", + "Resolving dependencies...\n", + "Up to date\n", + "1521\n", + "1543\n", + "Up to date\n", + "2039912\n", + "1942068080\n", + "Up to date\n", + "2724524\n", + "2775870\n", + "Up to date\n", + "82440\n", + "20774\n", + "Up to date\n", + "5092\n", + "20484\n", + "Up to date\n", + "352195\n", + "1600306001288\n", + "Up to date\n", + "336721\n", + "91638945\n", + "Up to date\n", + "255\n", + "982158\n", + "Up to date\n", + "15\n", + "1134\n", + "Up to date\n", + "339537\n", + "2412013412\n", + "Up to date\n", + "1627\n", + "329\n", + "Up to date\n", + "4495\n", + "131254\n", + "Up to date\n", + "763\n", + "███ █ █ ██ █ ███ ██ ███ ██ \n", + "█ █ █ █ █ █ █ █ █ █ █ █ █ █ █\n", + "█ █ ████ █ █ █ █ █ █ █ █ █ █\n", + "███ █ █ ████ █ ███ █ ███ ████\n", + "█ █ █ █ █ █ █ █ █ █ █ █ █ █ █\n", + "█ █ █ █ █ █ ████ █ █ ██ █ █ █ █\n", + "\n", + "Up to date\n", + "2712\n", + "8336623059567\n", + "Up to date\n", + "503\n", + "2853\n", + "Up to date\n", + "852\n", + "19348959966392\n", + "Up to date\n", + "5995\n", + "3202\n", + "Up to date\n", + "2501\n", + "4935\n", + "Up to date\n", + "355\n", + "10842\n", + "Up to date\n", + "5225\n", + "18131\n", + "Up to date\n", + "734820\n", + "193170338541590\n", + "Up to date\n", + "545118\n", + "1227298136842375\n", + "Up to date\n", + "14460\n", + "41366\n", + "Up to date\n", + "91398299697996\n", + "41171183141291\n", + "Up to date\n", + "435\n" + ] + } + ], + "source": [ + "! cd .. && for i in {01..25}; do /usr/bin/time -f \"%C,%S,%E,%M\" -o times.csv -a cabal run advent${i}; done" + ] + }, + { + "cell_type": "code", + "execution_count": 318, + "metadata": { + "Collapsed": "false", + "scrolled": true, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1521\n", + "1543\n", + "2039912\n", + "1942068080\n", + "2724524\n", + "2775870\n", + "82440\n", + "20774\n", + "5092\n", + "20484\n", + "352195\n", + "1600306001288\n", + "336721\n", + "91638945\n", + "255\n", + "982158\n", + "15\n", + "1134\n", + "339537\n", + "2412013412\n", + "1627\n", + "329\n", + "4495\n", + "131254\n", + "763\n", + "███ █ █ ██ █ ███ ██ ███ ██ \n", + "█ █ █ █ █ █ █ █ █ █ █ █ █ █ █\n", + "█ █ ████ █ █ █ █ █ █ █ █ █ █\n", + "███ █ █ ████ █ ███ █ ███ ████\n", + "█ █ █ █ █ █ █ █ █ █ █ █ █ █ █\n", + "█ █ █ █ █ █ ████ █ █ ██ █ █ █ █\n", + "\n", + "2712\n", + "8336623059567\n", + "503\n", + "2853\n", + "852\n", + "19348959966392\n", + "5995\n", + "3202\n", + "2501\n", + "4935\n", + "355\n", + "10842\n", + "5225\n", + "18131\n", + "734820\n", + "193170338541590\n", + "545118\n", + "1227298136842375\n", + "14460\n", + "41366\n", + "91398299697996\n", + "41171183141291\n", + "435\n" + ] + } + ], + "source": [ + "! cd .. && for i in {01..25}; do /usr/bin/time -f \"%C,%S,%E,%M\" -o times_raw.csv -a advent${i}; done" + ] + }, + { + "cell_type": "code", + "execution_count": 319, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mv: cannot stat '../*prof': No such file or directory\n" + ] + } + ], + "source": [ + "!mv ../*prof ." + ] + }, + { + "cell_type": "code", + "execution_count": 320, + "metadata": {}, + "outputs": [], + "source": [ + "!mv ../times.csv ." + ] + }, + { + "cell_type": "code", + "execution_count": 321, + "metadata": {}, + "outputs": [], + "source": [ + "!mv ../times_raw.csv ." + ] + }, + { + "cell_type": "code", + "execution_count": 322, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mv: cannot stat '../*hp': No such file or directory\n" + ] + } + ], + "source": [ + "!mv ../*hp ." + ] + }, + { + "cell_type": "code", + "execution_count": 323, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/bin/bash: -c: line 1: syntax error near unexpected token `;'\n", + "/bin/bash: -c: line 1: ` for f in *hp ; do hp2ps $<_io.TextIOWrapper name='advent24.prof' mode='r' encoding='UTF-8'> ; done'\n" + ] + } + ], + "source": [ + "! for f in *hp ; do hp2ps ${f} ; done" + ] + }, + { + "cell_type": "code", + "execution_count": 324, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "25" + ] + }, + "execution_count": 324, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(glob.glob('*prof'))" + ] + }, + { + "cell_type": "code", + "execution_count": 325, + "metadata": { + "Collapsed": "false", + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'program': 'advent13',\n", + " 'total_time': 0.03,\n", + " 'total_alloc': 4493632,\n", + " 'total_ticks': 96,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent10',\n", + " 'total_time': 0.02,\n", + " 'total_alloc': 2383248,\n", + " 'total_ticks': 60,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent03',\n", + " 'total_time': 0.05,\n", + " 'total_alloc': 8298128,\n", + " 'total_ticks': 168,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent07',\n", + " 'total_time': 0.04,\n", + " 'total_alloc': 5589544,\n", + " 'total_ticks': 132,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent20',\n", + " 'total_time': 35.11,\n", + " 'total_alloc': 3090735840,\n", + " 'total_ticks': 119712,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent19',\n", + " 'total_time': 21.74,\n", + " 'total_alloc': 2623652352,\n", + " 'total_ticks': 74148,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent01',\n", + " 'total_time': 0.06,\n", + " 'total_alloc': 12058592,\n", + " 'total_ticks': 192,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent18',\n", + " 'total_time': 1.73,\n", + " 'total_alloc': 588717288,\n", + " 'total_ticks': 5916,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent06',\n", + " 'total_time': 0.02,\n", + " 'total_alloc': 2507624,\n", + " 'total_ticks': 72,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent09',\n", + " 'total_time': 0.01,\n", + " 'total_alloc': 469984,\n", + " 'total_ticks': 36,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent08',\n", + " 'total_time': 6.57,\n", + " 'total_alloc': 2499222744,\n", + " 'total_ticks': 22404,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent23',\n", + " 'total_time': 172.99,\n", + " 'total_alloc': 38150694448,\n", + " 'total_ticks': 589896,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent21',\n", + " 'total_time': 9.43,\n", + " 'total_alloc': 2400838008,\n", + " 'total_ticks': 32160,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent22',\n", + " 'total_time': 5.54,\n", + " 'total_alloc': 1384180736,\n", + " 'total_ticks': 18876,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent16',\n", + " 'total_time': 0.05,\n", + " 'total_alloc': 8613496,\n", + " 'total_ticks': 180,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent25',\n", + " 'total_time': 25.72,\n", + " 'total_alloc': 1910248008,\n", + " 'total_ticks': 87696,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent11',\n", + " 'total_time': 0.12,\n", + " 'total_alloc': 39102056,\n", + " 'total_ticks': 396,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent02',\n", + " 'total_time': 0.02,\n", + " 'total_alloc': 1818928,\n", + " 'total_ticks': 72,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent15',\n", + " 'total_time': 13.51,\n", + " 'total_alloc': 2458599000,\n", + " 'total_ticks': 46080,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent17',\n", + " 'total_time': 0.2,\n", + " 'total_alloc': 88071992,\n", + " 'total_ticks': 672,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent05',\n", + " 'total_time': 2.26,\n", + " 'total_alloc': 434487576,\n", + " 'total_ticks': 7692,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent12',\n", + " 'total_time': 6.69,\n", + " 'total_alloc': 722598152,\n", + " 'total_ticks': 22800,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent04',\n", + " 'total_time': 0.19,\n", + " 'total_alloc': 54628920,\n", + " 'total_ticks': 636,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent14',\n", + " 'total_time': 0.05,\n", + " 'total_alloc': 15471000,\n", + " 'total_ticks': 180,\n", + " 'initial_capabilities': 12},\n", + " {'program': 'advent24',\n", + " 'total_time': 340.53,\n", + " 'total_alloc': 66538931736,\n", + " 'total_ticks': 1161240,\n", + " 'initial_capabilities': 12}]" + ] + }, + "execution_count": 325, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "profs = []\n", + "for fn in glob.glob('*prof'):\n", + " with open(fn) as f:\n", + " j = json.load(f)\n", + " prof = {}\n", + " for n in 'program total_time total_alloc total_ticks initial_capabilities'.split():\n", + " prof[n] = j[n]\n", + " profs.append(prof)\n", + "profs" + ] + }, + { + "cell_type": "code", + "execution_count": 326, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    \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", + " \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", + " \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", + " \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", + "
    total_timetotal_alloctotal_ticksinitial_capabilities
    program
    advent010.061205859219212
    advent020.0218189287212
    advent030.05829812816812
    advent040.195462892063612
    advent052.26434487576769212
    advent060.0225076247212
    advent070.04558954413212
    advent086.5724992227442240412
    advent090.014699843612
    advent100.0223832486012
    advent110.123910205639612
    advent126.697225981522280012
    advent130.0344936329612
    advent140.051547100018012
    advent1513.5124585990004608012
    advent160.05861349618012
    advent170.208807199267212
    advent181.73588717288591612
    advent1921.7426236523527414812
    advent2035.11309073584011971212
    advent219.4324008380083216012
    advent225.5413841807361887612
    advent23172.993815069444858989612
    advent24340.5366538931736116124012
    advent2525.7219102480088769612
    \n", + "
    " + ], + "text/plain": [ + " total_time total_alloc total_ticks initial_capabilities\n", + "program \n", + "advent01 0.06 12058592 192 12\n", + "advent02 0.02 1818928 72 12\n", + "advent03 0.05 8298128 168 12\n", + "advent04 0.19 54628920 636 12\n", + "advent05 2.26 434487576 7692 12\n", + "advent06 0.02 2507624 72 12\n", + "advent07 0.04 5589544 132 12\n", + "advent08 6.57 2499222744 22404 12\n", + "advent09 0.01 469984 36 12\n", + "advent10 0.02 2383248 60 12\n", + "advent11 0.12 39102056 396 12\n", + "advent12 6.69 722598152 22800 12\n", + "advent13 0.03 4493632 96 12\n", + "advent14 0.05 15471000 180 12\n", + "advent15 13.51 2458599000 46080 12\n", + "advent16 0.05 8613496 180 12\n", + "advent17 0.20 88071992 672 12\n", + "advent18 1.73 588717288 5916 12\n", + "advent19 21.74 2623652352 74148 12\n", + "advent20 35.11 3090735840 119712 12\n", + "advent21 9.43 2400838008 32160 12\n", + "advent22 5.54 1384180736 18876 12\n", + "advent23 172.99 38150694448 589896 12\n", + "advent24 340.53 66538931736 1161240 12\n", + "advent25 25.72 1910248008 87696 12" + ] + }, + "execution_count": 326, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "performance = pd.DataFrame(profs).set_index('program').sort_index()\n", + "performance" + ] + }, + { + "cell_type": "code", + "execution_count": 327, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 327, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "performance.total_ticks.plot.bar()" + ] + }, + { + "cell_type": "code", + "execution_count": 328, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 328, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "performance.total_ticks.plot.bar(logy=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 329, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 329, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "performance.total_alloc.plot.bar()" + ] + }, + { + "cell_type": "code", + "execution_count": 330, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 330, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "performance.total_alloc.plot.bar(logy=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 331, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "image/png": "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MrOm55177rlsu+223Hvvvbz++uuMHDly0GoaPXo0O+ywA3fcccf6huD4449n77335sYbb+Sggw7iW9/6FgcccMCg1SBJray7weorRnYZJH7m6sFafH8POxw0NY0h6MsVl6icU3ks8BqVEyi0pC233JIXXngBgH333Zf58+fT2dnJU089xaJFi5g2bdobngOwevVqtt9+ezbbbDO+853v1LzJvmtOtfe///1ccMEFAHR2dvL8888DlV0NP/jBD7jsssvWD2x85JFH2GmnnfjUpz7F4Ycfzm9+85t+v35J0qal1i0ElwDnAZetm1B1xaUPUPniXxwR1wO7AHdl5v8fEdcA/1mPQns7TLDexowZw/ve9z4mTZrEIYccwuTJk5kyZQoRwdlnn812223HmDFjGDZsGFOmTOGEE07glFNO4ZhjjuHqq69m//33p729vaZl7b///sydO5epU6fyuc997g2Pfe1rX2PWrFlcdNFFtLW1ccEFF7D99tsD0N7ezg033MAHPvAB2tvbeeCBB/jud7/L5ptvznbbbcfpp59e9/dFkjQ0Ra2bwyNiR+CGzJxU3H8PcGZmHlTcX/dN9iiwJjOvioj5mfl3vWW3t7fnSy+99IZpy5YtY9ddd635hag1uZ4lNUszdxlExKtUfmQPiTEE3V5xCfga8I2I2AdY1NPMETELmAWVzd+SJG1CSjeGYCANQU9XXHoZOKm3mYvLPM6DyhaCAdTRMm666SZOO+20N0wbP3481113XZMqkiSpYiANwaBdcWmoOuiggzjooIOaXYYkSRsYyJkK119xKSKGU7ni0vV9CYiIGRExzxPoSJI2Mf29/PGgqfWww0G54lJmLsjMWW1tbX2tW5KkVla6axnUtMug0VdckiRJjeXFjSRJUnMbgj6NIThzdH1vvajl8sdQ+yWQV6xYwaRJk3p/nRuZ79Zbb+Wwww7rc0Z3jj32WB555JFuH/vEJz7BAw88sNH5TzjhBK655poNpnd9P+677z5OOOGEAdUqSRp8TW0IyjyGoN4NQZncf//9dHZ2stNOO23wWGdnJ9/61reYOHFiv7K7vh+77bYbHR0d/PGPf+x3vZKkwecugx7MmTOH3/3ud0ydOpVTTz2VzOTUU09l0qRJ7LbbbsyfP3/982677TamTp3Kueeey4oVK9hnn33YY4892GOPPbjzzjtrWl5f53vmmWc48sgjmTx5Mu9+97vXX7fgxRdf5MQTT2S33XZj8uTJXHvttRvM+73vfY8jjjhi/f0tttiC008/nb333pu77rqL/fbbb/1lmy+66CJ23nln9ttvP04++WRmz569fr5Fixbx3ve+l5122mn91oKu7wfAjBkzuPLKK2t6HyRpE1G6owyaevnj4o2YMWLEiGaW0a25c+eydOlSlixZAsC1117LkiVLuPfee3n66afZa6+92HfffZk7dy7nnHMON9xwAwAvv/wyN998MyNHjuThhx9m5syZ679cN2abbbbp03xnnHEGu+++Oz/4wQ+45ZZb+NjHPsaSJUs466yzGD16NPfddx8Azz777Abz3nHHHcyc+edxoi+99BKTJk3iS1/60huet3LlSs466yzuuecettxySw444ACmTJmy/vHHH3+c22+/nd/+9rccfvjhHHvssRu8HwB77rknc+fO5bOf/Wyv74Mk9UvXXcGDd5XCehlSZyocsOJwiwXt7e0nN7OOWtx+++3MnDmTtrY2tt12W6ZPn87ixYvZaqut3vC81157jdmzZ7NkyRLa2tp46KGHasrv63y33377+l//BxxwAKtWrWL16tX85Cc/ecOv8Te/+c0bzPv444/z1re+df39trY2jjnmmA2e98tf/pLp06fzlre8BYC//du/fUNdRx55JJttthkTJ07kiSee6LHWbbbZhpUrPWeVJJVZUxuCVlLrRaDOPfdctt12W+69915ef/11Ro4cOSjzdVdPRJCZRHR3Vuk/GzVqFK+88sr6+yNHjqS7cRy9vebqLTsbe+4rr7zCqFGjNpolSWouxxD0YMstt+SFF15Yf3/fffdl/vz5dHZ28tRTT7Fo0SKmTZu2wfNWr17N9ttvz2abbcZ3vvMdaj0LY1/n23ffffne974HVI4+2Hrrrdlqq6344Ac/yHnnnbf+ed3tMth1111Zvnx5rzVNmzaNn/3sZzz77LOsXbu22/EIXXV9PwAeeuihfh1hIUlqnNbZQtDg/UFjxozhfe97H5MmTeKQQw7h7LPP5q677mLKlClEBGeffTbbbbcdY8aMYdiwYUyZMoUTTjiBU045hWOOOYarr76a/fffn/b29pqW19f5zjzzTE488UQmT57Mm970Ji699FIAvvCFL/CP//iPTJo0iba2Ns444wyOPvroN8x76KGHcuut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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "performance[['total_ticks', 'total_alloc']].plot.bar(\n", + " logy=True, secondary_y=['total_alloc'], \n", + " figsize=(8, 6), title=\"Internal time and memory\")\n", + "plt.savefig('internal_time_and_memory_log.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 332, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "image/png": "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TZq0QebixYvZY489mDt3LgsWLGDq1KlMnjyZiRMn8sADD7T+hZEklVKpd6e326xZs7j77ruZP38+l19+Oeeeey533HEHTz75JG9605vYe++9mTVrFt/4xje46qqrAHjhhRe49tprGT58OA888AAzZsxg3rx53T7OsGHDOO2005g3bx5nnXUWABdccMG66Z/97GeZNm0aV1xxBWvWrOG5557j6aefBuC+++7jyCOP5Ac/+AGTJ0/mM5/5DJ/73Of40Ic+xKpVq1izZk3/vDiSpNKxiXfhpptuYsaMGXR0dLDtttsybdo05s6dy+abb77efH/72984/vjjmT9/Ph0dHdx/f59+ZQfAddddx0UXXQRAR0cHY8aM4emnn+aJJ57gkEMO4fLLL+cNb3gDAG95y1v46le/ytKlS3n/+9/P+PHj+/z4kqRqcHd6F5o5CQ7AmWeeybbbbssdd9zBvHnzWLVqVb/VNGbMGHbccUduvvnmdeOOOuoo5syZw4gRI5g+fTrXXXddvz2+JKlc3BKvM3r0aJ599lkA9t57b7773e/ysY99jKeeeoobb7yRr3/96zzyyCPr5gFYsWIFY8eOZbPNNuPCCy9send2/WM1euc738k555zD3//937NmzZp1l2wdNmwYV155JdOnT2fUqFEcddRRLF68mJ133pnPfvazLF68mDvvvJP99tuvj6+EJA1Onf3qacnwhl8bnbqiTdX0XambeE8/CWu1rbbaire97W1MmDCBgw46iIkTJzJp0iQigjPOOIPtttuOrbbaiiFDhjBp0iSOPvpojjvuOA4//HAuu+wy9t13X0aObO5sevvuuy+zZs1i8uTJfPGLX1xv2re+9S1mzpzJ97//fTo6OjjnnHPYfvvtARg5ciRXXXUV73rXuxg5ciQLFy7kRz/6EUOHDmW77bbj5JNPbvnrIkkqp6bOnd4fOjt3+j333MOuu+46IPWofVzPkgbKQG+Jl+7c6ZIkaWCUenf6YHDNNddw4oknrjdu3LhxXHHFFQNUkSRpsLCJ97Pp06czffr0gS5DkjQIuTtdkqSKsolLklRRNnFJkirKJi5JUkWVu4mfOqa1tx40cylSaP5ypEuWLGHChAlNPdWulrvhhht473vf2+uMzhxxxBEsXry402nHHnssCxcu7Hb5o48+mp/85CcbjG98Pe666y6OPvroPtUqSepZuZt4m7W6iZfJggULWLNmDTvvvPMG09asWcP3vvc9dtttt43Kbnw9dt99d5YuXcpDDz200fVKknpmE6/TeD3xzOy3a4oDvV7uqaee4tBDD2XixIm8+c1v5s477wTgueee45hjjmH33Xdn4sSJXH755Rsse/HFF3PIIYesGx41ahQnn3wye+21F7/73e/YZ5991l1C9fvf/z677LIL++yzD5/85CfXXecc4MYbb+Stb30rO++887qt8sbXA+B973sfl156aVOvgyRp4/g78Tr11xMHuPzyy5k/f36/XFMcYJtttunVcqeccgp77LEHV155Jddddx0f/ehHmT9/PqeffjpjxozhrrvuAlh37fF6N998MzNmzFg3/PzzzzNhwgROO+209eZbtmwZp59+OrfffjujR49mv/32Y9KkSeumP/roo9x0003ce++9HHzwwRxxxBEbvB4AU6ZMYdasWXzhC1/o8XWQJG0cm3g3+vua4r1d7qabblq3lb3ffvuxfPlyVqxYwa9//ev1tnq33HLLDZZ99NFHeeUrX7luuKOjg8MPP3yD+f7whz8wbdo0XvGKVwDwgQ98YL26Dj30UDbbbDN22203HnvssS5r3WabbVi2bFm3z0eS1Dc28W5szDXFX3rpJYYPH94vy3VWT0SQmUREt8uOGDGClStXrhsePnw4HR0dTT1GvZe97GVNzbty5UpGjBjRbZYkqW/8TrxO4zW+9957b2bPns2aNWt44oknuPHGG5k6deoG861YsYLtt9+ezTbbjB/+8IdNX1O8t8vtvffeXHzxxUDtqPWtt96azTffnAMOOICzzjpr3Xyd7U7fddddWbRoUY81TZ06ld/85jc8/fTTrF69utPv1xt1dm30+++/f6OOzJckNa/cW+JtvjB74/XEzzjjDH73u9/12zXFe7vcqaeeyjHHHMPEiRN5+ctfzoUXXgjAl7/8ZT796U8zYcIEOjo6OOWUU3j/+9+/3rLvec97uOGGG9h///27fYwddtiBL33pS+y111686lWvYrfddmPMmO5/njdx4sT1Xo/Pf/7zXH/99bznPe29HrwkbWq8nvgm4q9//Sv77rsvN998c6e70es999xzjBo1itWrV3PYYYfx8Y9/nMMOO6zpx3rxxReZNm0aN910E0OGbPg50fUsaaB4PXFV0ogRI/jKV77CI4880uO8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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "performance[['total_ticks', 'total_alloc']].plot.bar(\n", + " logy=False, secondary_y=['total_alloc'], \n", + " figsize=(8, 6), title=\"Internal time and memory\")\n", + "plt.savefig('internal_time_and_memory_linear.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 333, + "metadata": {}, + "outputs": [], + "source": [ + "# times = pd.read_csv('times.csv', \n", + "# names=['program', 'system', 'elapsed', 'memory'], \n", + "# index_col='program')\n", + "# times.index = times.index.str.slice(start=len('cabal run '))\n", + "# times.elapsed = pd.to_numeric(times.elapsed.str.slice(start=2))\n", + "# times" + ] + }, + { + "cell_type": "code", + "execution_count": 334, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    \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", + " \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", + " \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", + " \n", + "
    systemelapsedmemory
    program
    advent010.010.0210212
    advent020.000.017876
    advent030.000.0110760
    advent040.020.0514236
    advent050.070.4749372
    advent060.000.017948
    advent070.000.0110164
    advent080.210.9812252
    advent090.000.016644
    advent100.000.017456
    advent110.010.0411272
    advent120.111.1561132
    advent130.000.0111504
    advent140.000.0211020
    advent150.181.3953240
    advent160.010.0112128
    advent170.000.0211604
    advent180.030.1711812
    advent190.153.8812524
    advent200.342.49207144
    advent210.161.0322020
    advent220.140.7612508
    advent232.2927.1998824
    advent244.0027.9212432
    advent250.194.2113748
    \n", + "
    " + ], + "text/plain": [ + " system elapsed memory\n", + "program \n", + "advent01 0.01 0.02 10212\n", + "advent02 0.00 0.01 7876\n", + "advent03 0.00 0.01 10760\n", + "advent04 0.02 0.05 14236\n", + "advent05 0.07 0.47 49372\n", + "advent06 0.00 0.01 7948\n", + "advent07 0.00 0.01 10164\n", + "advent08 0.21 0.98 12252\n", + "advent09 0.00 0.01 6644\n", + "advent10 0.00 0.01 7456\n", + "advent11 0.01 0.04 11272\n", + "advent12 0.11 1.15 61132\n", + "advent13 0.00 0.01 11504\n", + "advent14 0.00 0.02 11020\n", + "advent15 0.18 1.39 53240\n", + "advent16 0.01 0.01 12128\n", + "advent17 0.00 0.02 11604\n", + "advent18 0.03 0.17 11812\n", + "advent19 0.15 3.88 12524\n", + "advent20 0.34 2.49 207144\n", + "advent21 0.16 1.03 22020\n", + "advent22 0.14 0.76 12508\n", + "advent23 2.29 27.19 98824\n", + "advent24 4.00 27.92 12432\n", + "advent25 0.19 4.21 13748" + ] + }, + "execution_count": 334, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "times = pd.read_csv('times_raw.csv', \n", + " names=['program', 'system', 'elapsed', 'memory'], \n", + " index_col='program')\n", + "times.elapsed = pd.to_numeric(times.elapsed.str.slice(start=2))\n", + "times" + ] + }, + { + "cell_type": "code", + "execution_count": 335, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "system float64\n", + "elapsed float64\n", + "memory int64\n", + "dtype: object" + ] + }, + "execution_count": 335, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "times.dtypes" + ] + }, + { + "cell_type": "code", + "execution_count": 336, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    \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", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    systemelapsedmemory
    count25.00000025.00000025.000000
    mean0.3168002.87480027993.280000
    std0.8909167.52024743271.608039
    min0.0000000.0100006644.000000
    25%0.0000000.01000010760.000000
    50%0.0200000.05000012128.000000
    75%0.1600001.15000014236.000000
    max4.00000027.920000207144.000000
    \n", + "
    " + ], + "text/plain": [ + " system elapsed memory\n", + "count 25.000000 25.000000 25.000000\n", + "mean 0.316800 2.874800 27993.280000\n", + "std 0.890916 7.520247 43271.608039\n", + "min 0.000000 0.010000 6644.000000\n", + "25% 0.000000 0.010000 10760.000000\n", + "50% 0.020000 0.050000 12128.000000\n", + "75% 0.160000 1.150000 14236.000000\n", + "max 4.000000 27.920000 207144.000000" + ] + }, + "execution_count": 336, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "times.describe()" + ] + }, + { + "cell_type": "code", + "execution_count": 337, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    \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", + " \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", + " \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", + " \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", + " \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", + "
    total_timetotal_alloctotal_ticksinitial_capabilitiessystemelapsedmemory
    program
    advent010.0612058592192120.010.0210212
    advent020.02181892872120.000.017876
    advent030.058298128168120.000.0110760
    advent040.1954628920636120.020.0514236
    advent052.264344875767692120.070.4749372
    advent060.02250762472120.000.017948
    advent070.045589544132120.000.0110164
    advent086.57249922274422404120.210.9812252
    advent090.0146998436120.000.016644
    advent100.02238324860120.000.017456
    advent110.1239102056396120.010.0411272
    advent126.6972259815222800120.111.1561132
    advent130.03449363296120.000.0111504
    advent140.0515471000180120.000.0211020
    advent1513.51245859900046080120.181.3953240
    advent160.058613496180120.010.0112128
    advent170.2088071992672120.000.0211604
    advent181.735887172885916120.030.1711812
    advent1921.74262365235274148120.153.8812524
    advent2035.113090735840119712120.342.49207144
    advent219.43240083800832160120.161.0322020
    advent225.54138418073618876120.140.7612508
    advent23172.9938150694448589896122.2927.1998824
    advent24340.53665389317361161240124.0027.9212432
    advent2525.72191024800887696120.194.2113748
    \n", + "
    " + ], + "text/plain": [ + " total_time total_alloc total_ticks initial_capabilities system \\\n", + "program \n", + "advent01 0.06 12058592 192 12 0.01 \n", + "advent02 0.02 1818928 72 12 0.00 \n", + "advent03 0.05 8298128 168 12 0.00 \n", + "advent04 0.19 54628920 636 12 0.02 \n", + "advent05 2.26 434487576 7692 12 0.07 \n", + "advent06 0.02 2507624 72 12 0.00 \n", + "advent07 0.04 5589544 132 12 0.00 \n", + "advent08 6.57 2499222744 22404 12 0.21 \n", + "advent09 0.01 469984 36 12 0.00 \n", + "advent10 0.02 2383248 60 12 0.00 \n", + "advent11 0.12 39102056 396 12 0.01 \n", + "advent12 6.69 722598152 22800 12 0.11 \n", + "advent13 0.03 4493632 96 12 0.00 \n", + "advent14 0.05 15471000 180 12 0.00 \n", + "advent15 13.51 2458599000 46080 12 0.18 \n", + "advent16 0.05 8613496 180 12 0.01 \n", + "advent17 0.20 88071992 672 12 0.00 \n", + "advent18 1.73 588717288 5916 12 0.03 \n", + "advent19 21.74 2623652352 74148 12 0.15 \n", + "advent20 35.11 3090735840 119712 12 0.34 \n", + "advent21 9.43 2400838008 32160 12 0.16 \n", + "advent22 5.54 1384180736 18876 12 0.14 \n", + "advent23 172.99 38150694448 589896 12 2.29 \n", + "advent24 340.53 66538931736 1161240 12 4.00 \n", + "advent25 25.72 1910248008 87696 12 0.19 \n", + "\n", + " elapsed memory \n", + "program \n", + "advent01 0.02 10212 \n", + "advent02 0.01 7876 \n", + "advent03 0.01 10760 \n", + "advent04 0.05 14236 \n", + "advent05 0.47 49372 \n", + "advent06 0.01 7948 \n", + "advent07 0.01 10164 \n", + "advent08 0.98 12252 \n", + "advent09 0.01 6644 \n", + "advent10 0.01 7456 \n", + "advent11 0.04 11272 \n", + "advent12 1.15 61132 \n", + "advent13 0.01 11504 \n", + "advent14 0.02 11020 \n", + "advent15 1.39 53240 \n", + "advent16 0.01 12128 \n", + "advent17 0.02 11604 \n", + "advent18 0.17 11812 \n", + "advent19 3.88 12524 \n", + "advent20 2.49 207144 \n", + "advent21 1.03 22020 \n", + "advent22 0.76 12508 \n", + "advent23 27.19 98824 \n", + "advent24 27.92 12432 \n", + "advent25 4.21 13748 " + ] + }, + "execution_count": 337, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "performance = performance.merge(times, left_index=True, right_index=True)\n", + "# performance.drop(index='advent15loop', inplace=True)\n", + "performance" + ] + }, + { + "cell_type": "code", + "execution_count": 338, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['total_time', 'total_alloc', 'total_ticks', 'initial_capabilities',\n", + " 'system', 'elapsed', 'memory'],\n", + " dtype='object')" + ] + }, + "execution_count": 338, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "performance.columns" + ] + }, + { + "cell_type": "code", + "execution_count": 339, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "image/png": "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VCn1XgmdnZ3piIEkabSIiKcys3PX9xw5Tj6UJEmFUv6UsDPPPfcc3d3dPPPMM80uRQM0ceJEpkyZwrhx45pdiiSpHy3XGHR3d7PHHnswdepUqud7VwvITDZu3Eh3dzfTpk1rdjmSpH603E8JzzzzDHvttZdNQYuJCPbaay9HeiSp5FquMQBsClqU202Syq8lG4Mymjp1Kr///e8b/rwzZ87k1ltvbfjzSpLaU8vNMehr6vzlw5q3fsGbhzVPkqRW4ojBIHz961/niCOO4OCDD+af/umf6Onp2e72OXPmcNhhh/GqV72KRYv+8xTtu+++Ox/+8Ic59NBDmTVrFo8++igAF198MQcccABdXV2cfPLJADz55JO8613v4vDDD+eQQw7huuuuA+Dpp5/m5JNPpquri5NOOomnn276QbIkSW2klI1BRMyOiEV9P3DLYO3atSxZsoSbbrqJ1atX09HRwTe+8Y3t7nPZZZdx2223ceutt3LxxRezceNGoPJhf+ihh3L77bdz9NFH88lPfhKABQsWcMcdd7BmzRoWLlwIwGc+8xn+9m//llWrVnHDDTdw9tln8+STT/LlL3+ZSZMmsWbNGj72sY9x2223NfYPIElqa6X8KSEzlwHLOjs7z2x2LX396Ec/4rbbbuPwww8HKt/gX/ziF293n4svvpjvfOc7AGzYsIH77ruPvfbaizFjxnDSSScBcOqpp3LiiScC0NXVxSmnnMKcOXOYM2cOAD/84Q9ZunQpF154IVDZG+PBBx9k5cqVvP/97y8e19XVNeKvWZI0epSyMSizzOQd73gHF1xwwXbrFy9eDMBPfvITrr/+em6++WYmTZrEzJkz+91Fr3eW/vLly1m5ciVLly7lU5/6FHfffTeZybe+9S1mzJjR7+MkSRpupfwpocxmzZrFtddeyyOPPALAY489xgMPPFDcvnnzZvbcc08mTZrEPffcw89//vPitm3btnHttdcCcOWVV/La176Wbdu2sWHDBl7/+tfzuc99jk2bNvHEE09w7LHH8sUvfpHec1nccccdALzuda8rfrq46667WLNmTUNet6Q2d97k7S+j2NT5y7e7jDaOGAzQAQccwKc//WmOOeYYtm3bxrhx47j00kuL24877jgWLlxIV1cXM2bM4Mgjjyxu6+zs5O677+awww5j8uTJLFmyhJ6eHk499VQ2b95M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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# performance[['total_ticks', 'elapsed']].plot.bar(logy=True)\n", + "performance[['elapsed', 'memory']].plot.bar(\n", + " logy=True, secondary_y=['memory'], \n", + " figsize=(8, 6), title=\"External time and memory\")\n", + "plt.savefig('external_time_and_memory_log.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 340, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "image/png": "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LNhQKIwePZoHH3xwU//MZmZbotaI2C+3zGy7g6S+ZAXDryLiN6n5+XTKgfTzhdTeAuya6z4cWJ7ah1dp36iPpCZgMLCqg1jtctEAjBw5kve///1stdVW7L333kycOBFJvP/972fp0qVAdmvrGTNmMGbMmA13unz22WcB+OhHP8q2227LjjvuyODBgznssMMANvRfs2YNL730EgcddBAA06ZN46677trw/JXbawN84Qtf4Be/+AUAv/jFLzjuuOPelu+KFSvYcccdN2rLx6h46aWXWLt2Lf/4j/8IwKc//emNtk+cOJHBgwfTv39/9tprr41u1JXXp08f+vXrx9q1a9v/I5qZWZeluQWXAosj4vzcprlA5WqGacANufYp6YqIkWQTHh9IpzLWShqfYh7bpk8l1pHA7Wnew++BgyUNSRMgD05t7SrfnIY62HrrrTesb7XVVhseb7XVVhsmALZ3a+v777+/UP+ODBz4968lP+CAA1i6dCl33nkn69ev3+h0QsWAAQPednvufIyKzu4rks+7T58+Heb6xhtv0L9//w7jmZlZlx0AfBZYJGlBajsdmAFcI+l44FngKICIeEzSNcDjZFdenBgR61O/E4DZwADg5rRAVpRcIWkJ2QjDlBRrlaSzgcpQ8ncjYlVHyXqkoaD2bm1dxODBgxkyZAj//d//DcAVV1yxYdShmmOPPZapU6dWHWUA2HPPPVmyZEmnzztkyBC23XbbDbfzvvrqqwvl27dv343mUaxcuZIdd9zxbadJzMxs00TE3RGhiGiOiDFpuSkiVkbExIgYlX6uyvU5JyLeExF7RMTNufb5ETE6bTspjSYQEesi4qiI2D0ixkXEX3J9ZqX23SPiF53l66KhoDPOOIM333yT5uZmRo8ezRlnnNGl/pdddhmnnnoqzc3NLFiwgG9/+9vt7nvMMcewevVqpk6dWnX7xz/+8Y1Ob3Tk0ksvZfr06ey///5EBIMHd351yvTp02lubt4wEfKOO+7g0EMPLfR8ZmbWe/nW2CV07bXXcsMNN3DFFVe0u88RRxzBD37wA0aNGtVhrFdeeYVBgwYBMGPGDFasWMFPfvKTLuXziU98gu9///tvOzUDPn5mpdULbo3dU7e09q2xe47nNJTMV77yFW6++WZuuummDverFACdFQ033ngj3//+92ltbWW33XZj9uzZXcrnb3/7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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# performance[['total_ticks', 'elapsed']].plot.bar(logy=True)\n", + "performance[['elapsed', 'memory']].plot.bar(\n", + " logy=False, secondary_y=['memory'], \n", + " figsize=(8, 6), title=\"External time and memory\")\n", + "plt.savefig('external_time_and_memory_linear.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 341, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "image/png": "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HgNJklSqxBiDvrz00kt0dXWxYsWKgV+sShgzZgzjxo1j3XXXbXUpkqQ1VNnGoKuri4022oitttqK2sXfVGWZyZNPPklXVxdbb711q8uRJK2hyh5KWLFiBZtuuqlNQZuICDbddFP38EhSm6tsYwDYFLQZPy9Jan+VbgwkSVJzVXaMQW9bTbuyoXmLpx+82uefeeYZLrzwQo4//vj+MxYv5je/+Q1HH3306re1eDEf/OAHueeee/p8fsGCBSxdupQPfOADAMyePZt7772XadOmrVGeJElryj0G/XjmmWf4wQ9+sNrXLF68mAsvvHDI21qwYAFz584tH3/oQx/qtymQJGk42Rj0Y9q0afz3f/83EydO5KSTTuKkk05ixx13ZKeddmLWrFnla2644QYmTpzIt7/9bRYvXsx73/tedt11V3bddVd+85vfDLidF198kVNOOYVZs2YxceJEZs2axcyZMznhhBMAePTRRzn88MPZeeed2XnnnV+V+eCDD7LLLrswf/58Fi5cyKRJk5g4cSITJkzggQceaPwbI0lqhMrOfNg2hxKabfr06dxzzz0sWLCAyy67jHPOOYc777yTJ554gt133533ve99TJ8+nW9961tcccUVADz//PNcffXVjBkzhgceeIApU6Zw6623rnY7o0eP5h//8R+59dZbOeusswCYOXNm+fyJJ57I5MmT+fnPf053dzfLly/n6aefBuD+++/nqKOO4kc/+hETJ07kc5/7HJ///Of5+Mc/zosvvkh3d/fwvDmSpKHqzsyprS6iLzYGdbjxxhuZMmUKHR0dvOENb2Dy5MnMnz+fjTfe+BWve+mllzjhhBNYsGABHR0d/OEPfxjytq+99lrOP/98ADo6Ohg7dixPP/00jz/+OIceeiiXXXYZO+ywAwDvete7OP300+nq6uKII45g2223HfL2JUlrl4Y3BhGxDnAasDFwa2b+R6O30Wz1Xk/i29/+Nm94wxu48847efnllxkzZsyw1TR27Fi23HJLbrrpprIxOProo9ljjz248sorOeCAA/jhD3/I+9///mGrQZLaWV+D2heP6TWY/NRlTaqmOuoaYxAR50XEYxFxT6/lB0bE/RGxKCJWjZY7FNgCeAnoamy5zbPRRhvx7LPPAvC+972PWbNm0d3dzeOPP868efOYNGnSK14DsGzZMt74xjeyzjrr8OMf/7juXfm9c3raZ599OPvsswHo7u7mz3/+M1A7BHH55Zdz/vnnlwMgH3zwQbbZZhtOPPFEPvShD3HXXXet8c8vSW3l1LGvvGmN1bvHYCZwFnD+qgUR0QF8H9iPWgMwPyJmA9sBN2fmv0XEpcCvGlHoQKcXNtqmm27Ke97zHnbccUcOOuggJkyYwM4770xEcMYZZ7D55puz6aabMmrUKHbeeWeOOeYYjj/+eI488kguueQS9t57bzo767tw1t5778306dOZOHEiX/7yl1/x3He/+12mTp3KueeeS0dHB2effTZvfOMbAejs7OSKK65gv/32o7Ozk3vvvZcLLriAddddl80335xTTjml4e+LJGlkq/uyyxGxFXBFZu5YPH4XcGpmHlA8XvUbbQnwYmb+NCJmZebHBsru67LL9913H9tvv33dP4iqwc9NUkv03ktQxyGAVh5KGKmXXd6CWhOwSlex7GfAARHxPWBefytHxNSIuDUibl25cuUQypAkSY0ylMGHfU2Mn5n5PHDsQCtn5gxgBtT2GAyhjrZx1VVX8aUvfekVy7beemt+/vOft6giSZJeaSiNQRewZY/H44ClQytnZDvggAM44IADWl2GJEn9GsqhhPnAthGxdUSMBo4CZg8mICIOiYgZTsQjSVI11Hu64kXAzcB2EdEVEcdm5krgBOAq4D7gp5m5cDAbz8w5mTm1o6NjsHVLkqRhUNehhMyc0s/yucDcvp6TJEntx4sorYGtttqKJ554ounb3Wuvvfq99sKHP/xhHnzwwT6f+/SnP82999672uxjjjmGSy+99FXLe19B8u677+aYY46pv2hJUltp6bUSiqtKHbLeeusN/OJGz2Q1gqa5XLhwId3d3WyzzTaveq67u5sf/vCHa5y9qjE4+ujaub077bQTXV1dPPTQQ7z5zW9e41xJUjW1dI9B1ccYXHDBBeVljP/u7/6uzymODzvsMHbbbTd22GEHZsyYUS7fcMMN+eIXv8iuu+7KPvvsw+OPPw7AmWeeyfjx45kwYQJHHXUUAM899xyf+tSn2H333dlll134xS9+AcALL7zAUUcdxYQJE/jYxz7GCy+80GedP/nJTzj00ENfse1TTjmFPfbYg5tvvvkVexrOPfdc3va2t7HXXntx3HHHlZd3Bpg3bx7vfve72Wabbcq9B70vLQ1wyCGHcPHFF6/x+ypJqu5llz2U0I/77ruPWbNmcdNNN5VXS/zJT37yqtedd9553Hbbbdx6662ceeaZPPnkk0Dtl/2uu+7K7bffzuTJk/n6178O1C7nfMcdd3DXXXdxzjnnAHD66afz/ve/n/nz53Pddddx0kkn8dxzz3H22WezwQYbcNddd/HVr36V2267rc9ab7rpJnbbbbfy8XPPPceOO+7Ib3/7W/bcc89y+dKlSznttNO45ZZbuPrqq/n973//ipxHHnmEG2+8kSuuuIJp06aV9b73ve9lwYIFfOELXwDgHe94BzfccMOavrWSpOKyy5k5p9WF9NY+hxKa7Fe/+hW33XYbu+++O1D7632zzTZ71evOPPPMcoKiJUuW8MADD7Dpppuyzjrr8LGP1WaD/sQnPsERRxwBwIQJE/j4xz/OYYcdxmGHHQbAL3/5S2bPns23vvUtAFasWMFDDz3EvHnzOPHEE8v1JkyY0GetjzzyCK9//evLxx0dHRx55JGvet3vfvc7Jk+ezGtf+1oAPvKRj7zi0tCHHXYY66yzDuPHj+fRRx/t973ZbLPNWLrUKSskaSRqaWNQdEpzOjs7j2tlHX3JTP72b/+Wb37zm/2+5vrrr+eaa67h5ptvZoMNNmCvvfZixYoVfb42ojZR5JVXXsm8efOYPXs2p512GgsXLiQzueyyy9huu+36XW911l9//Vdsd8yYMfR1eGag62L0bNBW99oVK1aw/vrrD1iXJKn9eCihH/vssw+XXnopjz32GABPPfUUf/rTn17xmmXLlvGa17yGDTbYgN///vfccsst5XMvv/xyeZz+wgsvZM899+Tll19myZIl7L333pxxxhk888wzLF++nAMOOIDvfe975S/jO+64A6hd7nnV4Yt77rmn38sob7/99ixatGjAn2nSpEn8+te/5umnn2blypVcdtllA67T1yWh//CHP7DjjjsOuK4kqf3YGPRj/PjxfOMb32D//fdnwoQJ7LfffjzyyCOveM2BBx7IypUrmTBhAieffDLvfOc7y+c6OztZuHAhu+22G9deey2nnHIK3d3dfOITn2CnnXZil1124Qtf+AKbbLIJJ598Mi+99BITJkxgxx135OSTTwbgs5/9LMuXL2fChAmcccYZTJo0qc9aDz74YK6//voBf6YtttiCr3zlK+yxxx7su+++jB8/nrFjV3+2x4QJE8pLS68afHjddddx8MHNvQy2JKk56r7s8nAaiZdd3nDDDVm+fHlTtvXCCy+w9957c9NNN/V5CKGn5cuXs+GGG7Jy5UoOP/xwPvWpT3H44YfXva2//OUvTJ48mRtvvJFRo159JKrdPzdJbcrLLjeMgw9HgPXXX5+vf/3rPPzwwwPOLXDqqadyzTXXsGLFCvbff/9yAGS9HnroIaZPn95nUyBJzdD3L/QWFDJCOfhwmDRrb8Eq9V61cdWZD2tq2223Zdtttx1ShiSpuhxjIEmSSpVuDKow/kH18/OSpPZX2cZgzJgxPPnkk/6yaROZyZNPPsmYMR7ok6R2VtnBh+PGjaOrq6u8xoCqb8yYMYwbN67VZUiShqCygw/XXXddtt566xZUJUnS2quyhxIkSVLz2RhIkqSSjYEkSSrZGEiSpFJlz0qQJEnN19I9Bpk5JzOnDnThH0mS1BweSpAkSSUbA0mSVLIxkCSpzUXENhFxbkRcOtQsGwNJkiooIs6LiMci4p5eyw+MiPsjYlFETAPIzAcz89hGbNfGQJKkapoJHNhzQUR0AN8HDgLGA1MiYnwjN2pjIElSBWXmPOCpXosnAYuKPQQvAhcDhzZyuzYGkiQ136iIuLXHbWqd620BLOnxuAvYIiI2jYhzgF0i4stDKmwoKw+VExxJktZSKzPzHWuwXvSxLDPzSeAzQ6wJcIIjSZLaSRewZY/H44CljdyAhxIkSWof84FtI2LriBgNHAXMbuQGbAwkSWq+joiYURxS71NEXATcDGwXEV0RcWxmrgROAK4C7gN+mpkLG1lYS8cYSJK0lurOzNUOOMzMKf0snwvMHZaqcI+BJEnqwcZAkiSVbAwkSVLJxkCSpOYbcPBhqzj4UJKk5htw8GGruMdAkiSVnBJZkiSVnBJZkiSVPJQgSVLzOfhQkiSVHHwoSZKqz8ZAkiSVbAwkSVLJxkCSpOZz8KEkSSo5+FCSJFWfjYEkSSrZGEiSpJKNgSRJKtkYSJKkko2BJEnN5+mKkqTm22rala94vHj6wS2qRL2sPacrRsReEXFDRJwTEXs1Ol+SJA2fuhqDiDgvIh6LiHt6LT8wIu6PiEURMa1YnMByYAzQ1dhyJUnScKp3j8FM4MCeCyKiA/g+cBAwHpgSEeOBGzLzIOBLwNcbV6okSRpudTUGmTkPeKrX4knAosx8MDNfBC4GDs3Ml4vnnwbWa1ilkiRp2A1l8OEWwJIej7uAPSLiCOAAYBPgrP5WjoipwFSA0aNHD6EMSZLUKENpDKKPZZmZPwN+NtDKmTkDmAHQ2dmZQ6hDkqRqOXVsr8fLWlPHGhjKWQldwJY9Ho8Dlg6tHEmS1EpDaQzmA9tGxNYRMRo4Cpg9mICIOCQiZnR3dw+hDEmS2k57T3AUERcBewGvi4gu4GuZeW5EnABcBXQA52XmwsFsPDPnAHM6OzuPG1zZkrSW6b1rGtpq9/RI1nsSKYDFYwZcrbITHNXVGGTmlH6WzwXmNrQiSZLUMi2dErnYhXLIeut5VqMkSVXQ0osoZeaczJza0dHRyjIkSVLBqytKkqSSV1eUpAp61VURBx7MJjWEYwwkSVLJMQaSJKnkGANJklSyMZAkqfnae+ZDSZLUUO098+FwcfChJEnV4uBDSZJUcoyBJEkq2RhIkqSSjYEkSSo5+FCS1ianju1j2bLm16HKcvChJEkqOY+BpJbofZEggMXTD25BJZJ6coyBJEkq2RhIkqSSjYEkSSp5VoIkSSp5VoIkSSp5KEGSpObzssuSJKlU2csuu8dAkiSVbAwkSVLJQwmSpAH1nqnSWSpHLvcYSJKkkvMYSJKkkvMYSJKkkocSJElSycZAkiSVbAwkSVLJxkCSJJVsDCRJUsnGQJIklZz5UGoDa82sc6eO7fV4WWvqkNZiNgaqjLXml58kVZiHEiRJUsnGQJIklbxWgiRJKnmtBEmSVHLwoSSpKXoPMAYHGVeRjYHUjnqf1gee2iepIWwMJElqcxHRCfwAeBG4PjN/sqZZnpUgSVIFRcR5EfFYRNzTa/mBEXF/RCyKiGnF4iOASzPzOOBDQ9mujYEkSdU0Eziw54KI6AC+DxwEjAemRMR4YBywpHhZ91A26qEESdLgOc5l2GXmvIjYqtfiScCizHwQICIuBg4Fuqg1BwsY4h/97jGQJKn5RkXErT1uU+tcbwv+d88A1BqCLYCfAUdGxNnAnCEVNpSVpWHlBXUkjVwrM/Mda7Be9LEsM/M54JNDrAlwj4EkSe2kC9iyx+NxwNJGbsDGQJKk9jEf2DYito6I0cBRwOxGbsDGQJKk5uuIiBnFNYP6FBEXATcD20VEV0Qcm5krgROAq4D7gJ9m5sJGFuYYA0mSmq87M1c74DAzp/SzfC4wd1iqwj0GkiSpBxsDSZJUGpbGICI6I+K2iPjgcORLkqThUVdjMMj5mgG+BPy0kYVKkjSCDDj4sFXqHXw4EzgLOH/Vgh7zNe9H7bzK+RExG3gTcC8wpqGVSpI0cgw4+LBV6moMBjlf84ZAJ7WLO7wQEXMz8+XGlSxJGjGc4bRyhnK6Yl/zNe+RmScARMQxwBP9NQXFvNBTAUaPHj2EMiRJUqMMpTHoc77m8k7mzNWtnJkzgBkAnZ2dubrXSpKk5hjKWQnDPl+zJEkjVNsPPuxLOV8z8DC1+ZqPHkxA8YYcst566w2hDEmS2k5lBx/We7risMzXnJlzMnNqR0fHYOuWJEnDoN6zEloyX7MkSWqull5EyUMJkiRVS0sbg8ycA8zp7Ow8rpV1tJutpl35iseLpx/cokokSWuoIyJmAHOK34WV4WWXJUlqvvYefChJktYOjjGQJEmllu4x8HRFSZKqxUMJkiSpZGMgSZJKLW0MIuKQiJjR3d3dyjIkSWq2EXmthCFzHgNJI03veUbAuUbUJ09XlCRJ1ecERyPBqWP7WLas+XVIktqeewwkSVLJxkCSJJWc+VCSJJWc+VCSJJU8lCBJkko2BpIkNZ8THEmSpJITHEmSpOrzrARJklTyrARJklTyUIIkSSrZGEiSpJKNgSRJKtkYSJKkko2BJEkq2RhIktR8znzYF+cxkCStpZz5sC/OYyBJUrV4KEGSJJVsDCRJUsnGQJIklWwMJElSycZAkiSVbAwkSVLJxkCSJJVsDCRJUsnGQJIklWwMJElSyWslSJKkktdKkCRJJQ8lSJKkko2BJEnN1xERM4pD6pXS0jEGkiStpbozc2qri+iLewwkSVLJxkCSJJVsDCRJUsnGQJIklRx8KEnD7dSxvR4va00dUh3cYyBJkko2BpIkqWRjIEmSSjYGkiSpZGMgSZJKDW8MImL7iDgnIi6NiM82Ol+SJA2fuhqDiDgvIh6LiHt6LT8wIu6PiEURMQ0gM+/LzM8AHwXe0fiSJUnScKl3j8FM4MCeCyKiA/g+cBAwHpgSEeOL5z4E3Aj8qmGVSpKkYVdXY5CZ84Cnei2eBCzKzAcz80XgYuDQ4vWzM/PdwMcbWawkSRpeQ5n5cAtgSY/HXcAeEbEXcASwHjB3CPmSJKnJhtIYRB/LMjOvB64fcOWIqcBUgNGjRw+hDEmS1ChDOSuhC9iyx+NxwNJ6V87MGZn5jsx8x6hRXrJBkqQqGEpjMB/YNiK2jojRwFHA7MaUJUmSWqHe0xUvAm4GtouIrog4NjNXAicAVwH3AT/NzIWD2XhEHBIRM7q7uwdbtyRJGgZ17cPPzCn9LJ/LEAYYZuYcYE5nZ+dxa5ohSZL6FhHbAF8Fxmbmh+tZxymRJUmqoMFMLtifYkqBYwez3ZaO+ouIQ4BD1ltvvVaWIUlSFc0EzgLOX7Wgx+SC+1E7CWB+RMwGOoBv9lr/U5n52GA32tLGwEMJkiT1LTPnRcRWvRaXkwsCRMTFwKGZ+U3gg43YrocSJElqvlERcWuP29Q61+trcsEt+ntxRGwaEecAu0TEl+sqrM5CJElS46zMzDW50GCfkwv29+LMfBL4zGA24BgDSZLax5AmF6yHYwwkCdhq2pWvWrZ4+sEtqERarXJyQeBhapMLHt3IDXgooYn8h0eSVOiIiBnAnOKP5FcpJhfcC3hdRHQBX8vMcyNi1eSCHcB5g51ccCA2BpIkNV93Zq52wOFwTS44EMcYSJKkUktPV8zMOZk5taOjo5VlSJKkgvMYSJKkko2BJEnN1xERM4pD6pXi4ENJkppvwMGHreLgQ0mSVHLwoSRJKjnGQJIklWwMJElqPgcfSpKkUmUHH7rHQJIklWwMJElSydMVpWHkFTUltRtPV5QkSSUPJUiS1HyelSBJkkqelSBJkqrPxkCSJJVsDCRJUsnGQJIklZzHoNVOHdvr8bLW1CFJaqaOiJgBzMnMOa0upifnMZAkqfm6M3Nq1ZoC8FCCJEnqwcZAkiSVbAwkSVLJxkCSJJVsDCRJUsnGQJIklWwMJElSyasrSs3mpFaSKjzBkY2BJEnNV9nLLjslsiRJKjklsiRJKlX2UMJW0658xePF0w9uUSWSJK09PCtBkiSVKrvHQFJ1VWmPXu9awD2M0lDYGNTBf3gkSWsLDyVIkqSSjYEkSSrZGEiS1HwdETGjmM+nUhxjIElS81V25kP3GEiSpJKNgSRJKnkoQUNWpXPaJUlD4x4DSZJUsjGQJEklGwNJklQalsYgIg6LiH+PiF9ExP7DsQ1JktR4dTcGEXFeRDwWEff0Wn5gRNwfEYsiYhpAZl6emccBxwAfa2jFkiRp2Axmj8FM4MCeCyKiA/g+cBAwHpgSEeN7vOQfiuclSVIbqLsxyMx5wFO9Fk8CFmXmg5n5InAxcGjU/DPwn5l5e+PKlSRJw2mo8xhsASzp8bgL2AP4HLAvMDYi3pqZ5/ReMSKmAlMBRo8ePcQyJElSIwy1MYg+lmVmngmcuboVM3MGMAOgs7Mzh1iHpDo4GZWkgQz1rIQuYMsej8cBS4eYKUmSWmSojcF8YNuI2DoiRgNHAbPrXTkiDomIGd3d3UMsQ5IkNULdhxIi4iJgL+B1EdEFfC0zz42IE4CrgA7gvMxcWG9mZs4B5nR2dh434ItPHdvr8bJ6NyNpuPX+/xNGxv+j/ruj4dMRETOAOcXvwsqouzHIzCn9LJ8LzG1YRZIkjXzdmTm11UX0xSmRJUlSqaWXXY6IQ4BD1ltvvVaWIUmSCi3dY5CZczJzakdHRyvLkCRJBQ8lSJKk0og+lNB7MhdwQpeenOxGktSbhxIkSVLJQwmSJKlkYyBJkko2BpIkqTSiBx9Ka8qBq5LWVg4+lCRJJQ8lSJKkko2BJEkq2RhIkqSSgw8lSVLJwYeSJKnkoQRJklSyMZAkSSUbA0mSVLIxkCRphIqIwyLi3yPiFxGxfz3rtLQxiIhDImJGd3d3K8uQJKlyIuK8iHgsIu7ptfzAiLg/IhZFxLTVZWTm5Zl5HHAM8LF6tutZCZIkVdNM4MCeCyKiA/g+cBAwHpgSEeMjYqeIuKLXbbMeq/5Dsd6AWjqPgSRJ6ltmzouIrXotngQsyswHASLiYuDQzPwm8MHeGRERwHTgPzPz9nq2u/Y1BqeO7fV4WWtzqqT3zwRr9nM1KmcN9HlVxDFHN6YWP/P2MRI/K400oyLi1h6PZ2TmjDrW2wJY0uNxF7DHal7/OWBfYGxEvDUzzxmwsDqKkCRJjbUyM9+xButFH8uyvxdn5pnAmYPZgGclSJLUPrqALXs8HgcsbeQGbAwkSWof84FtI2LriBgNHAXMbuQGbAwkSWq+joiYUVxMsE8RcRFwM7BdRHRFxLGZuRI4AbgKuA/4aWYubGRhjjGQJKn5ujNz6upekJlT+lk+F5g7LFXhZZclSVIPTnAkSZJKjjGQJEklGwNJkppvwMGHreLgQ0mSmm/AwYet4h4DSZJUsjGQJEklGwNJklSyMZAkqfkqO/gwMvu9KFPzioh4GXhhgJeNAlY2YHMjMadKtZjTnJwq1WJOc3KqVIs5Q89ZPzMr+cd5JRqDekTErWt4icoRn1OlWsxpTk6VajGnOTlVqsWc5uW0QiW7FUmS1Bo2BpIkqdROjcEMc4Y1w5z2yqlSLeY0J6dKtZjTvJyma5sxBpIkafi10x4DSZI0zGwMJElSycZAkiSVbAwkSVKp7RqDiDhlEK89ICKOjYitei3/1CAyIiI+GhEfKe7vExFnRsTxETGk9y8irl2DdV7X6/EninqmRkQMIufwiHhtcf/1EXF+RNwdEbMiYtwgcv41It5T/0/Qb85rI+KUiPh08T5/NSKuiIj/GxGvGUTO3hFxVkT8IiIui4jpEfHWNajngIg4OyJmF1lnR8SBg81ZTX7d3+Me9fhdfnXGiPweF1l+l/tef8R9j6um7c5KiIiHMvPNdbzun4A9gduBQ4DvZOb3iuduz8xd69zeD4DNgNHAn4H1gDnAB4BHM/Pzdebc1XsR8DbgfoDMnFBnTll7RPwD8F7gQuCDQFdmfqHOnHszc3xxfxZwC3AJsC/w8czcr86cx4E/Aa8HZgEXZeYd9azbK2cucDewMbB9cf+nwH7Azpl5aB0Z04E3AL8CDgP+CPwBOB74p8y8pM5avkPtszkf6CoWjwP+Bnig3s98gG3U9T0uXut3uf+MEfc9LnL8LvefMeK+x5WTmZW7Ufuw+7o9C6ysM+NuYFRxfxNgLvDt4vEdg6jl7uK/6wJPAqOLx6NWPVdnzmzgAuDtwFuArYAlxf23DCLnjh73bwc6e9Q3mHru73H/tl7PLRhsPcC2wMnAQuD3wNeAtw0iZ0Hx3wAeXpN6ev78xedzU3H/NcA9g6jlD/0sD2r/mDbte7zq5/K7vPZ8j3t+Vj0+H7/LI/h7XLVbVQ8lPANsm5kb97ptBDxSZ8aozFwJkJnPUOtON46IS6h1mvValfESMD8zXywerwS66w3JzA8Bl1Gb9GLnzFwMvJSZf8rMPw2invUjYpeI2A3oyMznetRXdz3A9RHxjxGxfnH/MKjtvgSWDSIni+0/kJmnZeYOwEeBMdT+p6/XOsWu1i2BDVftZoyITan/83p51W5l4E1AR1Hb09T+IazXioiY1Mfy3YEVg8h5hqF/j8Hv8uqMxO8x+F1enZH4Pa6WVncmfd2AbwCT+nnun+vMuAKY3E/2y4Oo5T+BDftYvjnwuzX42TqBf6XWrXatwfrX9bq9sVi+KXDrIHLWBU4FHipuL1Pr/i8E3jyInDsa9JlPAR4tbkcC1wBXAw8DU+vM+Bi13cG/LH6mg4vlrwcuHEQtuwK/Be4tsn4J3Fcs262Z32O/y2vf99jv8tr3Pa7are3GGNSr+AuCzHzV5ZwjYovMfHiI+Z3Udhk9tobr7wy8KzPPGUodPfI6gPUy8/k1WHcstU7+yTVYd8PMXD7Y9frJ6qA27mVlRIwCJlLbHVv3XyTFX1nbAIuy9hfJUOrZHNiC2l9oXZn5P0PJG0IdfpfrW2/EfI+LHL/Lg8seEd/jKqhsY1CM5pxE7cucwFJq3WDdBTciw5z2ymlULavJf3tm/t6c6udUqZZW50TEulnbtd1z2esy84l2zalSLY3MqYJKNgYRsT/wA+ABarvgoDaS9q3A8Zn5y2ZkmNNeOY2qZYBt1D0C25zW5lSpllblFGMtfkxt5P4d1A5nLC6eG8wZLZXJqVItjcypklGtLqAf3wX2XfXmrhIRW1MbCLR9kzLMaa+chtQSEWf29xS1kdR1MWf4c6pUSxVzgDOAAzJzYUR8GLg6Iv46M29hcIMYq5RTpVoamVMZVW0MRvG/59z29DC1wUbNyjCnvXIaVcsngS8Cf+njuSnmVCqnSrVUMWd0Zi4EyMxLI+I+4GcRMY3iTIw2zKlSLY3MqYyqNgbnAfMj4mJq55VC7fSfo4rnmpVhTnvlNKqW+dTOFf9N7yci4lRzKpVTpVqqmPNSRGy+arBh8VftPtTODvirNs2pUi2NzKmMSo4xAIiI7YFD6TGSFpidmfc2M8Oc9sppUMZrgRU5xNHE5gx/TpVqqWjOvsDjmXlnr+VjgRMy8/R2y6lSLY3MqZSswDmT/d2Az9ezbLgzzGmvnCrVYo6fuTl+5u12a3kBA7zRt/ex7I5mZ5jTXjlVqsUcP3Nz/Mzb7VbJMQYRMQU4Gtg6Imb3eGojanNjNyXDnPbKqVIt5jQnp0q1mNOcnCrV0sicKqlkYwD8htr8268D/qXH8meB3lfEGs4Mc9orp0q1mNOcnCrVYk5zcqpUSyNzKqOygw8lSVLzVfXqigBExBER8UBELIuIP0fEsxHx52ZnmNNeOVWqxZzm5FSpFnOak1OlWhqZUwmtHuQwwGCORcD2rc4wp71yqlSLOX7m5viZt9ut0nsMgEcz874KZJjTXjlVqsWc5uRUqRZzmpNTpVoamdNylR5jEBHfpXaN7cvpMTVoZv6smRnmtFdOlWoxpzk5VarFnObkVKmWRuZUQVXPSlhlY+B5YP8eyxIYzBvdiAxz2iunSrWY05ycKtViTnNyqlRLI3NartJ7DCRJUnNVeoxBRLwtIn4VEfcUjydExD80O8Oc9sqpUi3mNCenSrWY05ycKtXSyJxKaPXox9XdgF8Dk+gxrSS1K441NcOc9sqpUi3m+Jmb42febrdK7zEANsjM3/VatrIFGea0V06VajGnOTlVqsWc5uRUqZZG5rRc1RuDJyLir6gN4CAiPkxt6slmZ5jTXjlVqsWc5uRUqRZzmpNTpVoamdN6rd5lMcCumW2Aa6iN9HwYuBF4S7MzzGmvnCrVYo6fuTl+5u12q/RZCRHRkZndEdEJrJOZz7Yiw5z2yqlSLeY0J6dKtZjTnJwq1dLInCqo+qGEP0bEDOCdwPIWZpjTXjlVqsWc5uRUqRZzmpNTpVoamdNyVW8MtqO2a+b/o/amnxURe7Ygw5z2yqlSLeY0J6dKtZjTnJwq1dLInNZr9bGMem/Aa4Dzge5WZpjTXjlVqsUcP3Nz/Mzb4Vb1PQZExOSI+AFwOzAG+GgrMsxpr5wq1WJOc3KqVIs5zcmpUi2NzGm1qg8+/COwAPgpMDszn2tFhjntlVOlWsxpTk6VajGnOTlVqqWROVVQ9cZg48z8c6szzGmvnCrVYk5zcqpUiznNyalSLY3MqYJKNgYR8T2KSSL6kpknNiPDnPbKqVIt5jQnp0q1mNOcnCrV0sicKqnqGINbgduoHaPZFXiguE0EupuYYU575VSpFnOak1OlWsxpTk6VamlkTnW0evTj6m7AdcC6PR6vC1zX7Axz2iunSrWY42dujp95u92qusdglTcBG/V4vGGxrNkZ5rRXTpVqMac5OVWqxZzm5FSplkbmtNyoVhcwgOnAHRFxXfF4MnBqCzLMaa+cKtViTnNyqlSLOc3JqVItjcxpuUoOPuwpIt4E/DVwH7ABsDQz5zU7w5z2yqlSLeY0J6dKtZjTnJwq1dLInJZr9bGMAY7ZfBq4G3ia2vGbF4Brm51hTnvlVKkWc/zMzfEzb7dbywsY4I2+m9pIzwXF47cDs5qdYU575VSpFnP8zM3xM2+3W9UHH67IzBUAEbFeZv6e2oUqmp1hTnvlVKkWc5qTU6VazGlOTpVqaWROy1V98GFXRGwCXA5cHRFPA0tbkGFOe+VUqRZzmpNTpVrMaU5OlWppZE7LVX7w4SoRMRkYC/xXZr7Yqgxz2iunSrWY05ycKtViTnNyqlRLI3NapW0aA0mSNPyqPsZAkiQ1kY2BJEkq2RhIkqSSjYE0wkRExxDXr/rZSpKGkYMPpTYSEVsB/wX8FtgF+APwN8C9wHnA/sBZQABfKf57ZWZ+qVj/WOBL1E6jegD4S2aeEBEzgaeKzNuBWcB3gPWpzeD2ycy8PyKOAQ4DOoAdgX8BRlObBvYvwAcy86nhewckDTf/MpDaz3bAsZl5U0ScBxxfLF+RmXsW87XfAuxGbXrWX0bEYcDvgJOpXTP+WeBa4M4euW8D9s3M7ojYGHhfZq6MiH2BfwKOLF63I7UGYgywCPhSZu4SEd+m1qR8Z5h+bklNYGMgtZ8lmXlTcf8C4MTi/qziv7sD12fm4wAR8RPgfcVzv171F31EXEKtGVjlkszsLu6PBf4jIrYFktq15Ve5LjOfBZ6NiGXAnGL53cCERvyAklrHMQZS++l9/G/V4+eK/0Y/6/W3fJXnetw/jVoDsCNwCLW9A6v8pcf9l3s8fhn/2JDano2B1H7eHBHvKu5PAW7s9fxvgckR8bpiIOIU4NfUDiVMjojXFAMMj6R/Y4GHi/vHNKxySZVnYyC1n/uAv42Iu4DXAmf3fDIzHwG+TO3Sr3cCt2fmLzLzYWpjBX4LXENtwOKyfrZxBvDNiLiJ2kBDSWsJz0qQ2khxVsIVxS7+NVl/w8xcXuwx+DlwXmb+vJE1Smpv7jGQ1i6nRsQC4B7gj9SuBCdJJfcYSJKkknsMJElSycZAkiSVbAwkSVLJxkCSJJVsDCRJUsnGQJIklf4fSaBRWHjgKL8AAAAASUVORK5CYII=\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# performance[['total_ticks', 'elapsed']].plot.bar(logy=True)\n", + "performance[['total_ticks', 'elapsed']].plot.bar(\n", + " logy=True, secondary_y=['elapsed'], \n", + " figsize=(8, 6), title=\"Internal vs external time\")\n", + "plt.savefig('internal_external_time.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 357, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAfcAAAGpCAYAAACQ8X+gAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAAsTAAALEwEAmpwYAAAvcElEQVR4nO3deZwcBZn/8c9DDhMSznBKQIIbkBAn4fYAA3IEUBcQDwIqKBiVRdSXy4LuDxYXWbN4oIiAWcHoApJFBGNkBeQwckqAEAhnFiIJyXKEQxIIkPD8/uhKthlmMj2TmZ6a4vN+vfqVrutbz3Q1PF3V1VWRmUiSpOpYq7cLkCRJ3cvmLklSxdjcJUmqGJu7JEkVY3OXJKlibO6SJFWMzV3qJRFxY0Qc29t1lFFEzIuIfTsx/5yI2KvnKpL6Fpu7KqUzTcHm2r7ONtdmiogpEfHt+nGZuUNm3thLJUmlY3OXuigi+vV2DWUUNf6/RepF/geoyoqIoyPipoj4XkQ8FxGPRcSBxbQzgD2BcyJiSUScU4x/V0RcGxHPRsRDEfGJurwpEXFeRFwVEUuBvYs93H+MiNkR8UJETI2IQcX8G0TE9Ih4ulj/9IgY3kDdb4+IlyNiw7pxO0bEMxExICL+LiL+VKzvmYiYupqs90TELRHxfETcs/LQdUS8r1h2y2J4TDHPuyLiP4GtgN8Vr80/rS6rmHZjRJwRETcDLwHbRERGxBcj4pHi7/9JREQx/zsj4vqIWFzUcXFErN/AazMROBL4p6K23xXjVx1piIjTIuKyiLgoIl6MiHsjYtuI+EZEPBUR8yNi/7rM9SLigohYFBFPRMS3/eCmPi8zffiozAOYB+xbPD8aeA34PNAP+BKwEIhi+o3AsXXLDgHmA58F+gM7Ac8AOxTTpwAvAO+n9sF4ULG+vwBvBzYEHgC+WMw/DDgMWBtYB7gMuLJufW9Yf6u/43rg83XD3wXOL57/Cvjnuhr2aCdjC2AxcFAx737F8MbF9DOK9QwGZgPHt/U6Nph1I/A4sEPx2g0AEpgOrE/tw8LTwAHF/H9XZLwN2BiYAfywvfW3+rumAN9ezXY/DVgGjC9q+SXwWPGaDSjeD4/VLXsl8NNi+29SbM8v9PZ72YePNXn06p57RFxYfJK+r8H5PxER9xcnz1zS0/WpEv6amf+RmSuAXwCbA5u2M++HgXmZ+fPMXJ6ZdwGXAx+rm+e3mXlzZr6emcuKcWdn5sLMfBb4HTAWIDMXZ+blmflSZr5IrZmOa7DuS4AJUDvMDRxejIPaB5Z3AG/PzGWZeVM7GZ8CrsrMq4p6rwVmUmvQUGuC61FrZguBn6ymno6yAKZk5pzitXutGDcpM5/PzMeBG/i/12ZuZl6bma9k5tPAD2j8tWnEnzPz6sxcTu1D1cZFLa8BlwJbR8T6EbEpcCDw1cxcmplPAWdRe72lPqu3D8tPAQ5oZMaIGAl8A3h/Zu4AfLXnylKF/O/KJ5n5UvF0aDvzvgPYvTjs/HxEPE/tEPBmdfPMX906qB2SHgoQEWtHxE8j4q8R8Tdqe6frN3jI99fAeyPi7cAHqO0F/7mY9k9AAH8pPuh+bjV/z8db/T17UPuAQ9HopgCjge9n5uruIrXarEJnXptNIuLS4jD434CLgI1Ws/7OerLu+cvAM8UHvJXDFLW8g9re/KK6v+un1PbgpT6rf2+uPDNnRMTW9eMi4p3U9iA2pvY/g89n5oPUDqX9JDOfK5Z9qsnlqnpaN7P5wJ8yc79OLLM6Xwe2A3bPzP+NiLHA3dQa8+oLy3w+Iq4BPgFsD/xqZfPNzP+l9t8DEbEH8MeImJGZc9v4e/4zMz/f1joiYgvgX4CfA9+PiF0z85V2/s7VZrWzzOp8p5i/JTMXR8QhwDkNLtudt7KcD7wCbFTs5UuV0Nt77m2ZDHw5M3cG/hE4txi/LbBtRNwcEbdFREN7/NJqPAlsUzc8ndp77NPFiWsDImLXiNi+i/nrUNtLfL44Oe5fOrn8JcBnqH1vv+prqIj4eN2Jec9Ra3Yr3rw4FwEfiYjxEdEvIgZFxF4RMbw41D8FuAA4BlgEnF63bOvXpt2sTv5NK60DLKH22mwBnNiJZVvX1mWZuQi4htqHm3UjYq3iZL/u/IpAarpSNfeIGAq8D7gsImZROzy28rBff2AksBe17yJ/1sjZtdJq/Aj4WHEm99nF9+L7U/u+dSG1Q8r/Tu2kr674IbWT1Z4BbgP+0Mnlp1F7zz+ZmffUjd8VuD0ilhTzfCUzH2u9cGbOBw4GvkntZLb51JroWsAJ1M49OKU4IvBZ4LMRsWex+HeA/1ccqv7HDrK64lvUTlh8Afg98JtOLHsBMKqo7courr/eZ4CBwP3UPiz9mjd+3SD1ObH6r9maUEDtsPz0zBwdEesCD2Xmm/7Diojzgdsyc0oxfB1wcmbe0cx6JUkqu1LtuWfm34DHIuLjsOpiGGOKyVcCexfjN6J2mP7R3qhTkqQy6+2fwv0KuBXYLiIWRMQx1M5OPiYi7gHmUDsUCHA1sDgi7qf2k5oTM3Nxb9QtSVKZ9fpheUmS1L1KdVhekiStOZu7JEkV02sXsVlrrbVy8ODBvbV6SZKa7qWXXsrM7PEd6w6be0RcSO2a209l5ug2ph8JnFQMLgG+1Oo3uW0aPHgwS5cu7WS5kiT1XRHxcsdzrblGPj1MYfXXf38MGJeZLdSucDW5G+qSJEld1OGee1vXf281/Za6wduArl6OUpIkdYPuPu5/DPDf3ZwpSZI6odtOqIuIvak19z1WM89EYCLAwIED3zT9tddeY8GCBSxbtuxN01ROgwYNYvjw4QwYMKC3S5EkFRq6iE399d/bmd4CXAEcmJkPN7LiIUOGZOsT6h577DHWWWcdhg0bRu2mVSqzzGTx4sW8+OKLjBgxorfLkaTSi4iXMnNIT69njQ/LR8RW1O7o9OlGG3t7li1bZmPvQyKCYcOGeaRFkkqmkZ/C/YrabVY3iogF1O5JPQAgM88HTgWGAecWTXl5Zu7S1YJs7H2L20uSyqeRs+UndDD9WODYbqtIkiStkV67Ql0jtj75992aN2/Sh1Y7/fnnn+eSSy7huOOOaz9j3jxuueUWjjjiiNWva948PvzhD3Pfffe1OX3WrFksXLiQgw46CIBp06Zx//33c/LJJ3cpT5Kklby2fJ3nn3+ec889d7XzzJs3j0suuWSN1zVr1iyuuuqqVcN///d/325jlySpM2zudU4++WT+53/+h7Fjx3LiiSdy4oknMnr0aN797nczderUVfP8+c9/ZuzYsZx11lnMmzePPffck5122omddtqJW265pYO1wKuvvsqpp57K1KlTGTt2LFOnTmXKlCkcf/zxADz55JMceuihjBkzhjFjxrwp89FHH2XHHXfkjjvuYM6cOey2226MHTuWlpYWHnnkke5/YSRJfUqpD8s326RJk7jvvvuYNWsWl19+Oeeffz733HMPzzzzDLvuuisf+MAHmDRpEt/73veYPn06AC+99BLXXnstgwYN4pFHHmHChAnMnDlztesZOHAg//qv/8rMmTM555xzAJgyZcqq6SeccALjxo3jiiuuYMWKFSxZsoTnnnsOgIceeojDDz+cn//854wdO5Yvf/nLfOUrX+HII4/k1VdfZcWKFT3z4kiS+gybeztuuukmJkyYQL9+/dh0000ZN24cd9xxB+uuu+4b5nvttdc4/vjjmTVrFv369ePhh9fo14AAXH/99fzyl78EoF+/fqy33no899xzPP300xx88MFcfvnl7LDDDgC8973v5YwzzmDBggV89KMfZeTIkWu8fklS3+Zh+XY0cnEfgLPOOotNN92Ue+65h5kzZ/Lqq6/2WE3rrbceW265JTfffPOqcUcccQTTpk1j8ODBjB8/nuuvv77H1i9J6hvcc6+zzjrr8OKLLwLwgQ98gJ/+9KccddRRPPvss8yYMYPvfve7PPHEE6vmAXjhhRcYPnw4a621Fr/4xS8aPixev67W9tlnH8477zy++tWvsmLFilW3xh04cCBXXnkl48ePZ+jQoRxxxBE8+uijbLPNNpxwwgk8+uijzJ49mw9+8INr+EpIUjW19SuseYNa/frptBeaVE3PKXVz7+ina91t2LBhvP/972f06NEceOCBtLS0MGbMGCKCM888k80224xhw4bRv39/xowZw9FHH81xxx3HYYcdxmWXXcbee+/NkCGNXVVw7733ZtKkSYwdO5ZvfOMbb5j2ox/9iIkTJ3LBBRfQr18/zjvvPDbffHMAhgwZwvTp09lvv/0YMmQI999/PxdddBEDBgxgs80249RTT+3210WS1Lc0dG35ntDWteUfeOABtt9++16pR13ndpPUV/T2nnufuba8JEkql1Iflq+Cq6++mpNOOukN40aMGMEVV1zRSxVJkqrO5t7Dxo8fz/jx43u7DEnSW4iH5SVJqhibuyRJFeNheUlS33Taeq2G+/7v07uLe+4N2nrrrXnmmWeavt699tqr3WvVf+xjH+PRRx9tc9qxxx7L/fffv9rso48+ml//+tdvGt/6znf33nsvRx99dONFS5J6Vbn33Ft/KlvjvOp8qpszZw4rVqxgm222edO0FStW8LOf/azL2Sub+8p71r/73e9mwYIFPP7442y11VZdzpUkNYd77q1cdNFFq26h+oUvfKHNy8kecsgh7Lzzzuywww5Mnjx51fihQ4fy9a9/nZ122ol99tmHp59+GoCzzz6bUaNG0dLSwuGHHw7A0qVL+dznPseuu+7KjjvuyG9/+1sAXn75ZQ4//HBaWlr45Cc/ycsvv9xmnRdffDEHH3zwG9Z96qmnsvvuu3Prrbe+YY//ggsuYNttt2Wvvfbi85///KpbywLMmDGD973vfWyzzTar9uJb39YW4CMf+QiXXnppl19XSVLz2NzrPPDAA0ydOpWbb7551V3eLr744jfNd+GFF3LnnXcyc+ZMzj77bBYvXgzUGvZOO+3EXXfdxbhx4/jWt74F1G4le/fddzN79mzOP/98AM444ww++MEPcscdd3DDDTdw4oknsnTpUs477zzWXnttZs+ezT//8z9z5513tlnrzTffzM4777xqeOnSpYwePZrbb7+dPfbYY9X4hQsXcvrpp3Pbbbdx7bXX8uCDD74hZ9GiRdx0001Mnz6dk08+eVW9e+65J7NmzeJrX/saALvssgt//vOfu/rSSpKaqNyH5Zvsuuuu484772TXXXcFanvRm2yyyZvmO/vss1ddhGb+/Pk88sgjDBs2jLXWWotPfvKTAHzqU5/iox/9KAAtLS0ceeSRHHLIIRxyyCEAXHPNNUybNo3vfe97ACxbtozHH3+cGTNmcMIJJ6xarqWlpc1aFy1axMYbb7xquF+/fhx22GFvmu8vf/kL48aNY8MNNwTg4x//+BtuS3vIIYew1lprMWrUKJ588sl2X5tNNtmEhQsXtjtdklQeNvc6mclRRx3Fd77znXbnufHGG/njH//Irbfeytprr81ee+3FsmXL2pw3IgD4/e9/z4wZM5g2bRqnn346c+bMITO5/PLL2W677dpdbnUGDx78hvUOGjSIfv36tfk3rc7b3va2huZdtmwZgwcP7rAuSVLv87B8nX322Ydf//rXPPXUUwA8++yz/PWvf33DPC+88AIbbLABa6+9Ng8++CC33Xbbqmmvv/76qu+tL7nkEvbYYw9ef/115s+fz957782ZZ57J888/z5IlSxg/fjw//vGPVzXUu+++G6jdanblVwH33Xcfs2fPbrPW7bffnrlz53b4N+2222786U9/4rnnnmP58uVcfvnlHS7T1u1oH374YUaPHt3hspKk3mdzrzNq1Ci+/e1vs//++9PS0sJ+++3HokWL3jDPAQccwPLly2lpaeGUU07hPe95z6ppQ4YMYc6cOey8885cf/31nHrqqaxYsYJPfepTvPvd72bHHXfka1/7Guuvvz6nnHIKr732Gi0tLYwePZpTTjkFgC99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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# performance[['total_ticks', 'elapsed']].plot.bar(logy=True)\n", + "performance[['total_ticks', 'elapsed']].plot.bar(\n", + " logy=False, secondary_y=['elapsed'], \n", + " figsize=(8, 6), title=\"Internal vs external time\")\n", + "plt.savefig('internal_external_time_linear.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 342, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "image/png": "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ec1rGlrvpJNOYrfdduOnP/0p1157LUceeSSLFy/mq1/9KhMmTODee+8F4Omnn27OmyFJGlYq1RA0Moeg1W6++WZmzpxJR0cHr33ta9lvv/1YtGgRW2yxxXqvW716NccffzyLFy+mo6OD3/72t3XlN7rezTffvO6v//e85z0sX76clStXcs0113DRRRete92WW27Z4E8qSRoJKtUQZOYCYEFnZ+exra5lQzJfce6kPn3rW9/ita99LXfffTcvv/wy48aN2yjr9VVPRJCZHvYnaWAnT+j1eGVr6qiA3hPW65lwPlw4h6ABm2++Oc8++ywA++67L/Pnz2ft2rU88cQT3Hjjjey5557rvQZg5cqVvP71r2fUqFGcf/759HXSpb40ut6+++7LD3/4QwCuv/56tt56a7bYYgve//73c+aZZ657nbsMJEl9qdQIQSNa0bVttdVW7LPPPkydOpWDDjqIadOmscsuuxARfOMb3+B1r3sdW221FZtssgm77LILn/jEJzjuuOM49NBDueSSS3j3u99NZ2dnXdtqdL2TTz6Zo446imnTprHpppty7rnnAvDFL36Rf/zHf2Tq1Kl0dHRw0kkn8ZGPfGTI74UkaXiJeoe+y9BjDsGxvU91e//997PTTju1pjANmZ+fVGHuMlinlbsMIuJPwHnAgmIXeqkqtcug6uchkCRpI1qbmbNa0QxAG+8yGC6uuuoqTjzxxPWWTZo0iZ/85CctqkiSNBLZELTYgQceyIEHHtjqMiRJI1ylGoJ2Og+BJEnDiXMIJElStRoCSZLUGjYEw9zpp5/Oeeed1+dzZ599dr/PdZs3bx7HH398n8997WtfW3f/pZdeYt9992XNmjWDL1aS1DKVmkPQkN7HzQ45r32Ou12zZg2bbLLhj27NmjWcc8453HnnnX0+96lPfWpIdXzta1/j85//PABjxozhgAMOYP78+RxxxBFDypUklc8RgjotW7aMt7zlLRxzzDFMnTqVI444gmuuuYZ99tmHyZMnc/vttwPw/PPP88lPfpI99tiD3Xbbjcsuuwyo/aV9yCGHMGPGDCZNmsSZZ57JN7/5TXbbbTf22msvnnrqKQAWL17MXnvtxbRp0/jwhz+87lTD+++/P5///OfZb7/9OOWUU5g0aRKrV68G4JlnnmGHHXZY97jbtddey+67776ueeiZ8e1vf5uTTz6Z0047DYBFixYxbdo09t5773WXde722GOPMX36dCZPnsznPvc5oHaZ5xdffJFdd911XQNwyCGHrDt9siSpvVSqIYiIGRExt97z/Zdt6dKlfOYzn+Gee+7hN7/5DRdccAE333wzp5122rrh81NOOYX3vOc9LFq0iOuuu44TTjiB559/HoAlS5ZwwQUXcPvtt/OFL3yBTTfdlLvuuou999573dD9kUceyde//nXuuecedt55Z77yla+s2/6KFSu44YYbOOmkk9h///258sraGbUuuugiDj30UEaPHr1evbfccgtve9vb1lvWnfHZz352veVHHXUUZ599Nrfddhu9J3UuXryY+fPnc++99zJ//nweeeQR5syZw/jx41m8ePG6JmDq1KksWrRoqG+zJKkFKtUQVP0og0mTJrHzzjszatQo3vrWt3LAAQcQEey8884sW7YMgJ///OfMmTOHXXfdlf33359Vq1bx+9//HoB3v/vdbL755myzzTZMmDCBGTNmAKxbf+XKlaxYsYL99tsPgL//+7/nxhtvXLf9j3/84+vuH3PMMXz/+98H4Pvf/z5HHXXUK+r9wx/+wDbbbLPesp4Z3VasWMGzzz7LO97xDgAOP/zw9Z4/4IADmDBhAuPGjWPKlCn87ne/6/P96ejoYMyYMetd3EmSyrDD7CvXu6lx7TuHoAV6nh9h1KhR6x6PGjVq3WS6zOTSSy9lxx13XG/dX/7yl3WtP5CeFzjaZ599WLZsGTfccANr165db4i/2/jx4+l9TYi+LpK0oetZ9Ky7o6NjwFr/9Kc/1X2JZ0lSdVRqhGA4OPDAAznjjDPW/ZK966676l53woQJbLnlltx0000AnH/++etGC/py5JFHMnPmzD5HBwB22mknli5dusHtbrnllmy++eb84he/AGq7IOoxevTo9eYtLF++nG222eYVuy4kSdVnQ9BkX/rSl1i9ejXTpk1j6tSpfOlLX2po/XPPPZcTTjiBadOmsXjxYr785S/3+9ojjjiCp59+mpkzZ/b5/EEHHbTeLoeBfO9732PWrFnsvffeZCYTJmz4KI5Zs2Yxbdq0dZMKr7vuOj7wgQ/UtT1JUrVU6vLH3To7O7N7Il43L5/7Sj/60Y+47LLLOP/88/t9zYc//GG+8Y1vMHny5AGznnvuOTbbbDMA5syZwx/+8Ae+/e1vN1TPRz7yEU49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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# performance[['total_ticks', 'elapsed']].plot.bar(logy=True)\n", + "performance[['total_alloc', 'memory']].plot.bar(\n", + " logy=True, secondary_y=['memory'], \n", + " figsize=(8, 6), title=\"Internal vs external memory\")\n", + "plt.savefig('internal_external_memory_log.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 343, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# performance[['total_ticks', 'elapsed']].plot.bar(logy=True)\n", + "performance[['total_alloc', 'memory']].plot.bar(\n", + " logy=False, secondary_y=['memory'], \n", + " figsize=(8, 6), title=\"Internal vs external memory\")\n", + "plt.savefig('internal_external_memory_linear.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 344, + "metadata": { + "Collapsed": "false" + }, + "outputs": [], + "source": [ + "# performance['elapsed_adj'] = performance['elapsed'] - 0.28\n", + "# performance" + ] + }, + { + "cell_type": "code", + "execution_count": 345, + "metadata": { + "Collapsed": "false" + }, + "outputs": [], + "source": [ + "# performance[['total_time', 'elapsed_adj']].plot.bar(logy=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 356, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(ncols=3, figsize=(20,5))\n", + "\n", + "performance['elapsed'].plot.bar(ax=ax[2],\n", + " logy=True, \n", + " title=\"Run times (wall clock), log scale\",\n", + "# figsize=(10,8)\n", + " )\n", + "ax[2].set_xlabel('Program')\n", + "\n", + "performance['elapsed'].plot.bar(ax=ax[0],\n", + " logy=False, \n", + " title=\"Run times (wall clock), linear scale\",\n", + "# figsize=(10,8)\n", + " )\n", + "ax[0].set_xlabel('Program')\n", + "\n", + "performance['elapsed'].plot.bar(ax=ax[1],\n", + " logy=False, \n", + " ylim=(0, 5.2),\n", + " title=\"Run times (wall clock), truncated linear scale\",\n", + "# figsize=(10,8)\n", + " )\n", + "ax[1].set_xlabel('Program')\n", + "\n", + "plt.savefig('run_times_combined.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 347, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(ncols=2, figsize=(13,5))\n", + "\n", + "performance['memory'].plot.bar(ax=ax[0],\n", + " logy=True, \n", + " title=\"Memory used, log scale\",\n", + "# figsize=(10,8)\n", + " )\n", + "ax[0].set_xlabel('Program')\n", + "\n", + "performance['memory'].plot.bar(ax=ax[1],\n", + " logy=False, \n", + " title=\"Memory used, linear scale\",\n", + "# figsize=(10,8)\n", + " )\n", + "ax[1].set_xlabel('Program')\n", + "\n", + "plt.savefig('memory_combined.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 348, + "metadata": { + "Collapsed": "false" + }, + "outputs": [], + "source": [ + "# ax = performance['elapsed_adj'].plot.bar(logy=False, \n", + "# title=\"Run times (wall clock), linear scale\",\n", + "# figsize=(10,8))\n", + "# ax.set_xlabel('Program')\n", + "# plt.savefig('run_times_linear.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 349, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['total_time', 'total_alloc', 'total_ticks', 'initial_capabilities',\n", + " 'system', 'elapsed', 'memory'],\n", + " dtype='object')" + ] + }, + "execution_count": 349, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "performance.columns" + ] + }, + { + "cell_type": "code", + "execution_count": 350, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 350, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "performance['memory'].plot.bar()" + ] + }, + { + "cell_type": "code", + "execution_count": 351, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 351, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "performance.plot.scatter('elapsed', 'total_alloc', logx=True, logy=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 352, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 352, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "performance.plot.scatter('memory', 'total_alloc', logx=True, logy=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 353, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 353, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "performance.plot.scatter('elapsed', 'total_ticks', logx=True, logy=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 354, + "metadata": { + "Collapsed": "false" + }, + "outputs": [], + "source": [ + "performance[['total_alloc', 'memory', 'elapsed']].to_csv('performance.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 355, + "metadata": { + "Collapsed": "false" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "| program | total_alloc | elapsed | memory |\n", + "|:----------|--------------:|----------:|---------:|\n", + "| advent01 | 12058592 | 0.02 | 10212 |\n", + "| advent02 | 1818928 | 0.01 | 7876 |\n", + "| advent03 | 8298128 | 0.01 | 10760 |\n", + "| advent04 | 54628920 | 0.05 | 14236 |\n", + "| advent05 | 434487576 | 0.47 | 49372 |\n", + "| advent06 | 2507624 | 0.01 | 7948 |\n", + "| advent07 | 5589544 | 0.01 | 10164 |\n", + "| advent08 | 2499222744 | 0.98 | 12252 |\n", + "| advent09 | 469984 | 0.01 | 6644 |\n", + "| advent10 | 2383248 | 0.01 | 7456 |\n", + "| advent11 | 39102056 | 0.04 | 11272 |\n", + "| advent12 | 722598152 | 1.15 | 61132 |\n", + "| advent13 | 4493632 | 0.01 | 11504 |\n", + "| advent14 | 15471000 | 0.02 | 11020 |\n", + "| advent15 | 2458599000 | 1.39 | 53240 |\n", + "| advent16 | 8613496 | 0.01 | 12128 |\n", + "| advent17 | 88071992 | 0.02 | 11604 |\n", + "| advent18 | 588717288 | 0.17 | 11812 |\n", + "| advent19 | 2623652352 | 3.88 | 12524 |\n", + "| advent20 | 3090735840 | 2.49 | 207144 |\n", + "| advent21 | 2400838008 | 1.03 | 22020 |\n", + "| advent22 | 1384180736 | 0.76 | 12508 |\n", + "| advent23 | 38150694448 | 27.19 | 98824 |\n", + "| advent24 | 66538931736 | 27.92 | 12432 |\n", + "| advent25 | 1910248008 | 4.21 | 13748 |\n" + ] + } + ], + "source": [ + "print(performance[['total_alloc', 'elapsed', 'memory']].to_markdown(floatfmt=['0.0f', '0.0f', '.2f', '0.0f']))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "jupytext": { + "formats": "ipynb,md" + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/profiling/profiling.md b/profiling/profiling.md new file mode 100644 index 0000000..569ac33 --- /dev/null +++ b/profiling/profiling.md @@ -0,0 +1,292 @@ +--- +jupyter: + jupytext: + formats: ipynb,md + text_representation: + extension: .md + format_name: markdown + format_version: '1.3' + jupytext_version: 1.11.1 + kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + +```python Collapsed="false" +import glob +import json +import pandas as pd +import numpy as np + +import matplotlib.pyplot as plt +%matplotlib inline +``` + +```python Collapsed="false" tags=[] +! cd .. && for i in {01..25}; do cabal run advent${i} --enable-profiling -- +RTS -N -pj -s -hT ; done +``` + +```python +! rm ../times.csv +! rm ../times_raw.csv +``` + +```python Collapsed="false" tags=[] +! cd .. && for i in {01..25}; do /usr/bin/time -f "%C,%S,%E,%M" -o times.csv -a cabal run advent${i}; done +``` + +```python Collapsed="false" tags=[] +! cd .. && for i in {01..25}; do /usr/bin/time -f "%C,%S,%E,%M" -o times_raw.csv -a advent${i}; done +``` + +```python +!mv ../*prof . +``` + +```python +!mv ../times.csv . +``` + +```python +!mv ../times_raw.csv . +``` + +```python +!mv ../*hp . +``` + +```python +! for f in *hp ; do hp2ps ${f} ; done +``` + +```python Collapsed="false" +len(glob.glob('*prof')) +``` + +```python Collapsed="false" +profs = [] +for fn in glob.glob('*prof'): + with open(fn) as f: + j = json.load(f) + prof = {} + for n in 'program total_time total_alloc total_ticks initial_capabilities'.split(): + prof[n] = j[n] + profs.append(prof) +profs +``` + +```python Collapsed="false" +performance = pd.DataFrame(profs).set_index('program').sort_index() +performance +``` + +```python Collapsed="false" +performance.total_ticks.plot.bar() +``` + +```python Collapsed="false" +performance.total_ticks.plot.bar(logy=True) +``` + +```python Collapsed="false" +performance.total_alloc.plot.bar() +``` + +```python Collapsed="false" +performance.total_alloc.plot.bar(logy=True) +``` + +```python Collapsed="false" +performance[['total_ticks', 'total_alloc']].plot.bar( + logy=True, secondary_y=['total_alloc'], + figsize=(8, 6), title="Internal time and memory") +plt.savefig('internal_time_and_memory_log.png') +``` + +```python Collapsed="false" +performance[['total_ticks', 'total_alloc']].plot.bar( + logy=False, secondary_y=['total_alloc'], + figsize=(8, 6), title="Internal time and memory") +plt.savefig('internal_time_and_memory_linear.png') +``` + +```python +# times = pd.read_csv('times.csv', +# names=['program', 'system', 'elapsed', 'memory'], +# index_col='program') +# times.index = times.index.str.slice(start=len('cabal run ')) +# times.elapsed = pd.to_numeric(times.elapsed.str.slice(start=2)) +# times +``` + +```python +times = pd.read_csv('times_raw.csv', + names=['program', 'system', 'elapsed', 'memory'], + index_col='program') +times.elapsed = pd.to_numeric(times.elapsed.str.slice(start=2)) +times +``` + +```python +times.dtypes +``` + +```python Collapsed="false" +times.describe() +``` + +```python Collapsed="false" +performance = performance.merge(times, left_index=True, right_index=True) +# performance.drop(index='advent15loop', inplace=True) +performance +``` + +```python Collapsed="false" +performance.columns +``` + +```python Collapsed="false" +# performance[['total_ticks', 'elapsed']].plot.bar(logy=True) +performance[['elapsed', 'memory']].plot.bar( + logy=True, secondary_y=['memory'], + figsize=(8, 6), title="External time and memory") +plt.savefig('external_time_and_memory_log.png') +``` + +```python Collapsed="false" +# performance[['total_ticks', 'elapsed']].plot.bar(logy=True) +performance[['elapsed', 'memory']].plot.bar( + logy=False, secondary_y=['memory'], + figsize=(8, 6), title="External time and memory") +plt.savefig('external_time_and_memory_linear.png') +``` + +```python Collapsed="false" +# performance[['total_ticks', 'elapsed']].plot.bar(logy=True) +performance[['total_ticks', 'elapsed']].plot.bar( + logy=True, secondary_y=['elapsed'], + figsize=(8, 6), title="Internal vs external time") +plt.savefig('internal_external_time.png') +``` + +```python Collapsed="false" +# performance[['total_ticks', 'elapsed']].plot.bar(logy=True) +performance[['total_ticks', 'elapsed']].plot.bar( + logy=False, secondary_y=['elapsed'], + figsize=(8, 6), title="Internal vs external time") +plt.savefig('internal_external_time_linear.png') +``` + +```python Collapsed="false" +# performance[['total_ticks', 'elapsed']].plot.bar(logy=True) +performance[['total_alloc', 'memory']].plot.bar( + logy=True, secondary_y=['memory'], + figsize=(8, 6), title="Internal vs external memory") +plt.savefig('internal_external_memory_log.png') +``` + +```python Collapsed="false" +# performance[['total_ticks', 'elapsed']].plot.bar(logy=True) +performance[['total_alloc', 'memory']].plot.bar( + logy=False, secondary_y=['memory'], + figsize=(8, 6), title="Internal vs external memory") +plt.savefig('internal_external_memory_linear.png') +``` + +```python Collapsed="false" +# performance['elapsed_adj'] = performance['elapsed'] - 0.28 +# performance +``` + +```python Collapsed="false" +# performance[['total_time', 'elapsed_adj']].plot.bar(logy=True) +``` + +```python Collapsed="false" +fig, ax = plt.subplots(ncols=3, figsize=(20,5)) + +performance['elapsed'].plot.bar(ax=ax[2], + logy=True, + title="Run times (wall clock), log scale", +# figsize=(10,8) + ) +ax[2].set_xlabel('Program') + +performance['elapsed'].plot.bar(ax=ax[0], + logy=False, + title="Run times (wall clock), linear scale", +# figsize=(10,8) + ) +ax[0].set_xlabel('Program') + +performance['elapsed'].plot.bar(ax=ax[1], + logy=False, + ylim=(0, 5.2), + title="Run times (wall clock), truncated linear scale", +# figsize=(10,8) + ) +ax[1].set_xlabel('Program') + +plt.savefig('run_times_combined.png') +``` + +```python Collapsed="false" +fig, ax = plt.subplots(ncols=2, figsize=(13,5)) + +performance['memory'].plot.bar(ax=ax[0], + logy=True, + title="Memory used, log scale", +# figsize=(10,8) + ) +ax[0].set_xlabel('Program') + +performance['memory'].plot.bar(ax=ax[1], + logy=False, + title="Memory used, linear scale", +# figsize=(10,8) + ) +ax[1].set_xlabel('Program') + +plt.savefig('memory_combined.png') +``` + +```python Collapsed="false" +# ax = performance['elapsed_adj'].plot.bar(logy=False, +# title="Run times (wall clock), linear scale", +# figsize=(10,8)) +# ax.set_xlabel('Program') +# plt.savefig('run_times_linear.png') +``` + +```python Collapsed="false" +performance.columns +``` + +```python Collapsed="false" +performance['memory'].plot.bar() +``` + +```python Collapsed="false" +performance.plot.scatter('elapsed', 'total_alloc', logx=True, logy=True) +``` + +```python Collapsed="false" +performance.plot.scatter('memory', 'total_alloc', logx=True, logy=True) +``` + +```python Collapsed="false" +performance.plot.scatter('elapsed', 'total_ticks', logx=True, logy=True) +``` + +```python Collapsed="false" +performance[['total_alloc', 'memory', 'elapsed']].to_csv('performance.csv') +``` + +```python Collapsed="false" +print(performance[['total_alloc', 'elapsed', 'memory']].to_markdown(floatfmt=['0.0f', '0.0f', '.2f', '0.0f'])) +``` + +```python + +``` -- 2.34.1 From 59554a0b7b46b8d37e5a4b0bfdd67efefe285dc7 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Tue, 10 May 2022 17:49:00 +0100 Subject: [PATCH 14/16] Minor tweak --- advent22/Main.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/advent22/Main.hs b/advent22/Main.hs index 3712b67..dc67b3f 100644 --- a/advent22/Main.hs +++ b/advent22/Main.hs @@ -80,7 +80,9 @@ segmentSize cuboids (here, there) | otherwise = 0 segment :: [Int] -> [(Int, Int)] -segment evs = if null evs then [] else zip evs $ tail evs +-- segment evs = if null evs then [] else zip evs $ tail evs +segment [] = [] +segment evs@(_ : tevs) = zip evs tevs -- Parse the input file -- 2.34.1 From afdee5e8491a7ec802ad4c0897e2550cc405ac80 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Tue, 14 Jun 2022 14:53:22 +0100 Subject: [PATCH 15/16] Added profiling --- profiling/external_time_and_memory.png | Bin 0 -> 11336 bytes profiling/external_time_and_memory_linear.png | Bin 0 -> 14172 bytes profiling/external_time_and_memory_log.png | Bin 0 -> 11372 bytes profiling/imports.png | Bin 0 -> 37537 bytes profiling/internal_external_memory.png | Bin 0 -> 12221 bytes profiling/internal_external_memory_linear.png | Bin 0 -> 14485 bytes profiling/internal_external_memory_log.png | Bin 0 -> 12117 bytes profiling/internal_external_time.png | Bin 0 -> 12394 bytes profiling/internal_external_time_linear.png | Bin 0 -> 12210 bytes profiling/internal_time_and_memory.png | Bin 0 -> 12691 bytes profiling/internal_time_and_memory_linear.png | Bin 0 -> 12165 bytes profiling/internal_time_and_memory_log.png | Bin 0 -> 12840 bytes profiling/memory_combined.png | Bin 0 -> 13232 bytes profiling/modules.png | Bin 0 -> 16380 bytes profiling/packages.png | Bin 0 -> 16380 bytes profiling/performance.csv | 26 +++++++++++++++++ profiling/performance.md | 27 ++++++++++++++++++ profiling/run_times_combined.png | Bin 0 -> 14477 bytes profiling/run_times_linear.png | Bin 0 -> 10494 bytes profiling/run_times_log.png | Bin 0 -> 14648 bytes profiling/time-results.csv | 27 ++++++++++++++++++ profiling/time-results.md | 27 ++++++++++++++++++ profiling/times.csv | 25 ++++++++++++++++ profiling/times_raw.csv | 25 ++++++++++++++++ 24 files changed, 157 insertions(+) create mode 100644 profiling/external_time_and_memory.png create mode 100644 profiling/external_time_and_memory_linear.png create mode 100644 profiling/external_time_and_memory_log.png create mode 100644 profiling/imports.png create mode 100644 profiling/internal_external_memory.png create mode 100644 profiling/internal_external_memory_linear.png create mode 100644 profiling/internal_external_memory_log.png create mode 100644 profiling/internal_external_time.png create mode 100644 profiling/internal_external_time_linear.png create mode 100644 profiling/internal_time_and_memory.png create mode 100644 profiling/internal_time_and_memory_linear.png create mode 100644 profiling/internal_time_and_memory_log.png create mode 100644 profiling/memory_combined.png create mode 100644 profiling/modules.png create mode 100644 profiling/packages.png create mode 100644 profiling/performance.csv create mode 100644 profiling/performance.md create mode 100644 profiling/run_times_combined.png create mode 100644 profiling/run_times_linear.png create mode 100644 profiling/run_times_log.png create mode 100644 profiling/time-results.csv create mode 100644 profiling/time-results.md create mode 100644 profiling/times.csv create mode 100644 profiling/times_raw.csv diff --git a/profiling/external_time_and_memory.png b/profiling/external_time_and_memory.png new file mode 100644 index 0000000000000000000000000000000000000000..7f44a073db1496bf0290cc56402ea4a71c1bccb7 GIT binary patch literal 11336 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 CHG2>M literal 0 HcmV?d00001 diff --git a/profiling/external_time_and_memory_linear.png b/profiling/external_time_and_memory_linear.png new file mode 100644 index 0000000000000000000000000000000000000000..52e07c2bf76f438368747a40a08377b424ec985c GIT binary patch literal 14172 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%0D4^# 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 BMeqOs literal 0 HcmV?d00001 diff --git a/profiling/internal_external_memory_linear.png b/profiling/internal_external_memory_linear.png new file mode 100644 index 0000000000000000000000000000000000000000..c59f7fa600f0dd1a50a4777b0b44acd0121955b0 GIT binary patch literal 14485 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 z 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 Xm{5V)5CmTlL};GV#uxlx@#FshFvMmf literal 0 HcmV?d00001 diff --git a/profiling/internal_external_memory_log.png b/profiling/internal_external_memory_log.png new file mode 100644 index 0000000000000000000000000000000000000000..f63c7b3bba5008f234125dd38b4969c1164c941f GIT binary patch literal 12117 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 literal 0 HcmV?d00001 diff --git a/profiling/internal_external_time.png b/profiling/internal_external_time.png new file mode 100644 index 0000000000000000000000000000000000000000..c16cb188f3e89d1850c3ac1364f06a7815137f1d GIT binary patch literal 12394 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 literal 0 HcmV?d00001 diff --git a/profiling/internal_external_time_linear.png b/profiling/internal_external_time_linear.png new file mode 100644 index 0000000000000000000000000000000000000000..8ec00fded8bda960f8bad4f9827d623ed165f1ee GIT binary patch literal 12210 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 literal 0 HcmV?d00001 diff --git a/profiling/internal_time_and_memory.png b/profiling/internal_time_and_memory.png new file mode 100644 index 0000000000000000000000000000000000000000..376f60d8f1533d5d92628161209e704cdb9bbb89 GIT binary patch literal 12691 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 literal 0 HcmV?d00001 diff --git a/profiling/internal_time_and_memory_linear.png b/profiling/internal_time_and_memory_linear.png new file mode 100644 index 0000000000000000000000000000000000000000..a3a18513e097697e4416dec81f5a9e63b6bf32e0 GIT binary patch literal 12165 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 azQmY$9ewht4tx?1(bm*O=bX2`_kRGvUNQav literal 0 HcmV?d00001 diff --git a/profiling/internal_time_and_memory_log.png b/profiling/internal_time_and_memory_log.png new file mode 100644 index 0000000000000000000000000000000000000000..835f207f04ebe411ace5e3606f4d1618de150686 GIT binary patch literal 12840 zcmd6OXIPWj7H%LEm1b;6cLG+VMnI6FLjbX$Qbg%Rg7gyUB|(lDrD+5qO7oyXK$?J* zP~sRtA%IGi8bN|m1CbJGcPHwMbLM!@bN}5RdBXE$*R|Jr*Sp^RapSCskE^U6(8V9^ z=Hrb}Jfx_4aM$H4SA5Z0N=jaTHc<5OcU6*)9=-qu+30)xA{qh_*vkHJLGGpPgg{i1 zjgiO9gVUx4LMm+n(r1>d5z^>_a3*~Vvf+g?va zpOb0RyjqOT_wH2cs4F~&dqql61DXMD{W3Oa0R{QtkheI%s?He14% zvA&91syBT4`1WR)7|h2rNDAKzmM`uID^Z6JnvJ0)+>cuAhquPzd@K@O=pP6n#w2(A z!w*ln@S(?%NxinwRxjGDdUe&0nhF?DjA4Er$TTU~8AD1De3;SXY|lN&nXG7in*r;@a2aaG6Gw7~BO(n6rEv#sz633QM%G zTd&5YUN9OcjjHEedurNen>>3OaXxu5&>ESx6?Vpe5)GS8Xj;;T&0e0Leu~>^#?o2Y z1DC#m6OeVv5ieTLf%%yspCsZMWrzD3E_3+_^ zrZC$ruo3wp772Gj8Wv`ugR#zRV

    OYcr43BN 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 literal 0 HcmV?d00001 diff --git a/profiling/run_times_log.png b/profiling/run_times_log.png new file mode 100644 index 0000000000000000000000000000000000000000..2098debecd5f00f01fff7a175ca192564b4bc0a3 GIT binary patch literal 14648 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 literal 0 HcmV?d00001 diff --git a/profiling/time-results.csv b/profiling/time-results.csv new file mode 100644 index 0000000..04e90b6 --- /dev/null +++ b/profiling/time-results.csv @@ -0,0 +1,27 @@ +Program,Elapsed time (s),Max memory +advent01, 00.39, 72440 +advent02, 00.41, 72440 +advent03, 00.37, 72504 +advent04, 00.43, 72504 +advent05, 00.43, 72440 +advent06, 00.41, 72504 +advent07, 00.39, 72444 +advent08, 00.44, 72508 +advent09, 00.66, 72508 +advent10, 00.36, 72444 +advent11, 16.75, 72504 +advent12, 00.38, 72508 +advent13, 00.36, 72436 +advent14, 00.61, 72508 +advent15, 02.15, 240372 +advent15loop, 01.88, 240444 +advent16, 00.38, 72444 +advent17, 01.77, 72444 +advent18, 00.39, 72444 +advent19, 00.46, 72504 +advent20, 04.12, 72436 +advent21, 00.39, 72508 +advent22, 02.02, 72500 +advent23, 01.91, 95500 +advent24, 03.48, 72504 +advent25, 00.41, 72504 diff --git a/profiling/time-results.md b/profiling/time-results.md new file mode 100644 index 0000000..70c50c0 --- /dev/null +++ b/profiling/time-results.md @@ -0,0 +1,27 @@ +| Program | Elapsed time (mm:ss) | Max memory | +| advent01 | 0:00.39 | 72440 | +| advent02 | 0:00.41 | 72440 | +| advent03 | 0:00.37 | 72504 | +| advent04 | 0:00.43 | 72504 | +| advent05 | 0:00.43 | 72440 | +| advent06 | 0:00.41 | 72504 | +| advent07 | 0:00.39 | 72444 | +| advent08 | 0:00.44 | 72508 | +| advent09 | 0:00.66 | 72508 | +| advent10 | 0:00.36 | 72444 | +| advent11 | 0:16.75 | 72504 | +| advent12 | 0:00.38 | 72508 | +| advent13 | 0:00.36 | 72436 | +| advent14 | 0:00.61 | 72508 | +| advent15 | 0:02.15 | 240372 | +| advent15loop | 0:01.88 | 240444 | +| advent16 | 0:00.38 | 72444 | +| advent17 | 0:01.77 | 72444 | +| advent18 | 0:00.39 | 72444 | +| advent19 | 0:00.46 | 72504 | +| advent20 | 0:04.12 | 72436 | +| advent21 | 0:00.39 | 72508 | +| advent22 | 0:02.02 | 72500 | +| advent23 | 0:01.91 | 95500 | +| advent24 | 0:03.48 | 72504 | +| advent25 | 0:00.41 | 72504 | diff --git a/profiling/times.csv b/profiling/times.csv new file mode 100644 index 0000000..57cd0b7 --- /dev/null +++ b/profiling/times.csv @@ -0,0 +1,25 @@ +cabal run advent01,0.19,0:02.61,295056 +cabal run advent02,0.03,0:00.30,78584 +cabal run advent03,0.02,0:00.29,78584 +cabal run advent04,0.02,0:00.31,77560 +cabal run advent05,0.13,0:00.69,77568 +cabal run advent06,0.03,0:00.30,78592 +cabal run advent07,0.04,0:00.31,77560 +cabal run advent08,0.15,0:01.21,77564 +cabal run advent09,0.03,0:00.30,78588 +cabal run advent10,0.03,0:00.29,78584 +cabal run advent11,0.03,0:00.31,78588 +cabal run advent12,0.19,0:01.47,77564 +cabal run advent13,0.04,0:00.29,77564 +cabal run advent14,0.02,0:00.32,77560 +cabal run advent15,0.22,0:01.70,78588 +cabal run advent16,0.04,0:00.31,77568 +cabal run advent17,0.02,0:00.30,78584 +cabal run advent18,0.09,0:00.46,78584 +cabal run advent19,0.10,0:04.08,78576 +cabal run advent20,0.29,0:02.73,207732 +cabal run advent21,0.19,0:01.36,78584 +cabal run advent22,0.11,0:01.06,78584 +cabal run advent23,2.27,0:27.17,98176 +cabal run advent24,4.12,0:28.00,78588 +cabal run advent25,0.22,0:04.57,77568 diff --git a/profiling/times_raw.csv b/profiling/times_raw.csv new file mode 100644 index 0000000..cfc98ea --- /dev/null +++ b/profiling/times_raw.csv @@ -0,0 +1,25 @@ +advent01,0.01,0:00.02,10212 +advent02,0.00,0:00.01,7876 +advent03,0.00,0:00.01,10760 +advent04,0.02,0:00.05,14236 +advent05,0.07,0:00.47,49372 +advent06,0.00,0:00.01,7948 +advent07,0.00,0:00.01,10164 +advent08,0.21,0:00.98,12252 +advent09,0.00,0:00.01,6644 +advent10,0.00,0:00.01,7456 +advent11,0.01,0:00.04,11272 +advent12,0.11,0:01.15,61132 +advent13,0.00,0:00.01,11504 +advent14,0.00,0:00.02,11020 +advent15,0.18,0:01.39,53240 +advent16,0.01,0:00.01,12128 +advent17,0.00,0:00.02,11604 +advent18,0.03,0:00.17,11812 +advent19,0.15,0:03.88,12524 +advent20,0.34,0:02.49,207144 +advent21,0.16,0:01.03,22020 +advent22,0.14,0:00.76,12508 +advent23,2.29,0:27.19,98824 +advent24,4.00,0:27.92,12432 +advent25,0.19,0:04.21,13748 -- 2.34.1 From 1ab3e062eb1b3b28a8aead9834afc962ca142451 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Tue, 14 Jun 2022 14:53:39 +0100 Subject: [PATCH 16/16] Tweaked some parsing code --- advent21/Main.hs | 2 +- advent22/Main.hs | 3 ++- advent24/Main.hs | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/advent21/Main.hs b/advent21/Main.hs index 01d23e7..3048daf 100644 --- a/advent21/Main.hs +++ b/advent21/Main.hs @@ -113,7 +113,7 @@ mod1 a b = ((a - 1) `mod` b) + 1 -- Parsing -playerP = ("1" *> pure Player1) <|> ("2" *> pure Player2) +playerP = (Player1 <$ "1") <|> (Player2 <$ "2") playerStateP = playerify <$> ("Player " *> playerP) <*> (" starting position: " *> decimal) where playerify name pos = (name, PlayerState {position = pos, score = 0}) diff --git a/advent22/Main.hs b/advent22/Main.hs index dc67b3f..ca6bddd 100644 --- a/advent22/Main.hs +++ b/advent22/Main.hs @@ -99,7 +99,8 @@ cuboidP = cubify <$> (partiyP <* " ") <*> (boundsP `sepBy` ",") } vecify [c1, c2, c3] = V3 c1 c2 c3 -partiyP = ("on" *> pure On) <|> ("off" *> pure Off) +-- partiyP = ("on" *> pure On) <|> ("off" *> pure Off) +partiyP = (On <$ "on") <|> (Off <$ "off") boundsP = (,) <$> (("x" <|> "y" <|> "z") *> "=" *> signed decimal) <*> (".." *> signed decimal) diff --git a/advent24/Main.hs b/advent24/Main.hs index ae03fac..e1836b2 100644 --- a/advent24/Main.hs +++ b/advent24/Main.hs @@ -217,10 +217,10 @@ eqlP = Eql <$> ("eql " *> registerP) <*> (" " *> argumentP) registerP, wP, xP, yP, zP :: Parser Register registerP = choice [wP, xP, yP, zP] -wP = "w" *> pure W -xP = "x" *> pure X -yP = "y" *> pure Y -zP = "z" *> pure Z +wP = W <$ "w" +xP = X <$ "x" +yP = Y <$ "y" +zP = Z <$ "z" argumentP :: Parser Argument argumentP = (Reg <$> registerP) <|> (Lit <$> signed decimal) -- 2.34.1