module Part2 where import Commons import Data.Array (assocs, bounds, (//)) getReachableOdd :: Garden -> Int getReachableOdd garden = let ((yMin, xMin), (yMax, xMax)) = bounds garden n = (yMax - yMin + div (yMax - yMin) 2) newGarden = garden // [((1 + div (yMax - yMin) 2, 1 + div (xMax - xMin) 2), Plot {reachable = True})] in length $ getReachableAfterNMove n newGarden getReachableEven :: Garden -> Int getReachableEven garden = let ((yMin, xMin), (yMax, xMax)) = bounds garden n = (yMax - yMin + 1 + div (yMax - yMin) 2) newGarden = garden // [((1 + div (yMax - yMin) 2, 1 + div (xMax - xMin) 2), Plot {reachable = True})] in length $ getReachableAfterNMove n newGarden getReachableCardinals :: Garden -> [Int] getReachableCardinals garden = let ((yMin, xMin), (yMax, xMax)) = bounds garden n = yMax - yMin (yMean, xMean) = (1 + div (yMax - yMin) 2, 1 + div (xMax - xMin) 2) in [length $ getReachableAfterNMove n $ garden // [((yMean, xMin), Plot {reachable = True})], length $ getReachableAfterNMove n $ garden // [((yMean, xMax), Plot {reachable = True})], length $ getReachableAfterNMove n $ garden // [((yMin, xMean), Plot {reachable = True})], length $ getReachableAfterNMove n $ garden // [((yMax, xMean), Plot {reachable = True})]] getReachableOddCorners :: Garden -> [Int] getReachableOddCorners garden = let ((yMin, xMin), (yMax, xMax)) = bounds garden n = yMax - yMin + div (yMax - yMin) 2 in [length $ getReachableAfterNMove n $ garden // [((yMin, xMin), Plot {reachable = True})], length $ getReachableAfterNMove n $ garden // [((yMin, xMax), Plot {reachable = True})], length $ getReachableAfterNMove n $ garden // [((yMax, xMin), Plot {reachable = True})], length $ getReachableAfterNMove n $ garden // [((yMax, xMax), Plot {reachable = True})]] getReachableEvenCorners :: Garden -> [Int] getReachableEvenCorners garden = let ((yMin, xMin), (yMax, xMax)) = bounds garden n = div (yMax - yMin) 2 - 1 in [length $ getReachableAfterNMove n $ garden // [((yMin, xMin), Plot {reachable = True})], length $ getReachableAfterNMove n $ garden // [((yMin, xMax), Plot {reachable = True})], length $ getReachableAfterNMove n $ garden // [((yMax, xMin), Plot {reachable = True})], length $ getReachableAfterNMove n $ garden // [((yMax, xMax), Plot {reachable = True})]] getReachableAfterN :: Int -> Garden -> Int getReachableAfterN n garden = let ((yMin, xMin), (yMax, xMax)) = bounds garden x = div (n - div (yMax - yMin) 2) (yMax - yMin + 1) in x * x * getReachableEven garden + x * sum (getReachableEvenCorners garden) + (x - 1) * (x - 1) * getReachableOdd garden + (x - 1) * sum (getReachableOddCorners garden) + sum (getReachableCardinals garden)