{-# Language QuasiQuotes, DataKinds, NumDecimals, LambdaCase, BlockArguments #-}
module Main (main) where
import Advent.Format (format)
import Advent.Permutation (Permutation, rotateRight, runPermutation, swap)
import Data.Semigroup (Dual(..), stimes)
import Data.Char (chr, ord)
import GHC.TypeLits (KnownNat)
[format|(s%d|x%d/%d|p%c/%c)&,%n|]
main :: IO ()
IO ()
main =
do dance <- (Either (Either Int (Int, Int)) (Char, Char) -> Dance 16)
-> Input -> Dance 16
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Either (Either Int (Int, Int)) (Char, Char) -> Dance 16
forall (n :: Nat).
KnownNat n =>
Either (Either Int (Int, Int)) (Char, Char) -> Dance n
danceStep (Input -> Dance 16) -> IO Input -> IO (Dance 16)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Int -> IO Input
getInput Int
2017 Int
16
putStrLn (runDance (dance :: Dance 16))
putStrLn (runDance (stimes (1e9 :: Int) dance))
danceStep :: KnownNat n => Either (Either Int (Int, Int)) (Char, Char) -> Dance n
danceStep :: forall (n :: Nat).
KnownNat n =>
Either (Either Int (Int, Int)) (Char, Char) -> Dance n
danceStep = \case
Left (Left Int
n) -> Int -> Dance n
forall (n :: Nat). KnownNat n => Int -> Dance n
spinDance Int
n
Left (Right (Int
x,Int
y)) -> Int -> Int -> Dance n
forall (n :: Nat). KnownNat n => Int -> Int -> Dance n
swapDance Int
x Int
y
Right (Char
x,Char
y) -> Char -> Char -> Dance n
forall (n :: Nat). KnownNat n => Char -> Char -> Dance n
partDance Char
x Char
y
intToLetter :: Int -> Char
intToLetter :: Int -> Char
intToLetter Int
i = Int -> Char
chr (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Char -> Int
ord Char
'a')
letterToInt :: Char -> Int
letterToInt :: Char -> Int
letterToInt Char
c = Char -> Int
ord Char
c Int -> Int -> Int
forall a. Num a => a -> a -> a
- Char -> Int
ord Char
'a'
type Dance n = (Dual (Permutation n), Permutation n)
runDance :: KnownNat n => Dance n -> String
runDance :: forall (n :: Nat). KnownNat n => Dance n -> String
runDance (Dual Permutation n
r, Permutation n
p) = (Int -> Char) -> Permutation n -> String
forall a (n :: Nat). (Int -> a) -> Permutation n -> [a]
runPermutation Int -> Char
intToLetter (Permutation n
r Permutation n -> Permutation n -> Permutation n
forall a. Semigroup a => a -> a -> a
<> Permutation n
p)
spinDance :: KnownNat n => Int -> Dance n
spinDance :: forall (n :: Nat). KnownNat n => Int -> Dance n
spinDance Int
n = (Dual (Permutation n)
forall a. Monoid a => a
mempty, Int -> Permutation n
forall (n :: Nat). KnownNat n => Int -> Permutation n
rotateRight Int
n)
swapDance :: KnownNat n => Int -> Int -> Dance n
swapDance :: forall (n :: Nat). KnownNat n => Int -> Int -> Dance n
swapDance Int
x Int
y = (Dual (Permutation n)
forall a. Monoid a => a
mempty, Int -> Int -> Permutation n
forall (n :: Nat). KnownNat n => Int -> Int -> Permutation n
swap Int
x Int
y)
partDance :: KnownNat n => Char -> Char -> Dance n
partDance :: forall (n :: Nat). KnownNat n => Char -> Char -> Dance n
partDance Char
x Char
y = (Permutation n -> Dual (Permutation n)
forall a. a -> Dual a
Dual (Int -> Int -> Permutation n
forall (n :: Nat). KnownNat n => Int -> Int -> Permutation n
swap (Char -> Int
letterToInt Char
x) (Char -> Int
letterToInt Char
y)), Permutation n
forall a. Monoid a => a
mempty)