module AdventOfCode where import Data.Char import Data.List import Data.List.Unique (allUnique) import Data.Maybe import Data.Array -- Day 1 pairs j xs = take (length xs) $ zip (cycle xs) $ drop j (cycle xs) hash = sum . map fst . filter (uncurry (==)) captcha j = show . hash . pairs j . map digitToInt captcha1 = captcha 1 captcha2 ds = captcha (length ds `div` 2) ds -- Day 2 readCells :: String -> [[Int]] readCells = map (map read) . map words . lines minmax xs = (minimum xs, maximum xs) checksum buff = show $ sum $ map (uncurry . flip $ (-)) . map minmax $ readCells buff -- Day 2 calculateRow row = result where sorted = reverse . sort $ row result = fromJust $ fmap (uncurry div) $ find ((==) 0 . uncurry rem) [ (i, j) | i <- sorted, j <- tail sorted, j < i ] sumEvenlyDivisibleValues buff = show $ sum . map calculateRow $ readCells buff -- Day 3 chunk (b, t) = let seq = [(t-1), (t-2)..(b)] ++ [(b+1)..(t+1)] in concat . replicate 4 $ take (length seq - 1) seq memory = [0,0,1,2,1,2,1,2,1,2] ++ (concatMap chunk $ zip [2..] [4,6..]) distanceToAddress buff = show $ memory !! (read buff) -- Day 4 readDay4 :: String -> [[String]] readDay4 = map words . lines both fn gn x = fn x && gn x validPassPhrase1 = allUnique boolToInt True = 1 boolToInt False = 0 validPassPhrase2 = both allUnique noPermutations noPermutations :: [String] -> Bool noPermutations phrase = all noPermutations' phrase where noPermutations' word = all ((flip notElem) (filter ((/=) word) phrase)) (permutations word) day41 buff = show $ sum . map (boolToInt . validPassPhrase1) $ readDay4 buff day42 buff = show $ sum . map (boolToInt . validPassPhrase2) $ readDay4 buff -- Day 5 type Program = (Array Int Int, Int) data Solution = Partial Program Int | Complete Int inBounds (a, b) x = a <= x && x <= b -- Part 1 -- runProgram (Complete jumps) = jumps -- runProgram (Partial (instructions, pointer) jumps) = -- if inBounds bounds' next -- then runProgram $ Partial ((instructions // update), next) jumps' -- else runProgram $ Complete jumps' -- where -- instruction = instructions ! pointer -- next = pointer + instruction -- bounds' = bounds instructions -- jumps' = jumps + 1 -- update = [(pointer, instruction + 1)] -- Part 2 runProgram (Complete jumps) = jumps runProgram (Partial (instructions, pointer) jumps) = if inBounds bounds' next then runProgram $ Partial ((instructions // update), next) jumps' else runProgram $ Complete jumps' where instruction = instructions ! pointer next = pointer + instruction bounds' = bounds instructions jumps' = jumps + 1 updatedInstruction = if instruction > 2 then instruction - 1 else instruction + 1 update = [(pointer, updatedInstruction)] makeProgram xs = Partial (listArray (0, length xs - 1) xs, 0) 0 day51 = show . runProgram . makeProgram . map read . lines