DEV Community

Discussion on: Advent of Code 2019 Solution Megathread - Day 4: Secure Container

Collapse
 
nordfjord profile image
Einar Norðfjörð

Haskell solution

module Main where

import           Data.List

splitWhen :: (Char -> Bool) -> String -> [String]
splitWhen p s =
  case dropWhile p s of
    "" -> []
    s' -> w : splitWhen p s''
      where (w, s'') = break p s'

toPair :: [a] -> (a, a)
toPair (x:y:xs) = (x, y)

isAscending :: String -> Bool
isAscending []       = True
isAscending [_]      = True
isAscending (x:y:xs) = x <= y && isAscending (y : xs)

hasAdjacentDigits :: String -> Bool
hasAdjacentDigits xs = any (> 1) (length <$> group xs)

hasAdjacentDigitsInGroups :: String -> Bool
hasAdjacentDigitsInGroups xs =
  let sequenceLengths = length <$> group xs
   in (any (== 2) sequenceLengths)

validate :: String -> Bool
validate xs = (isAscending xs) && (hasAdjacentDigits xs)

validatePart2 :: String -> Bool
validatePart2 xs = (isAscending xs) && (hasAdjacentDigitsInGroups xs)

main :: IO ()
main = do
  (from, to) <- getContents >>= pure . splitWhen (== '-') >>= pure . toPair
  putStrLn "Part 1"
  putStrLn "Test Cases:"
  print $
    length $
    filter (== True) $
    (validate . show) <$> [(read from :: Int) .. (read to :: Int)]
  putStr "\n\n"
  putStrLn "Part 2"
  print $
    length $
    filter (== True) $
    (validatePart2 . show) <$> [(read from :: Int) .. (read to :: Int)]