1
+ import Data.Char
2
+ import Text.Parsec
3
+ import Parsing
4
+ import qualified Data.HashMap.Strict as M
5
+ import Chart2d
6
+ import Data.List
7
+
8
+ main :: IO ()
9
+ main = optimisticInteract readD solve
10
+
11
+ readD :: Parser [[Char ]]
12
+ readD = (many1 $ oneOf " |-LJ7F.S" ) `sepEndBy` newline
13
+
14
+
15
+ solve lines = unlines [
16
+ show $ lines
17
+ , showMC chart
18
+ , show v
19
+ , show answer
20
+ ]
21
+ where
22
+ answer = length $ findClosure loop (mapStart chart start)
23
+ (v, loop) = fillFrom [start] 0 M. empty chart
24
+
25
+ mapStart ch s@ (x,y) = M. insert s s' ch
26
+ where
27
+ s'
28
+ | ns == [(x,y- 1 ),(x,y+ 1 )] = ' |'
29
+ | ns == [(x- 1 ,y),(x+ 1 ,y)] = ' -'
30
+ | ns == [(x+ 1 ,y),(x,y- 1 )] = ' L'
31
+ | ns == [(x- 1 ,y),(x,y- 1 )] = ' J'
32
+ | ns == [(x- 1 ,y),(x,y+ 1 )] = ' 7'
33
+ | ns == [(x+ 1 ,y),(x,y+ 1 )] = ' F'
34
+ where
35
+ ns = filter (`M.member` loop) $ pipenext chart s
36
+
37
+ chart = readM lines
38
+ start = head . M. keys $ M. filter (== ' S' ) chart
39
+
40
+ fillFrom cs v mem ch
41
+ | null cs' = (v,mem)
42
+ | otherwise = fillFrom cs' (v+ 1 ) mem' ch
43
+ where
44
+ cs' = filter (not . (`M.member` mem)) $ concatMap (pipenext ch) cs
45
+ mem' = M. union mem . M. fromList $ zip cs' (repeat True )
46
+
47
+ pipenext ch c = [nx | nx <- next c, any (== c) $ next nx]
48
+ where
49
+ next c@ (x,y)
50
+ | here == ' .' = []
51
+ | here == ' |' = [(x,y- 1 ),(x,y+ 1 )]
52
+ | here == ' -' = [(x- 1 ,y),(x+ 1 ,y)]
53
+ | here == ' L' = [(x,y- 1 ),(x+ 1 ,y)]
54
+ | here == ' J' = [(x,y- 1 ),(x- 1 ,y)]
55
+ | here == ' 7' = [(x- 1 ,y),(x,y+ 1 )]
56
+ | here == ' F' = [(x,y+ 1 ),(x+ 1 ,y)]
57
+ | here == ' S' = [(x+ 1 ,y),(x- 1 ,y),(x,y- 1 ),(x,y+ 1 )]
58
+ where
59
+ here = ch M. ! c
60
+
61
+ findClosure loop ch = concatMap (helper False 0 ) [y | y <- [0 .. maxy]]
62
+ where
63
+ (maxx, maxy) = maximum $ M. keys ch
64
+
65
+ helper _ x _
66
+ | x > maxx = []
67
+ helper b x y
68
+ | not inLoop && b = (x,y) : helper b (x+ 1 ) y
69
+ | not inLoop = helper b (x+ 1 ) y
70
+ where
71
+ inLoop = M. member (x,y) loop
72
+ helper b x y
73
+ | here == ' L' && there == ' J' = helper b (x'+ 1 ) y
74
+ | here == ' L' && there == ' 7' = helper (not b) (x'+ 1 ) y
75
+ | here == ' F' && there == ' 7' = helper b (x'+ 1 ) y
76
+ | here == ' F' && there == ' J' = helper (not b) (x'+ 1 ) y
77
+ | here == ' |' = helper (not b) (x+ 1 ) y
78
+ where
79
+ here = ch M. ! (x,y)
80
+ there = ch M. ! (x',y)
81
+ x' = head . dropWhile (\ x' -> ch M. ! (x',y) == ' -' ) $ [x+ 1 .. maxx]
0 commit comments