{-# Language ImportQualifiedPost #-}
module Main (main) where
import Advent (getInputLines, countBy)
import Advent.Coord (coordLines, Coord(..), manhattan, scaleCoord)
import Data.Foldable (Foldable(toList))
import Data.List (sortOn, transpose)
import Data.Map qualified as Map
import Data.Ratio ((%))
import Data.Set (Set)
import Data.Set qualified as Set
main :: IO ()
IO ()
main =
do [String]
inp <- Int -> Int -> IO [String]
getInputLines Int
2019 Int
10
let locs :: Set Coord
locs = [Coord] -> Set Coord
forall a. Ord a => [a] -> Set a
Set.fromList [Coord
c | (Coord
c,Char
'#') <- [String] -> [(Coord, Char)]
coordLines [String]
inp]
let (Int
vis, Coord
base) = Set Coord -> (Int, Coord)
findBase Set Coord
locs
Int -> IO ()
forall a. Show a => a -> IO ()
print Int
vis
let C Int
y Int
x = Coord -> Set Coord -> [Coord]
spiral Coord
base (Coord -> Set Coord -> Set Coord
forall a. Ord a => a -> Set a -> Set a
Set.delete Coord
base Set Coord
locs) [Coord] -> Int -> Coord
forall a. HasCallStack => [a] -> Int -> a
!! Int
199
Int -> IO ()
forall a. Show a => a -> IO ()
print (Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
100 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
y)
findBase :: Set Coord -> (Int, Coord)
findBase :: Set Coord -> (Int, Coord)
findBase Set Coord
m = [(Int, Coord)] -> (Int, Coord)
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [((Coord -> Bool) -> Set Coord -> Int
forall (f :: * -> *) a. Foldable f => (a -> Bool) -> f a -> Int
countBy (Set Coord -> Coord -> Coord -> Bool
lineOfSight Set Coord
m Coord
i) Set Coord
m, Coord
i) | Coord
i <- Set Coord -> [Coord]
forall a. Set a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Set Coord
m]
spiral ::
Coord ->
Set Coord ->
[Coord]
spiral :: Coord -> Set Coord -> [Coord]
spiral Coord
base
= [[Coord]] -> [Coord]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
([[Coord]] -> [Coord])
-> (Set Coord -> [[Coord]]) -> Set Coord -> [Coord]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Coord]] -> [[Coord]]
forall a. [[a]] -> [[a]]
transpose
([[Coord]] -> [[Coord]])
-> (Set Coord -> [[Coord]]) -> Set Coord -> [[Coord]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Coord] -> [Coord]) -> [[Coord]] -> [[Coord]]
forall a b. (a -> b) -> [a] -> [b]
map ((Coord -> Int) -> [Coord] -> [Coord]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn (Coord -> Coord -> Int
manhattan Coord
base))
([[Coord]] -> [[Coord]])
-> (Set Coord -> [[Coord]]) -> Set Coord -> [[Coord]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Coord -> Rational) -> [Coord] -> [[Coord]]
forall b a. Ord b => (a -> b) -> [a] -> [[a]]
groupOn (Coord -> Rational
toAngle (Coord -> Rational) -> (Coord -> Coord) -> Coord -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Coord -> Coord -> Coord
forall a. Num a => a -> a -> a
subtract Coord
base)
([Coord] -> [[Coord]])
-> (Set Coord -> [Coord]) -> Set Coord -> [[Coord]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set Coord -> [Coord]
forall a. Set a -> [a]
Set.toList
lineOfSight ::
Set Coord ->
Coord -> Coord -> Bool
lineOfSight :: Set Coord -> Coord -> Coord -> Bool
lineOfSight Set Coord
ast Coord
a Coord
b = Coord
a Coord -> Coord -> Bool
forall a. Eq a => a -> a -> Bool
/= Coord
b Bool -> Bool -> Bool
&& [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and [Coord -> Set Coord -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.notMember Coord
c Set Coord
ast | Coord
c <- Coord -> Coord -> [Coord]
between Coord
a Coord
b]
between :: Coord -> Coord -> [Coord]
between :: Coord -> Coord -> [Coord]
between Coord
a Coord
b = [Coord
a Coord -> Coord -> Coord
forall a. Num a => a -> a -> a
+ Int -> Coord -> Coord
scaleCoord Int
i Coord
unit | Int
i <- [Int
1 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]]
where
C Int
dy Int
dx = Coord
b Coord -> Coord -> Coord
forall a. Num a => a -> a -> a
- Coord
a
n :: Int
n = Int -> Int -> Int
forall a. Integral a => a -> a -> a
gcd Int
dx Int
dy
unit :: Coord
unit = Int -> Int -> Coord
C (Int
dy Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
n) (Int
dx Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
n)
toAngle :: Coord -> Rational
toAngle :: Coord -> Rational
toAngle (C Int
y Int
x)
| Int
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0, Int
y Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = -Rational
1
| Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0, Int
y Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Int -> Int -> Int -> Rational
forall {a} {a}. (Integral a, Integral a) => a -> a -> a -> Ratio a
mk Int
1 Int
x (-Int
y)
| Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0, Int
y Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 = Int -> Int -> Int -> Rational
forall {a} {a}. (Integral a, Integral a) => a -> a -> a -> Ratio a
mk Int
2 Int
y Int
x
| Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0, Int
y Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 = Int -> Int -> Int -> Rational
forall {a} {a}. (Integral a, Integral a) => a -> a -> a -> Ratio a
mk Int
3 (-Int
x) Int
y
| Bool
otherwise = Int -> Int -> Int -> Rational
forall {a} {a}. (Integral a, Integral a) => a -> a -> a -> Ratio a
mk Int
4 Int
y Int
x
where
mk :: a -> a -> a -> Ratio a
mk a
q a
a a
b = a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
qa -> a -> a
forall a. Num a => a -> a -> a
*(a
aa -> a -> a
forall a. Num a => a -> a -> a
+a
b)a -> a -> a
forall a. Num a => a -> a -> a
-a
b) a -> a -> Ratio a
forall a. Integral a => a -> a -> Ratio a
% a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
aa -> a -> a
forall a. Num a => a -> a -> a
+a
b)
groupOn :: Ord b => (a -> b) -> [a] -> [[a]]
groupOn :: forall b a. Ord b => (a -> b) -> [a] -> [[a]]
groupOn a -> b
f [a]
xs = Map b [a] -> [[a]]
forall k a. Map k a -> [a]
Map.elems (([a] -> [a] -> [a]) -> [(b, [a])] -> Map b [a]
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
(++) [(a -> b
f a
x, [a
x]) | a
x <- [a]
xs])