module Main (main) where -- | Part 1 type Report = [Int] grabReports :: String -> [Report] grabReports = map (map (\x -> read x :: Int) . words) . lines isReportSafeWith :: (Int -> Int -> Bool) -> Report -> Bool isReportSafeWith _ [] = True isReportSafeWith _ [_] = True isReportSafeWith f (x : y : xs) = f x y && isReportSafeWith f (y : xs) reportDecreasing :: Int -> Int -> Bool reportDecreasing x y = 1 <= x - y && x - y <= 3 reportIncreasing :: Int -> Int -> Bool reportIncreasing x y = 1 <= y - x && y - x <= 3 isReportSafe :: Report -> Bool isReportSafe report = isReportSafeWith reportDecreasing report || isReportSafeWith reportIncreasing report part1 :: String -> IO () part1 = print . length . filter isReportSafe . grabReports -- | Part 2 removeItem :: Int -> Report -> Report removeItem n report = removeItem' n report 0 where removeItem' :: Int -> Report -> Int -> Report removeItem' _ [] _ = [] removeItem' n' (r : rs) i | n' == i = removeItem' n' rs (i + 1) | otherwise = r : removeItem' n' rs (i + 1) reportPermutations :: Report -> [Report] reportPermutations report = report : [removeItem i report | i <- [0 .. length report - 1]] isReportSafePerm :: Report -> Bool isReportSafePerm report = any isReportSafe (reportPermutations report) part2 :: String -> IO () part2 = print . length . filter isReportSafePerm . grabReports -- | Main main :: IO () main = readFile "resources/day2.txt" >>= part2