diff --git a/.gitignore b/.gitignore index ad4ede2..9f5022c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ -*.txt -*.hi -*.o +input +.stack-work diff --git a/Setup.hs b/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/adventofcode2024.cabal b/adventofcode2024.cabal new file mode 100644 index 0000000..49c3054 --- /dev/null +++ b/adventofcode2024.cabal @@ -0,0 +1,60 @@ +cabal-version: 2.2 + +name: adventofcode2024 +version: 0.1.0.0 +-- synopsis: +-- description: +homepage: https://github.com/Fuxino/adventofcode2024#readme +license: MIT +license-file: LICENSE +author: Daniele Fucini +maintainer: dfucini@gmail.com +copyright: 2024 Daniele Fucini +category: Web +build-type: Simple +extra-source-files: README.md + +executable adventofcode2024 + hs-source-dirs: src + main-is: Main.hs + default-language: Haskell2010 + build-depends: base >= 4.7 && < 5 + , split + , containers + , regex-tdfa + , matrix + ghc-options: -Wall + -Wcompat + -Widentities + -Wincomplete-record-updates + -Wincomplete-uni-patterns + -Wmissing-export-lists + -Wmissing-home-modules + -Wpartial-fields + -Wredundant-constraints + other-modules: + Day1.Puzzle1 + Day1.Puzzle2 + Day2.Puzzle1 + Day2.Puzzle2 + Day3.Puzzle1 + Day3.Puzzle2 + Day4.Puzzle1 + Day4.Puzzle2 + Day5.Puzzle1 + Day5.Puzzle2 + Day6.Puzzle1 + Day6.Puzzle2 + Day7.Puzzle1 + Day7.Puzzle2 + Day8.Puzzle1 + Day8.Puzzle2 + Day9.Puzzle1 + Day9.Puzzle2 + Day10.Puzzle1 + Day11.Puzzle1 + Day11.Puzzle2 + Day12.Puzzle1 + Day13.Puzzle1 + Day13.Puzzle2 + Day14.Puzzle1 diff --git a/Day1/puzzle1.hs b/src/Day1/Puzzle1.hs similarity index 51% rename from Day1/puzzle1.hs rename to src/Day1/Puzzle1.hs index 42d4714..04ba920 100644 --- a/Day1/puzzle1.hs +++ b/src/Day1/Puzzle1.hs @@ -1,9 +1,13 @@ +module Day1.Puzzle1 (day1_1) where + import Data.List (transpose, sort) listDistance :: [Int] -> [Int] -> Int listDistance xs ys = sum $ map abs $ zipWith (-) (sort xs) (sort ys) -main = do - contents <- lines <$> readFile "day1.txt" +day1_1 :: IO () +day1_1 = do + contents <- lines <$> readFile "input/day1.txt" let [x, y] = transpose $ map read . words <$> contents - print $ listDistance x y + putStrLn $ "Day 1, Puzzle 1 solution: " + ++ show (listDistance x y) diff --git a/Day1/puzzle2.hs b/src/Day1/Puzzle2.hs similarity index 64% rename from Day1/puzzle2.hs rename to src/Day1/Puzzle2.hs index f7118d2..b62b8f7 100644 --- a/Day1/puzzle2.hs +++ b/src/Day1/Puzzle2.hs @@ -1,3 +1,5 @@ +module Day1.Puzzle2 (day1_2) where + import Data.List (transpose, sort, group, uncons) import Data.Maybe (fromJust) @@ -5,7 +7,9 @@ similarityScore :: [Int] -> [Int] -> Int 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 ] -main = do - contents <- lines <$> readFile "day1.txt" +day1_2 :: IO () +day1_2 = do + contents <- lines <$> readFile "input/day1.txt" let [x, y] = transpose $ map read . words <$> contents - print $ similarityScore x y + putStrLn $ "Day 1, Puzzle 2 solution: " + ++ show (similarityScore x y) diff --git a/Day10/puzzle1.hs b/src/Day10/Puzzle1.hs similarity index 89% rename from Day10/puzzle1.hs rename to src/Day10/Puzzle1.hs index 5d0fd9f..aa27429 100644 --- a/Day10/puzzle1.hs +++ b/src/Day10/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day10.Puzzle1 (day10_1) where + import Data.Char (digitToInt) import Data.List (uncons) import Data.List.Split (chunksOf) @@ -19,8 +21,9 @@ listVertices :: [String] -> [[V]] listVertices grid = let l = length $ fst . fromJust $ uncons grid in chunksOf l $ zip (map (:[]) (concat grid)) [0..] -main = do - contents <- lines <$> readFile "day10.txt" +day10_1 :: IO () +day10_1 = do + contents <- lines <$> readFile "input/day10.txt" let grid = listVertices contents edgeCoords = [ (x, y) | x <- [0..length grid -1], y <- [0..length (fst . fromJust $ uncons grid) - 1] ] edgeList = [ (x, y, z) | ((x, y), z) <- zip (concat grid) (map (getEdges grid) edgeCoords) ] @@ -28,4 +31,4 @@ main = do startList = [ x | (_, x, _) <- filter (\(x, _, _) -> x == "0") $ map nodeFromVertex $ vertices graph ] endList = [ x | (_, x, _) <- filter (\(x, _, _) -> x == "9") $ map nodeFromVertex $ vertices graph ] paths = filter id $ [ path graph x y | x <- startList, y <- endList ] - print $ length paths + putStrLn $ "Day 10, Puzzle 1 solution: " ++ show (length paths) diff --git a/Day11/puzzle2.hs b/src/Day11/Puzzle1.hs similarity index 73% rename from Day11/puzzle2.hs rename to src/Day11/Puzzle1.hs index 5bb51f4..a474aba 100644 --- a/Day11/puzzle2.hs +++ b/src/Day11/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day11.Puzzle1 (day11_1) where + import qualified Data.Map.Strict as M blinkStone :: (Int, Int) -> [(Int, Int)] @@ -12,6 +14,8 @@ blink :: Int -> M.Map Int Int -> M.Map Int Int blink 0 m = m blink n m = blink (n - 1) $ M.fromListWith (+) $ concatMap blinkStone $ M.toList m -main = do - contents <- M.fromListWith (+) . flip zip (repeat 1) . map read . words <$> readFile "day11.txt" - print . M.foldl (+) 0 $ blink 75 contents +day11_1 :: IO () +day11_1 = do + contents <- M.fromListWith (+) . flip zip (repeat 1) . map read . words <$> readFile "input/day11.txt" + putStrLn $ "Day 11, Puzzle 1 solution: " + ++ show (M.foldl (+) 0 $ blink 25 contents) diff --git a/Day11/puzzle1.hs b/src/Day11/Puzzle2.hs similarity index 73% rename from Day11/puzzle1.hs rename to src/Day11/Puzzle2.hs index 2df7bbc..671aa51 100644 --- a/Day11/puzzle1.hs +++ b/src/Day11/Puzzle2.hs @@ -1,3 +1,5 @@ +module Day11.Puzzle2 (day11_2) where + import qualified Data.Map.Strict as M blinkStone :: (Int, Int) -> [(Int, Int)] @@ -12,6 +14,8 @@ blink :: Int -> M.Map Int Int -> M.Map Int Int blink 0 m = m blink n m = blink (n - 1) $ M.fromListWith (+) $ concatMap blinkStone $ M.toList m -main = do - contents <- M.fromListWith (+) . flip zip (repeat 1) . map read . words <$> readFile "day11.txt" - print . M.foldl (+) 0 $ blink 25 contents +day11_2 :: IO () +day11_2 = do + contents <- M.fromListWith (+) . flip zip (repeat 1) . map read . words <$> readFile "input/day11.txt" + putStrLn $ "Day 11, Puzzle 2 solution: " + ++ show (M.foldl (+) 0 $ blink 75 contents) diff --git a/Day12/puzzle1.hs b/src/Day12/Puzzle1.hs similarity index 88% rename from Day12/puzzle1.hs rename to src/Day12/Puzzle1.hs index a70d267..a1a2b6b 100644 --- a/Day12/puzzle1.hs +++ b/src/Day12/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day12.Puzzle1 (day12_1) where + import Data.List (uncons) import Data.List.Split (chunksOf) import Data.Maybe (fromJust) @@ -24,8 +26,9 @@ calculatePerimeter nodeFromVertex p = let edges = concat [ x | (_, _, x) <- toLi area = 4 * length p in area - length edges -main = do - contents <- lines <$> readFile "day12.txt" +day12_1 :: IO () +day12_1= do + contents <- lines <$> readFile "input/day12.txt" let grid = listVertices contents edgeCoords = [ (x, y) | x <- [0..length grid -1], y <- [0..length (fst . fromJust $ uncons grid) - 1] ] edgeList = [ (x, y, z) | ((x, y), z) <- zip (concat grid) (map (getEdges grid) edgeCoords) ] @@ -33,4 +36,5 @@ main = do plots = scc graph areas = map length plots perimeters = map (calculatePerimeter nodeFromVertex) plots - print . sum $ zipWith (*) areas perimeters + putStrLn $ "Day 12, Puzzle 1 solution: " + ++ show (sum $ zipWith (*) areas perimeters) diff --git a/Day13/puzzle1.hs b/src/Day13/Puzzle1.hs similarity index 83% rename from Day13/puzzle1.hs rename to src/Day13/Puzzle1.hs index 2b5ad5b..387ec09 100644 --- a/Day13/puzzle1.hs +++ b/src/Day13/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day13.Puzzle1 (day13_1) where + import Data.Char (isDigit) import Data.List (uncons) import Data.List.Split (splitOn, chunksOf) @@ -25,8 +27,10 @@ solve eqSystem = let rowEchelonList = toList . fromRight (zero 1 1) $ rref eqSys cost :: [Int] -> Int cost [x, y] = 3 * x + y -main = do - contents <- map concat . chunksOf 4 . lines <$> readFile "day13.txt" +day13_1 :: IO () +day13_1 = do + contents <- map concat . chunksOf 4 . lines <$> readFile "input/day13.txt" let eqSystems = map getMatrix contents solutions = (map . map) round $ mapMaybe solve eqSystems - print . sum $ map cost solutions + putStrLn $ "Day 13, Puzzle 1 solution: " + ++ show (sum $ map cost solutions) diff --git a/Day13/puzzle2.hs b/src/Day13/Puzzle2.hs similarity index 84% rename from Day13/puzzle2.hs rename to src/Day13/Puzzle2.hs index 7ba5a4e..c01fcfe 100644 --- a/Day13/puzzle2.hs +++ b/src/Day13/Puzzle2.hs @@ -1,3 +1,5 @@ +module Day13.Puzzle2 (day13_2) where + import Data.Char (isDigit) import Data.List (uncons) import Data.List.Split (splitOn, chunksOf) @@ -28,8 +30,10 @@ solve eqSystem = let rowEchelonList = toList . fromRight (zero 1 1) $ rref eqSys cost :: [Int] -> Int cost [x, y] = 3 * x + y -main = do - contents <- map concat . chunksOf 4 . lines <$> readFile "day13.txt" +day13_2 :: IO () +day13_2 = do + contents <- map concat . chunksOf 4 . lines <$> readFile "input/day13.txt" let eqSystems = map getMatrix contents solutions = (map . map) round $ mapMaybe solve eqSystems - print . sum $ map cost solutions + putStrLn $ "Day 13, Puzzle 2 solution: " + ++ show (sum $ map cost solutions) diff --git a/Day14/puzzle1.hs b/src/Day14/Puzzle1.hs similarity index 86% rename from Day14/puzzle1.hs rename to src/Day14/Puzzle1.hs index 2a9de1d..4ae15ab 100644 --- a/Day14/puzzle1.hs +++ b/src/Day14/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day14.Puzzle1 (day14_1) where + import Data.Char (isDigit) import Data.List.Split (splitOn) @@ -30,12 +32,14 @@ quadrant r | otherwise = -1 where p = fst r -main = do - contents <- lines <$> readFile "day14.txt" +day14_1 :: IO () +day14_1= do + contents <- lines <$> readFile "input/day14.txt" let robots = map readRobot contents robots' = map (moveRobot 100) robots firstQ = length $ filter (\r -> quadrant r == 0) robots' secondQ = length $ filter (\r -> quadrant r == 1) robots' thirdQ = length $ filter (\r -> quadrant r == 2) robots' fourthQ = length $ filter (\r -> quadrant r == 3) robots' - print $ firstQ * secondQ * thirdQ * fourthQ + putStrLn $ "Day 14, Puzzle 1 solution: " + ++ show (firstQ * secondQ * thirdQ * fourthQ) diff --git a/Day2/puzzle1.hs b/src/Day2/Puzzle1.hs similarity index 66% rename from Day2/puzzle1.hs rename to src/Day2/Puzzle1.hs index 4f79186..1f61a8d 100644 --- a/Day2/puzzle1.hs +++ b/src/Day2/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day2.Puzzle1 (day2_1) where + import Data.List (sort, sortBy) import Data.Ord @@ -7,7 +9,9 @@ isSafe xs = (isAscending xs || isDescending xs) && maximum distances <= 3 && min isDescending xs = xs == sortBy (comparing Down) xs distances = map abs $ zipWith (-) xs (drop 1 xs) -main = do - contents <- lines <$> readFile "day2.txt" +day2_1 :: IO () +day2_1 = do + contents <- lines <$> readFile "input/day2.txt" let reports = map read . words <$> contents - print . length $ filter isSafe reports + putStrLn $ "Day 2, Puzzle 1 solution: " + ++ show (length $ filter isSafe reports) diff --git a/Day2/puzzle2.hs b/src/Day2/Puzzle2.hs similarity index 72% rename from Day2/puzzle2.hs rename to src/Day2/Puzzle2.hs index 22e3fe8..8739d05 100644 --- a/Day2/puzzle2.hs +++ b/src/Day2/Puzzle2.hs @@ -1,3 +1,5 @@ +module Day2.Puzzle2 (day2_2) where + import Data.List (sort, sortBy, inits, tails) import Data.Ord @@ -12,7 +14,9 @@ removeLevel xs = zipWith (++) ys zs where ys = map init $ drop 1 (inits xs) zs = map (drop 1) $ init (tails xs) -main = do - contents <- lines <$> readFile "day2.txt" +day2_2 :: IO () +day2_2 = do + contents <- lines <$> readFile "input/day2.txt" let reports = map read . words <$> contents - print . length . filter (any isSafe) $ map removeLevel reports + putStrLn $ "Day 2, Puzzle 2 solution: " + ++ show (length . filter (any isSafe) $ map removeLevel reports) diff --git a/Day3/puzzle1.hs b/src/Day3/Puzzle1.hs similarity index 65% rename from Day3/puzzle1.hs rename to src/Day3/Puzzle1.hs index 4af28bf..068d59c 100644 --- a/Day3/puzzle1.hs +++ b/src/Day3/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day3.Puzzle1 (day3_1) where + import Data.List.Split (splitOn) import Data.Char (isDigit) import Text.Regex.TDFA (getAllTextMatches, (=~)) @@ -6,7 +8,9 @@ sumMul :: [String] -> Int sumMul xs = let vals = map (splitOn "," . filter (`elem` "0123456789,")) xs in sum $ map (product . map read) vals -main = do - contents <- readFile "day3.txt" +day3_1 :: IO () +day3_1 = do + contents <- readFile "input/day3.txt" let mults = getAllTextMatches (contents =~ "mul\\([0-9]+,[0-9]+\\)") :: [String] - print $ sumMul mults + putStrLn $ "Day 3, Puzzle 1 solution: " + ++ show (sumMul mults) diff --git a/Day3/puzzle2.hs b/src/Day3/Puzzle2.hs similarity index 71% rename from Day3/puzzle2.hs rename to src/Day3/Puzzle2.hs index 305fd3e..5b819ba 100644 --- a/Day3/puzzle2.hs +++ b/src/Day3/Puzzle2.hs @@ -1,3 +1,5 @@ +module Day3.Puzzle2 (day3_2) where + import Data.List (isPrefixOf) import Data.List.Split (split, splitOn, startsWith) import Data.Char (isDigit) @@ -10,7 +12,9 @@ sumMul xs = let vals = map (splitOn "," . filter (`elem` "0123456789,")) xs filterDonts :: [String] -> String filterDonts = concat . filter (not . isPrefixOf "don't()") . concatMap (split (startsWith "do()")) -main = do - contents <- split (startsWith "don't()") <$> readFile "day3.txt" +day3_2 :: IO() +day3_2 = do + contents <- split (startsWith "don't()") <$> readFile "input/day3.txt" let mults = getAllTextMatches (filterDonts contents =~ "mul\\([0-9]+,[0-9]+\\)") :: [String] - print $ sumMul mults + putStrLn $ "Day 3, Puzzle 2 solution: " + ++ show (sumMul mults) diff --git a/Day4/puzzle1.hs b/src/Day4/Puzzle1.hs similarity index 85% rename from Day4/puzzle1.hs rename to src/Day4/Puzzle1.hs index 8be62d7..812576b 100644 --- a/Day4/puzzle1.hs +++ b/src/Day4/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day4.Puzzle1 (day4_1) where + import Data.List (transpose, isPrefixOf) diagonals :: [String] -> [String] @@ -15,7 +17,9 @@ countOccurrences word text = sum (map (countOccurrences' word) text) + sum (map countOccurrences' word text@(_:rest) = if word `isPrefixOf` text then 1 + countOccurrences' word rest else countOccurrences' word rest - -main = do - contents <- lines <$> readFile "day4.txt" - print $ countOccurrences "XMAS" contents + +day4_1 :: IO () +day4_1 = do + contents <- lines <$> readFile "input/day4.txt" + putStrLn $ "Day 4, Puzzle 1 solution: " + ++ show (countOccurrences "XMAS" contents) diff --git a/Day4/puzzle2.hs b/src/Day4/Puzzle2.hs similarity index 88% rename from Day4/puzzle2.hs rename to src/Day4/Puzzle2.hs index 7a606ac..1a5cd54 100644 --- a/Day4/puzzle2.hs +++ b/src/Day4/Puzzle2.hs @@ -1,3 +1,5 @@ +module Day4.Puzzle2 (day4_2) where + import Data.List (transpose, isPrefixOf, tails) diagonals :: [String] -> [String] @@ -20,7 +22,8 @@ submatricesVert _ [xs, ys] = [] submatricesVert n matrix@(xs:xxs) = submatrix matrix ++ submatricesVert n xxs where submatrix matrix = [take n $ map (take n) matrix] -main = do - contents <- lines <$> readFile "day4.txt" +day4_2 :: IO () +day4_2 = do + contents <- lines <$> readFile "input/day4.txt" let xmas = length . filter (\x -> countOccurrences "MAS" x == 2) . concatMap (submatricesVert 3) . transpose $ map tails contents - print xmas + putStrLn $ "Day 4, Puzzle 2 solution: " ++ show xmas diff --git a/Day5/puzzle1.hs b/src/Day5/Puzzle1.hs similarity index 69% rename from Day5/puzzle1.hs rename to src/Day5/Puzzle1.hs index bb3397b..3870ba7 100644 --- a/Day5/puzzle1.hs +++ b/src/Day5/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day5.Puzzle1 (day5_1) where + import Data.List.Split (splitOn) isSorted :: [(String, String)] -> [String] -> Bool @@ -8,9 +10,11 @@ isSorted rules (x:xs) = let after = [ p | (p, n) <- rules, n == x ] getMiddle :: [String] -> String getMiddle xs = xs !! (length xs `div` 2) -main = do - contents <- map (splitOn "|") . lines <$> readFile "day5.txt" +day5_1 :: IO () +day5_1 = do + contents <- map (splitOn "|") . lines <$> readFile "input/day5.txt" let rules = [ (x, y) | [x, y] <- takeWhile (/= [""]) contents ] updates = concatMap (map (splitOn ",")) . drop 1 $ dropWhile (/= [""]) contents sorted = filter (isSorted rules) updates - print . sum $ map (read . getMiddle) sorted + putStrLn $ "Day 5, Puzzle 1 solution: " + ++ show (sum $ map (read . getMiddle) sorted) diff --git a/Day5/puzzle2.hs b/src/Day5/Puzzle2.hs similarity index 81% rename from Day5/puzzle2.hs rename to src/Day5/Puzzle2.hs index 9d12b26..7c13eef 100644 --- a/Day5/puzzle2.hs +++ b/src/Day5/Puzzle2.hs @@ -1,3 +1,5 @@ +module Day5.Puzzle2 (day5_2) where + import Data.List ((\\)) import Data.List.Split (splitOn) @@ -16,9 +18,11 @@ sortOnRules rules (x:xs) = sortOnRules rules beforeArray ++ [x] ++ sortOnRules r beforeArray = xs \\ afterArray before = [ p | (p, n) <- rules, n == x ] -main = do - contents <- map (splitOn "|") . lines <$> readFile "day5.txt" +day5_2 :: IO () +day5_2 = do + contents <- map (splitOn "|") . lines <$> readFile "input/day5.txt" 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 fixUnsorted = map (sortOnRules rules) unsorted - print . sum $ map getMiddle fixUnsorted + putStrLn $ "Day 5, Puzzle 2 solution: " + ++ show (sum $ map getMiddle fixUnsorted) diff --git a/Day6/puzzle1.hs b/src/Day6/Puzzle1.hs similarity index 92% rename from Day6/puzzle1.hs rename to src/Day6/Puzzle1.hs index b5889ba..d68476a 100644 --- a/Day6/puzzle1.hs +++ b/src/Day6/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day6.Puzzle1 (day6_1) where + import Data.List (elemIndex, uncons) import Data.Maybe (isJust, fromMaybe, fromJust) @@ -56,9 +58,11 @@ visitGrid (x, y) direction grid = let newGrid = markVisited (x, y) 'X' grid then visitGrid nextPosition newDirection newGrid else newGrid -main = do - contents <- lines <$> readFile "day6.txt" +day6_1 :: IO () +day6_1 = do + contents <- lines <$> readFile "input/day6.txt" let (x, y) = (\w x y z -> fst . fromJust $ uncons $ filter ((>= 0) . fst) [w, x, y, z]) <$> getStartPosition 'v' <*> getStartPosition '^' <*> getStartPosition '<' <*> getStartPosition '>' $ contents direction = getDirection $ (contents !! x) !! y - print . length . filter (== 'X') . concat $ visitGrid (x, y) direction contents + putStrLn $ "Day 6, Puzzle 1 solution: " + ++ show (length . filter (== 'X') . concat $ visitGrid (x, y) direction contents) diff --git a/Day6/puzzle2.hs b/src/Day6/Puzzle2.hs similarity index 96% rename from Day6/puzzle2.hs rename to src/Day6/Puzzle2.hs index f41736f..f00af62 100644 --- a/Day6/puzzle2.hs +++ b/src/Day6/Puzzle2.hs @@ -1,3 +1,5 @@ +module Day6.Puzzle2 (day6_2) where + import Data.List (elemIndex, uncons) import Data.Maybe (isJust, fromMaybe, fromJust) @@ -77,13 +79,13 @@ 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' ] in zipWith (`markVisited` '#') positions (replicate (length positions) grid) - -main = do - contents <- lines <$> readFile "day6.txt" +day6_2 :: IO () +day6_2 = do + contents <- lines <$> readFile "input/day6.txt" let (x, y) = (\w x y z -> fst . fromJust $ uncons $ filter ((>= 0) . fst) [w, x, y, z]) <$> getStartPosition 'v' <*> getStartPosition '^' <*> getStartPosition '<' <*> getStartPosition '>' $ contents direction = getDirection $ (contents !! x) !! y grid = visitGrid (x, y) direction contents gridObstacles = setGridObstacles (x, y) grid loops = filter (checkGridLoop (x, y) direction) gridObstacles - print $ length loops + putStrLn $ "Day 6, Puzzle 2 solution: " ++ show (length loops) diff --git a/Day7/puzzle1.hs b/src/Day7/Puzzle1.hs similarity index 78% rename from Day7/puzzle1.hs rename to src/Day7/Puzzle1.hs index 9d50f4d..7767bc0 100644 --- a/Day7/puzzle1.hs +++ b/src/Day7/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day7.Puzzle1 (day7_1) where + import Data.List (transpose) import Data.List.Split (splitOn) @@ -11,9 +13,11 @@ isSolvable cur (result, x:y:ys) = isSolvable (cur + x + y) (result, ys) || isSolvable (cur * x + y) (result, ys) || isSolvable (cur * x * y) (result, ys) -main = do - [x, y] <- transpose . map (splitOn ":") . lines <$> readFile "day7.txt" +day7_1 :: IO () +day7_1 = do + [x, y] <- transpose . map (splitOn ":") . lines <$> readFile "input/day7.txt" let results = map read x values = map read <$> map words y equations = zip results values - print . sum . map fst $ filter (isSolvable 0) equations + putStrLn $ "Day 7, Puzzle 1 solution: " + ++ show (sum . map fst $ filter (isSolvable 0) equations) diff --git a/Day7/puzzle2.hs b/src/Day7/Puzzle2.hs similarity index 86% rename from Day7/puzzle2.hs rename to src/Day7/Puzzle2.hs index 164f63b..43d33f5 100644 --- a/Day7/puzzle2.hs +++ b/src/Day7/Puzzle2.hs @@ -1,3 +1,5 @@ +module Day7.Puzzle2 (day7_2) where + import Data.List (transpose) import Data.List.Split (splitOn) @@ -19,9 +21,11 @@ isSolvable cur (result, x:y:ys) = isSolvable (cur + x + y) (result, ys) || isSolvable ((cur `concatInt` x) * y) (result, ys) || isSolvable ((cur `concatInt` x) `concatInt` y) (result, ys) -main = do - [x, y] <- transpose . map (splitOn ":") . lines <$> readFile "day7.txt" +day7_2 :: IO () +day7_2 = do + [x, y] <- transpose . map (splitOn ":") . lines <$> readFile "input/day7.txt" let results = map read x values = map read <$> map words y equations = zip results values - print . sum . map fst $ filter (isSolvable 0) equations + putStrLn $ "Day 7, Puzzle 2 solution: " + ++ show (sum . map fst $ filter (isSolvable 0) equations) diff --git a/Day8/puzzle1.hs b/src/Day8/Puzzle1.hs similarity index 89% rename from Day8/puzzle1.hs rename to src/Day8/Puzzle1.hs index 229cde1..633a9ad 100644 --- a/Day8/puzzle1.hs +++ b/src/Day8/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day8.Puzzle1 (day8_1) where + import Data.List (uncons) import Data.Maybe (fromJust) import Control.Applicative @@ -28,10 +30,11 @@ getAntinodes a b maxX maxY = let xa = fst $ coordinates a then [] else filter (\c -> isInside c maxX maxY) [(2 * xa - xb, 2 * ya - yb), (2 * xb - xa, 2 * yb - ya)] -main = do - contents <- lines <$> readFile "day8.txt" +day8_1 :: IO () +day8_1 = do + contents <- lines <$> readFile "input/day8.txt" let antennas = getAntennas contents x = length contents y = length $ fst . fromJust $ uncons contents antinodes = Set.fromList $ concat [ getAntinodes a b x y | a <- antennas, b <- antennas, a /= b, frequency a == frequency b ] - print $ length antinodes + putStrLn $ "Day 8, Puzzle 1 solution: " ++ show (length antinodes) diff --git a/Day8/puzzle2.hs b/src/Day8/Puzzle2.hs similarity index 92% rename from Day8/puzzle2.hs rename to src/Day8/Puzzle2.hs index 9738ecd..84e1b16 100644 --- a/Day8/puzzle2.hs +++ b/src/Day8/Puzzle2.hs @@ -1,3 +1,5 @@ +module Day8.Puzzle2 (day8_2) where + import Data.List (uncons) import Data.Maybe (fromJust) import Control.Applicative @@ -37,10 +39,11 @@ getAntinodes a b maxX maxY = let xa = fst $ coordinates a ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (distX, distY)) ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (-distX, -distY)) -main = do - contents <- lines <$> readFile "day8.txt" +day8_2 :: IO () +day8_2 = do + contents <- lines <$> readFile "input/day8.txt" let antennas = getAntennas contents x = length contents y = length $ fst . fromJust $ uncons contents antinodes = fromList $ concat [ getAntinodes a b x y | a <- antennas, b <- antennas, a /= b, frequency a == frequency b ] - print $ length antinodes + putStrLn $ "Day 8, Puzzle 2 solution: " ++ show (length antinodes) diff --git a/Day9/puzzle1.hs b/src/Day9/Puzzle1.hs similarity index 81% rename from Day9/puzzle1.hs rename to src/Day9/Puzzle1.hs index 296b8ef..969960e 100644 --- a/Day9/puzzle1.hs +++ b/src/Day9/Puzzle1.hs @@ -1,3 +1,5 @@ +module Day9.Puzzle1 (day9_1) where + import Data.List (intersperse) import Data.Char (digitToInt) import Data.Maybe (fromJust, fromMaybe) @@ -21,7 +23,9 @@ compact xs checksum :: [Int] -> Int checksum xs = sum $ zipWith (*) xs [0..] -main = do - contents <- init <$> readFile "day9.txt" +day9_1 :: IO () +day9_1 = do + contents <- init <$> readFile "input/day9.txt" let diskMap = map digitToInt contents - print . checksum . F.toList . compact $ parseDiskMap diskMap + putStrLn $ "Day 9, Puzzle 1 solution: " + ++ show (checksum . F.toList . compact $ parseDiskMap diskMap) diff --git a/Day9/puzzle2.hs b/src/Day9/Puzzle2.hs similarity index 92% rename from Day9/puzzle2.hs rename to src/Day9/Puzzle2.hs index 524eeff..4a9cb65 100644 --- a/Day9/puzzle2.hs +++ b/src/Day9/Puzzle2.hs @@ -1,3 +1,5 @@ +module Day9.Puzzle2 (day9_2) where + import Data.List (intersperse, groupBy) import Data.Char (digitToInt) import Data.Maybe (fromMaybe) @@ -53,9 +55,10 @@ tuplesToIntList disk = let listDisk = F.toList disk checksum :: [Int] -> Int checksum xs = sum $ zipWith (*) (maskMinus1 xs) [0..] -main = do - contents <- init <$> readFile "day9.txt" +day9_2 :: IO () +day9_2 = do + contents <- init <$> readFile "input/day9.txt" let disk = parseDiskMap $ map digitToInt contents i = fromMaybe (-1) $ S.findIndexR (\x -> fst x /= -1) disk compactedDisk = tuplesToIntList $ S.filter (\x -> snd x > 0) $ compactFiles i disk - print $ checksum compactedDisk + putStrLn $ "Day 9, Puzzle 2 solution: " ++ show (checksum compactedDisk) diff --git a/src/Main.hs b/src/Main.hs new file mode 100644 index 0000000..7bf322c --- /dev/null +++ b/src/Main.hs @@ -0,0 +1,59 @@ +module Main (main) where + +import Day1.Puzzle1 +import Day1.Puzzle2 +import Day2.Puzzle1 +import Day2.Puzzle2 +import Day3.Puzzle1 +import Day3.Puzzle2 +import Day4.Puzzle1 +import Day4.Puzzle2 +import Day5.Puzzle1 +import Day5.Puzzle2 +import Day6.Puzzle1 +import Day6.Puzzle2 +import Day7.Puzzle1 +import Day7.Puzzle2 +import Day8.Puzzle1 +import Day8.Puzzle2 +import Day9.Puzzle1 +import Day9.Puzzle2 +import Day10.Puzzle1 +import Day11.Puzzle1 +import Day11.Puzzle2 +import Day12.Puzzle1 +import Day13.Puzzle1 +import Day13.Puzzle2 +import Day14.Puzzle1 +import System.Environment (getArgs) + +main :: IO () +main = do + args <- getArgs + case args of + "1":"1":_ -> day1_1 + "1":"2":_ -> day1_2 + "2":"1":_ -> day2_1 + "2":"2":_ -> day2_2 + "3":"1":_ -> day3_1 + "3":"2":_ -> day3_2 + "4":"1":_ -> day4_1 + "4":"2":_ -> day4_2 + "5":"1":_ -> day5_1 + "5":"2":_ -> day5_2 + "6":"1":_ -> day6_1 + "6":"2":_ -> day6_2 + "7":"1":_ -> day7_1 + "7":"2":_ -> day7_2 + "8":"1":_ -> day8_1 + "8":"2":_ -> day8_2 + "9":"1":_ -> day9_1 + "9":"2":_ -> day9_2 + "10":"1":_ -> day10_1 + "11":"1":_ -> day11_1 + "11":"2":_ -> day11_2 + "12":"1":_ -> day12_1 + "13":"1":_ -> day13_1 + "13":"2":_ -> day13_2 + "14":"1":_ -> day14_1 + _ -> error "Not implemented" diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 0000000..1620b4f --- /dev/null +++ b/stack.yaml @@ -0,0 +1,67 @@ +# This file was automatically generated by 'stack init' +# +# Some commonly used options have been documented as comments in this file. +# For advanced use and comprehensive documentation of the format, please see: +# https://docs.haskellstack.org/en/stable/yaml_configuration/ + +# A 'specific' Stackage snapshot or a compiler version. +# A snapshot resolver dictates the compiler version and the set of packages +# to be used for project dependencies. For example: +# +# snapshot: lts-22.28 +# snapshot: nightly-2024-07-05 +# snapshot: ghc-9.6.6 +# +# The location of a snapshot can be provided as a file or url. Stack assumes +# a snapshot provided as a file might change, whereas a url resource does not. +# +# snapshot: ./custom-snapshot.yaml +# snapshot: https://example.com/snapshots/2024-01-01.yaml +snapshot: + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/23/0.yaml + +# User packages to be built. +# Various formats can be used as shown in the example below. +# +# packages: +# - some-directory +# - https://example.com/foo/bar/baz-0.0.2.tar.gz +# subdirs: +# - auto-update +# - wai +packages: +- . +# Dependency packages to be pulled from upstream that are not in the snapshot. +# These entries can reference officially published versions as well as +# forks / in-progress versions pinned to a git hash. For example: +# +# extra-deps: +# - acme-missiles-0.3 +# - git: https://github.com/commercialhaskell/stack.git +# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a +# +# extra-deps: [] + +# Override default flag values for project packages and extra-deps +# flags: {} + +# Extra package databases containing global packages +# extra-package-dbs: [] + +# Control whether we use the GHC we find on the path +# system-ghc: true +# +# Require a specific version of Stack, using version ranges +# require-stack-version: -any # Default +# require-stack-version: ">=3.1" +# +# Override the architecture used by Stack, especially useful on Windows +# arch: i386 +# arch: x86_64 +# +# Extra directories used by Stack for building +# extra-include-dirs: [/path/to/dir] +# extra-lib-dirs: [/path/to/dir] +# +# Allow a newer minor version of GHC than the snapshot specifies +# compiler-check: newer-minor diff --git a/stack.yaml.lock b/stack.yaml.lock new file mode 100644 index 0000000..a4edf3e --- /dev/null +++ b/stack.yaml.lock @@ -0,0 +1,13 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/lock_files + +packages: [] +snapshots: +- completed: + sha256: 9444fadfa30b67a93080254d53872478c087592ad64443e47c546cdcd13149ae + size: 678857 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/23/0.yaml + original: + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/23/0.yaml