parent
5d482a4230
commit
84c70f3f43
3 changed files with 1228 additions and 0 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,69 @@ |
||||
{-# LANGUAGE OverloadedStrings #-} |
||||
|
||||
module Day6 |
||||
( |
||||
module Day6 |
||||
) where |
||||
|
||||
import qualified Data.Attoparsec.Text as P |
||||
import qualified Data.Text as T |
||||
import qualified Data.Map as M |
||||
import Control.Applicative (liftA2, (<|>)) |
||||
import Data.Maybe |
||||
import Data.Semigroup |
||||
import Data.List ((\\)) |
||||
|
||||
type DistanceOrbits = [T.Text] |
||||
type OrbitMap = M.Map T.Text DistanceOrbits |
||||
|
||||
parseOrbits :: P.Parser OrbitMap |
||||
parseOrbits = |
||||
M.fromListWith (++) <$> P.many1 parseOrbitLine |
||||
|
||||
parseOrbitLine :: P.Parser (T.Text, DistanceOrbits) |
||||
parseOrbitLine = do |
||||
key <- P.takeWhile (/= ')') |
||||
P.char ')' |
||||
val <- P.takeWhile (/= '\n') |
||||
P.char '\n' |
||||
return (key, [val]) |
||||
|
||||
countOrbits :: String -> Integer |
||||
countOrbits s = let m = parseOrbits' s in |
||||
countOrbits' ("COM", 0) m |
||||
|
||||
parseOrbits' :: String -> OrbitMap |
||||
parseOrbits' s = let parsed = P.parse parseOrbits (T.pack s) in |
||||
case parsed of |
||||
P.Done _ r -> r |
||||
P.Partial f -> |
||||
fromMaybe M.empty |
||||
(P.maybeResult (P.feed parsed "")) |
||||
_ -> M.empty |
||||
|
||||
countOrbits' :: (T.Text, Integer) -> OrbitMap -> Integer |
||||
countOrbits' (root, currDist) m = |
||||
let mxs = m M.!? root in |
||||
case mxs of |
||||
Nothing -> currDist |
||||
Just xs -> foldr (\a b -> b + countOrbits' (a, currDist + 1) m ) currDist xs |
||||
|
||||
pathFromRoot :: T.Text -> OrbitMap -> [T.Text] |
||||
pathFromRoot result m = fromMaybe [] $ go "COM" [] |
||||
where go x out = |
||||
if x == result |
||||
then Just (out ++ [result]) |
||||
else case m M.!? x of |
||||
Nothing -> Nothing |
||||
Just ys -> getFirst <$> |
||||
foldr ((<>) . fmap First) |
||||
Nothing |
||||
(fmap (\a -> go a (out ++ [x])) ys) |
||||
|
||||
nOrbits :: String -> Integer |
||||
nOrbits s = |
||||
let m = parseOrbits' s |
||||
p1 = pathFromRoot "YOU" m |
||||
p2 = pathFromRoot "SAN" m |
||||
in |
||||
fromIntegral $ length (p1 \\ p2) + length (p2 \\ p1) - 2 |
Loading…
Reference in new issue