X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=adventofcode16%2Fapp%2Fadvent04.hs;fp=adventofcode16%2Fapp%2Fadvent04.hs;h=85b75552678ec85137db5b479dca8450e0e6610b;hb=fd498a2713d69a5d55179ff07e58ce296d6fba94;hp=0000000000000000000000000000000000000000;hpb=3a26b187d5dc23b05fb73daabe52a92976a7a3c7;p=advent-of-code-16.git diff --git a/adventofcode16/app/advent04.hs b/adventofcode16/app/advent04.hs new file mode 100644 index 0000000..85b7555 --- /dev/null +++ b/adventofcode16/app/advent04.hs @@ -0,0 +1,66 @@ +module Main(main) where + +import Data.List (last, intersperse, sortBy, intercalate, isInfixOf, init) +import Data.List.Split (splitOn) +import Data.Char (isLetter, ord, chr) +import qualified Data.Map.Lazy as Map + +data Room = Room { name :: String + , sector :: Int + , checksum :: String + } deriving (Show) + +main :: IO () +main = do + instrText <- readFile "data/advent04.txt" + let rooms = map (parseLine) $ lines instrText + part1 rooms + part2 rooms + + +part1 :: [Room] -> IO () +part1 rooms = do + print $ sum $ map (sector) validRooms + where + validChecksum room = (checksum room) == makeChecksum (name room) + validRooms = filter (validChecksum) rooms + +part2 :: [Room] -> IO () +part2 rooms = do + print $ fst $ head $ filter (\sn -> isInfixOf "north" (snd sn)) sectorNames + where + validChecksum room = (checksum room) == makeChecksum (name room) + validRooms = filter (validChecksum) rooms + sectorNames = [((sector r), + shiftWord (sector r) (name r)) | r <- validRooms] + + +parseLine :: String -> Room +parseLine line = Room {name=name, sector=sector, checksum=checksum} + where components = splitOn "-" line + name = intercalate "-" $ init components + sector = read $ head $ splitOn "[" $ last components + checksum = filter (isLetter) $ last components + +countedLetters :: String -> [(Char, Int)] +countedLetters name = sortBy sortCLetter $ unsortedCountedLetters name + where unsortedCountedLetters name = + Map.toList $ Map.fromListWith (+) [(c, 1) | c <- filter (isLetter) name] + +sortCLetter :: (Char, Int) -> (Char, Int) -> Ordering +sortCLetter (l1, n1) (l2, n2) + | n1 < n2 = GT + | n1 > n2 = LT + | n1 == n2 = compare l1 l2 + +makeChecksum :: String -> String +makeChecksum name = [l | (l, _) <- take 5 $ countedLetters name] + + +shiftWord :: Int -> String -> String +shiftWord shift letters = map (shiftLetter shift) letters + +shiftLetter :: Int -> Char -> Char +shiftLetter shift letter + | isLetter letter = chr $ (ord letter - ord 'a' + shift) `mod` 26 + ord 'a' + | otherwise = ' '