aoc2022/19-a.hs

67 lines
1.9 KiB
Haskell

{-# LANGUAGE InstanceSigs #-}
import Common
-- not to be confused with AStar.hs! that one was bugged :)
import Data.Graph.AStar
import Data.List.Split (splitOn)
import Data.List (elemIndex)
import Data.Maybe (fromJust, mapMaybe)
import qualified Data.Map.Strict as M
import Data.Map.Strict (Map, (!))
import qualified Data.HashSet as HS
import Data.HashSet (HashSet)
import Data.Hashable (Hashable (hash, hashWithSalt))
import Data.Bits
data Material = Ore | Clay | Obsidian | Geode
deriving (Eq, Show)
newtype Robot = Robot Material
deriving (Eq, Show)
data Recipe = Recipe [(Int, Material)] Robot
deriving (Eq, Show)
type Blueprint = [Recipe]
parseMaterial :: String -> Material
parseMaterial "ore" = Ore
parseMaterial "clay" = Clay
parseMaterial "obsidian" = Obsidian
parseMaterial "geode" = Geode
parseMaterial _ = undefined
parseRecipe :: String -> Maybe Recipe
parseRecipe s = do
let split = words s
typeIndex <- elemIndex "Each" split
recipeIndex <- elemIndex "costs" split
let ingredients = map ((\[a, b] -> (read a, parseMaterial b)) . words . trim) $ splitOn "and" $ unwords $ drop (recipeIndex + 1) split
let robotType = parseMaterial $ split !! (typeIndex + 1)
return $ Recipe ingredients (Robot robotType)
parse :: String -> [Recipe]
parse s = mapMaybe parseRecipe recipes
where
recipes = map trim $ splitOn "." s
newtype State = State (Map Material Int, Map Robot Int, Int)
deriving (Eq)
-- for Some reason hashable doesn't export these. Cool :)
hashInt s x = (s * 16777619) `xor` x
defaultHashWithSalt salt x = salt `hashInt` hash x
instance Hashable State where
hash :: State -> Int
hash (State (materials, robots, minute)) = foldr hashInt minute (M.elems materials ++ M.elems robots)
hashWithSalt :: Int -> State -> Int
hashWithSalt = defaultHashWithSalt
nextNodes :: Blueprint -> State -> HashSet State
nextNodes recipes s = set
where set = HS.fromList [s]
main = interact $
show
. map parse . lines