Refactor code
This commit is contained in:
80
src/Day08.hs
Normal file
80
src/Day08.hs
Normal file
@@ -0,0 +1,80 @@
|
||||
module Day08
|
||||
( day08_1,
|
||||
day08_2,
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Applicative
|
||||
import Data.Bifunctor (bimap)
|
||||
import Data.List (uncons)
|
||||
import Data.Maybe (fromJust)
|
||||
import Data.Set (fromList)
|
||||
|
||||
type Freq = Char
|
||||
|
||||
type Coords = (Int, Int)
|
||||
|
||||
data Antenna = Antenna
|
||||
{ frequency :: Freq,
|
||||
coordinates :: Coords
|
||||
}
|
||||
deriving (Show, Eq)
|
||||
|
||||
readAntenna :: Freq -> Coords -> Antenna
|
||||
readAntenna freq coords = Antenna {frequency = freq, coordinates = coords}
|
||||
|
||||
getAntennas :: [String] -> [Antenna]
|
||||
getAntennas grid = concat . getZipList $ getAntennasRow <$> ZipList [0 ..] <*> ZipList grid
|
||||
where
|
||||
getAntennasRow n row = [readAntenna x (n, y) | (x, y) <- zip row [0 ..], x /= '.']
|
||||
|
||||
isInside :: Coords -> Int -> Int -> Bool
|
||||
isInside c x y = fst c >= 0 && fst c < x && snd c >= 0 && snd c < y
|
||||
|
||||
generateCoords :: Coords -> Coords -> [Coords]
|
||||
generateCoords c offset = scanl shiftCoords c (repeat offset)
|
||||
where
|
||||
shiftCoords x = bimap (fst x +) (snd x +)
|
||||
|
||||
getAntinodes :: Antenna -> Antenna -> Int -> Int -> [Coords]
|
||||
getAntinodes a b maxX maxY =
|
||||
let xa = fst $ coordinates a
|
||||
ya = snd $ coordinates a
|
||||
xb = fst $ coordinates b
|
||||
yb = snd $ coordinates b
|
||||
in if frequency a /= frequency b || coordinates a == coordinates b
|
||||
then []
|
||||
else filter (\c -> isInside c maxX maxY) [(2 * xa - xb, 2 * ya - yb), (2 * xb - xa, 2 * yb - ya)]
|
||||
|
||||
getAntinodes' :: Antenna -> Antenna -> Int -> Int -> [Coords]
|
||||
getAntinodes' a b maxX maxY =
|
||||
let xa = fst $ coordinates a
|
||||
ya = snd $ coordinates a
|
||||
xb = fst $ coordinates b
|
||||
yb = snd $ coordinates b
|
||||
distX = xa - xb
|
||||
distY = ya - yb
|
||||
in if frequency a /= frequency b || coordinates a == coordinates b
|
||||
then []
|
||||
else
|
||||
filter (\c -> isInside c maxX maxY) [(2 * xa - xb, 2 * ya - yb), (2 * xb - xa, 2 * yb - ya)]
|
||||
++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (distX, distY))
|
||||
++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (-distX, -distY))
|
||||
|
||||
day08_1 :: IO ()
|
||||
day08_1 = do
|
||||
contents <- lines <$> readFile "input/day8.txt"
|
||||
let antennas = getAntennas contents
|
||||
x = length contents
|
||||
y = length $ fst . fromJust $ uncons contents
|
||||
antinodes = fromList $ concat [getAntinodes a b x y | a <- antennas, b <- antennas, a /= b, frequency a == frequency b]
|
||||
putStrLn $ "Day 8, Puzzle 1 solution: " ++ show (length antinodes)
|
||||
|
||||
day08_2 :: IO ()
|
||||
day08_2 = do
|
||||
contents <- lines <$> readFile "input/day8.txt"
|
||||
let antennas = getAntennas contents
|
||||
x = length contents
|
||||
y = length $ fst . fromJust $ uncons contents
|
||||
antinodes = fromList $ concat [getAntinodes' a b x y | a <- antennas, b <- antennas, a /= b, frequency a == frequency b]
|
||||
putStrLn $ "Day 8, Puzzle 2 solution: " ++ show (length antinodes)
|
||||
Reference in New Issue
Block a user