improved 12
This commit is contained in:
parent
46a6c20cde
commit
cec5485fda
|
@ -3,25 +3,79 @@ module Main where
|
|||
import Data.Char
|
||||
import Data.List
|
||||
import qualified Data.Map as M
|
||||
import Debug.Trace
|
||||
|
||||
type Db = M.Map String Node
|
||||
|
||||
data Path =
|
||||
Simple [String]
|
||||
| Extra [String]
|
||||
deriving Show
|
||||
data Node = Node {
|
||||
big :: Bool
|
||||
, nbs :: [String]
|
||||
} deriving Show
|
||||
|
||||
type Path = [String]
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
raw <- getContents
|
||||
let input = mkDb $ map splitInp $ lines raw
|
||||
let input = findPaths [ Simple ["start"] ] [] $ mkDb $ map splitInp $ lines raw
|
||||
in do
|
||||
putStrLn $ "day12a: " ++ (show $ solveA 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 adjs = foldl f (M.fromList $ (map mkInitDb $ getUniques adjs)) adjs
|
||||
where
|
||||
|
@ -36,49 +90,3 @@ mkInitDb s = (,) s
|
|||
|
||||
getUniques :: [(String,String)] -> [String]
|
||||
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
7
code/src/12/test.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
start-A
|
||||
start-b
|
||||
A-c
|
||||
A-b
|
||||
b-d
|
||||
A-end
|
||||
b-end
|
Loading…
Reference in a new issue