import Control.Arrow
import Data.Ix
import Data.List.Split

type SeedMap = [((Int, Int), Int)]

main :: IO ()
main = do
  input <- map (map words . lines) . splitOn "\n\n" <$> readFile "input"
  let (seeds, maps) = parse input
  print $ day5a maps seeds
  print $ day5a maps (pairwise seeds)

parse :: [[[String]]] -> ([Int], [SeedMap])
parse = parseSeeds &&& map parseMap . tail
  where
    parseSeeds = map read . tail . head . head

parseMap :: [[String]] -> SeedMap
parseMap = map (f . map read) . tail
  where
    f [x, y, z] = ((y, y + pred z), x - y)

applyMap :: Int -> SeedMap -> Int
applyMap x m =
  if null filtered
    then x
    else x + snd (head filtered)
  where
    filtered = filter ((`inRange` x) . fst) m

day5a :: [SeedMap] -> [Int] -> Int
day5a maps = minimum . map f
  where
    f x = foldl applyMap x maps

pairwise :: [Int] -> [Int]
pairwise [] = []
pairwise (x:y:xs) = take y [x ..] ++ pairwise xs
pairwise _ = error "List length must be even"
