{-# Language QuasiQuotes, ImportQualifiedPost #-}
module Main (main) where
import Advent.Format (format)
import Data.Char (digitToInt)
import Data.List (findIndex, isPrefixOf, tails, foldl')
import Data.Maybe (fromJust)
import Data.Sequence (Seq)
import Data.Sequence qualified as Seq
main :: IO ()
IO ()
main =
do Int
input <- [format|2018 14 %u%n|]
String -> IO ()
putStrLn (Int -> String
part1 Int
input)
Int -> IO ()
forall a. Show a => a -> IO ()
print (Int -> Int
part2 Int
input)
part1 :: Int -> String
part1 :: Int -> String
part1 Int
input = (Int -> String) -> [Int] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Int -> String
forall a. Show a => a -> String
show (Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
take Int
10 (Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
drop Int
input [Int]
entries))
part2 :: Int -> Int
part2 :: Int -> Int
part2 Int
input = Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (([Int] -> Bool) -> [[Int]] -> Maybe Int
forall a. (a -> Bool) -> [a] -> Maybe Int
findIndex (Int -> [Int]
toDigits Int
input [Int] -> [Int] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) ([Int] -> [[Int]]
forall a. [a] -> [[a]]
tails [Int]
entries))
data Cooks = Cooks !Int !Int !(Seq Int)
deriving Int -> Cooks -> ShowS
[Cooks] -> ShowS
Cooks -> String
(Int -> Cooks -> ShowS)
-> (Cooks -> String) -> ([Cooks] -> ShowS) -> Show Cooks
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Cooks -> ShowS
showsPrec :: Int -> Cooks -> ShowS
$cshow :: Cooks -> String
show :: Cooks -> String
$cshowList :: [Cooks] -> ShowS
showList :: [Cooks] -> ShowS
Show
entries :: [Int]
entries :: [Int]
entries = Int
3 Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: Int
7 Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: Cooks -> [Int]
generate (Int -> Int -> Seq Int -> Cooks
Cooks Int
0 Int
1 ([Int] -> Seq Int
forall a. [a] -> Seq a
Seq.fromList [Int
3,Int
7]))
toDigits :: Int -> [Int]
toDigits :: Int -> [Int]
toDigits = (Char -> Int) -> String -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Int
digitToInt (String -> [Int]) -> (Int -> String) -> Int -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show
generate :: Cooks -> [Int]
generate :: Cooks -> [Int]
generate (Cooks Int
elf1 Int
elf2 Seq Int
recipies) =
[Int]
news [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ Cooks -> [Int]
generate (Int -> Int -> Seq Int -> Cooks
Cooks Int
elf1' Int
elf2' Seq Int
recipies')
where
elf1r :: Int
elf1r = Seq Int -> Int -> Int
forall a. Seq a -> Int -> a
Seq.index Seq Int
recipies Int
elf1
elf2r :: Int
elf2r = Seq Int -> Int -> Int
forall a. Seq a -> Int -> a
Seq.index Seq Int
recipies Int
elf2
news :: [Int]
news = Int -> [Int]
toDigits (Int
elf1r Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
elf2r)
recipies' :: Seq Int
recipies' = (Seq Int -> Int -> Seq Int) -> Seq Int -> [Int] -> Seq Int
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Seq Int -> Int -> Seq Int
forall a. Seq a -> a -> Seq a
(Seq.|>) Seq Int
recipies [Int]
news
elf1' :: Int
elf1' = Int -> Int -> Int
nextPos Int
elf1 Int
elf1r
elf2' :: Int
elf2' = Int -> Int -> Int
nextPos Int
elf2 Int
elf2r
nextPos :: Int -> Int -> Int
nextPos Int
i Int
r = (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Seq Int -> Int
forall a. Seq a -> Int
Seq.length Seq Int
recipies'