Add 2015 day 6

This commit is contained in:
Xavier Morel
2020-12-07 14:34:31 +01:00
parent bf633bf483
commit e1c3de4580
3 changed files with 380 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
module Y2015.Day06 (y15day06) where
import Data.List.Split
data Ranges = Ranges {
minWidth :: Int
, maxWidth :: Int
, minHeight :: Int
, maxHeight :: Int
} deriving Show
data Instruction = Toggle Ranges | TurnOn Ranges | TurnOff Ranges deriving Show
type Lights = [Bool]
getRanges :: [String] -> Ranges
getRanges parts = Ranges minW maxW minH maxH
where start = map read $ splitOn "," $ parts !! 0 :: [Int]
end = map read $ splitOn "," $ parts !! 2 :: [Int]
widths = [start !! 0, end !! 0]
heights = [start !! 1, end !! 1]
minW = minimum widths
maxW = maximum widths
minH = minimum heights
maxH = maximum heights
parseEntry :: [String] -> Instruction
parseEntry parts
| parts !! 0 == "turn" && parts !! 1 == "on" = TurnOn $ getRanges $ tail $ tail $ parts
| parts !! 0 == "turn" && parts !! 1 == "off" = TurnOff $ getRanges $ tail $ tail $ parts
| parts !! 0 == "toggle" = Toggle $ getRanges $ tail $ parts
applyInstructionP1 :: (Int, Int) -> Bool -> Instruction -> Bool
applyInstructionP1 (x, y) cur (TurnOn (Ranges minX maxX minY maxY))
| x >= minX && x <= maxX && y >= minY && y <= maxY = True
| otherwise = cur
applyInstructionP1 (x, y) cur (TurnOff (Ranges minX maxX minY maxY))
| x >= minX && x <= maxX && y >= minY && y <= maxY = False
| otherwise = cur
applyInstructionP1 (x, y) cur (Toggle (Ranges minX maxX minY maxY))
| x >= minX && x <= maxX && y >= minY && y <= maxY = not cur
| otherwise = cur
applyInstructionsP1 :: [Instruction] -> Bool -> (Int, Int) -> Bool
applyInstructionsP1 [] cur _ = cur
applyInstructionsP1 (inst:next) cur pos = applyInstructionsP1 next newState pos
where newState = applyInstructionP1 pos cur inst
countLightsP1 :: [Instruction] -> Int
countLightsP1 instr = length $ filter (== True) $ map (applyInstructionsP1 instr False) allPos
where allPos = map (\n -> (n `div` 1000, mod n 1000)) $ take 1000000 $ iterate (+1) 0
applyInstructionP2 :: (Int, Int) -> Int -> Instruction -> Int
applyInstructionP2 (x, y) cur (TurnOn (Ranges minX maxX minY maxY))
| x >= minX && x <= maxX && y >= minY && y <= maxY = cur + 1
| otherwise = cur
applyInstructionP2 (x, y) cur (TurnOff (Ranges minX maxX minY maxY))
| x >= minX && x <= maxX && y >= minY && y <= maxY && cur > 0 = cur - 1
| otherwise = cur
applyInstructionP2 (x, y) cur (Toggle (Ranges minX maxX minY maxY))
| x >= minX && x <= maxX && y >= minY && y <= maxY = cur + 2
| otherwise = cur
applyInstructionsP2 :: [Instruction] -> Int -> (Int, Int) -> Int
applyInstructionsP2 [] cur _ = cur
applyInstructionsP2 (inst:next) cur pos = applyInstructionsP2 next newState pos
where newState = applyInstructionP2 pos cur inst
countLightsP2 :: [Instruction] -> Int
countLightsP2 instr = sum $ map (applyInstructionsP2 instr 0) allPos
where allPos = map (\n -> (n `div` 1000, mod n 1000)) $ take 1000000 $ iterate (+1) 0
y15day06 :: [String] -> (String, String)
y15day06 input = (part1, part2)
where part1 = show $ countLightsP1 instructions
part2 = show $ countLightsP2 instructions
instructions = map (parseEntry . splitOn " ") input

View File

@@ -5,6 +5,7 @@ import Y2015.Day02
import Y2015.Day03
import Y2015.Day04
import Y2015.Day05
import Y2015.Day06
year2015 :: String -> [String] -> (String, String)
year2015 "01" = y15day01
@@ -12,3 +13,4 @@ year2015 "02" = y15day02
year2015 "03" = y15day03
year2015 "04" = y15day04
year2015 "05" = y15day05
year2015 "06" = y15day06