Fix code style with ormolu

This commit is contained in:
daniele 2024-12-15 10:31:53 +01:00
parent 7b40fc7814
commit ba73f8c638
Signed by: fuxino
GPG Key ID: 981A2B2A3BBF5514
25 changed files with 538 additions and 418 deletions

View File

@ -2,7 +2,7 @@
module Day1.Puzzle1 (day1_1) where module Day1.Puzzle1 (day1_1) where
import Data.List (transpose, sort) import Data.List (sort, transpose)
listDistance :: [Int] -> [Int] -> Int listDistance :: [Int] -> [Int] -> Int
listDistance xs ys = sum $ map abs $ zipWith (-) (sort xs) (sort ys) listDistance xs ys = sum $ map abs $ zipWith (-) (sort xs) (sort ys)
@ -11,5 +11,6 @@ day1_1 :: IO ()
day1_1 = do day1_1 = do
contents <- lines <$> readFile "input/day1.txt" contents <- lines <$> readFile "input/day1.txt"
let [x, y] = transpose $ map read . words <$> contents let [x, y] = transpose $ map read . words <$> contents
putStrLn $ "Day 1, Puzzle 1 solution: " putStrLn $
"Day 1, Puzzle 1 solution: "
++ show (listDistance x y) ++ show (listDistance x y)

View File

@ -2,16 +2,18 @@
module Day1.Puzzle2 (day1_2) where module Day1.Puzzle2 (day1_2) where
import Data.List (transpose, sort, group, uncons) import Data.List (group, sort, transpose, uncons)
import Data.Maybe (fromJust) import Data.Maybe (fromJust)
similarityScore :: [Int] -> [Int] -> Int similarityScore :: [Int] -> [Int] -> Int
similarityScore xs ys = let elemsY = [ (fst . fromJust $ uncons y, length y) | y <- (group . sort) ys ] similarityScore xs ys =
let elemsY = [(fst . fromJust $ uncons y, length y) | y <- (group . sort) ys]
in sum [x * snd y | x <- xs, y <- elemsY, x == fst y] in sum [x * snd y | x <- xs, y <- elemsY, x == fst y]
day1_2 :: IO () day1_2 :: IO ()
day1_2 = do day1_2 = do
contents <- lines <$> readFile "input/day1.txt" contents <- lines <$> readFile "input/day1.txt"
let [x, y] = transpose $ map read . words <$> contents let [x, y] = transpose $ map read . words <$> contents
putStrLn $ "Day 1, Puzzle 2 solution: " putStrLn $
"Day 1, Puzzle 2 solution: "
++ show (similarityScore x y) ++ show (similarityScore x y)

View File

@ -1,24 +1,27 @@
module Day10.Puzzle1 (day10_1) where module Day10.Puzzle1 (day10_1) where
import Data.Char (digitToInt) import Data.Char (digitToInt)
import Data.Graph (graphFromEdges, path, vertices)
import Data.List (uncons) import Data.List (uncons)
import Data.List.Split (chunksOf) import Data.List.Split (chunksOf)
import Data.Maybe (fromJust) import Data.Maybe (fromJust)
import Data.Graph (graphFromEdges, path, vertices)
type Coords = (Int, Int) type Coords = (Int, Int)
type V = (String, Int) type V = (String, Int)
getValue :: [[V]] -> Coords -> V getValue :: [[V]] -> Coords -> V
getValue grid (i, j) = grid !! i !! j getValue grid (i, j) = grid !! i !! j
getEdges :: [[V]] -> Coords -> [Int] getEdges :: [[V]] -> Coords -> [Int]
getEdges grid (i, j) = let value = fst $ grid !! i !! j getEdges grid (i, j) =
let value = fst $ grid !! i !! j
adjI = filter (\x -> fst x >= 0 && fst x < length grid && snd x >= 0 && snd x < length (fst . fromJust $ uncons grid)) [(i, j + 1), (i + 1, j), (i, j - 1), (i - 1, j)] adjI = filter (\x -> fst x >= 0 && fst x < length grid && snd x >= 0 && snd x < length (fst . fromJust $ uncons grid)) [(i, j + 1), (i + 1, j), (i, j - 1), (i - 1, j)]
in [snd x | x <- map (getValue grid) adjI, digitToInt (fst . fromJust $ uncons value) == digitToInt (fst . fromJust $ uncons (fst x)) - 1] in [snd x | x <- map (getValue grid) adjI, digitToInt (fst . fromJust $ uncons value) == digitToInt (fst . fromJust $ uncons (fst x)) - 1]
listVertices :: [String] -> [[V]] listVertices :: [String] -> [[V]]
listVertices grid = let l = length $ fst . fromJust $ uncons grid listVertices grid =
let l = length $ fst . fromJust $ uncons grid
in chunksOf l $ zip (map (: []) (concat grid)) [0 ..] in chunksOf l $ zip (map (: []) (concat grid)) [0 ..]
day10_1 :: IO () day10_1 :: IO ()

View File

@ -4,7 +4,8 @@ import qualified Data.Map.Strict as M
blinkStone :: (Int, Int) -> [(Int, Int)] blinkStone :: (Int, Int) -> [(Int, Int)]
blinkStone (0, n) = [(1, n)] blinkStone (0, n) = [(1, n)]
blinkStone (s, n) = let ss = show s blinkStone (s, n) =
let ss = show s
nDigit = length ss nDigit = length ss
in if even nDigit in if even nDigit
then zip (map read [take (nDigit `div` 2) ss, drop (nDigit `div` 2) ss]) [n, n] then zip (map read [take (nDigit `div` 2) ss, drop (nDigit `div` 2) ss]) [n, n]
@ -17,5 +18,6 @@ blink n m = blink (n - 1) $ M.fromListWith (+) $ concatMap blinkStone $ M.toList
day11_1 :: IO () day11_1 :: IO ()
day11_1 = do day11_1 = do
contents <- M.fromListWith (+) . flip zip (repeat 1) . map read . words <$> readFile "input/day11.txt" contents <- M.fromListWith (+) . flip zip (repeat 1) . map read . words <$> readFile "input/day11.txt"
putStrLn $ "Day 11, Puzzle 1 solution: " putStrLn $
"Day 11, Puzzle 1 solution: "
++ show (M.foldl (+) 0 $ blink 25 contents) ++ show (M.foldl (+) 0 $ blink 25 contents)

View File

@ -4,7 +4,8 @@ import qualified Data.Map.Strict as M
blinkStone :: (Int, Int) -> [(Int, Int)] blinkStone :: (Int, Int) -> [(Int, Int)]
blinkStone (0, n) = [(1, n)] blinkStone (0, n) = [(1, n)]
blinkStone (s, n) = let ss = show s blinkStone (s, n) =
let ss = show s
nDigit = length ss nDigit = length ss
in if even nDigit in if even nDigit
then zip (map read [take (nDigit `div` 2) ss, drop (nDigit `div` 2) ss]) [n, n] then zip (map read [take (nDigit `div` 2) ss, drop (nDigit `div` 2) ss]) [n, n]
@ -17,5 +18,6 @@ blink n m = blink (n - 1) $ M.fromListWith (+) $ concatMap blinkStone $ M.toList
day11_2 :: IO () day11_2 :: IO ()
day11_2 = do day11_2 = do
contents <- M.fromListWith (+) . flip zip (repeat 1) . map read . words <$> readFile "input/day11.txt" contents <- M.fromListWith (+) . flip zip (repeat 1) . map read . words <$> readFile "input/day11.txt"
putStrLn $ "Day 11, Puzzle 2 solution: " putStrLn $
"Day 11, Puzzle 2 solution: "
++ show (M.foldl (+) 0 $ blink 75 contents) ++ show (M.foldl (+) 0 $ blink 75 contents)

View File

