Skip to content

Commit e0a039d

Browse files
committed
Day 4: Camp Cleanup
1 parent 535abf2 commit e0a039d

File tree

7 files changed

+71
-1
lines changed

7 files changed

+71
-1
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ Development occurs in language-specific directories:
88
|[Day1.hs](hs/src/Day1.hs)|[Day1.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day1.kt)|[day1.py](py/aoc2022/day1.py)|[day1.rs](rs/src/day1.rs)|
99
|[Day2.hs](hs/src/Day2.hs)|[Day2.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day2.kt)|[day2.py](py/aoc2022/day2.py)|[day2.rs](rs/src/day2.rs)|
1010
|[Day3.hs](hs/src/Day3.hs)|[Day3.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day3.kt)|[day3.py](py/aoc2022/day3.py)|[day3.rs](rs/src/day3.rs)|
11+
|[Day4.hs](hs/src/Day4.hs)|

hs/aoc2022.cabal

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ data-files:
1414
day1.txt
1515
, day2.txt
1616
, day3.txt
17+
, day4.txt
1718

1819
extra-source-files:
1920
README.md
@@ -23,6 +24,7 @@ library
2324
Day1
2425
, Day2
2526
, Day3
27+
, Day4
2628
build-depends:
2729
base ^>=4.16.0.0
2830
, split ^>=0.2.3.5
@@ -57,6 +59,7 @@ test-suite aoc2022-test
5759
Day1Spec
5860
, Day2Spec
5961
, Day3Spec
62+
, Day4Spec
6063
hs-source-dirs: test
6164
default-language: GHC2021
6265
build-tool-depends:

hs/app/Main.hs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module Main (main) where
44
import Day1 (day1a, day1b)
55
import Day2 (day2a, day2b)
66
import Day3 (day3a, day3b)
7+
import Day4 (day4a, day4b)
78

89
import Control.Monad ((<=<), when)
910
import Data.Maybe (mapMaybe)
@@ -30,3 +31,4 @@ main = do
3031
run 1 print [day1a, day1b]
3132
run 2 print [day2a, day2b]
3233
run 3 print [day3a, day3b]
34+
run 4 (either fail print) [day4a, day4b]

hs/bench/Main.hs

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import qualified Data.Text.IO as TIO (readFile)
66
import Day1 (day1a, day1b)
77
import Day2 (day2a, day2b)
88
import Day3 (day3a, day3b)
9+
import Day4 (day4a, day4b)
910
import Paths_aoc2022 (getDataFileName)
1011

1112
getDayInput :: Int -> IO Text
@@ -25,4 +26,8 @@ main = defaultMain
2526
[ bench "part 1" $ nf day3a input
2627
, bench "part 2" $ nf day3b input
2728
]
29+
, env (getDayInput 4) $ \input -> bgroup "Day 4"
30+
[ bench "part 1" $ nf day4a input
31+
, bench "part 2" $ nf day4b input
32+
]
2833
]

hs/src/Common.hs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
module Common (readEntire) where
1+
module Common (count, readEntire) where
22

3+
import Data.Foldable (toList)
34
import Data.Text (Text)
45
import qualified Data.Text as T (null)
56
import Data.Text.Read (Reader)
67

8+
count :: (Foldable t) => (a -> Bool) -> t a -> Int
9+
count p = length . filter p . toList
10+
711
readEntire :: Reader a -> Text -> Either String a
812
readEntire reader input = do
913
(a, t) <- reader input

hs/src/Day4.hs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{-|
2+
Module: Day4
3+
Description: <https://adventofcode.com/2022/day/4 Day 4: Camp Cleanup>
4+
-}
5+
{-# LANGUAGE OverloadedStrings #-}
6+
module Day4 (day4a, day4b) where
7+
8+
import Common (count)
9+
import Control.Monad (ap)
10+
import Data.Maybe (fromMaybe)
11+
import Data.Text (Text)
12+
import qualified Data.Text as T (lines, stripPrefix)
13+
import qualified Data.Text.Read as T (decimal)
14+
15+
parse :: (Integral a) => Text -> Either String (a, a, a, a)
16+
parse line = do
17+
(a, line) <- T.decimal line
18+
(b, line) <- T.decimal $ fromMaybe `ap` T.stripPrefix "-" $ line
19+
(c, line) <- T.decimal $ fromMaybe `ap` T.stripPrefix "," $ line
20+
(d, line) <- T.decimal $ fromMaybe `ap` T.stripPrefix "-" $ line
21+
pure (a, b, c, d)
22+
23+
day4a :: Text -> Either String Int
24+
day4a input = fmap (count ok) . sequence $ parse <$> T.lines input where
25+
ok (a, b, c, d) = a >= c && b <= d || a <= c && b >= d
26+
27+
day4b :: Text -> Either String Int
28+
day4b input = fmap (count ok) . sequence $ parse <$> T.lines input where
29+
ok (a, b, c, d) = a <= d && b >= c

hs/test/Day4Spec.hs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
module Day4Spec (spec) where
3+
4+
import Data.Text (Text)
5+
import qualified Data.Text as T (unlines)
6+
import Day4 (day4a, day4b)
7+
import Test.Hspec (Spec, describe, it, shouldBe)
8+
9+
example :: Text
10+
example = T.unlines
11+
[ "2-4,6-8"
12+
, "2-3,4-5"
13+
, "5-7,7-9"
14+
, "2-8,3-7"
15+
, "6-6,4-6"
16+
, "2-6,4-8"
17+
]
18+
19+
spec :: Spec
20+
spec = do
21+
describe "part 1" $ do
22+
it "examples" $ do
23+
day4a example `shouldBe` Right 2
24+
describe "part 2" $ do
25+
it "examples" $ do
26+
day4b example `shouldBe` Right 4

0 commit comments

Comments
 (0)