summaryrefslogtreecommitdiff
path: root/2021/13.hs
blob: 26e7a6d3aa782cbcee41f42dc7b785b840fc98b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{-# LANGUAGE TupleSections #-}
module Main where

import qualified Data.Array as A
import Data.List

import Input
import Util


generate :: A.Ix i => (i, i) -> (i -> a) -> A.Array i a
generate bounds f = A.listArray bounds (map f (A.range bounds))

main :: IO ()
main = do
    inp <- getInput 13
    let pointstrs :| foldstrs:_ = splitOn null inp
        points :: [(Int, Int)]
        points = map (\s -> let [a,b] = toList (splitOn (== ',') s) in (read a, read b)) pointstrs
        folds :: [(Char, Int)]
        folds = map (\s -> let [a,b] = toList (splitOn (== '=') s) in (last a, read b)) foldstrs
        minmax = (,) <$> minimum <*> maximum
        arr0 = let (x1, x2) = minmax (map fst points)
                   (y1, y2) = minmax (map snd points)
               in A.accumArray (+) 0 ((x1, y1), (x2, y2)) (map (,1::Int) points)
        at arr idx | A.inRange (A.bounds arr) idx = arr A.! idx
                   | otherwise = 0
        doFold 'x' lim arr =
            let ((x1, y1), (x2, y2)) = A.bounds arr
            in generate ((min x1 (lim - (x2 - lim)), y1), (lim - 1, y2)) $ \(x, y) ->
                 arr `at` (x, y) + arr `at` (lim + (lim - x), y)
        doFold 'y' lim arr =
            let ((x1, y1), (x2, y2)) = A.bounds arr
            in generate ((x1, min y1 (lim - (y2 - lim))), (x2, lim - 1)) $ \(x, y) ->
                 arr `at` (x, y) + arr `at` (x, lim + (lim - y))
        doFold _ _ _ = error "rip"
        nvisible = length . filter (>0) . A.elems
        draw arr =
            let ((x1, y1), (x2, y2)) = A.bounds arr
            in unlines [concat [if arr A.! (x, y) > 0 then "█" else "·"
                               | x <- [x1..x2]]
                       | y <- [y1..y2]]
    print (nvisible (let (dir, lim) = head folds in doFold dir lim arr0))
    putStr (draw (foldl' (\arr (dir, lim) -> doFold dir lim arr) arr0 folds))