Easy one to get through, no edge-cases biting me this time.
I learned this year again: running in interpreted mode can cause significant slowdowns. Later, I'll hopefully find the time clean it up, this solution feels ugly. Reading everyone else did it also like this or with regex makes me feel better about it though.
Haskell
Code from this morning (AoC is at 06:00 at my place)
module Main (main) where
import qualified Text.ParserCombinators.ReadP as ReadP
import Numeric.Natural (Natural)
import Control.Monad ((<$!>), guard)
import qualified Data.List as List
import Control.Arrow ((>>>))
import qualified Data.Text as Text
import qualified Data.Foldable as Foldable
newtype Range = Range { getRange :: (Natural, Natural) }
deriving Show
parseRange :: ReadP.ReadP Range
parseRange = do
n1 <- ReadP.readS_to_P reads
_ <- ReadP.char '-'
n2 <- ReadP.readS_to_P reads
pure . Range $ (n1, n2)
parseLine :: ReadP.ReadP [Range]
parseLine = parseRange `ReadP.sepBy` ReadP.char ','
main :: IO ()
main = do
ranges <- fst . last . ReadP.readP_to_S parseLine <$!> getContents
print $ part1 ranges
print $ part2 ranges
part1 :: [Range] -> Natural
part1 = List.concatMap (uncurry enumFromTo . getRange)
>>> List.filter isDoublePattern
>>> Foldable.sum
part2 :: [Range] -> Natural
part2 = List.concatMap (uncurry enumFromTo . getRange)
>>> List.filter isMultiplePattern
>>> Foldable.sum
isMultiplePattern :: Natural -> Bool
isMultiplePattern n = let
textN = Text.show n
textLength = Text.length textN
in flip any (divisorsOf textLength) $ \ divisor -> let
patternLength = textLength `div` divisor
patternPart = Text.take (fromIntegral patternLength) textN
in Text.replicate (fromIntegral divisor) patternPart == textN
isDoublePattern :: Natural -> Bool
isDoublePattern n = let
textN = Text.show n
evenLength = even (Text.length textN)
(first, second) = Text.splitAt (Text.length textN `div` 2) textN
in evenLength && first == second
divisorsOf :: Integral b => b -> [b]
divisorsOf n = do
x <- [2..n]
guard ((n `mod` x) == 0)
pure x
Using the interpreter, this solution made me wait for two minutes until I could submit. x.x After testing it again in compiled mode, it only takes four seconds.