Day 8
This commit is contained in:
parent
5fdb7df49f
commit
ce3144639c
4 changed files with 178 additions and 4 deletions
7
Main.hs
7
Main.hs
|
@ -9,6 +9,7 @@ import Day4
|
||||||
import Day5
|
import Day5
|
||||||
import Day6
|
import Day6
|
||||||
import Day7
|
import Day7
|
||||||
|
import Day8
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
|
@ -25,5 +26,7 @@ main = do
|
||||||
-- Day5.main
|
-- Day5.main
|
||||||
-- putStrLn "Day 6"
|
-- putStrLn "Day 6"
|
||||||
-- Day6.main
|
-- Day6.main
|
||||||
putStrLn "Day 7"
|
-- putStrLn "Day 7"
|
||||||
Day7.main
|
-- Day7.main
|
||||||
|
putStrLn "Day 8"
|
||||||
|
Day8.main
|
||||||
|
|
50
inputs/day8.input
Normal file
50
inputs/day8.input
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
..................................................
|
||||||
|
.................................C................
|
||||||
|
.e..........7O....................................
|
||||||
|
.....................................z............
|
||||||
|
......................t.........C.......k.........
|
||||||
|
............h................................9....
|
||||||
|
.............5.7....O.............9C..............
|
||||||
|
.......5.O................T.......................
|
||||||
|
.............................o...c....z...........
|
||||||
|
.hH...........e..7.............................w..
|
||||||
|
......H...................c....3.T..5.............
|
||||||
|
.....H........5..........B...........3..z..c......
|
||||||
|
....6........H.........t..........................
|
||||||
|
........O..................e........3.............
|
||||||
|
............e.........o..............9............
|
||||||
|
.........s.........o..............................
|
||||||
|
.......................k........4.....3..z.w......
|
||||||
|
......s.................t..T.k............8.......
|
||||||
|
.......s............................T.....w.......
|
||||||
|
..................................C.7.............
|
||||||
|
..................................................
|
||||||
|
.........................t......b.w...............
|
||||||
|
............................X...................8.
|
||||||
|
.............6..........k.........................
|
||||||
|
............................1................8....
|
||||||
|
...............................8..................
|
||||||
|
....h........................b....................
|
||||||
|
............................................c.....
|
||||||
|
..J...............................................
|
||||||
|
.....................................K............
|
||||||
|
..............................x...................
|
||||||
|
..................................................
|
||||||
|
....2......0...................x...........1......
|
||||||
|
...4.....0......................1b................
|
||||||
|
.............h......................K.jW..........
|
||||||
|
6...........0...............W.....................
|
||||||
|
.........6........B...............................
|
||||||
|
.......2................B..........x........K.....
|
||||||
|
..................................................
|
||||||
|
.................................G.......j........
|
||||||
|
....................E.............................
|
||||||
|
.......................................S...ZX.....
|
||||||
|
.....4.......2...B........Wj.....S................
|
||||||
|
..o...............2..................W....j.......
|
||||||
|
.....................E..........S..........J......
|
||||||
|
................E......................1..........
|
||||||
|
......................G........K.........g........
|
||||||
|
..............................G....J....S.........
|
||||||
|
...................G....................Z..Xg.....
|
||||||
|
4..................E..............J.g....X........
|
|
@ -13,16 +13,17 @@ dependencies:
|
||||||
- bytestring
|
- bytestring
|
||||||
- containers
|
- containers
|
||||||
- hashable
|
- hashable
|
||||||
|
- linear
|
||||||
- matrix
|
- matrix
|
||||||
- parallel
|
- parallel
|
||||||
- safe
|
- safe
|
||||||
- scientific
|
- scientific
|
||||||
|
- split
|
||||||
- text
|
- text
|
||||||
- unliftio
|
- unliftio
|
||||||
- unordered-containers
|
- unordered-containers
|
||||||
- utility-ht
|
- utility-ht
|
||||||
- vector
|
- vector
|
||||||
- split
|
|
||||||
|
|
||||||
executables:
|
executables:
|
||||||
aoc24:
|
aoc24:
|
||||||
|
@ -45,7 +46,7 @@ library:
|
||||||
- Day5
|
- Day5
|
||||||
- Day6
|
- Day6
|
||||||
- Day7
|
- Day7
|
||||||
# - Day8
|
- Day8
|
||||||
# - Day9
|
# - Day9
|
||||||
# - Day10
|
# - Day10
|
||||||
# - Day11
|
# - Day11
|
||||||
|
|
120
src/Day8.hs
Normal file
120
src/Day8.hs
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
module Day8 where
|
||||||
|
|
||||||
|
-- import Debug.Trace
|
||||||
|
import Data.Attoparsec.Text (
|
||||||
|
Parser,
|
||||||
|
endOfLine,
|
||||||
|
many1,
|
||||||
|
parseOnly,
|
||||||
|
satisfy,
|
||||||
|
sepBy,
|
||||||
|
)
|
||||||
|
import Data.Char (isAlphaNum, isAscii)
|
||||||
|
import qualified Data.HashMap.Strict as H
|
||||||
|
import qualified Data.HashSet as S
|
||||||
|
import Data.List (tails)
|
||||||
|
import Data.String (IsString)
|
||||||
|
import Data.Text (Text)
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import qualified Data.Text.IO as T
|
||||||
|
import GHC.Float (int2Float)
|
||||||
|
|
||||||
|
type Antennas = H.HashMap Char [Pos]
|
||||||
|
type Antinodes = S.HashSet Pos
|
||||||
|
type Pos = (Int, Int)
|
||||||
|
type Bounds2D = (Pos, Pos)
|
||||||
|
|
||||||
|
parseInput :: Parser (Antennas, Bounds2D)
|
||||||
|
parseInput = do
|
||||||
|
xs <- concat . flip (zipWith f) [0 ..] . reverse <$> parseLine `sepBy` endOfLine
|
||||||
|
pure (toAntennas xs, findBounds xs)
|
||||||
|
where
|
||||||
|
f :: [(Char, Int)] -> Int -> [(Char, [Pos])]
|
||||||
|
f xs i = map (\(a, b) -> (a, [(b, i)])) xs
|
||||||
|
toAntennas = H.fromListWith (++) . filter (('.' /=) . fst)
|
||||||
|
findBounds :: [(Char, [Pos])] -> Bounds2D
|
||||||
|
findBounds = (\xs -> (minimum xs, maximum xs)) . concat . H.fromListWith (++)
|
||||||
|
|
||||||
|
parseLine :: Parser [(Char, Int)]
|
||||||
|
parseLine =
|
||||||
|
(`zip` [0 ..])
|
||||||
|
<$> many1 (satisfy (\c -> (isAscii c && isAlphaNum c) || (c == '.')))
|
||||||
|
|
||||||
|
allPairs :: [a] -> [(a, a)]
|
||||||
|
allPairs l = [(x, y) | (x : ys) <- tails l, y <- ys]
|
||||||
|
|
||||||
|
findAntinodes :: [Pos] -> Antinodes
|
||||||
|
findAntinodes = foldMap findAntinode . allPairs
|
||||||
|
|
||||||
|
findAntinode :: (Pos, Pos) -> Antinodes
|
||||||
|
findAntinode ((x1, y1), (x2, y2)) =
|
||||||
|
S.fromList
|
||||||
|
[ (x2 + (x2 - x1), y2 + (y2 - y1))
|
||||||
|
, (x1 - (x2 - x1), y1 - (y2 - y1))
|
||||||
|
]
|
||||||
|
|
||||||
|
inBounds :: Pos -> Pos -> Pos -> Bool
|
||||||
|
inBounds (xmin, ymin) (xmax, ymax) (x, y) =
|
||||||
|
xmin <= x && x <= xmax && ymin <= y && y <= ymax
|
||||||
|
|
||||||
|
solveA :: Text -> Either String Int
|
||||||
|
solveA txt = do
|
||||||
|
(antennas, bounds) <- parseOnly parseInput txt
|
||||||
|
let allAN = foldMap findAntinodes antennas
|
||||||
|
pure $ S.size $ S.filter (uncurry inBounds bounds) allAN
|
||||||
|
|
||||||
|
findAntinodes' :: Bounds2D -> [Pos] -> Antinodes
|
||||||
|
findAntinodes' b = foldMap (findAntinode' b) . allPairs
|
||||||
|
|
||||||
|
max' :: Bounds2D -> Int
|
||||||
|
max' ((xmin, ymin), (xmax, ymax)) =
|
||||||
|
ceiling $
|
||||||
|
sqrt
|
||||||
|
( (int2Float xmax - int2Float xmin) ^ (2 :: Integer)
|
||||||
|
+ (int2Float ymax - int2Float ymin) ^ (2 :: Integer)
|
||||||
|
)
|
||||||
|
|
||||||
|
findAntinode' :: Bounds2D -> (Pos, Pos) -> Antinodes
|
||||||
|
findAntinode' b ((x1, y1), (x2, y2)) =
|
||||||
|
S.filter (uncurry inBounds b) $
|
||||||
|
S.fromList $
|
||||||
|
concatMap go [0 .. (max' b)]
|
||||||
|
where
|
||||||
|
go n =
|
||||||
|
[ (x2 + n * (x2 - x1), y2 + n * (y2 - y1))
|
||||||
|
, (x1 - n * (x2 - x1), y1 - n * (y2 - y1))
|
||||||
|
]
|
||||||
|
|
||||||
|
solveB :: Text -> Either String Int
|
||||||
|
solveB txt = do
|
||||||
|
(antennas, bounds) <- parseOnly parseInput txt
|
||||||
|
let allAN = foldMap (findAntinodes' bounds) antennas
|
||||||
|
pure $ S.size $ S.filter (uncurry inBounds bounds) allAN
|
||||||
|
|
||||||
|
inputEx :: (IsString s) => [s]
|
||||||
|
inputEx =
|
||||||
|
[ "............"
|
||||||
|
, "........0..."
|
||||||
|
, ".....0......"
|
||||||
|
, ".......0...."
|
||||||
|
, "....0......."
|
||||||
|
, "......A....."
|
||||||
|
, "............"
|
||||||
|
, "............"
|
||||||
|
, "........A..."
|
||||||
|
, ".........A.."
|
||||||
|
, "............"
|
||||||
|
, "............"
|
||||||
|
]
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
input <- T.readFile "inputs/day8.input"
|
||||||
|
putStrLn "Part 1"
|
||||||
|
print $ solveA $ T.unlines inputEx
|
||||||
|
print $ solveA input
|
||||||
|
putStrLn "Part 2"
|
||||||
|
print $ solveB $ T.unlines inputEx
|
||||||
|
print $ solveB input
|
Loading…
Reference in a new issue