import AoC

import Control.Applicative (empty)
import Control.Monad.Zip (mzip)
import Data.List (intercalate)
import Data.Maybe (catMaybes)

compose2 :: (a' -> b' -> c) -> (a -> a') -> (b -> b') -> a -> b -> c
compose2 f g h x y = f (g x) (h y)

(??) :: Functor f => f (a -> b) -> a -> f b
f ?? x = fmap ($ x) f

countHits :: (Int, Int) -> [[Bool]] -> Int
countHits = length . filterMap lookup . catMaybes .: compose2 (zipWith mzip) maybeIndices justLines
    where justRightSteps = map (pure . Just) . enumFromThen 0
          downNothings = flip replicate Nothing . pred
          maybeIndices = uncurry $ compose2 (flip intercalate) justRightSteps downNothings
          justLines = map Just
          lookup = uncurry $ flip (!!)
          filterMap = filter id .: map

treeCharToBool :: Char -> Bool
treeCharToBool = (== '#')

main = runAoC (map (cycle . map treeCharToBool) . lines) part1 part2
    where part1 = countHits (3, 1)
          part2 = product . (fmap countHits [(1,1), (3,1), (5,1), (7,1), (1,2)] ??)