7
									
								
								Lib.hs
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								Lib.hs
									
									
									
									
									
								
							@@ -1,6 +1,7 @@
 | 
			
		||||
module Lib (readFile', split, count, tRead) where
 | 
			
		||||
module Lib (readFile', tRead, buildGrid, split, count) where
 | 
			
		||||
 | 
			
		||||
import Data.ByteString qualified as B (readFile)
 | 
			
		||||
import Data.Map qualified as M
 | 
			
		||||
import Data.Text (Text)
 | 
			
		||||
import Data.Text.Encoding qualified as T (decodeUtf8)
 | 
			
		||||
import Data.Text.Read qualified as TR
 | 
			
		||||
@@ -13,6 +14,10 @@ readFile' f = T.decodeUtf8 <$> B.readFile f
 | 
			
		||||
tRead :: Text -> Int
 | 
			
		||||
tRead = (\(Right (n, _)) -> n) . TR.signed TR.decimal
 | 
			
		||||
 | 
			
		||||
-- Data.Map --
 | 
			
		||||
buildGrid :: [[a]] -> M.Map (Int, Int) a
 | 
			
		||||
buildGrid xs = M.fromList [((x, y), a) | (row, x) <- zip xs [0 ..], (a, y) <- zip row [0 ..]]
 | 
			
		||||
 | 
			
		||||
-- Utility --
 | 
			
		||||
split :: (Eq a) => a -> [a] -> [[a]]
 | 
			
		||||
split delimiter list =
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								day10.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								day10.hs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
import Data.List (find)
 | 
			
		||||
import Data.Map qualified as M
 | 
			
		||||
import Data.Maybe (catMaybes, isNothing, mapMaybe)
 | 
			
		||||
import Data.Set qualified as S
 | 
			
		||||
import Lib (buildGrid, readFile')
 | 
			
		||||
 | 
			
		||||
data Direction = East | West | North | South deriving (Show, Eq)
 | 
			
		||||
 | 
			
		||||
type Coord = (Int, Int)
 | 
			
		||||
 | 
			
		||||
main :: IO ()
 | 
			
		||||
main = do
 | 
			
		||||
  grid <- buildGrid . lines <$> readFile "day10.in"
 | 
			
		||||
  let [((sx, sy), _)] = M.toList $ M.filter (== 'S') grid
 | 
			
		||||
  let path =
 | 
			
		||||
        head $
 | 
			
		||||
          mapMaybe
 | 
			
		||||
            (uncurry $ travel grid [])
 | 
			
		||||
            [ ((sx - 1, sy), North),
 | 
			
		||||
              ((sx, sy + 1), East)
 | 
			
		||||
            ]
 | 
			
		||||
 | 
			
		||||
  putStr "Q1: "
 | 
			
		||||
  print $ div (length path) 2
 | 
			
		||||
 | 
			
		||||
  putStr "Q2: "
 | 
			
		||||
  print $ pick (shoelace path) (length path)
 | 
			
		||||
 | 
			
		||||
travel :: M.Map Coord Char -> [Coord] -> Coord -> Direction -> Maybe [Coord]
 | 
			
		||||
travel grid a c@(x, y) d
 | 
			
		||||
  | isNothing (M.lookup c grid) || cur == '.' = Nothing
 | 
			
		||||
  | cur == 'S' = Just $ c : a
 | 
			
		||||
  | (cur, d) `elem` [('L', West), ('|', North), ('J', East)] = travel grid (c : a) (x - 1, y) North
 | 
			
		||||
  | (cur, d) `elem` [('F', West), ('|', South), ('7', East)] = travel grid (c : a) (x + 1, y) South
 | 
			
		||||
  | (cur, d) `elem` [('L', South), ('-', East), ('F', North)] = travel grid (c : a) (x, y + 1) East
 | 
			
		||||
  | (cur, d) `elem` [('J', South), ('-', West), ('7', North)] = travel grid (c : a) (x, y - 1) West
 | 
			
		||||
  where
 | 
			
		||||
    cur = grid M.! c
 | 
			
		||||
 | 
			
		||||
-- https://en.wikipedia.org/wiki/Shoelace_formula
 | 
			
		||||
-- this just uses trapezoids/triangles from consecutive points
 | 
			
		||||
shoelace :: [Coord] -> Int
 | 
			
		||||
shoelace xs = flip div 2 . abs . sum $ zipWith (\(x1, y1) (x2, y2) -> (x1 * y2) - (x2 * y1)) xs (tail $ cycle xs)
 | 
			
		||||
 | 
			
		||||
-- https://en.wikipedia.org/wiki/Pick%27s_theorem
 | 
			
		||||
-- area -> path length -> integers inside
 | 
			
		||||
pick :: Int -> Int -> Int
 | 
			
		||||
pick a b = (a + 1) - div b 2
 | 
			
		||||
		Reference in New Issue
	
	Block a user