39 lines
1.0 KiB
Haskell
39 lines
1.0 KiB
Haskell
import Data.List
|
|
import Data.List.Split
|
|
import Data.Char (isDigit)
|
|
|
|
main :: IO ()
|
|
main = do
|
|
input <- readFile "5/riley.txt"
|
|
let x = parse <$> lines input
|
|
print $ f x
|
|
print $ g x
|
|
where
|
|
f = solve . filter (not . diagonal)
|
|
g = solve
|
|
|
|
-- | Extract all the numbers from the given string
|
|
parse :: String -> [Int]
|
|
parse = map read . wordsBy (not . isDigit)
|
|
|
|
-- | Determine if the given line is diagonal.
|
|
diagonal :: [Int] -> Bool
|
|
diagonal [ x1, y1, x2, y2 ] = x1 /= x2 && y1 /= y2
|
|
|
|
solve :: [[Int]] -> Int
|
|
solve = length . filter ((>= 2) . length) . group . sort . (>>= range)
|
|
|
|
-- | Transform a line to a list of points on that line.
|
|
range :: [Int] -> [(Int,Int)]
|
|
range [ x1, y1, x2, y2 ]
|
|
| x1 == x2 = [ (x1,y) | y <- ys ]
|
|
| y1 == y2 = [ (x,y1) | x <- xs ]
|
|
| otherwise = zip xs ys
|
|
where xs = gen x1 x2
|
|
ys = gen y1 y2
|
|
|
|
-- | Generate a list of numbers from `a` to `b`.
|
|
gen :: Int -> Int -> [Int]
|
|
gen a b | a > b = [ b .. a ]
|
|
| otherwise = reverse [ a .. b ]
|