@ -1,28 +1,32 @@
module Day12.Puzzle1 (day12_1) where module Day12.Puzzle1 (day12_1) where
import Data.Foldable (toList)
import Data.Graph (Tree, Vertex, graphFromEdges, scc)
import Data.List (uncons) import Data.List (uncons)
import Data.List.Split (chunksOf) import Data.List.Split (chunksOf)
import Data.Maybe (fromJust) import Data.Maybe (fromJust)
import Data.Graph (Tree, Vertex, graphFromEdges, scc)
import Data.Foldable (toList)
type Coords = (Int, Int) type Coords = (Int, Int)
type V = (String, Int) type V = (String, Int)
getValue :: [[V]] -> Coords -> V getValue :: [[V]] -> Coords -> V
getValue grid (i, j) = grid !! i !! j getValue grid (i, j) = grid !! i !! j
getEdges :: [[V]] -> Coords -> [Int] getEdges :: [[V]] -> Coords -> [Int]
getEdges grid (i, j) = let value = fst $ grid !! i !! j getEdges grid (i, j) =
let value = fst $ grid !! i !! j
adjI = filter (\x -> fst x >= 0 && fst x < length grid && snd x >= 0 && snd x < length (fst . fromJust $ uncons grid)) [(i, j + 1), (i + 1, j), (i, j - 1), (i - 1, j)] adjI = filter (\x -> fst x >= 0 && fst x < length grid && snd x >= 0 && snd x < length (fst . fromJust $ uncons grid)) [(i, j + 1), (i + 1, j), (i, j - 1), (i - 1, j)]
in [snd x | x <- map (getValue grid) adjI, (fst . fromJust $ uncons value) == (fst . fromJust $ uncons (fst x))] in [snd x | x <- map (getValue grid) adjI, (fst . fromJust $ uncons value) == (fst . fromJust $ uncons (fst x))]
listVertices :: [String] -> [[V]] listVertices :: [String] -> [[V]]
listVertices grid = let l = length $ fst . fromJust $ uncons grid listVertices grid =
let l = length $ fst . fromJust $ uncons grid
in chunksOf l $ zip (map (: []) (concat grid)) [0 ..] in chunksOf l $ zip (map (: []) (concat grid)) [0 ..]
calculatePerimeter :: (Vertex -> (String, Vertex, [Vertex])) -> Tree Vertex -> Int calculatePerimeter :: (Vertex -> (String, Vertex, [Vertex])) -> Tree Vertex -> Int
calculatePerimeter nodeFromVertex p = let edges = concat [ x | (_, _, x) <- toList $ fmap nodeFromVertex p ] calculatePerimeter nodeFromVertex p =
let edges = concat [x | (_, _, x) <- toList $ fmap nodeFromVertex p]
area = 4 * length p area = 4 * length p
in area - length edges in area - length edges
@ -36,5 +40,6 @@ day12_1= do
plots = scc graph plots = scc graph
areas = map length plots areas = map length plots
perimeters = map (calculatePerimeter nodeFromVertex) plots perimeters = map (calculatePerimeter nodeFromVertex) plots
putStrLn $ "Day 12, Puzzle 1 solution: " putStrLn $
"Day 12, Puzzle 1 solution: "
++ show (sum $ zipWith (*) areas perimeters) ++ show (sum $ zipWith (*) areas perimeters)

View File

@ -3,24 +3,27 @@
module Day13.Puzzle1 (day13_1) where module Day13.Puzzle1 (day13_1) where
import Data.Char (isDigit) import Data.Char (isDigit)
import Data.List (uncons)
import Data.List.Split (splitOn, chunksOf)
import Data.Matrix (Matrix, fromLists, toList, rref, zero)
import Data.Either (fromRight) import Data.Either (fromRight)
import Data.Maybe (mapMaybe, fromJust) import Data.List (uncons)
import Data.List.Split (chunksOf, splitOn)
import Data.Matrix (Matrix, fromLists, rref, toList, zero)
import Data.Maybe (fromJust, mapMaybe)
isAlmostInt :: (RealFrac a) => a -> Bool isAlmostInt :: (RealFrac a) => a -> Bool
isAlmostInt x = let diff = x - fromInteger (round x) isAlmostInt x =
let diff = x - fromInteger (round x)
in abs diff < 0.001 in abs diff < 0.001
getMatrix :: (Read a) => String -> Matrix a getMatrix :: (Read a) => String -> Matrix a
getMatrix s = let nValues = map (map read . splitOn ",") . splitOn ":" . drop 1 $ filter (\x -> isDigit x || x == ',' || x == ':') s getMatrix s =
let nValues = map (map read . splitOn ",") . splitOn ":" . drop 1 $ filter (\x -> isDigit x || x == ',' || x == ':') s
eq1 = map (fst . fromJust . uncons) nValues eq1 = map (fst . fromJust . uncons) nValues
eq2 = map last nValues eq2 = map last nValues
in fromLists [eq1, eq2] in fromLists [eq1, eq2]
solve :: (RealFrac a) => Matrix a -> Maybe [a] solve :: (RealFrac a) => Matrix a -> Maybe [a]
solve eqSystem = let rowEchelonList = toList . fromRight (zero 1 1) $ rref eqSystem solve eqSystem =
let rowEchelonList = toList . fromRight (zero 1 1) $ rref eqSystem
solutions = [rowEchelonList !! 2, rowEchelonList !! 5] solutions = [rowEchelonList !! 2, rowEchelonList !! 5]
in if all isAlmostInt solutions in if all isAlmostInt solutions
then Just solutions then Just solutions
@ -35,5 +38,6 @@ day13_1 = do
contents <- map concat . chunksOf 4 . lines <$> readFile "input/day13.txt" contents <- map concat . chunksOf 4 . lines <$> readFile "input/day13.txt"
let eqSystems = map getMatrix contents let eqSystems = map getMatrix contents
solutions = (map . map) round $ mapMaybe solve eqSystems solutions = (map . map) round $ mapMaybe solve eqSystems
putStrLn $ "Day 13, Puzzle 1 solution: " putStrLn $
"Day 13, Puzzle 1 solution: "
++ show (sum $ map cost solutions) ++ show (sum $ map cost solutions)

View File

@ -3,14 +3,15 @@
module Day13.Puzzle2 (day13_2) where module Day13.Puzzle2 (day13_2) where
import Data.Char (isDigit) import Data.Char (isDigit)
import Data.List (uncons)
import Data.List.Split (splitOn, chunksOf)
import Data.Matrix (Matrix, fromLists, toList, rref, zero)
import Data.Either (fromRight) import Data.Either (fromRight)
import Data.Maybe (mapMaybe, fromJust) import Data.List (uncons)
import Data.List.Split (chunksOf, splitOn)
import Data.Matrix (Matrix, fromLists, rref, toList, zero)
import Data.Maybe (fromJust, mapMaybe)
isAlmostInt :: (RealFrac a) => a -> Bool isAlmostInt :: (RealFrac a) => a -> Bool
isAlmostInt x = let diff = x - fromInteger (round x) isAlmostInt x =
let diff = x - fromInteger (round x)
in abs diff < 0.001 in abs diff < 0.001
multRes :: (Num a) => [a] -> [a] multRes :: (Num a) => [a] -> [a]
@ -18,13 +19,15 @@ multRes [x, y, z] = [x, y, z + 10000000000000]
multRes xs = xs multRes xs = xs
getMatrix :: (Num a, Read a) => String -> Matrix a getMatrix :: (Num a, Read a) => String -> Matrix a
getMatrix s = let nValues = map (map read . splitOn ",") . splitOn ":" . drop 1 $ filter (\x -> isDigit x || x == ',' || x == ':') s getMatrix s =
let nValues = map (map read . splitOn ",") . splitOn ":" . drop 1 $ filter (\x -> isDigit x || x == ',' || x == ':') s
eq1 = multRes $ map (fst . fromJust . uncons) nValues eq1 = multRes $ map (fst . fromJust . uncons) nValues
eq2 = multRes $ map last nValues eq2 = multRes $ map last nValues
in fromLists [eq1, eq2] in fromLists [eq1, eq2]
solve :: (RealFrac a) => Matrix a -> Maybe [a] solve :: (RealFrac a) => Matrix a -> Maybe [a]
solve eqSystem = let rowEchelonList = toList . fromRight (zero 1 1) $ rref eqSystem solve eqSystem =
let rowEchelonList = toList . fromRight (zero 1 1) $ rref eqSystem
solutions = [rowEchelonList !! 2, rowEchelonList !! 5] solutions = [rowEchelonList !! 2, rowEchelonList !! 5]
in if all isAlmostInt solutions in if all isAlmostInt solutions
then Just solutions then Just solutions
@ -39,5 +42,6 @@ day13_2 = do
contents <- map concat . chunksOf 4 . lines <$> readFile "input/day13.txt" contents <- map concat . chunksOf 4 . lines <$> readFile "input/day13.txt"
let eqSystems = map getMatrix contents let eqSystems = map getMatrix contents
solutions = (map . map) round $ mapMaybe solve eqSystems solutions = (map . map) round $ mapMaybe solve eqSystems
putStrLn $ "Day 13, Puzzle 2 solution: " putStrLn $
"Day 13, Puzzle 2 solution: "
++ show (sum $ map cost solutions) ++ show (sum $ map cost solutions)

