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
|
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
import qualified Data.Text as T
import Data.Set (Set)
import Data.List
import qualified Data.Set as S
type Coord = (Int, Int)
data FoldInstr = Fold Axis Int deriving (Show, Eq, Ord)
data Axis = XAxis | YAxis deriving (Show, Eq, Ord)
parseCoords :: String -> Coord
parseCoords s = (read x, read y)
where [x, y] = map T.unpack $ T.splitOn "," (T.pack s)
parseFold :: String -> FoldInstr
parseFold (stripPrefix "fold along y=" -> Just cs) = Fold YAxis (read cs)
parseFold (stripPrefix "fold along x=" -> Just cs) = Fold XAxis (read cs)
parseFile :: String -> (Set Coord, [FoldInstr])
parseFile s = (S.fromList $ map parseCoords (lines coordSection), map parseFold (lines foldSection))
where [coordSection, foldSection] = map T.unpack $ T.splitOn "\n\n" (T.pack s)
performFold :: Set Coord -> FoldInstr -> Set Coord
performFold coords (Fold YAxis ye) = S.map (\(x, y) -> (x, -(abs (y - ye)) + ye)) coords
performFold coords (Fold XAxis xe) = S.map (\(x, y) -> (-(abs (x - xe)) + xe, y)) coords
displayCoords :: Set Coord -> String
displayCoords coords = intercalate "\n" (map displayLine [sy..ey])
where sx = minimum (S.map fst coords)
ex = maximum (S.map fst coords)
sy = minimum (S.map snd coords)
ey = maximum (S.map snd coords)
displayLine y = map (displayCoord y) [sx..ex]
displayCoord y x | S.member (x, y) coords = '#'
| otherwise = '.'
main :: IO ()
main = do
f <- readFile "./input"
let (coords, instrs) = parseFile f;
let result = foldl performFold coords instrs;
putStrLn $ displayCoords result
|