{-# Language QuasiQuotes, DataKinds, NumDecimals, ScopedTypeVariables, OverloadedStrings #-}
module Main where
import Advent.Format ( format )
import Advent.Permutation (Permutation, rotateRight, runPermutation, swap)
import Data.Semigroup (Semigroup, (<>), Dual(..), sconcat, stimes)
import Data.Char (chr, ord)
import GHC.TypeLits (KnownNat)
main :: IO ()
IO ()
main =
do [Either (Either Int (Int, Int)) (Char, Char)]
input <- [format|2017 16 (s%d|x%d/%d|p%c/%c)&,%n|]
let toDance :: Either (Either Int (Int, Int)) (Char, Char) -> Dance n
toDance (Left (Left Int
n)) = Int -> Dance n
forall (n :: Nat). KnownNat n => Int -> Dance n
spinDance Int
n
toDance (Left (Right (Int
x,Int
y))) = Int -> Int -> Dance n
forall (n :: Nat). KnownNat n => Int -> Int -> Dance n
swapDance Int
x Int
y
toDance (Right (Char
x,Char
y)) = Char -> Char -> Dance n
forall (n :: Nat). KnownNat n => Char -> Char -> Dance n
partDance Char
x Char
y
let dance :: Dance 16
dance = (Either (Either Int (Int, Int)) (Char, Char) -> Dance 16)
-> [Either (Either Int (Int, Int)) (Char, Char)] -> 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
toDance [Either (Either Int (Int, Int)) (Char, Char)]
input :: Dance 16
[Char] -> IO ()
putStrLn (Dance 16 -> [Char]
forall (n :: Nat). KnownNat n => Dance n -> [Char]
runDance Dance 16
dance)
[Char] -> IO ()
putStrLn (Dance 16 -> [Char]
forall (n :: Nat). KnownNat n => Dance n -> [Char]
runDance (Integer -> Dance 16 -> Dance 16
forall b. Integral b => b -> Dance 16 -> Dance 16
forall a b. (Semigroup a, Integral b) => b -> a -> a
stimes Integer
1e9 Dance 16
dance))
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 -> [Char]
runDance (Dual Permutation n
r, Permutation n
p) = (Int -> Char) -> Permutation n -> [Char]
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)