View File

@ -6,33 +6,42 @@ import Data.Char (isDigit)
import Data.List.Split (splitOn) import Data.List.Split (splitOn)
type Position = (Int, Int) type Position = (Int, Int)
type Velocity = (Int, Int) type Velocity = (Int, Int)
type Robot = (Position, Velocity) type Robot = (Position, Velocity)
readRobot :: String -> Robot readRobot :: String -> Robot
readRobot s = let [ps, vs] = splitOn " " s readRobot s =
let [ps, vs] = splitOn " " s
[px, py] = map read . splitOn "," $ filter (\x -> isDigit x || x == ',' || x == '-') ps [px, py] = map read . splitOn "," $ filter (\x -> isDigit x || x == ',' || x == '-') ps
[vx, vy] = map read . splitOn "," $ filter (\x -> isDigit x || x == ',' || x == '-') vs [vx, vy] = map read . splitOn "," $ filter (\x -> isDigit x || x == ',' || x == '-') vs
in ((px, py), (vx, vy)) in ((px, py), (vx, vy))
moveRobot :: Int -> Robot -> Robot moveRobot :: Int -> Robot -> Robot
moveRobot 0 r = r moveRobot 0 r = r
moveRobot n r = let (px, py) = fst r moveRobot n r =
let (px, py) = fst r
(vx, vy) = snd r (vx, vy) = snd r
in moveRobot (n - 1) (((px + vx) `mod` 101, (py + vy) `mod` 103), (vx, vy)) in moveRobot (n - 1) (((px + vx) `mod` 101, (py + vy) `mod` 103), (vx, vy))
quadrant :: Robot -> Int quadrant :: Robot -> Int
quadrant r quadrant r
| fst p `elem` [0..49] && | fst p `elem` [0 .. 49]
snd p `elem` [0..50] = 0 && snd p `elem` [0 .. 50] =
| fst p `elem` [51..100] && 0
snd p `elem` [0..50] = 1 | fst p `elem` [51 .. 100]
| fst p `elem` [0..49] && && snd p `elem` [0 .. 50] =
snd p `elem` [52..102] = 2 1
| fst p `elem` [51..100] && | fst p `elem` [0 .. 49]
snd p `elem` [52..102] = 3 && snd p `elem` [52 .. 102] =
2
| fst p `elem` [51 .. 100]
&& snd p `elem` [52 .. 102] =
3
| otherwise = -1 | otherwise = -1
where p = fst r where
p = fst r
day14_1 :: IO () day14_1 :: IO ()
day14_1 = do day14_1 = do
@ -43,5 +52,6 @@ day14_1= do
secondQ = length $ filter (\r -> quadrant r == 1) robots' secondQ = length $ filter (\r -> quadrant r == 1) robots'
thirdQ = length $ filter (\r -> quadrant r == 2) robots' thirdQ = length $ filter (\r -> quadrant r == 2) robots'
fourthQ = length $ filter (\r -> quadrant r == 3) robots' fourthQ = length $ filter (\r -> quadrant r == 3) robots'
putStrLn $ "Day 14, Puzzle 1 solution: " putStrLn $
"Day 14, Puzzle 1 solution: "
++ show (firstQ * secondQ * thirdQ * fourthQ) ++ show (firstQ * secondQ * thirdQ * fourthQ)

View File

@ -5,7 +5,8 @@ import Data.Ord
isSafe :: [Int] -> Bool isSafe :: [Int] -> Bool
isSafe xs = (isAscending xs || isDescending xs) && maximum distances <= 3 && minimum distances >= 1 isSafe xs = (isAscending xs || isDescending xs) && maximum distances <= 3 && minimum distances >= 1
where isAscending x = x == sort x where
isAscending x = x == sort x
isDescending x = x == sortBy (comparing Down) x isDescending x = x == sortBy (comparing Down) x
distances = map abs $ zipWith (-) xs (drop 1 xs) distances = map abs $ zipWith (-) xs (drop 1 xs)
@ -13,5 +14,6 @@ day2_1 :: IO ()
day2_1 = do day2_1 = do
contents <- lines <$> readFile "input/day2.txt" contents <- lines <$> readFile "input/day2.txt"
let reports = map read . words <$> contents let reports = map read . words <$> contents
putStrLn $ "Day 2, Puzzle 1 solution: " putStrLn $
"Day 2, Puzzle 1 solution: "
++ show (length $ filter isSafe reports) ++ show (length $ filter isSafe reports)

View File

@ -1,22 +1,25 @@
module Day2.Puzzle2 (day2_2) where module Day2.Puzzle2 (day2_2) where
import Data.List (sort, sortBy, inits, tails) import Data.List (inits, sort, sortBy, tails)
import Data.Ord import Data.Ord
isSafe :: [Int] -> Bool isSafe :: [Int] -> Bool
isSafe xs = (isAscending xs || isDescending xs) && maximum distances <= 3 && minimum distances >= 1 isSafe xs = (isAscending xs || isDescending xs) && maximum distances <= 3 && minimum distances >= 1
where isAscending x = x == sort x where
isAscending x = x == sort x
isDescending x = x == sortBy (comparing Down) x isDescending x = x == sortBy (comparing Down) x
distances = map abs $ zipWith (-) xs (drop 1 xs) distances = map abs $ zipWith (-) xs (drop 1 xs)
removeLevel :: [Int] -> [[Int]] removeLevel :: [Int] -> [[Int]]
removeLevel xs = zipWith (++) ys zs removeLevel xs = zipWith (++) ys zs
where ys = map init $ drop 1 (inits xs) where
ys = map init $ drop 1 (inits xs)
zs = map (drop 1) $ init (tails xs) zs = map (drop 1) $ init (tails xs)
day2_2 :: IO () day2_2 :: IO ()
day2_2 = do day2_2 = do
contents <- lines <$> readFile "input/day2.txt" contents <- lines <$> readFile "input/day2.txt"
let reports = map read . words <$> contents let reports = map read . words <$> contents
putStrLn $ "Day 2, Puzzle 2 solution: " putStrLn $
"Day 2, Puzzle 2 solution: "
++ show (length . filter (any isSafe) $ map removeLevel reports) ++ show (length . filter (any isSafe) $ map removeLevel reports)

View File

@ -4,12 +4,14 @@ import Data.List.Split (splitOn)
import Text.Regex.TDFA (getAllTextMatches, (=~)) import Text.Regex.TDFA (getAllTextMatches, (=~))
sumMul :: [String] -> Int sumMul :: [String] -> Int
sumMul xs = let vals = map (splitOn "," . filter (`elem` "0123456789,")) xs sumMul xs =
let vals = map (splitOn "," . filter (`elem` "0123456789,")) xs
in sum $ map (product . map read) vals in sum $ map (product . map read) vals
day3_1 :: IO () day3_1 :: IO ()
day3_1 = do day3_1 = do
contents <- readFile "input/day3.txt" contents <- readFile "input/day3.txt"
let mults = getAllTextMatches (contents =~ "mul\\([0-9]+,[0-9]+\\)") :: [String] let mults = getAllTextMatches (contents =~ "mul\\([0-9]+,[0-9]+\\)") :: [String]
putStrLn $ "Day 3, Puzzle 1 solution: " putStrLn $
"Day 3, Puzzle 1 solution: "
++ show (sumMul mults) ++ show (sumMul mults)

