Improve day04

This commit is contained in:
Felix Albrigtsen 2022-12-04 13:29:07 +01:00
parent c8bfd92a39
commit bab470906e
1 changed files with 9 additions and 22 deletions

View File

@ -4,23 +4,25 @@ main = do
let list = [] let list = []
file <- readFile "input.txt" file <- readFile "input.txt"
let inputLines = lines file let inputLines = lines file
let pairs = map (splitWhen (==',')) inputLines let stringpairs = map (splitWhen (==',')) inputLines
-- Each pair is a set of two numbers separated by a dash let listpairs = map (map parseRange) stringpairs
let limits = map (map parseRange) pairs let pairs = map (\x -> (head x, last x)) listpairs
let containedWithin = map rangeListIsContained limits -- Each line of input has now gone from "1-2,3-4" to ((1,2),(3,4))
let containedWithin = map (uncurry rangeIsContained) pairs
let containedCount = length $ filter (==True) containedWithin let containedCount = length $ filter (==True) containedWithin
print "Part 1: " print "Part 1: "
print containedCount print containedCount
let overlap = map rangeListOverlap limits let overlap = map (uncurry rangeOverlaps) pairs
let overlapCount = length $ filter (==True) overlap let overlapCount = length $ filter (==True) overlap
print "Part 2: " print "Part 2: "
print overlapCount print overlapCount
-- "1-3" -> (1,3)
parseRange :: String -> (Int, Int) parseRange :: String -> (Int, Int)
parseRange pair = do parseRange pair = do
let numbers = splitWhen (=='-') pair let numbers = splitWhen (=='-') pair
@ -28,7 +30,6 @@ parseRange pair = do
let second = read (numbers !! 1) :: Int let second = read (numbers !! 1) :: Int
(first, second) (first, second)
-- True if the first range is entirely contained in the second range, or vice versa -- True if the first range is entirely contained in the second range, or vice versa
rangeIsContained :: (Int, Int) -> (Int, Int) -> Bool rangeIsContained :: (Int, Int) -> (Int, Int) -> Bool
rangeIsContained (lo1, hi1) (lo2, hi2) rangeIsContained (lo1, hi1) (lo2, hi2)
@ -36,7 +37,7 @@ rangeIsContained (lo1, hi1) (lo2, hi2)
| lo1 >= lo2 && hi1 <= hi2 = True | lo1 >= lo2 && hi1 <= hi2 = True
| otherwise = False | otherwise = False
-- True if any endpoint of a range is within the other range -- True if any part of the two ranges overlap
rangeOverlaps :: (Int, Int) -> (Int, Int) -> Bool rangeOverlaps :: (Int, Int) -> (Int, Int) -> Bool
rangeOverlaps (lo1, hi1) (lo2, hi2) rangeOverlaps (lo1, hi1) (lo2, hi2)
| rangeIsContained (lo1, lo1) (lo2, hi2) = True | rangeIsContained (lo1, lo1) (lo2, hi2) = True
@ -44,20 +45,6 @@ rangeOverlaps (lo1, hi1) (lo2, hi2)
| hi2 >= lo1 && hi2 <= hi1 = True | hi2 >= lo1 && hi2 <= hi1 = True
| otherwise = False | otherwise = False
-- This is mega dirty, should probably be replaced with a smart map.
rangeListIsContained :: [(Int, Int)] -> Bool
rangeListIsContained ranges = do
let first = ranges !! 0
let second = ranges !! 1
rangeIsContained first second
rangeListOverlap :: [(Int, Int)] -> Bool
rangeListOverlap ranges = do
let first = ranges !! 0
let second = ranges !! 1
rangeOverlaps first second
-- Modified from Prelude.words -- Modified from Prelude.words
splitWhen :: (Char -> Bool) -> String -> [String] splitWhen :: (Char -> Bool) -> String -> [String]
splitWhen p s = case dropWhile p s of splitWhen p s = case dropWhile p s of