import Data.List.Split (splitOn) lineSafe' :: [Int] -> Bool lineSafe' [] = True lineSafe' l@(_:xs) = (all (> 0) diffs || all (< 0) diffs) && all validItem diffs where diffs = zipWith (-) xs l validItem x = x /= 0 && abs x <= 3 allRemoved :: [a] -> [[a]] allRemoved [] = [] allRemoved (x:xs) = xs:map (x:) (allRemoved xs) lineSafe :: [Int] -> Bool lineSafe = any lineSafe' . allRemoved main :: IO () main = print . length . filter testLine . lines =<< readFile "data.txt" where testLine = lineSafe . map read . splitOn " "