View File

@ -5,15 +5,17 @@ import Data.List.Split (split, splitOn, startsWith)
import Text.Regex.TDFA (getAllTextMatches, (=~)) import Text.Regex.TDFA (getAllTextMatches, (=~))
sumMul :: [String] -> Int sumMul :: [String] -> Int
sumMul xs = let vals = map (splitOn "," . filter (`elem` "0123456789,")) xs sumMul xs =
let vals = map (splitOn "," . filter (`elem` "0123456789,")) xs
in sum $ map (product . map read) vals in sum $ map (product . map read) vals
filterDonts :: [String] -> String filterDonts :: [String] -> String
filterDonts = concat . filter (not . isPrefixOf "don't()") . concatMap (split (startsWith "do()")) filterDonts = concat . concatMap (filter (not . isPrefixOf "don't()") . split (startsWith "do()"))
day3_2 :: IO () day3_2 :: IO ()
day3_2 = do day3_2 = do
contents <- split (startsWith "don't()") <$> readFile "input/day3.txt" contents <- split (startsWith "don't()") <$> readFile "input/day3.txt"
let mults = getAllTextMatches (filterDonts contents =~ "mul\\([0-9]+,[0-9]+\\)") :: [String] let mults = getAllTextMatches (filterDonts contents =~ "mul\\([0-9]+,[0-9]+\\)") :: [String]
putStrLn $ "Day 3, Puzzle 2 solution: " putStrLn $
"Day 3, Puzzle 2 solution: "
++ show (sumMul mults) ++ show (sumMul mults)

View File

