Browse Source

Day 1 + Day 2

main
Annwan 3 weeks ago
commit
e497c34b9b
  1. 2
      .gitignore
  2. 5
      CHANGELOG.md
  3. 29
      LICENSE
  4. 41
      aoc2024.cabal
  5. 23
      run/Main.hs
  6. 36
      src/Day1.hs
  7. 40
      src/Day2.hs
  8. 17
      test/Main.hs

2
.gitignore

@ -0,0 +1,2 @@
/dist-newstyle
/inputs

5
CHANGELOG.md

@ -0,0 +1,5 @@
# Revision history for aoc2024
## 0.1.0.0 -- YYYY-mm-dd
* First version. Released on an unsuspecting world.

29
LICENSE

@ -0,0 +1,29 @@
Copyright (c) 2024, Annwan
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

41
aoc2024.cabal

@ -0,0 +1,41 @@
cabal-version: 3.4
name: aoc2024
version: 0.1.0.0
synopsis: AOC 2024 solutions
homepage: https://git.annwan.me/Annwan/aoc2024
license: BSD-3-Clause
license-file: LICENSE
author: Annwan
maintainer: annwan@annwan.me
build-type: Simple
extra-doc-files: CHANGELOG.md
common warnings
ghc-options: -Wall
library
import: warnings
exposed-modules: Day1, Day2
build-depends: base ^>=4.18.0.0
hs-source-dirs: src
default-language: GHC2021
test-suite aoc2024-test
import: warnings
default-language: GHC2021
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Main.hs
build-depends:
base ^>=4.18.0.0,
aoc2024,
hspec,
hspec-contrib
executable aoc2024-runner
import: warnings
default-language: GHC2021
hs-source-dirs: run
main-is: Main.hs
build-depends:
base ^>=4.18.0.0,
aoc2024,

23
run/Main.hs

@ -0,0 +1,23 @@
module Main where
import qualified Day1 as D1
import qualified Day2 as D2
solutions :: [(String -> String, String -> String)]
solutions = [(D1.part1, D1.part2),
(D2.part1, D2.part2)]
run :: Int -> Int -> IO ()
run day part = do
input <- readFile ("inputs/" ++ show day)
let select = if part == 1 then fst else snd
putStrLn $ select (solutions !! (day - 1)) input
pure ()
main :: IO ()
main = do
day <- getLine
problem <- getLine
run (read day :: Int) (read problem :: Int)

36
src/Day1.hs

@ -0,0 +1,36 @@
module Day1 (part1, part2) where
import Data.List (transpose, sort)
part1' :: [[Integer]] -> Integer
part1' [a, b] = sum
. map (\(x, y) -> abs (x - y))
$ zip (sort a) (sort b)
part1' _ = error "Unreachable"
part1 :: String -> String
part1 = show . part1' . prepare
where
prepare :: String -> [[Integer]]
prepare = transpose
. map (map read . words)
. lines
part2' :: [[Integer]] -> Integer
part2' [a, b] = sum
. zipWith (*) a
. map (\x -> count x b)
$ a
where
count :: Eq a => a -> [a] -> Integer
count what (x:xs) = count what xs + if what == x then 1 else 0
count _ [] = 0
part2' _ = error "Unreachable"
part2 :: String -> String
part2 = show . part2'. prepare
where
prepare :: String -> [[Integer]]
prepare = transpose
. map (map read . words)
. lines

40
src/Day2.hs

@ -0,0 +1,40 @@
module Day2 (part1, part2) where
import Data.List (subsequences)
isSafe :: [Integer] -> Bool
isSafe x = isSafeIntevals x && (isAscending x || isDescending x)
where
isSafeIntevals :: [Integer] -> Bool
isSafeIntevals = all (\(a, b) -> 3 >= abs (a - b)) . pairs
isAscending :: [Integer] -> Bool
isAscending = all (\(a, b) -> a < b) . pairs
isDescending :: [Integer] -> Bool
isDescending = all (\(a, b) -> a > b) . pairs
pairs :: [a] -> [(a, a)]
pairs [_] = []
pairs [] = []
pairs (x1:x2:xs) = (x1, x2) : pairs (x2:xs)
part1 :: String -> String
part1 = show
. length
. filter isSafe
. prepare
where
prepare :: String -> [[Integer]]
prepare = map (map read . words)
. lines
part2 :: String -> String
part2 = show
. length
. filter (\x ->
isSafe x
|| any isSafe [y | y <- subsequences x, length y == length x - 1])
. prepare
where
prepare :: String -> [[Integer]]
prepare = map (map read . words) . lines

17
test/Main.hs

@ -0,0 +1,17 @@
module Main (main) where
import Test.Hspec
import Day1
import Day2
main :: IO ()
main = hspec $ do
describe "Day1" $ do
it "solves part 1" $ do
Day1.part1 "3 4\n4 3\n2 5\n1 3\n3 9\n3 3\n" `shouldBe` "11"
it "solves part 2" $ do
Day1.part2 "3 4\n4 3\n2 5\n1 3\n3 9\n3 3\n" `shouldBe` "31"
describe "Day 2" $ do
it "solves part 1" $ do
Day2.part1 "7 6 4 2 1\n1 2 7 8 9\n9 7 6 2 1\n1 3 2 4 5\n8 6 4 4 1\n1 3 6 7 9" `shouldBe` "2"
it "solves part 2" $ do
Day2.part2 "7 6 4 2 1\n1 2 7 8 9\n9 7 6 2 1\n1 3 2 4 5\n8 6 4 4 1\n1 3 6 7 9" `shouldBe` "4"
Loading…
Cancel
Save