{-# Language QuasiQuotes, ImportQualifiedPost #-}
module Main where
import Data.Char (isLower, ord)
import Data.List (foldl1')
import Data.Set qualified as Set
import Advent (format, chunks)
main :: IO ()
IO ()
main =
do [[Char]]
input <- [format|2022 3 (%s%n)*|]
Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (([Char] -> Int) -> [[Char]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ([[Char]] -> Int
score ([[Char]] -> Int) -> ([Char] -> [[Char]]) -> [Char] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [[Char]]
halves) [[Char]]
input))
Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (([[Char]] -> Int) -> [[[Char]]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map [[Char]] -> Int
score (Int -> [[Char]] -> [[[Char]]]
forall a. Int -> [a] -> [[a]]
chunks Int
3 [[Char]]
input)))
halves :: String -> [String]
halves :: [Char] -> [[Char]]
halves [Char]
xs = Int -> [Char] -> [[Char]]
forall a. Int -> [a] -> [[a]]
chunks ([Char] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Char]
xs Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2) [Char]
xs
score :: [String] -> Int
score :: [[Char]] -> Int
score = Char -> Int
priority (Char -> Int) -> ([[Char]] -> Char) -> [[Char]] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set Char -> Char
forall a. Ord a => Set a -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum (Set Char -> Char) -> ([[Char]] -> Set Char) -> [[Char]] -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Set Char -> Set Char -> Set Char) -> [Set Char] -> Set Char
forall a. HasCallStack => (a -> a -> a) -> [a] -> a
foldl1' Set Char -> Set Char -> Set Char
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection ([Set Char] -> Set Char)
-> ([[Char]] -> [Set Char]) -> [[Char]] -> Set Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char] -> Set Char) -> [[Char]] -> [Set Char]
forall a b. (a -> b) -> [a] -> [b]
map [Char] -> Set Char
forall a. Ord a => [a] -> Set a
Set.fromList
priority :: Char -> Int
priority :: Char -> Int
priority Char
x
| Char -> Bool
isLower Char
x = Char -> Int
ord Char
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- Char -> Int
ord Char
'a' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
| Bool
otherwise = Char -> Int
ord Char
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- Char -> Int
ord Char
'A' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
27