summaryrefslogtreecommitdiff
path: root/day-07/sol.hs
blob: 8de828b20e6220041b784e13b9f07a777dcade54 (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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import           Data.List    (find, transpose)
import qualified Data.Set     as Set
import qualified Data.Text    as Text
import qualified Data.Text.IO as Text

countVisibleTrees ::
     [[Int]] -> [Int] -> Int -> (Set.Set (Int, Int)) -> (Set.Set (Int, Int))
countVisibleTrees [] _ _ seen = seen
countVisibleTrees (row:rows) maxTrees depth seen =
  countVisibleTrees
    rows
    (zipWith (\x y -> max x y) row maxTrees)
    (depth + 1)
    (foldl
       (\acc x -> Set.insert x acc)
       seen
       (zipWith
          (\i x ->
             if x == 1
               then (depth, i)
               else (0, 0))
          [0 ..]
          (zipWith
             (\x y ->
                if x > y
                  then 1
                  else 0)
             row
             maxTrees)))

treeScore :: [[Int]] -> (Int, Int) -> Int -> Int -> [Int]
treeScore digits (x, y) width height =
  let currentHeight = ((digits !! y) !! x)
   in [ (case (find
                 (\x -> (digits !! y) !! x >= currentHeight)
                 [(x + 1) .. (width - 1)]) of
           Just value -> (value - x)
           Nothing    -> (width - x - 1))
      , (case (find
                 (\x -> (digits !! y) !! x >= currentHeight)
                 (reverse [0 .. (x - 1)])) of
           Just value -> (x - value)
           Nothing    -> x)
      , (case (find
                 (\y -> (digits !! y) !! x >= currentHeight)
                 (reverse [0 .. (y - 1)])) of
           Just value -> (y - value)
           Nothing    -> y)
      , (case (find
                 (\y -> (digits !! y) !! x >= currentHeight)
                 [(y + 1) .. (height - 1)]) of
           Just value -> (value - y)
           Nothing    -> (height - y - 1))
      ]

getDigitsFromString :: String -> [Int]
getDigitsFromString = map (read . (: ""))

rotl :: [[Int]] -> [[Int]]
rotl = reverse . transpose

rotr :: [[Int]] -> [[Int]]
rotr = transpose . reverse

mmult :: [[Int]] -> [[Int]] -> [[Int]]
mmult a b = [[sum $ zipWith (*) ar bc | bc <- (transpose b)] | ar <- a]

main = do
  ls <- fmap Text.lines (Text.readFile "input")
  let digits = map (getDigitsFromString . Text.unpack) ls
  let height = length digits
  let width = length (head digits)
  let topDownSeen =
        countVisibleTrees digits (take width (repeat (-1))) 0 Set.empty
  let rightLeftSeen =
        Set.map
          (\x -> ((snd x), width - (fst x) - 1))
          (countVisibleTrees
             (rotl digits)
             (take height (repeat (-1)))
             0
             Set.empty)
  let downTopSeen =
        Set.map
          (\x -> (height - (fst x) - 1, (snd x)))
          (countVisibleTrees
             (reverse digits)
             (take width (repeat (-1)))
             0
             Set.empty)
  let leftRightSeen =
        Set.map
          (\x -> (height - (snd x) - 1, (fst x)))
          (countVisibleTrees
             (rotr digits)
             (take height (repeat (-1)))
             0
             Set.empty)
  let allSeen =
        (foldl
           (\acc x -> Set.union acc x)
           Set.empty
           [topDownSeen, rightLeftSeen, downTopSeen, leftRightSeen])
  print (Set.size allSeen)
  print
    (maximum
       (map
          (\y ->
             maximum
               (map
                  (\x ->
                     (foldl
                        (\acc x -> acc * x)
                        1
                        (treeScore digits (x, y) width height)))
                  [0 .. (width - 1)]))
          [0 .. (height - 1)]))