|
| 1 | +import Data.List |
| 2 | +import Data.Ix |
| 3 | + |
| 4 | +splitOn :: Char -> String -> (String, String) |
| 5 | +splitOn separator str = (takeWhile (/= separator) str, tail $ dropWhile (/= separator) str) |
| 6 | + |
| 7 | +unique :: Eq a => [a] -> [a] |
| 8 | +unique [] = [] |
| 9 | +unique (x:xs) = x:unique (filter ((/=) x) xs) |
| 10 | + |
| 11 | +foldUpCoords :: Int -> (Int, Int) -> (Int, Int) |
| 12 | +foldUpCoords foldLine (x, y) |
| 13 | + | foldLine >= y = (x, y) |
| 14 | + | otherwise = (x, foldLine - (y - foldLine)) |
| 15 | + |
| 16 | +foldLeftCoords :: Int -> (Int, Int) -> (Int, Int) |
| 17 | +foldLeftCoords foldLine (x, y) |
| 18 | + | foldLine >= x = (x, y) |
| 19 | + | otherwise = (foldLine - (x - foldLine), y) |
| 20 | + |
| 21 | +foldCoords :: Char -> Int -> (Int, Int) -> (Int, Int) |
| 22 | +foldCoords axis |
| 23 | + | axis == 'x' = foldLeftCoords |
| 24 | + | otherwise = foldUpCoords |
| 25 | + |
| 26 | +foldOne :: (Char, Int) -> [(Int, Int)] -> [(Int, Int)] |
| 27 | +foldOne (axis, foldLine) listCoords = unique $ filter (\(x, y) -> x >= 0 && y >= 0) |
| 28 | + [ foldCoords axis foldLine coords | coords <- listCoords ] |
| 29 | + |
| 30 | +foldAll :: [(Char, Int)] -> [(Int, Int)] -> [(Int, Int)] |
| 31 | +foldAll [] listCoords = listCoords |
| 32 | +foldAll (f:folds) listCoords = foldAll folds (foldOne f listCoords) |
| 33 | + |
| 34 | +-- utils for pretty print |
| 35 | +maxCoords_ :: Int -> Int -> [(Int, Int)] -> (Int, Int) |
| 36 | +maxCoords_ maxX maxY [] = ( maxX , maxY ) |
| 37 | +maxCoords_ maxX maxY ((x, y):coords)= maxCoords_ (maximum [ maxX, x ]) (maximum [maxY , y ]) coords |
| 38 | + |
| 39 | +maxCoords :: [(Int, Int)] -> (Int, Int) |
| 40 | +maxCoords coords = maxCoords_ 0 0 coords |
| 41 | + |
| 42 | +allCoords :: [(Int, Int)] -> [(Int, Int)] |
| 43 | +allCoords coords = [(y, x) | (x, y) <- range ((0,0), (snd $ maxCoords coords, fst $ maxCoords coords))] |
| 44 | + |
| 45 | +chunk :: Int -> [a] -> [[a]] |
| 46 | +chunk _ [] = [] |
| 47 | +chunk n l |
| 48 | + | n > 0 = (take n l) : (chunk n (drop n l)) |
| 49 | + | otherwise = error "Negative or zero n" |
| 50 | + |
| 51 | +printMatrix :: [(Int, Int)] -> IO () |
| 52 | +printMatrix coords = mapM_ putStrLn $ chunk ((fst $ maxCoords coords) + 1) |
| 53 | + [if c `elem` coords then '#' else '.' | c <- allCoords coords] |
| 54 | + |
| 55 | +main = do |
| 56 | + ls <- readFile "day13/input.txt" |
| 57 | + let coords = map (\c -> (read $ (fst c)::Int, read $ (snd c)::Int)) |
| 58 | + . map (splitOn ',') |
| 59 | + . takeWhile (/="") $ lines ls |
| 60 | + let folds = map (\f -> (head $ fst f, read $ (snd f)::Int)) |
| 61 | + . map (splitOn '=' . drop 11) |
| 62 | + . drop (length coords + 1) $ lines ls |
| 63 | + putStrLn $ "Part 1: " ++ show (length $ foldOne (head $ folds) coords) |
| 64 | + putStrLn $ "Part 2:" |
| 65 | + printMatrix $ foldAll folds coords |
0 commit comments