diff --git a/Day8/puzzle1.hs b/Day8/puzzle1.hs new file mode 100644 index 0000000..d39bf4f --- /dev/null +++ b/Day8/puzzle1.hs @@ -0,0 +1,45 @@ +import Control.Applicative +import qualified Data.Set as Set + +type Freq = Char +type Coords = (Int, Int) +data Antenna = Antenna { frequency :: Freq + , coordinates :: Coords + } deriving (Show, Eq) + +readAntenna :: Freq -> Coords -> Antenna +readAntenna frequency coordinates = Antenna {frequency=frequency, coordinates=coordinates} + +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 + +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 = abs $ xa - xb + distY = abs $ ya - yb + in if frequency a /= frequency b || coordinates a == coordinates b + then [] + else if xa > xb && ya > yb + then filter (\c -> isInside c maxX maxY) [(xb - distX, yb - distY), (xa + distX, ya + distY)] + else if xa > xb && ya < yb + then filter (\c -> isInside c maxX maxY) [(xa + distX, ya - distY), (xb - distX, yb + distY)] + else if xa == xb && ya > yb + then filter (\c -> isInside c maxX maxY) [(xa, ya + distY), (xb, yb - distY)] + else if ya == yb && xa > xb + then filter (\c -> isInside c maxX maxY) [(xa + distX, ya), (xb - distX, yb)] + else getAntinodes b a maxX maxY + +main = do + contents <- lines <$> readFile "day8.txt" + let antennas = getAntennas contents + x = length contents + y = length $ head contents + antinodes = Set.fromList $ concat [ getAntinodes a b x y | a <- antennas, b <- antennas, a /= b, frequency a == frequency b ] + print $ length antinodes diff --git a/Day8/puzzle2.hs b/Day8/puzzle2.hs new file mode 100644 index 0000000..af68975 --- /dev/null +++ b/Day8/puzzle2.hs @@ -0,0 +1,81 @@ +import Control.Applicative +import Data.Set (fromList) +import Data.Bifunctor (bimap) + +type Freq = Char +type Coords = (Int, Int) +data Antenna = Antenna { frequency :: Freq + , coordinates :: Coords + } deriving (Show, Eq) + +readAntenna :: Freq -> Coords -> Antenna +readAntenna frequency coordinates = Antenna {frequency=frequency, coordinates=coordinates} + +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 c = bimap (fst c +) (snd c +) + +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 = abs $ xa - xb + distY = abs $ ya - yb + in if frequency a /= frequency b || coordinates a == coordinates b + then [] + else if xa > xb && ya > yb + then filter (\c -> isInside c maxX maxY) [(xa + distX, ya + distY), (xb - distX, yb - distY)] + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (distX, distY)) + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (-distX, -distY)) + ++ [coordinates a, coordinates b] + else if xa > xb && ya < yb + then filter (\c -> isInside c maxX maxY) [(xa + distX, ya - distY), (xb - distX, yb + distY)] + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (distX, -distY)) + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (-distX, distY)) + ++ [coordinates a, coordinates b] + else if xa == xb && ya > yb + then filter (\c -> isInside c maxX maxY) [(xa, ya + distY), (xb, yb - distY)] + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (0, distY)) + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (0, -distY)) + ++ [coordinates a, coordinates b] + else if xa == xb && ya < yb + then filter (\c -> isInside c maxX maxY) [(xa, ya - distY), (xb, yb + distY)] + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (0, -distY)) + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (0, distY)) + ++ [coordinates a, coordinates b] + else if ya == yb && xa > xb + then filter (\c -> isInside c maxX maxY) [(xa + distX, ya), (xb - distX, yb)] + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (distX, 0)) + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (-distX, 0)) + ++ [coordinates a, coordinates b] + else if ya == yb && xa < xb + then filter (\c -> isInside c maxX maxY) [(xa - distX, ya), (xb + distX, yb)] + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (-distX, 0)) + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (distX, 0)) + ++ [coordinates a, coordinates b] + else if xa < xb && ya > yb + then filter (\c -> isInside c maxX maxY) [(xa - distX, ya + distY), (xb + distX, yb - distY)] + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (-distX, distY)) + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (distX, -distY)) + ++ [coordinates a, coordinates b] + else filter (\c -> isInside c maxX maxY) [(xa - distX, ya - distY), (xb + distX, yb + distY)] + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates a) (-distX, -distY)) + ++ takeWhile (\c -> isInside c maxX maxY) (generateCoords (coordinates b) (distX, distY)) + ++ [coordinates a, coordinates b] + + +main = do + contents <- lines <$> readFile "day8.txt" + let antennas = getAntennas contents + x = length contents + y = length $ head contents + antinodes = fromList $ concat [ getAntinodes a b x y | a <- antennas, b <- antennas, a /= b, frequency a == frequency b ] + print $ length antinodes