Generalise puzzle parts type

This commit is contained in:
George Thomas 2026-01-04 02:14:35 +00:00
parent 8442ce8dba
commit 784e6f2fb2
2 changed files with 39 additions and 21 deletions

View File

@ -2,6 +2,8 @@ module Main (main) where
import Pre import Pre
import Data.Functor.Contravariant
import Data.Functor.Identity
import Data.Text.IO qualified as T import Data.Text.IO qualified as T
import Puzzles.Day1 qualified as Day1 import Puzzles.Day1 qualified as Day1
import Puzzles.Day10 qualified as Day10 import Puzzles.Day10 qualified as Day10
@ -39,7 +41,9 @@ main =
in in
describe pt do describe pt do
input <- liftIO $ parseFile $ "../inputs/" <> t <> "/" <> pt input <- liftIO $ parseFile $ "../inputs/" <> t <> "/" <> pt
let (os, rs) = applyPuzzleParts input parts let (rs, os) =
((unHListF . mapHListF (Const . fst)) &&& (fromHListF . mapHListF (Identity . snd))) $
mapHListF (\(Fanout (f, Op o)) -> (o &&& id) $ f input) parts
for_ (zip [1 :: Int ..] rs) $ uncurry $ \(show -> n) -> for_ (zip [1 :: Int ..] rs) $ uncurry $ \(show -> n) ->
it n . pureGoldenTextFile ("../outputs/" <> t <> "/" <> pt <> "/" <> n) . (<> "\n") it n . pureGoldenTextFile ("../outputs/" <> t <> "/" <> pt <> "/" <> n) . (<> "\n")
describe "extra" $ extraTests isRealData ("../outputs/" <> t <> "/" <> pt <> "/extra/") input os describe "extra" $ extraTests isRealData ("../outputs/" <> t <> "/" <> pt <> "/extra/") input os

View File

@ -41,11 +41,14 @@ module Pre (
allUnorderedPairs, allUnorderedPairs,
adjacentPairs, adjacentPairs,
sortPair, sortPair,
PuzzleParts, HListF (..),
applyPuzzleParts, mapHListF,
fromHListF,
unHListF,
(/\), (/\),
(/\\), (/\\),
nil, nil,
Fanout (..),
) )
where where
@ -73,6 +76,8 @@ import Data.Foldable hiding (foldl1, foldr1, maximum, maximumBy, minimum, minimu
import Data.Foldable1 import Data.Foldable1
import Data.Function import Data.Function
import Data.Functor import Data.Functor
import Data.Functor.Contravariant
import Data.Functor.Identity
import Data.Kind (Type) import Data.Kind (Type)
import Data.List (List, sortOn, transpose) import Data.List (List, sortOn, transpose)
import Data.List.Extra (dropEnd, enumerate, firstJust, notNull, splitOn) import Data.List.Extra (dropEnd, enumerate, firstJust, notNull, splitOn)
@ -127,32 +132,41 @@ adjacentPairs = \case
sortPair :: (Ord a) => (a, a) -> (a, a) sortPair :: (Ord a) => (a, a) -> (a, a)
sortPair (a, b) = if a <= b then (a, b) else (b, a) sortPair (a, b) = if a <= b then (a, b) else (b, a)
type PuzzleParts input = HListF (Fanout ((->) input) (Op Text))
infixr 9 /\\ infixr 9 /\\
(/\\) :: (input -> output, output -> Text) -> PuzzleParts input outputs -> PuzzleParts input (output : outputs) (/\\) :: (input -> output, output -> Text) -> PuzzleParts input outputs -> PuzzleParts input (output : outputs)
(/\\) = uncurry PuzzlePartsCons (/\\) (f, o) = HConsF $ Fanout (f, Op o)
infixr 9 /\ infixr 9 /\
(/\) :: (Show output) => (input -> output) -> PuzzleParts input outputs -> PuzzleParts input (output : outputs) (/\) :: (Show output) => (input -> output) -> PuzzleParts input outputs -> PuzzleParts input (output : outputs)
(/\) = flip PuzzlePartsCons T.show (/\) f = HConsF $ Fanout (f, Op T.show)
nil :: PuzzleParts input '[] nil :: PuzzleParts input '[]
nil = PuzzlePartsNil nil = HNilF
data PuzzleParts (input :: Type) (outputs :: List Type) :: Type where data HListF (f :: Type -> Type) (as :: List Type) :: Type where
PuzzlePartsNil :: PuzzleParts input '[] HNilF :: HListF f '[]
PuzzlePartsCons :: HConsF ::
(input -> output) -> f a ->
(output -> Text) -> HListF f as ->
PuzzleParts input outputs -> HListF f (a ': as)
PuzzleParts input (output ': outputs)
applyPuzzleParts :: mapHListF :: (forall a. f a -> g a) -> HListF f as -> HListF g as
forall input outputs. mapHListF t = \case
input -> HNilF -> HNilF
PuzzleParts input outputs -> HConsF x xs -> HConsF (t x) $ mapHListF t xs
(HList outputs, [Text])
applyPuzzleParts e = \case fromHListF :: HListF Identity as -> HList as
PuzzlePartsNil -> (HNil, []) fromHListF = \case
PuzzlePartsCons f o ps -> let r = f e in bimap (HCons r) (o r :) $ applyPuzzleParts e ps HNilF -> HNil
HConsF (Identity x) xs -> HCons x $ fromHListF xs
unHListF :: HListF (Const b) as -> List b
unHListF = \case
HNilF -> []
HConsF (Const x) xs -> x : unHListF xs
instance Semigroup (TestDefM a b ()) where instance Semigroup (TestDefM a b ()) where
(<>) = (>>) (<>) = (>>)
instance Monoid (TestDefM a b ()) where instance Monoid (TestDefM a b ()) where
mempty = pure () mempty = pure ()
newtype Fanout f g a = Fanout (f a, g a)