Day 03
This commit is contained in:
@@ -20,3 +20,11 @@ executable day02
|
|||||||
build-depends: base ^>=4.15.1.0, MissingH
|
build-depends: base ^>=4.15.1.0, MissingH
|
||||||
hs-source-dirs: day02
|
hs-source-dirs: day02
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable day03
|
||||||
|
main-is: Main.hs
|
||||||
|
other-modules: Commons Part1 Part2
|
||||||
|
|
||||||
|
build-depends: base ^>=4.15.1.0
|
||||||
|
hs-source-dirs: day03
|
||||||
|
default-language: Haskell2010
|
||||||
|
|||||||
62
day03/Commons.hs
Normal file
62
day03/Commons.hs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
module Commons where
|
||||||
|
|
||||||
|
import GHC.IO.Handle (isEOF)
|
||||||
|
import Data.Char (isDigit)
|
||||||
|
|
||||||
|
|
||||||
|
data Coordinates = Coordinates { x :: Int, y :: Int } deriving (Eq, Show)
|
||||||
|
data NumberPart = NumberPart { value :: Int, numberLength :: Int, neighbors :: [Coordinates] } deriving Show
|
||||||
|
data SymbolPart = SymbolPart { symbol :: Char, coordinates :: Coordinates } deriving Show
|
||||||
|
data Engine = Engine { numbers :: [NumberPart], symbols :: [SymbolPart] } deriving Show
|
||||||
|
|
||||||
|
|
||||||
|
parseNumberPartNeighborsIn :: Int -> Int -> Int -> [Coordinates]
|
||||||
|
parseNumberPartNeighborsIn row column length | length > 0 = Coordinates {x = column + length - 1, y = row - 1}:
|
||||||
|
Coordinates {x = column + length - 1, y = row + 1}:
|
||||||
|
parseNumberPartNeighborsIn row column (length - 1)
|
||||||
|
| length == 0 = []
|
||||||
|
|
||||||
|
parseNumberPartNeighbors :: Int -> Int -> Int -> [Coordinates]
|
||||||
|
parseNumberPartNeighbors row column length = Coordinates {x = column - 1, y = row - 1}:
|
||||||
|
Coordinates {x = column - 1, y = row}:
|
||||||
|
Coordinates {x = column - 1, y = row+1}:
|
||||||
|
Coordinates {x = column + length, y = row - 1}:
|
||||||
|
Coordinates {x = column + length, y = row }:
|
||||||
|
Coordinates {x = column + length, y = row + 1}:
|
||||||
|
parseNumberPartNeighborsIn row column length
|
||||||
|
|
||||||
|
parseNumberPartValue :: String -> String
|
||||||
|
parseNumberPartValue (h: t) | isDigit h = h: parseNumberPartValue t
|
||||||
|
parseNumberPartValue _ = []
|
||||||
|
|
||||||
|
parseNumberPart :: Int -> Int -> String -> NumberPart
|
||||||
|
parseNumberPart row column rawNumber = let value = parseNumberPartValue rawNumber
|
||||||
|
l = length value
|
||||||
|
in NumberPart {value = read value, numberLength = l,
|
||||||
|
neighbors = parseNumberPartNeighbors row column l}
|
||||||
|
|
||||||
|
parseLine :: Int -> Int -> String -> Engine -> Engine
|
||||||
|
parseLine _ _ [] engine = engine
|
||||||
|
parseLine row column (h: t) engine | isDigit h = let newNumberPart = parseNumberPart row column (h: t)
|
||||||
|
newNumberLength = numberLength newNumberPart
|
||||||
|
in parseLine row (column + newNumberLength)
|
||||||
|
(drop (newNumberLength - 1) t)
|
||||||
|
engine {numbers = newNumberPart: numbers engine}
|
||||||
|
| h /= '.' = let newSymbolPart = SymbolPart {
|
||||||
|
symbol = h,
|
||||||
|
coordinates = Coordinates {x = column, y = row}
|
||||||
|
}
|
||||||
|
in parseLine row (column + 1) t
|
||||||
|
engine {symbols = newSymbolPart: symbols engine}
|
||||||
|
| otherwise = parseLine row (column + 1) t engine
|
||||||
|
|
||||||
|
parseEngine :: Int -> Engine -> IO Engine
|
||||||
|
parseEngine row engine = do done <- isEOF
|
||||||
|
if done
|
||||||
|
then return engine
|
||||||
|
else do line <- getLine
|
||||||
|
let newEngine = parseLine row 1 line engine
|
||||||
|
parseEngine (row+1) newEngine
|
||||||
|
|
||||||
|
parse :: IO Engine
|
||||||
|
parse = parseEngine 1 Engine {numbers = [], symbols = []}
|
||||||
12
day03/Main.hs
Normal file
12
day03/Main.hs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import Commons
|
||||||
|
import qualified Part1
|
||||||
|
import qualified Part2
|
||||||
|
|
||||||
|
|
||||||
|
main = do engine <- parse
|
||||||
|
let part1Res = sum (Part1.getActualPartValuesNumbersFromEngine engine)
|
||||||
|
print part1Res
|
||||||
|
let part2Res = sum (Part2.getGearRatiosFromEngine engine)
|
||||||
|
print part2Res
|
||||||
18
day03/Part1.hs
Normal file
18
day03/Part1.hs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
module Part1 where
|
||||||
|
|
||||||
|
import Commons
|
||||||
|
|
||||||
|
|
||||||
|
isSymbolNeighbor :: [Coordinates] -> [Coordinates] -> Bool
|
||||||
|
isSymbolNeighbor [] _ = False
|
||||||
|
isSymbolNeighbor (h: t) symbolsCoordinates = h `elem` symbolsCoordinates || isSymbolNeighbor t symbolsCoordinates
|
||||||
|
|
||||||
|
getActualPartNumbers :: [NumberPart] -> [Coordinates] -> [NumberPart]
|
||||||
|
getActualPartNumbers [] _ = []
|
||||||
|
getActualPartNumbers (h: t) symbolsCoordinates
|
||||||
|
| isSymbolNeighbor (neighbors h) symbolsCoordinates = h: getActualPartNumbers t symbolsCoordinates
|
||||||
|
| otherwise = getActualPartNumbers t symbolsCoordinates
|
||||||
|
|
||||||
|
getActualPartValuesNumbersFromEngine :: Engine -> [Int]
|
||||||
|
getActualPartValuesNumbersFromEngine engine =
|
||||||
|
map value (getActualPartNumbers (numbers engine) (map coordinates (symbols engine)))
|
||||||
35
day03/Part2.hs
Normal file
35
day03/Part2.hs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
module Part2 where
|
||||||
|
|
||||||
|
import Commons
|
||||||
|
|
||||||
|
|
||||||
|
getNumberNeighbors :: Coordinates -> [NumberPart] -> Int
|
||||||
|
getNumberNeighbors _ [] = 0
|
||||||
|
getNumberNeighbors symbolCoordinates (h: t)
|
||||||
|
| symbolCoordinates `elem` neighbors h = 1 + getNumberNeighbors symbolCoordinates t
|
||||||
|
| otherwise = getNumberNeighbors symbolCoordinates t
|
||||||
|
|
||||||
|
isGear :: SymbolPart -> [NumberPart] -> Bool
|
||||||
|
isGear symbolPart numberParts | symbol symbolPart == '*' = getNumberNeighbors (coordinates symbolPart) numberParts == 2
|
||||||
|
| otherwise = False
|
||||||
|
|
||||||
|
getRatioNeighbors :: Coordinates -> [NumberPart] -> Int
|
||||||
|
getRatioNeighbors _ [] = 1
|
||||||
|
getRatioNeighbors symbolCoordinates (h: t)
|
||||||
|
| symbolCoordinates `elem` neighbors h = value h * getRatioNeighbors symbolCoordinates t
|
||||||
|
| otherwise = getRatioNeighbors symbolCoordinates t
|
||||||
|
|
||||||
|
getGearRatio :: SymbolPart -> [NumberPart] -> Int
|
||||||
|
getGearRatio symbolPart numberParts
|
||||||
|
| isGear symbolPart numberParts = getRatioNeighbors (coordinates symbolPart) numberParts
|
||||||
|
| otherwise = 0
|
||||||
|
|
||||||
|
getGearRatios :: [SymbolPart] -> [NumberPart] -> [Int]
|
||||||
|
getGearRatios [] _ = []
|
||||||
|
getGearRatios (h: t) numberParts = let gearRatio = getGearRatio h numberParts
|
||||||
|
in if gearRatio > 0
|
||||||
|
then gearRatio: getGearRatios t numberParts
|
||||||
|
else getGearRatios t numberParts
|
||||||
|
|
||||||
|
getGearRatiosFromEngine :: Engine -> [Int]
|
||||||
|
getGearRatiosFromEngine engine = getGearRatios (symbols engine) (numbers engine)
|
||||||
Reference in New Issue
Block a user