@ -1,25 +1,34 @@
module Day4.Puzzle1 (day4_1) where module Day4.Puzzle1 (day4_1) where
import Data.List (transpose, isPrefixOf) import Data.List (isPrefixOf, transpose)
diagonals :: [String] -> [String] diagonals :: [String] -> [String]
diagonals xs = diagonals' xs ++ diagonals' ((transpose . reverse) xs) diagonals xs = diagonals' xs ++ diagonals' ((transpose . reverse) xs)
where diagonals' x = transpose (zipWith drop [0..] x) where
diagonals' x =
transpose (zipWith drop [0 ..] x)
++ transpose (zipWith drop [1 ..] (transpose x)) ++ transpose (zipWith drop [1 ..] (transpose x))
countOccurrences :: String -> [String] -> Int countOccurrences :: String -> [String] -> Int
countOccurrences word text = sum (map (countOccurrences' word) text) + sum (map (countOccurrences' word . reverse) text) countOccurrences word text =
+ sum (map (countOccurrences' word) cols) + sum (map (countOccurrences' word . reverse) cols) sum (map (countOccurrences' word) text)
+ sum (map (countOccurrences' word) diags) + sum (map (countOccurrences' word . reverse) diags) + sum (map (countOccurrences' word . reverse) text)
where cols = transpose text + sum (map (countOccurrences' word) cols)
+ sum (map (countOccurrences' word . reverse) cols)
+ sum (map (countOccurrences' word) diags)
+ sum (map (countOccurrences' word . reverse) diags)
where
cols = transpose text
diags = diagonals text diags = diagonals text
countOccurrences' _ [] = 0 countOccurrences' _ [] = 0
countOccurrences' w txt@(_:rest) = if w `isPrefixOf` txt countOccurrences' w txt@(_ : rest) =
if w `isPrefixOf` txt
then 1 + countOccurrences' word rest then 1 + countOccurrences' word rest
else countOccurrences' w rest else countOccurrences' w rest
day4_1 :: IO () day4_1 :: IO ()
day4_1 = do day4_1 = do
contents <- lines <$> readFile "input/day4.txt" contents <- lines <$> readFile "input/day4.txt"
putStrLn $ "Day 4, Puzzle 1 solution: " putStrLn $
"Day 4, Puzzle 1 solution: "
++ show (countOccurrences "XMAS" contents) ++ show (countOccurrences "XMAS" contents)

View File

@ -1,17 +1,21 @@
module Day4.Puzzle2 (day4_2) where module Day4.Puzzle2 (day4_2) where
import Data.List (transpose, isPrefixOf, tails) import Data.List (isPrefixOf, tails, transpose)
diagonals :: [String] -> [String] diagonals :: [String] -> [String]
diagonals xs = diagonals' xs ++ diagonals' ((transpose . reverse) xs) diagonals xs = diagonals' xs ++ diagonals' ((transpose . reverse) xs)
where diagonals' x = transpose (zipWith drop [0..] x) where
diagonals' x =
transpose (zipWith drop [0 ..] x)
++ transpose (zipWith drop [1 ..] (transpose x)) ++ transpose (zipWith drop [1 ..] (transpose x))
countOccurrences :: String -> [String] -> Int countOccurrences :: String -> [String] -> Int
countOccurrences word text = sum (map (countOccurrences' word) diags) + sum (map (countOccurrences' word . reverse) diags) countOccurrences word text = sum (map (countOccurrences' word) diags) + sum (map (countOccurrences' word . reverse) diags)
where diags = diagonals text where
diags = diagonals text
countOccurrences' _ [] = 0 countOccurrences' _ [] = 0
countOccurrences' w txt@(_:rest) = if w `isPrefixOf` txt countOccurrences' w txt@(_ : rest) =
if w `isPrefixOf` txt
then 1 + countOccurrences' w rest then 1 + countOccurrences' w rest
else countOccurrences' w rest else countOccurrences' w rest
@ -20,10 +24,11 @@ submatricesVert _ [] = []
submatricesVert _ [_] = [] submatricesVert _ [_] = []
submatricesVert _ [_, _] = [] submatricesVert _ [_, _] = []
submatricesVert n matrix@(_ : xxs) = submatrix matrix ++ submatricesVert n xxs submatricesVert n matrix@(_ : xxs) = submatrix matrix ++ submatricesVert n xxs
where submatrix m = [take n $ map (take n) m] where
submatrix m = [take n $ map (take n) m]
day4_2 :: IO () day4_2 :: IO ()
day4_2 = do day4_2 = do
contents <- lines <$> readFile "input/day4.txt" contents <- lines <$> readFile "input/day4.txt"
let xmas = length . filter (\x -> countOccurrences "MAS" x == 2) . concatMap (submatricesVert 3) . transpose $ map tails contents let xmas = length . concatMap (filter (\x -> countOccurrences "MAS" x == 2) . submatricesVert 3) . transpose $ map tails contents
putStrLn $ "Day 4, Puzzle 2 solution: " ++ show xmas putStrLn $ "Day 4, Puzzle 2 solution: " ++ show xmas

View File

@ -6,7 +6,8 @@ import Data.List.Split (splitOn)
isSorted :: [(String, String)] -> [String] -> Bool isSorted :: [(String, String)] -> [String] -> Bool
isSorted _ [_] = True isSorted _ [_] = True
isSorted rules (x:xs) = let after = [ p | (p, n) <- rules, n == x ] isSorted rules (x : xs) =
let after = [p | (p, n) <- rules, n == x]
in not (any (`elem` after) xs) && isSorted rules xs in not (any (`elem` after) xs) && isSorted rules xs
getMiddle :: [String] -> String getMiddle :: [String] -> String
@ -18,5 +19,6 @@ day5_1 = do
let rules = [(x, y) | [x, y] <- takeWhile (/= [""]) contents] let rules = [(x, y) | [x, y] <- takeWhile (/= [""]) contents]
updates = concatMap (map (splitOn ",")) . drop 1 $ dropWhile (/= [""]) contents updates = concatMap (map (splitOn ",")) . drop 1 $ dropWhile (/= [""]) contents
sorted = filter (isSorted rules) updates sorted = filter (isSorted rules) updates
putStrLn $ "Day 5, Puzzle 1 solution: " putStrLn $
"Day 5, Puzzle 1 solution: "
++ (show :: Int -> String) (sum $ map (read . getMiddle) sorted) ++ (show :: Int -> String) (sum $ map (read . getMiddle) sorted)

View File

@ -7,7 +7,8 @@ import Data.List.Split (splitOn)
isSorted :: [(Int, Int)] -> [Int] -> Bool isSorted :: [(Int, Int)] -> [Int] -> Bool
isSorted _ [_] = True isSorted _ [_] = True
isSorted rules (x:xs) = let after = [ p | (p, n) <- rules, n == x ] isSorted rules (x : xs) =
let after = [p | (p, n) <- rules, n == x]
in not (any (`elem` after) xs) && isSorted rules xs in not (any (`elem` after) xs) && isSorted rules xs
getMiddle :: [Int] -> Int getMiddle :: [Int] -> Int
@ -16,7 +17,8 @@ getMiddle xs = xs !! (length xs `div` 2)
sortOnRules :: [(Int, Int)] -> [Int] -> [Int] sortOnRules :: [(Int, Int)] -> [Int] -> [Int]
sortOnRules _ [] = [] sortOnRules _ [] = []
sortOnRules rules (x : xs) = sortOnRules rules beforeArray ++ [x] ++ sortOnRules rules afterArray sortOnRules rules (x : xs) = sortOnRules rules beforeArray ++ [x] ++ sortOnRules rules afterArray
where afterArray = xs \\ before where
afterArray = xs \\ before
beforeArray = xs \\ afterArray beforeArray = xs \\ afterArray
before = [p | (p, n) <- rules, n == x] before = [p | (p, n) <- rules, n == x]
@ -26,5 +28,6 @@ day5_2 = do
let rules = [(read x, read y) | [x, y] <- takeWhile (/= [""]) contents] let rules = [(read x, read y) | [x, y] <- takeWhile (/= [""]) contents]
unsorted = filter (not . isSorted rules) . map (map read) $ concatMap (map (splitOn ",")) . drop 1 $ dropWhile (/= [""]) contents unsorted = filter (not . isSorted rules) . map (map read) $ concatMap (map (splitOn ",")) . drop 1 $ dropWhile (/= [""]) contents
fixUnsorted = map (sortOnRules rules) unsorted fixUnsorted = map (sortOnRules rules) unsorted
putStrLn $ "Day 5, Puzzle 2 solution: " putStrLn $
"Day 5, Puzzle 2 solution: "
++ show (sum $ map getMiddle fixUnsorted) ++ show (sum $ map getMiddle fixUnsorted)

View File

@ -1,11 +1,13 @@
module Day6.Puzzle1 (day6_1) where module Day6.Puzzle1 (day6_1) where
import Data.List (elemIndex, uncons) import Data.List (elemIndex, uncons)
import Data.Maybe (isJust, fromMaybe, fromJust) import Data.Maybe (fromJust, fromMaybe, isJust)
type Grid = [String] type Grid = [String]
type Position = (Int, Int) type Position = (Int, Int)
data Direction = U | R | D | L deriving Eq
data Direction = U | R | D | L deriving (Eq)
getDirection :: Char -> Maybe Direction getDirection :: Char -> Maybe Direction
getDirection '^' = Just U getDirection '^' = Just U
@ -16,7 +18,8 @@ getDirection _ = Nothing
getStartPosition :: Char -> Grid -> Position getStartPosition :: Char -> Grid -> Position
getStartPosition c grid = (x, y) getStartPosition c grid = (x, y)
where x = fromMaybe (-1) . elemIndex True . map (isJust . elemIndex c) $ grid where
x = fromMaybe (-1) . elemIndex True . map (isJust . elemIndex c) $ grid
y = if x == -1 then -1 else fromMaybe (-1) . elemIndex c $ grid !! x y = if x == -1 then -1 else fromMaybe (-1) . elemIndex c $ grid !! x
getGridVal :: Position -> Grid -> Char getGridVal :: Position -> Grid -> Char
@ -26,34 +29,40 @@ isInside :: Position -> Grid -> Bool
isInside (x, y) grid = x >= 0 && y >= 0 && x < length grid && y < length (fst . fromJust $ uncons grid) isInside (x, y) grid = x >= 0 && y >= 0 && x < length grid && y < length (fst . fromJust $ uncons grid)
getNextPosition :: Position -> Direction -> Grid -> (Position, Direction) getNextPosition :: Position -> Direction -> Grid -> (Position, Direction)
getNextPosition (x, y) U grid = let newPos = (x - 1, y) getNextPosition (x, y) U grid =
let newPos = (x - 1, y)
gridVal = getGridVal newPos grid gridVal = getGridVal newPos grid
in if newPos `isInside` grid && gridVal == '#' in if newPos `isInside` grid && gridVal == '#'
then getNextPosition (x, y) R grid then getNextPosition (x, y) R grid
else (newPos, U) else (newPos, U)
getNextPosition (x, y) R grid = let newPos = (x, y + 1) getNextPosition (x, y) R grid =
let newPos = (x, y + 1)
gridVal = getGridVal newPos grid gridVal = getGridVal newPos grid
in if newPos `isInside` grid && gridVal == '#' in if newPos `isInside` grid && gridVal == '#'
then getNextPosition (x, y) D grid then getNextPosition (x, y) D grid
else (newPos, R) else (newPos, R)
getNextPosition (x, y) D grid = let newPos = (x + 1, y) getNextPosition (x, y) D grid =
let newPos = (x + 1, y)
gridVal = getGridVal newPos grid gridVal = getGridVal newPos grid
in if newPos `isInside` grid && gridVal == '#' in if newPos `isInside` grid && gridVal == '#'
then getNextPosition (x, y) L grid then getNextPosition (x, y) L grid
else (newPos, D) else (newPos, D)
getNextPosition (x, y) L grid = let newPos = (x, y - 1) getNextPosition (x, y) L grid =
let newPos = (x, y - 1)
gridVal = getGridVal newPos grid gridVal = getGridVal newPos grid
in if newPos `isInside` grid && gridVal == '#' in if newPos `isInside` grid && gridVal == '#'
then getNextPosition (x, y) U grid then getNextPosition (x, y) U grid
else (newPos, L) else (newPos, L)
markVisited :: Position -> Char -> Grid -> Grid markVisited :: Position -> Char -> Grid -> Grid
markVisited (x, y) c grid = let row = grid !! x markVisited (x, y) c grid =
let row = grid !! x
newRow = take y row ++ [c] ++ drop (y + 1) row newRow = take y row ++ [c] ++ drop (y + 1) row
in take x grid ++ [newRow] ++ drop (x + 1) grid in take x grid ++ [newRow] ++ drop (x + 1) grid
visitGrid :: Position -> Direction -> Grid -> Grid visitGrid :: Position -> Direction -> Grid -> Grid
visitGrid (x, y) direction grid = let newGrid = markVisited (x, y) 'X' grid visitGrid (x, y) direction grid =
let newGrid = markVisited (x, y) 'X' grid
(nextPosition, newDirection) = getNextPosition (x, y) direction grid (nextPosition, newDirection) = getNextPosition (x, y) direction grid
in if nextPosition `isInside` newGrid in if nextPosition `isInside` newGrid
then visitGrid nextPosition newDirection newGrid then visitGrid nextPosition newDirection newGrid
@ -62,8 +71,14 @@ visitGrid (x, y) direction grid = let newGrid = markVisited (x, y) 'X' grid
day6_1 :: IO () day6_1 :: IO ()
day6_1 = do day6_1 = do
contents <- lines <$> readFile "input/day6.txt" contents <- lines <$> readFile "input/day6.txt"
let (x, y) = (\a b c d -> fst . fromJust $ uncons $ filter ((>= 0) . fst) [a, b, c, d]) <$> getStartPosition 'v' <*> getStartPosition '^' let (x, y) =
<*> getStartPosition '<' <*> getStartPosition '>' $ contents (\a b c d -> fst . fromJust $ uncons $ filter ((>= 0) . fst) [a, b, c, d])
<$> getStartPosition 'v'
<*> getStartPosition '^'
<*> getStartPosition '<'
<*> getStartPosition '>'
$ contents
direction = fromJust . getDirection $ (contents !! x) !! y direction = fromJust . getDirection $ (contents !! x) !! y
putStrLn $ "Day 6, Puzzle 1 solution: " putStrLn $
++ show (length . filter (== 'X') . concat $ visitGrid (x, y) direction contents) "Day 6, Puzzle 1 solution: "
++ show (length . concatMap (filter (== 'X')) $ visitGrid (x, y) direction contents)

View File

@ -1,11 +1,13 @@
module Day6.Puzzle2 (day6_2) where module Day6.Puzzle2 (day6_2) where
import Data.List (elemIndex, uncons) import Data.List (elemIndex, uncons)
import Data.Maybe (isJust, fromMaybe, fromJust) import Data.Maybe (fromJust, fromMaybe, isJust)
type Grid = [String] type Grid = [String]
type Position = (Int, Int) type Position = (Int, Int)
data Direction = U | R | D | L deriving Eq
data Direction = U | R | D | L deriving (Eq)
getDirection :: Char -> Maybe Direction getDirection :: Char -> Maybe Direction
getDirection '^' = Just U getDirection '^' = Just U
@ -22,7 +24,8 @@ printDirection L = '<'
getStartPosition :: Char -> Grid -> Position getStartPosition :: Char -> Grid -> Position
getStartPosition c grid = (x, y) getStartPosition c grid = (x, y)
where x = fromMaybe (-1) . elemIndex True . map (isJust . elemIndex c) $ grid where
x = fromMaybe (-1) . elemIndex True . map (isJust . elemIndex c) $ grid
y = if x == -1 then -1 else fromMaybe (-1) . elemIndex c $ grid !! x y = if x == -1 then -1 else fromMaybe (-1) . elemIndex c $ grid !! x
getGridVal :: Position -> Grid -> Char getGridVal :: Position -> Grid -> Char
@ -32,59 +35,74 @@ isInside :: Position -> Grid -> Bool
isInside (x, y) grid = x >= 0 && y >= 0 && x < length grid && y < length (fst . fromJust $ uncons grid) isInside (x, y) grid = x >= 0 && y >= 0 && x < length grid && y < length (fst . fromJust $ uncons grid)
getNextPosition :: Position -> Direction -> Grid -> (Position, Direction) getNextPosition :: Position -> Direction -> Grid -> (Position, Direction)
getNextPosition (x, y) U grid = let newPos = (x - 1, y) getNextPosition (x, y) U grid =
let newPos = (x - 1, y)
gridVal = getGridVal newPos grid gridVal = getGridVal newPos grid
in if newPos `isInside` grid && gridVal == '#' in if newPos `isInside` grid && gridVal == '#'
then getNextPosition (x, y) R grid then getNextPosition (x, y) R grid
else (newPos, U) else (newPos, U)
getNextPosition (x, y) R grid = let newPos = (x, y + 1) getNextPosition (x, y) R grid =
let newPos = (x, y + 1)
gridVal = getGridVal newPos grid gridVal = getGridVal newPos grid
in if newPos `isInside` grid && gridVal == '#' in if newPos `isInside` grid && gridVal == '#'
then getNextPosition (x, y) D grid then getNextPosition (x, y) D grid
else (newPos, R) else (newPos, R)
getNextPosition (x, y) D grid = let newPos = (x + 1, y) getNextPosition (x, y) D grid =
let newPos = (x + 1, y)
gridVal = getGridVal newPos grid gridVal = getGridVal newPos grid
in if newPos `isInside` grid && gridVal == '#' in if newPos `isInside` grid && gridVal == '#'
then getNextPosition (x, y) L grid then getNextPosition (x, y) L grid
else (newPos, D) else (newPos, D)
getNextPosition (x, y) L grid = let newPos = (x, y - 1) getNextPosition (x, y) L grid =
let newPos = (x, y - 1)
gridVal = getGridVal newPos grid gridVal = getGridVal newPos grid
in if newPos `isInside` grid && gridVal == '#' in if newPos `isInside` grid && gridVal == '#'
then getNextPosition (x, y) U grid then getNextPosition (x, y) U grid
else (newPos, L) else (newPos, L)
markVisited :: Position -> Char -> Grid -> Grid markVisited :: Position -> Char -> Grid -> Grid
markVisited (x, y) c grid = let gridVal = getGridVal (x, y) grid markVisited (x, y) c grid =
let gridVal = getGridVal (x, y) grid
in if gridVal == '#' || gridVal == '^' || gridVal == '>' || gridVal == 'v' || gridVal == '<' in if gridVal == '#' || gridVal == '^' || gridVal == '>' || gridVal == 'v' || gridVal == '<'
then grid then grid
else let row = grid !! x else
let row = grid !! x
newRow = take y row ++ [c] ++ drop (y + 1) row newRow = take y row ++ [c] ++ drop (y + 1) row
in take x grid ++ [newRow] ++ drop (x + 1) grid in take x grid ++ [newRow] ++ drop (x + 1) grid
visitGrid :: Position -> Direction -> Grid -> Grid visitGrid :: Position -> Direction -> Grid -> Grid
visitGrid (x, y) direction grid = let newGrid = markVisited (x, y) 'X' grid visitGrid (x, y) direction grid =
let newGrid = markVisited (x, y) 'X' grid
(nextPosition, newDirection) = getNextPosition (x, y) direction grid (nextPosition, newDirection) = getNextPosition (x, y) direction grid
in if nextPosition `isInside` newGrid in if nextPosition `isInside` newGrid
then visitGrid nextPosition newDirection newGrid then visitGrid nextPosition newDirection newGrid
else newGrid else newGrid
checkGridLoop :: Position -> Direction -> Grid -> Bool checkGridLoop :: Position -> Direction -> Grid -> Bool
checkGridLoop startPosition direction grid = let (nextPosition, newDirection) = getNextPosition startPosition direction grid checkGridLoop startPosition direction grid =
let (nextPosition, newDirection) = getNextPosition startPosition direction grid
newDirectionChar = printDirection newDirection newDirectionChar = printDirection newDirection
newGrid = markVisited nextPosition newDirectionChar grid newGrid = markVisited nextPosition newDirectionChar grid
in (nextPosition `isInside` grid) in (nextPosition `isInside` grid)
&& ( (getGridVal nextPosition grid == newDirectionChar) && ( (getGridVal nextPosition grid == newDirectionChar)
|| checkGridLoop nextPosition newDirection newGrid) || checkGridLoop nextPosition newDirection newGrid
)
setGridObstacles :: Position -> Grid -> [Grid] setGridObstacles :: Position -> Grid -> [Grid]
setGridObstacles startPosition grid = let positions = [ (x, y) | x <- [0..(length grid - 1)], y <- [0..(length (fst . fromJust $ uncons grid) - 1)], (x, y) /= startPosition, getGridVal (x, y) grid == 'X' ] setGridObstacles startPosition grid =
let positions = [(x, y) | x <- [0 .. (length grid - 1)], y <- [0 .. (length (fst . fromJust $ uncons grid) - 1)], (x, y) /= startPosition, getGridVal (x, y) grid == 'X']
in zipWith (`markVisited` '#') positions (replicate (length positions) grid) in zipWith (`markVisited` '#') positions (replicate (length positions) grid)
day6_2 :: IO () day6_2 :: IO ()
day6_2 = do day6_2 = do
contents <- lines <$> readFile "input/day6.txt" contents <- lines <$> readFile "input/day6.txt"
let (x, y) = (\a b c d -> fst . fromJust $ uncons $ filter ((>= 0) . fst) [a, b, c, d]) <$> getStartPosition 'v' <*> getStartPosition '^' let (x, y) =
<*> getStartPosition '<' <*> getStartPosition '>' $ contents (\a b c d -> fst . fromJust $ uncons $ filter ((>= 0) . fst) [a, b, c, d])
<$> getStartPosition 'v'
<*> getStartPosition '^'
<*> getStartPosition '<'
<*> getStartPosition '>'
$ contents
direction = fromJust . getDirection $ (contents !! x) !! y direction = fromJust . getDirection $ (contents !! x) !! y
grid = visitGrid (x, y) direction contents grid = visitGrid (x, y) direction contents
gridObstacles = setGridObstacles (x, y) grid gridObstacles = setGridObstacles (x, y) grid

View File

@ -8,7 +8,8 @@ type Equation = (Int, [Int])
isSolvable :: Int -> Equation -> Bool isSolvable :: Int -> Equation -> Bool
isSolvable cur (result, []) = cur == result isSolvable cur (result, []) = cur == result
isSolvable cur (result, [x]) = cur + x == result || cur * x == result isSolvable cur (result, [x]) = cur + x == result || cur * x == result
isSolvable cur (result, x:y:ys) = isSolvable (cur + x + y) (result, ys) isSolvable cur (result, x : y : ys) =
isSolvable (cur + x + y) (result, ys)
|| isSolvable ((cur + x) * y) (result, ys) || isSolvable ((cur + x) * y) (result, ys)
|| isSolvable (cur * x + y) (result, ys) || isSolvable (cur * x + y) (result, ys)
|| isSolvable (cur * x * y) (result, ys) || isSolvable (cur * x * y) (result, ys)
@ -19,5 +20,6 @@ day7_1 = do
let results = map read x let results = map read x
values = map read <$> map words y values = map read <$> map words y
equations = zip results values equations = zip results values
putStrLn $ "Day 7, Puzzle 1 solution: " putStrLn $
"Day 7, Puzzle 1 solution: "
++ show (sum . map fst $ filter (isSolvable 0) equations) ++ show (sum . map fst $ filter (isSolvable 0) equations)

View File

@ -11,7 +11,8 @@ concatInt x y = read $ show x ++ show y
isSolvable :: Int -> Equation -> Bool isSolvable :: Int -> Equation -> Bool
isSolvable cur (result, []) = cur == result isSolvable cur (result, []) = cur == result
isSolvable cur (result, [x]) = cur + x == result || cur * x == result || cur `concatInt` x == result isSolvable cur (result, [x]) = cur + x == result || cur * x == result || cur `concatInt` x == result
isSolvable cur (result, x:y:ys) = isSolvable (cur + x + y) (result, ys) isSolvable cur (result, x : y : ys) =
isSolvable (cur + x + y) (result, ys)
|| isSolvable ((cur + x) * y) (result, ys) || isSolvable ((cur + x) * y) (result, ys)
|| isSolvable ((cur + x) `concatInt` y) (result, ys) || isSolvable ((cur + x) `concatInt` y) (result, ys)
|| isSolvable (cur * x + y) (result, ys) || isSolvable (cur * x + y) (result, ys)
@ -27,5 +28,6 @@ day7_2 = do
let results = map read x let results = map read x
values = map read <$> map words y values = map read <$> map words y
equations = zip results values equations = zip results values
putStrLn $ "Day 7, Puzzle 2 solution: " putStrLn $
"Day 7, Puzzle 2 solution: "
++ show (sum . map fst $ filter (isSolvable 0) equations) ++ show (sum . map fst $ filter (isSolvable 0) equations)

View File

@ -1,28 +1,34 @@
module Day8.Puzzle1 (day8_1) where module Day8.Puzzle1 (day8_1) where
import Control.Applicative
import Data.List (uncons) import Data.List (uncons)
import Data.Maybe (fromJust) import Data.Maybe (fromJust)
import Control.Applicative
import qualified Data.Set as Set import qualified Data.Set as Set
type Freq = Char type Freq = Char
type Coords = (Int, Int) type Coords = (Int, Int)
data Antenna = Antenna { frequency :: Freq
, coordinates :: Coords data Antenna = Antenna
} deriving (Show, Eq) { frequency :: Freq,
coordinates :: Coords
}
deriving (Show, Eq)
readAntenna :: Freq -> Coords -> Antenna readAntenna :: Freq -> Coords -> Antenna
readAntenna freq coords = Antenna {frequency = freq, coordinates = coords} readAntenna freq coords = Antenna {frequency = freq, coordinates = coords}
getAntennas :: [String] -> [Antenna] getAntennas :: [String] -> [Antenna]
getAntennas grid = concat . getZipList $ getAntennasRow <$> ZipList [0 ..] <*> ZipList grid getAntennas grid = concat . getZipList $ getAntennasRow <$> ZipList [0 ..] <*> ZipList grid
where getAntennasRow n row = [ readAntenna x (n, y) | (x, y) <- zip row [0..], x /= '.' ] where
getAntennasRow n row = [readAntenna x (n, y) | (x, y) <- zip row [0 ..], x /= '.']
isInside :: Coords -> Int -> Int -> Bool isInside :: Coords -> Int -> Int -> Bool
isInside c x y = fst c >= 0 && fst c < x && snd c >= 0 && snd c < y isInside c x y = fst c >= 0 && fst c < x && snd c >= 0 && snd c < y
getAntinodes :: Antenna -> Antenna -> Int -> Int -> [Coords] getAntinodes :: Antenna -> Antenna -> Int -> Int -> [Coords]
getAntinodes a b maxX maxY = let xa = fst $ coordinates a getAntinodes a b maxX maxY =
let xa = fst $ coordinates a
ya = snd $ coordinates a ya = snd $ coordinates a
xb = fst $ coordinates b xb = fst $ coordinates b
yb = snd $ coordinates b yb = snd $ coordinates b

View File

@ -1,33 +1,40 @@
module Day8.Puzzle2 (day8_2) where module Day8.Puzzle2 (day8_2) where
import Control.Applicative
import Data.Bifunctor (bimap)
import Data.List (uncons) import Data.List (uncons)
import Data.Maybe (fromJust) import Data.Maybe (fromJust)
import Control.Applicative
import Data.Set (fromList) import Data.Set (fromList)
import Data.Bifunctor (bimap)
type Freq = Char type Freq = Char
type Coords = (Int, Int) type Coords = (Int, Int)
data Antenna = Antenna { frequency :: Freq
, coordinates :: Coords data Antenna = Antenna
} deriving (Show, Eq) { frequency :: Freq,
coordinates :: Coords
}
deriving (Show, Eq)
readAntenna :: Freq -> Coords -> Antenna readAntenna :: Freq -> Coords -> Antenna
readAntenna freq coords = Antenna {frequency = freq, coordinates = coords} readAntenna freq coords = Antenna {frequency = freq, coordinates = coords}
getAntennas :: [String] -> [Antenna] getAntennas :: [String] -> [Antenna]
getAntennas grid = concat . getZipList $ getAntennasRow <$> ZipList [0 ..] <*> ZipList grid getAntennas grid = concat . getZipList $ getAntennasRow <$> ZipList [0 ..] <*> ZipList grid
where getAntennasRow n row = [ readAntenna x (n, y) | (x, y) <- zip row [0..], x /= '.' ] where
getAntennasRow n row = [readAntenna x (n, y) | (x, y) <- zip row [0 ..], x /= '.']
isInside :: Coords -> Int -> Int -> Bool isInside :: Coords -> Int -> Int -> Bool
isInside c x y = fst c >= 0 && fst c < x && snd c >= 0 && snd c < y isInside c x y = fst c >= 0 && fst c < x && snd c >= 0 && snd c < y
generateCoords :: Coords -> Coords -> [Coords] generateCoords :: Coords -> Coords -> [Coords]
generateCoords c offset = scanl shiftCoords c (repeat offset) generateCoords c offset = scanl shiftCoords c (repeat offset)
where shiftCoords x = bimap (fst x +) (snd x +) where
shiftCoords x = bimap (fst x +) (snd x +)
getAntinodes :: Antenna -> Antenna -> Int -> Int -> [Coords] getAntinodes :: Antenna -> Antenna -> Int -> Int -> [Coords]
getAntinodes a b maxX maxY = let xa = fst $ coordinates a getAntinodes a b maxX maxY =
let xa = fst $ coordinates a
ya = snd $ coordinates a ya = snd $ coordinates a
xb = fst $ coordinates b xb = fst $ coordinates b
yb = snd $ coordinates b yb = snd $ coordinates b
@ -35,7 +42,8 @@ getAntinodes a b maxX maxY = let xa = fst $ coordinates a
distY = ya - yb distY = ya - yb
in if frequency a /= frequency b || coordinates a == coordinates b in if frequency a /= frequency b || coordinates a == coordinates b
then [] then []
else filter (\c -> isInside c maxX maxY) [(2 * xa - xb, 2 * ya - yb), (2 * xb - xa, 2 * yb - ya)] else
filter (\c -> isInside c maxX maxY) [(2 * xa - xb, 2 * ya - yb), (2 * xb - xa, 2 * yb - ya)]
++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (distX, distY)) ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (distX, distY))
++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (-distX, -distY)) ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (-distX, -distY))

View File

@ -1,21 +1,23 @@
module Day9.Puzzle1 (day9_1) where module Day9.Puzzle1 (day9_1) where
import Data.List (intersperse) import Control.Applicative
import Data.Char (digitToInt) import Data.Char (digitToInt)
import qualified Data.Foldable as F
import Data.List (intersperse)
import Data.Maybe (fromJust, fromMaybe) import Data.Maybe (fromJust, fromMaybe)
import qualified Data.Sequence as S import qualified Data.Sequence as S
import qualified Data.Foldable as F
import Control.Applicative
parseDiskMap :: [Int] -> S.Seq Int parseDiskMap :: [Int] -> S.Seq Int
parseDiskMap xs = let values = intersperse (-1) [0..] parseDiskMap xs =
let values = intersperse (-1) [0 ..]
in S.fromList . concat . getZipList $ replicate <$> ZipList xs <*> ZipList values in S.fromList . concat . getZipList $ replicate <$> ZipList xs <*> ZipList values
compact :: S.Seq Int -> S.Seq Int compact :: S.Seq Int -> S.Seq Int
compact xs compact xs
| fileIndex == -1 = xs | fileIndex == -1 = xs
| otherwise = S.filter (/= -1) $ startDisk S.>< (compact . S.insertAt 0 fileVal . S.deleteAt 0 $ S.deleteAt fileIndex endDisk) | otherwise = S.filter (/= -1) $ startDisk S.>< (compact . S.insertAt 0 fileVal . S.deleteAt 0 $ S.deleteAt fileIndex endDisk)
where spaceIndex = fromJust $ S.elemIndexL (-1) xs where
spaceIndex = fromJust $ S.elemIndexL (-1) xs
(startDisk, endDisk) = S.splitAt spaceIndex xs (startDisk, endDisk) = S.splitAt spaceIndex xs
fileIndex = fromMaybe (-1) (S.findIndexR (/= -1) endDisk) fileIndex = fromMaybe (-1) (S.findIndexR (/= -1) endDisk)
fileVal = S.index endDisk fileIndex fileVal = S.index endDisk fileIndex
@ -27,5 +29,6 @@ day9_1 :: IO ()
day9_1 = do day9_1 = do
contents <- init <$> readFile "input/day9.txt" contents <- init <$> readFile "input/day9.txt"
let diskMap = map digitToInt contents let diskMap = map digitToInt contents
putStrLn $ "Day 9, Puzzle 1 solution: " putStrLn $
"Day 9, Puzzle 1 solution: "
++ show (checksum . F.toList . compact $ parseDiskMap diskMap) ++ show (checksum . F.toList . compact $ parseDiskMap diskMap)

View File

@ -2,17 +2,18 @@
module Day9.Puzzle2 (day9_2) where module Day9.Puzzle2 (day9_2) where
import Data.List (intersperse, groupBy)
import Data.Char (digitToInt) import Data.Char (digitToInt)
import Data.Maybe (fromMaybe)
import Data.Function (on)
import qualified Data.Sequence as S
import qualified Data.Foldable as F import qualified Data.Foldable as F
import Data.Function (on)
import Data.List (groupBy, intersperse)
import Data.Maybe (fromMaybe)
import qualified Data.Sequence as S
type DiskElem = (Int, Int) type DiskElem = (Int, Int)
parseDiskMap :: [Int] -> S.Seq DiskElem parseDiskMap :: [Int] -> S.Seq DiskElem
parseDiskMap xs = let values = intersperse (-1) [0..] parseDiskMap xs =
let values = intersperse (-1) [0 ..]
in S.fromList $ zip values xs in S.fromList $ zip values xs
isSpaceEnough :: Int -> DiskElem -> Bool isSpaceEnough :: Int -> DiskElem -> Bool
@ -29,16 +30,19 @@ compareFileValue :: Int -> DiskElem -> Bool
compareFileValue x (v, _) = x == v compareFileValue x (v, _) = x == v
moveFile :: Int -> Int -> DiskElem -> DiskElem -> S.Seq DiskElem -> S.Seq DiskElem moveFile :: Int -> Int -> DiskElem -> DiskElem -> S.Seq DiskElem -> S.Seq DiskElem
moveFile i sIndex sVal fVal xs = let xs' = F.toList . S.insertAt sIndex fVal . S.insertAt sIndex sVal . S.deleteAt sIndex . S.insertAt i (-1, snd fVal) $ S.deleteAt i xs moveFile i sIndex sVal fVal xs =
let xs' = F.toList . S.insertAt sIndex fVal . S.insertAt sIndex sVal . S.deleteAt sIndex . S.insertAt i (-1, snd fVal) $ S.deleteAt i xs
in S.fromList $ map (foldl1 combineSpace) $ groupBy ((==) `on` fst) xs' in S.fromList $ map (foldl1 combineSpace) $ groupBy ((==) `on` fst) xs'
compactFiles :: Int -> S.Seq DiskElem -> S.Seq DiskElem compactFiles :: Int -> S.Seq DiskElem -> S.Seq DiskElem
compactFiles (-1) xs = xs compactFiles (-1) xs = xs
compactFiles 0 xs = xs compactFiles 0 xs = xs
compactFiles n xs = if fst fVal == -1 || sIndex == -1 || sIndex >= n compactFiles n xs =
if fst fVal == -1 || sIndex == -1 || sIndex >= n
then compactFiles (n - 1) xs then compactFiles (n - 1) xs
else compactFiles fIndex xs' else compactFiles fIndex xs'
where fVal = S.index xs n where
fVal = S.index xs n
sIndex = fromMaybe (-1) $ S.findIndexL (isSpaceEnough (snd fVal)) xs sIndex = fromMaybe (-1) $ S.findIndexL (isSpaceEnough (snd fVal)) xs
sVal = updateSpace (snd fVal) (fromMaybe (-1, 0) $ S.lookup sIndex xs) sVal = updateSpace (snd fVal) (fromMaybe (-1, 0) $ S.lookup sIndex xs)
xs' = moveFile n sIndex sVal fVal xs xs' = moveFile n sIndex sVal fVal xs
@ -51,7 +55,8 @@ maskMinus1 (l:ls)
| otherwise = l : maskMinus1 ls | otherwise = l : maskMinus1 ls
tuplesToIntList :: S.Seq DiskElem -> [Int] tuplesToIntList :: S.Seq DiskElem -> [Int]
tuplesToIntList disk = let listDisk = F.toList disk tuplesToIntList disk =
let listDisk = F.toList disk
in concatMap (\x -> replicate (snd x) (fst x)) listDisk in concatMap (\x -> replicate (snd x) (fst x)) listDisk
checksum :: [Int] -> Int checksum :: [Int] -> Int