improved 12

This commit is contained in:
thornAvery 2021-12-14 03:17:58 +00:00
parent 46a6c20cde
commit cec5485fda
2 changed files with 66 additions and 51 deletions

View file

@ -3,25 +3,79 @@ module Main where
import Data.Char import Data.Char
import Data.List import Data.List
import qualified Data.Map as M import qualified Data.Map as M
import Debug.Trace
type Db = M.Map String Node type Db = M.Map String Node
data Path =
Simple [String]
| Extra [String]
deriving Show
data Node = Node { data Node = Node {
big :: Bool big :: Bool
, nbs :: [String] , nbs :: [String]
} deriving Show } deriving Show
type Path = [String]
main :: IO () main :: IO ()
main = do main = do
raw <- getContents raw <- getContents
let input = mkDb $ map splitInp $ lines raw let input = findPaths [ Simple ["start"] ] [] $ mkDb $ map splitInp $ lines raw
in do in do
putStrLn $ "day12a: " ++ (show $ solveA input) putStrLn $ "day12a: " ++ (show $ solveA input)
putStrLn $ "day12b: " ++ (show $ solveB input) putStrLn $ "day12b: " ++ (show $ solveB input)
solveA :: [Path] -> Int
solveA ps = length $ [ x | Simple x <- ps ]
solveB :: [Path] -> Int
solveB = length
findPaths :: [Path] -> [Path] -> Db -> [Path]
findPaths [] comp _ = comp
findPaths (k:ks) comp db =
if rec k == "end"
then findPaths ks (k:comp) db
else case k of
(Extra ps) -> go stepExtra ps
(Simple ps) -> go stepSimple ps
where
rec (Extra (k:_)) = k
rec (Simple (k:_)) = k
rec _ = error "empty path"
go f ps = findPaths ((f db ps) ++ ks) comp db
stepExtra :: Db -> [String] -> [Path]
stepExtra _ [] = error "empty list"
stepExtra db ps = map (Extra . (flip (:) ps)) (l (head ps) db)
where
isBig s = isUpper $ head s
l k db = filter (\n -> (n /= "start") && ((isBig n) || not (n `elem` ps))) $ nbs $ db M.! k
stepSimple :: Db -> [String] -> [Path]
stepSimple _ [] = error "empty list"
stepSimple db ps = map (\p -> (c (p:ps))) (l (head ps) db)
where
isBig s = isUpper $ head s
c ps = if isBig (head ps)
then Simple ps
else
let smalls = filter (not . isBig) ps
in if any (== (head smalls)) (tail smalls)
then Extra ps
else Simple ps
l k db = filter (/= "start") $ nbs $ db M.! k
-- io and parsing
splitInp :: String -> (String,String)
splitInp s = (\(a,b) -> (a, drop 1 b)) $ splitAt n s
where
n = findIn '-' s
findIn :: Char -> String -> Int
findIn c s = go 0 c s
where
go n c (s:ss) = if c == s then n else go (n+1) c ss
go n c [] = error "bad parse"
mkDb :: [(String,String)] -> Db mkDb :: [(String,String)] -> Db
mkDb adjs = foldl f (M.fromList $ (map mkInitDb $ getUniques adjs)) adjs mkDb adjs = foldl f (M.fromList $ (map mkInitDb $ getUniques adjs)) adjs
where where
@ -36,49 +90,3 @@ mkInitDb s = (,) s
getUniques :: [(String,String)] -> [String] getUniques :: [(String,String)] -> [String]
getUniques is = nub $ foldl (\t (a,b) -> (a:b:t)) [] is getUniques is = nub $ foldl (\t (a,b) -> (a:b:t)) [] is
findPaths :: (Db -> [String] -> [[String]]) -> [[String]] -> [[String]] -> Db -> [[String]]
findPaths f [] comp _ = comp
findPaths f (k:ks) comp db = findPaths f (ks ++ new) (nk comp) db
where
nk = if (head k) == "end"
then (k:)
else id
new = if (head k) /= "end"
then f db k
else []
nextSteps :: Db -> [String] -> [[String]]
nextSteps db me = filter f $ map (\n -> (n:me)) nobs
where
f ss = (isUpper $ (head . head) ss)
|| not (any (\n -> n == (head ss)) (tail ss))
nobs = (nbs $ db M.! (head me))
nextSteps' :: Db -> [String] -> [[String]]
nextSteps' db me = filter f $ map (\n -> (n:me)) nobs
where
f ss = (isUpper $ (head . head) ss)
|| length (g ss) == length (nub (g ss))+1
|| not (any (\n -> n == (head ss)) (tail ss))
nobs = filter (/= "start") (nbs $ db M.! (head me))
g ss = filter (\s -> not $ isUpper (head s)) ss
solveA :: Db -> Int
solveA db = length $ findPaths nextSteps [["start"]] [] db
solveB :: Db -> Int
solveB db = length $ findPaths nextSteps' [["start"]] [] db
-- io and parsing
splitInp :: String -> (String,String)
splitInp s = (\(a,b) -> (a, drop 1 b)) $ splitAt n s
where
n = findIn '-' s
findIn :: Char -> String -> Int
findIn c s = go 0 c s
where
go n c (s:ss) = if c == s then n else go (n+1) c ss
go n c [] = error "bad parse"

7
code/src/12/test.txt Normal file
View file

@ -0,0 +1,7 @@
start-A
start-b
A-c
A-b
b-d
A-end
b-end