# [Year 2015 Day 10](https://adventofcode.com/2015/day/10) This day doesn't really add anything new, but we will show off our new views for viewing integers as lists of digits. ```idris hide module Years.Y2015.Day10 import Control.Eff import Runner ``` ```idris import Data.String import Data.List1 import Data.List.Lazy import Data.Monoid.Exponentiation import Data.Nat.Views import Util import Util.Digits ``` ```idris hide %default total ``` # Solver Functions Produce a lazy lists of the digits of a number, in descending order of significance. This effectively translates our new [`Descending`](../../Util/Digits.md#descending-order) view to a `LazyList`. ```idris lazyDigits : Integer -> LazyList Integer lazyDigits i with (descending i) lazyDigits i | (NegDec rec) = lazyDigits _ | rec lazyDigits 0 | Start = [] lazyDigits ((digit * (10 ^ magnitude)) + rest) | (Prev _ digit rest rec) = digit :: lazyDigits _ | rec ``` Apply the look-and-say rule to list of digits. We operate in the list-of-digits space for efficiency, this number will grow into the millions of digits, and Idris is currently lacking some needed primitive operations to perform this operation in `Integer` space reasonably efficiently. A `LazyList` is used here to avoid having to actually instantiate the entirety of these reasonably large lists. ```idris lookAndSay : LazyList Integer -> LazyList Integer lookAndSay digits = -- Flatten the list once more lazyConcat -- Convert the produced numbers into lists of their digits . map lazyDigits -- re-flatten our list . lazyConcat -- Count the number of occurrences of each digit and emit [occurances, digit] . map (\xs@(head ::: tail) => (the (LazyList _) [natToInteger $ length xs, head])) -- Group identical digits . lazyGroup $ digits ``` Apply the look-and-say rule to an integer, for repl testing ```idris lookAndSay' : Integer -> Integer lookAndSay' i = let digits = lazyDigits i res = lookAndSay digits in unDigits res 0 where unDigits : LazyList Integer -> (acc : Integer) -> Integer unDigits [] acc = acc unDigits (x :: xs) acc = unDigits xs (acc * 10 + x) ``` Repeatedly apply `lookAndSay` to a seed value, with logging ```idris repeatLogged : Has Logger fs => (count : Nat) -> (seed : LazyList Integer) -> Eff fs $ LazyList Integer repeatLogged 0 seed = pure seed repeatLogged (S k) seed = do trace "Remaining iterations: \{show (S k)} digits: \{show . count (const True) $ seed}" repeatLogged k (lookAndSay seed) ``` # Part Functions ## Part 1 Parse our input, convert it into a list of digits, then run our `lookAndSay` function on it 40 times, and count the output digits. ```idris part1 : Eff (PartEff String) (Nat, LazyList Integer) part1 = do input <- askAt "input" >>= (note "Invalid input" . parsePositive) let input = lazyDigits input info "Input: \{show input}" output <- repeatLogged 40 input pure (count (const True) output, output) ``` ## Part 2 Same thing, but 10 more times ```idris part2 : (digits : LazyList Integer) -> Eff (PartEff String) Nat part2 digits = do output <- repeatLogged 10 digits pure $ count (const True) output ``` ```idris hide public export day10 : Day day10 = Both 10 part1 part2 ```