{-# Language QuasiQuotes, TemplateHaskell #-}
module Main (main) where
import Advent (format, arrIx, stageTH)
import Data.Array (range, (!), listArray)
import Data.List (intercalate)
data C = C_HASH | C_DOT | C_QUESTION
stageTH
main :: IO ()
IO ()
main =
do input <- [format|2023 12 (@C* %d&,%n)*|]
print (sum [ways g s | (s,g) <- input])
print (sum [ways (concat (replicate 5 g)) (unfoldSprings s) | (s,g) <- input])
unfoldSprings :: [C] -> [C]
unfoldSprings :: [C] -> [C]
unfoldSprings = [C] -> [[C]] -> [C]
forall a. [a] -> [[a]] -> [a]
intercalate [C
C_QUESTION] ([[C]] -> [C]) -> ([C] -> [[C]]) -> [C] -> [C]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [C] -> [[C]]
forall a. Int -> a -> [a]
replicate Int
5
ways :: [Int] -> [C] -> Int
ways :: [Int] -> [C] -> Int
ways [Int]
groups [C]
springs = Array (Int, Int) Int
answersA Array (Int, Int) Int -> (Int, Int) -> Int
forall i e. Ix i => Array i e -> i -> e
! (Int
0,Int
0)
where
groupsN :: Int
groupsN = [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
groups
groupsA :: Array Int Int
groupsA = (Int, Int) -> [Int] -> Array Int Int
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0, Int
groupsN Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [Int]
groups
springsN :: Int
springsN = [C] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [C]
springs
springsA :: Array Int C
springsA = (Int, Int) -> [C] -> Array Int C
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0, Int
springsN Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [C]
springs
answersB :: ((Int, Int), (Int, Int))
answersB = ((Int
0, Int
0), (Int
groupsN, Int
springsN))
answersA :: Array (Int, Int) Int
answersA = ((Int, Int), (Int, Int)) -> [Int] -> Array (Int, Int) Int
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray ((Int, Int), (Int, Int))
answersB [Int -> Int -> Int
go Int
i Int
j | (Int
i,Int
j) <- ((Int, Int), (Int, Int)) -> [(Int, Int)]
forall a. Ix a => (a, a) -> [a]
range ((Int, Int), (Int, Int))
answersB]
rec :: Int -> Int -> Int
rec Int
groupI Int
springI = Array (Int, Int) Int
answersA Array (Int, Int) Int -> (Int, Int) -> Int
forall i e. Ix i => Array i e -> i -> e
! (Int
groupI, Int
springI)
go :: Int -> Int -> Int
go Int
groupI Int
springI =
let dotCase :: Int
dotCase = Int -> Int -> Int
rec Int
groupI (Int
springI Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
hashCase :: Int
hashCase = Int -> Int -> Int
startGroup Int
groupI (Int
springI Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
{-# Inline hashCase #-} in
case Array Int C -> Int -> Maybe C
forall (a :: * -> * -> *) e i (f :: * -> *).
(IArray a e, Ix i, Alternative f) =>
a i e -> i -> f e
arrIx Array Int C
springsA Int
springI of
Maybe C
Nothing -> if Int
groupI Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
groupsN then Int
1 else Int
0
Just C
C_DOT -> Int
dotCase
Just C
C_HASH -> Int
hashCase
Just C
C_QUESTION -> Int
hashCase Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dotCase
startGroup :: Int -> Int -> Int
startGroup Int
groupI Int
springI =
case Array Int Int -> Int -> Maybe Int
forall (a :: * -> * -> *) e i (f :: * -> *).
(IArray a e, Ix i, Alternative f) =>
a i e -> i -> f e
arrIx Array Int Int
groupsA Int
groupI of
Just Int
n -> Int -> Int -> Int -> Int
loopGroup (Int
groupI Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int
springI (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
Maybe Int
Nothing -> Int
0
loopGroup :: Int -> Int -> Int -> Int
loopGroup Int
groupI Int
springI Int
0 =
let dotCase :: Int
dotCase = Int -> Int -> Int
rec Int
groupI (Int
springI Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) in
case Array Int C -> Int -> Maybe C
forall (a :: * -> * -> *) e i (f :: * -> *).
(IArray a e, Ix i, Alternative f) =>
a i e -> i -> f e
arrIx Array Int C
springsA Int
springI of
Maybe C
Nothing -> if Int
groupI Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
groupsN then Int
1 else Int
0
Just C
C_DOT -> Int
dotCase
Just C
C_HASH -> Int
0
Just C
C_QUESTION -> Int
dotCase
loopGroup Int
groupI Int
springI Int
n =
let hashCase :: Int
hashCase = Int -> Int -> Int -> Int
loopGroup Int
groupI (Int
springI Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) in
case Array Int C -> Int -> Maybe C
forall (a :: * -> * -> *) e i (f :: * -> *).
(IArray a e, Ix i, Alternative f) =>
a i e -> i -> f e
arrIx Array Int C
springsA Int
springI of
Maybe C
Nothing -> Int
0
Just C
C_DOT -> Int
0
Just C
C_HASH -> Int
hashCase
Just C
C_QUESTION -> Int
hashCase