Last active
November 28, 2020 14:57
-
-
Save pete-murphy/51c2d975a51ca280b3c6043be0662c20 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import qualified Control.Monad as Monad | |
import Control.Monad.Trans.State (State) | |
import qualified Control.Monad.Trans.State as State | |
import Data.Function ((&)) | |
import Control.Arrow ((&&&)) | |
data Node = Node {children :: [Node], metadata :: [Int]} | |
allMetadata :: Node -> [Int] | |
allMetadata node = metadata node ++ concatMap allMetadata (children node) | |
getInt :: State [Int] Int | |
getInt = do | |
-- first : rest <- State.get | |
-- ^^ The above is valid if using GHC < 8.8.1, but recent versions will | |
-- complain about missing 'MonadFail' instance for 'Identity' ('State' is | |
-- defined as 'StateT Identity', and the pattern match might fail. If you want | |
-- to dig further into the weeds, see: | |
-- https://hackage.haskell.org/package/base-4.14.0.0/docs/Control-Monad-Fail.html#t:MonadFail) | |
(first, rest) <- State.gets (head &&& tail) | |
State.put rest | |
pure first | |
getNode :: State [Int] Node | |
getNode = do | |
n <- getInt | |
m <- getInt | |
Node <$> Monad.replicateM n getNode <*> Monad.replicateM m getInt | |
main :: IO () | |
main = do | |
input <- readFile "input" | |
input | |
& words | |
& map read | |
& State.evalState getNode | |
& allMetadata | |
& sum | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import fs from "fs" | |
import * as St from "fp-ts/lib/State" | |
import State = St.State | |
import * as A from "fp-ts/lib/Array" | |
import { pipe } from "fp-ts/lib/pipeable" | |
import { sequenceS, sequenceT } from "fp-ts/lib/Apply" | |
import { fold, monoidSum } from "fp-ts/lib/Monoid" | |
interface Node { | |
children: readonly Node[] | |
metadata: readonly number[] | |
} | |
const allMetadata: (node: Node) => number[] = node => [ | |
...node.metadata, | |
...node.children.flatMap(allMetadata), | |
] | |
const getInt: State<number[], number> = pipe( | |
St.get<number[]>(), | |
St.chain(([first, ...rest]) => | |
pipe( | |
St.of<number[], number>(first), | |
St.chainFirst(() => St.put(rest)) | |
) | |
) | |
) | |
const getNode: State<number[], Node> = pipe( | |
sequenceT(St.state)(getInt, getInt), | |
St.chain( | |
([n, m]): State<number[], Node> => | |
sequenceS(St.state)({ | |
children: St.sequenceArray(A.replicate(n, getNode)), | |
metadata: St.sequenceArray(A.replicate(m, getInt)), | |
}) | |
) | |
) | |
const words = (str: string) => str.split(/\s/) | |
const main = () => | |
pipe( | |
fs.readFileSync("input", "utf8"), | |
words, | |
A.map(Number), | |
ns => St.evaluate(ns)(getNode), | |
allMetadata, | |
fold(monoidSum), | |
console.log | |
) | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Taylor Fausak's original Haskell solution here: https://github.com/tfausak/advent-of-code/blob/c4588983fc2d0a6b81f46d5c70c2fd8bf89c7486/2018/8/1.hs