diff --git a/.gitignore b/.gitignore index 5224155..fbd3d96 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ inputs/ support/*.o support/advent-support tmp/ +book/ +index.html diff --git a/README.md b/README.md index 48644ce..1598931 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,9 @@ Idris files. ## Authors Note +This entire book is a single literate code base, the source code is available at +. + The solutions contained in this project are intended to be read in sequential order, though can reasonably be read in any order if you have a good level of familiarity with more advanced functional programming topics. @@ -22,7 +25,7 @@ mailing list on source hut. While this project is intended to read more like a book, while it is still a work in progress, you can follow its development as a psuedo-blog by subscribing to the rss feed for the repository in your feed reader: -https://git.stranger.systems/Idris/advent.rss +. ## Index of non-day modules diff --git a/book.toml b/book.toml new file mode 100644 index 0000000..4ad1625 --- /dev/null +++ b/book.toml @@ -0,0 +1,13 @@ +[book] +authors = ["Nathan McCarty"] +language = "en" +multilingual = false +src = "src" +title = "Idris 2 by Highly Contrived Example" + +[build] +create-missing = false +use-default-preprocessors = false + +[output.html] +preferred-dark-theme = "ayu" diff --git a/scripts/build-book b/scripts/build-book new file mode 100755 index 0000000..5572774 --- /dev/null +++ b/scripts/build-book @@ -0,0 +1,101 @@ +#!/usr/bin/env raku + +use File::Temp; +use Shell::Command; +use paths; + +unit sub MAIN(Bool :$upload); + +my $tempdir = tempdir.IO; +my $ttc-number = dir('build/ttc').first.basename; +my $ttc = "build/ttc/$ttc-number".IO; + +# Filenames to ignore while processing source files +my Str:D @ignored = ["README.md", "SUMMARY.md"]; +# Check to see if a filename is ignored +sub not-ignored($path) { + for @ignored -> $ignored { + return False if $path.ends-with: $ignored; + } + return True; +} + +# Copy a file from the current directory to the temporary directory, preserving +# realtive path. Resolves symlinks in source, but does not reflect symlink +# resoultion in the output path +sub cp-temp($src) { + my $src-path = do given $src { + when Str { + $src.IO + } + when IO::Path { + $src + } + default { + die "Invalid source $src, {$src.WHAT}" + } + } + my $output-path = $tempdir.add($src-path.relative).IO; + # Create the parent directory if needed + if !$output-path.parent.d { + $output-path.parent.mkdir; + + } + # Copy the file + $src-path.resolve.copy: $output-path; +} + +# Invoke katla on a source file, streaming its output to the temporary directory +sub katla($src, $ttc-src) { + # Run katla and collect the output + my $katla = run 'katla', 'markdown', $src, $ttc-src, :out; + my $output = $katla.out.slurp(:close); + # TODO: Post process them to set themeing correctly + $output ~~ s:g/''//; + $output ~~ s:g/'
'//; + $output ~~ s:g/''/<\/code><\/pre>/; + $output ~~ s:g/'class="IdrisKeyword"'/class="hljs-keyword"/; + $output ~~ s:g/'class="IdrisModule"'/class="hljs-symbol hljs-emphasis"/; + $output ~~ s:g/'class="IdrisComment"'/class="hljs-comment"/; + $output ~~ s:g/'class="IdrisFunction"'/class="hljs-symbol"/; + $output ~~ s:g/'class="IdrisBound"'/class="hljs-name"/; + $output ~~ s:g/'class="IdrisData"'/class="hljs-title"/; + $output ~~ s:g/'class="IdrisType"'/class="hljs-type"/; + $output ~~ s:g/'class="IdrisNamespace"'/class="hljs-symbol hljs-emphasis"/; + + # Spurt the output to the temporary directory + my $output-path = $tempdir.add: $src; + if !$output-path.parent.d { + $output-path.parent.mkdir; + } + $output-path.spurt($output); +} + +# Copy our metadata files +cp-temp "book.toml"; +cp-temp "src/README.md"; +cp-temp "src/SUMMARY.md"; + +# Katla over the source files +for paths("src", :file(*.¬-ignored)) -> $path { + my $ttc-path = $ttc.add($path.IO.relative: "src").extension: "ttm"; + katla $path.IO.relative, $ttc-path.relative; +} + +# Build the book + +indir $tempdir, { + my $mdbook = run ; + die "Ooops" unless $mdbook; +} + +# Copy it over +rm_rf "book"; +cp $tempdir.add("book"), "book", :r; + +if $upload { + my $rsync = run 'rsync', '-avzh', $tempdir.add("book").Str, + 'ubuntu@static.stranger.systems:/var/www/static.stranger.systems/idris-by-contrived-example'; + die "rsync went bad" unless $rsync; +} diff --git a/src/Array.md b/src/Array.md index 98bf078..2721297 100644 --- a/src/Array.md +++ b/src/Array.md @@ -12,9 +12,9 @@ import Decidable.Equality import Control.WellFounded ``` - +``` ```idris %default total @@ -89,9 +89,9 @@ Iterable (LazyList a) a where ## Immutable arrays - +``` Immutable arrays created from vectors that provide constant time indexing and slicing operations. diff --git a/src/Main.md b/src/Main.md index f602362..1d0e2c1 100644 --- a/src/Main.md +++ b/src/Main.md @@ -76,7 +76,7 @@ data Error : Type where A `Show` implementation for `Error` is provided, hidden in this document for brevity. - +``` ## Extract the year and day diff --git a/src/Parser/Interface.md b/src/Parser/Interface.md index 49fe300..79583cf 100644 --- a/src/Parser/Interface.md +++ b/src/Parser/Interface.md @@ -27,7 +27,7 @@ data ParseError : Type where -> (rest : List ParseError) -> ParseError ``` - +``` ## Type Alias @@ -219,23 +219,23 @@ Lift a parser producing a `List` or `List1` of `Char` into a parser producing a ```idris -- TODO: Rename these export -parseString : Parser (List Char) -> Parser String -parseString x = do +liftString : Parser (List Char) -> Parser String +liftString x = do xs <- x pure $ pack xs export -parseString' : Parser (List1 Char) -> Parser String -parseString' x = parseString $ map forget x +liftString' : Parser (List1 Char) -> Parser String +liftString' x = liftString $ map forget x ``` Attempt to parse a specified character ```idris export -parseExactChar : Char -> Parser Char -parseExactChar c = do - result <- parseExactChar' c +charExact : Char -> Parser Char +charExact c = do + result <- charExact' c case result of GotChar char => pure char GotError err => throwParseError "Got \{show err} Expected \{show c}" @@ -246,10 +246,10 @@ Attempt to parse one of a list of chars ```idris export -parseTheseChars : List Char -> Parser Char -parseTheseChars cs = do +theseChars : List Char -> Parser Char +theseChars cs = do pnote "Parsing one of: \{show cs}" - result <- parseChar (\x => any (== x) cs) + result <- charPredicate (\x => any (== x) cs) case result of GotChar char => pure char GotError err => throwParseError "Got \{show err} Expected one of \{show cs}" @@ -267,7 +267,7 @@ exactString str with (asList str) pure "" exactString input@(strCons c str) | (c :: x) = do pnote "Parsing exact string \{show input}" - GotChar next <- parseChar (== c) + GotChar next <- charPredicate (== c) | GotError err => throwParseError "Got \{show err} expected \{show c}" | EndOfInput => throwParseError "End of input" rest <- exactString str | x @@ -282,12 +282,12 @@ delimited : (before, after : Char) -> Parser a -> Parser a delimited before after x = do pnote "Parsing delimited by \{show before} \{show after}" starting_state <- save - _ <- parseExactChar before + _ <- charExact before Right val <- tryEither x | Left err => do load starting_state throw err - Just _ <- tryMaybe $ parseExactChar after + Just _ <- tryMaybe $ charExact after | _ => do load starting_state throw $ MkParseError starting_state "Unmatched delimiter \{show before}" diff --git a/src/Parser/JSON.md b/src/Parser/JSON.md index 311057d..6602210 100644 --- a/src/Parser/JSON.md +++ b/src/Parser/JSON.md @@ -9,7 +9,7 @@ import public Parser.Numbers import Structures.Dependent.DList ``` - +``` ## JSON components @@ -54,7 +54,7 @@ data JSONValue : JSONType -> Type where %name JSONValue value, value2, value3 ``` - +``` ## Parsers @@ -109,12 +109,7 @@ Define a `whitespace` character class based on the json specifications whitespace : Parser Char whitespace = do pnote "Whitespace character" - result <- - parseChar (\x => any (== x) $ the (List _) [' ', '\n', '\r', '\t']) - case result of - GotChar char => pure char - GotError err => throwParseError "Expected whitespace, got: \{show err}" - EndOfInput => throwParseError "End of Input" + theseChars [' ', '\n', '\r', '\t'] ``` Convenience function @@ -162,12 +157,12 @@ object = do keyValue : Parser (t : JSONType ** (String, JSONValue t)) keyValue = do VString key <- surround whitespace string - _ <- parseExactChar ':' + _ <- charExact ':' (typ ** val) <- value pure (typ ** (key, val)) restKeyValue : Parser (t : JSONType ** (String, JSONValue t)) restKeyValue = do - _ <- parseExactChar ',' + _ <- charExact ',' keyValue pairs : Parser (List1 (t : JSONType ** (String, JSONValue t))) pairs = do @@ -194,7 +189,7 @@ array = do pure $ VArray Nil restValue : Parser (t : JSONType ** JSONValue t) restValue = do - _ <- parseExactChar ',' + _ <- charExact ',' value values : Parser (List1 (t : JSONType ** JSONValue t)) values = do @@ -211,13 +206,13 @@ array = do ```idris string = do pnote "JSON String" - str <- parseString $ delimited '"' '"' (many stringCharacter) + str <- liftString $ delimited '"' '"' (many stringCharacter) pure $ VString str where -- TODO: Handle control characters properly stringCharacter : Parser Char stringCharacter = do - result <- parseChar (not . (== '"')) + result <- charPredicate (not . (== '"')) case result of GotChar char => pure char GotError err => diff --git a/src/Parser/Numbers.md b/src/Parser/Numbers.md index 0c069ec..e7adbf8 100644 --- a/src/Parser/Numbers.md +++ b/src/Parser/Numbers.md @@ -9,9 +9,9 @@ import Data.Vect import Control.Eff ``` - +``` ## Base Abstraction @@ -63,7 +63,7 @@ nat b = do where parseDigit : Parser Nat parseDigit = do - GotChar char <- parseChar (hasDigit b) + GotChar char <- charPredicate (hasDigit b) | GotError e => throwParseError "\{show e} is not a digit" | EndOfInput => throwParseError "End Of Input" case digitValue b char of @@ -82,7 +82,7 @@ natBase10 = nat base10 export integer : Base -> Parser Integer integer b = do - negative <- map isJust . tryMaybe $ parseExactChar '-' + negative <- map isJust . tryMaybe $ charExact '-' value <- map natToInteger $ nat b if negative then pure $ negate value @@ -120,13 +120,13 @@ double = do where parseDigit : Parser Char parseDigit = do - GotChar char <- parseChar (hasDigit base10) + GotChar char <- charPredicate (hasDigit base10) | GotError e => throwParseError "\{show e} is not a digit" | EndOfInput => throwParseError "End Of Input" pure char integer : Parser String integer = do - sign <- tryMaybe $ parseExactChar '-' + sign <- tryMaybe $ charExact '-' error <- replaceError "Expected digit" digits <- map forget $ atLeastOne error parseDigit case sign of @@ -134,14 +134,14 @@ double = do Just x => pure $ pack (x :: digits) fraction : Parser String fraction = do - decimal <- parseExactChar '.' + decimal <- charExact '.' error <- replaceError "Expected digit" digits <- map forget $ atLeastOne error parseDigit pure $ pack digits exponent : Parser String exponent = do - e <- parseTheseChars ['e', 'E'] - sign <- parseTheseChars ['+', '-'] + e <- theseChars ['e', 'E'] + sign <- theseChars ['+', '-'] error <- replaceError "Expected digit" digits <- map forget $ atLeastOne error parseDigit pure . pack $ sign :: digits diff --git a/src/Parser/ParserState.md b/src/Parser/ParserState.md index 8668a16..1927d75 100644 --- a/src/Parser/ParserState.md +++ b/src/Parser/ParserState.md @@ -51,7 +51,7 @@ record Index (length : Int64) where {auto 0 prf : IsIndex length index} ``` - +``` Stores the location we are currently at in the string, and metadata about it for providing good error messages. Parsing an empty input isn't very interesting, so @@ -156,7 +156,7 @@ positionPair pi = in (linum, col) ``` - +``` ### More Barbie Functionality @@ -216,7 +216,7 @@ data ParserState : Type -> Type where Note : Lazy String -> ParserState () ``` - +``` ### Actions @@ -243,14 +243,14 @@ load pi = send $ Load pi ||| predicate, updates the state if parsing succeeds, does not alter it in an ||| error condition. export -parseChar : Has ParserState fs => (predicate : Char -> Bool) +charPredicate : Has ParserState fs => (predicate : Char -> Bool) -> Eff fs ParseCharResult -parseChar predicate = send $ ParseChar predicate +charPredicate predicate = send $ ParseChar predicate ||| Parse a char by exact value export -parseExactChar' : Has ParserState fs => (chr : Char) -> Eff fs ParseCharResult -parseExactChar' chr = send $ ParseExactChar chr +charExact' : Has ParserState fs => (chr : Char) -> Eff fs ParseCharResult +charExact' chr = send $ ParseExactChar chr ||| "Parse" the end of input, returning `True` if the parser state is currently ||| at the end of the input @@ -366,4 +366,4 @@ runParserState s = ## Footnotes -[^1]: https://github.com/stefan-hoeck/idris2-barbies +[^1]: diff --git a/src/README.md b/src/README.md new file mode 120000 index 0000000..32d46ee --- /dev/null +++ b/src/README.md @@ -0,0 +1 @@ +../README.md \ No newline at end of file diff --git a/src/SUMMARY.md b/src/SUMMARY.md new file mode 100644 index 0000000..2cf1e0b --- /dev/null +++ b/src/SUMMARY.md @@ -0,0 +1,35 @@ +# Summary + +[README](README.md) + +# Running the code + +- [Runner - Divide Code Into Years and Days](Runner.md) +- [Main - Select a Day and Year to Run](Main.md) + +# Utility Mini-Library + +- [Util - Extend Standard Types](Util.md) + - [Util.Eff - Effects and Effect Accessories](Util/Eff.md) + - [Util.Digits - Pattern Matching Integers as Lists of Digits](Util/Eff.md) +- [Array - Arrays With Constant Time Indexing and Slicing](Array.md) +- [Parser - Recursive Descent Parsing, With Effects](Parser.md) + - [Interface - Core Parsing Functionality](Parser/Interface.md) + - [ParserState - Custom Effect for Parser Internal State](Parser/ParserState.md) + - [Numbers - Parsers for Numerical Values](Parser/Numbers.md) + - [JSON - A JSON Parser](Parser/JSON.md) + +# Problems + +- [2015](Years/Y2015.md) + - [Day 1 - Warmup](Years/Y2015/Day1.md) + - [Day 2 - Early Effectful Parsing](Years/Y2015/Day2.md) + - [Day 3 - Mutually Recursive Functions](Years/Y2015/Day3.md) + - [Day 4 - Basic FFI](Years/Y2015/Day4.md) + - [Day 5 - Views and Dependent Pattern Matching](Years/Y2015/Day5.md) + - [Day 6 - Naive 2D Grid](Years/Y2015/Day6.md) + - [Day 7 - Dependent Maps and Indexed Type Familes](Years/Y2015/Day7.md) + - [Day 8 - Proper Effectful Parsers](Years/Y2015/Day8.md) + - [Day 9 - Naive Graph Traversal](Years/Y2015/Day9.md) + - [Day 10 - Digits View](Years/Y2015/Day10.md) + - [Day 11 - Refinement Types](Years/Y2015/Day11.md) diff --git a/src/Util.md b/src/Util.md index c7a9bbc..4e8de44 100644 --- a/src/Util.md +++ b/src/Util.md @@ -29,9 +29,9 @@ repeatN (S times') f seed = repeatN times' f (f seed) ## Either - +``` ### mapLeft @@ -47,9 +47,9 @@ Applies a function to the contents of a `Left` if the value of the given ## List - +``` ### contains @@ -94,12 +94,12 @@ Define some operations for pairs of numbers, treating them roughly like vectors ### Addition and Subtraction - +``` ```idris public export @@ -115,9 +115,9 @@ namespace Pair Extend `Data.SortedSet` - +``` ### length @@ -133,9 +133,9 @@ Count the number of elements in a sorted set Extend `Data.String` - +``` ### isSubstr diff --git a/src/Util/Digits.md b/src/Util/Digits.md index 4cf58b0..6609c6c 100644 --- a/src/Util/Digits.md +++ b/src/Util/Digits.md @@ -6,11 +6,11 @@ module Util.Digits import Data.Monoid.Exponentiation ``` - +``` This module provides views and associated functionality for treating `Integers` as if they were lists of numbers. @@ -22,10 +22,10 @@ teaching purposes, we'll do it here, but please consider a library like [prim](https://github.com/stefan-hoeck/idris2-prim) if you find yourself needing to prove properties about primitive types. - +``` ## Primitive functionality @@ -50,14 +50,14 @@ most significant digit. For a clarifying example: - +``` ```idris ascList (ascending 12345) == [5, 4, 3, 2, 1] @@ -121,14 +121,14 @@ least significant digit. For a clarifying example: - +``` ```idris decList (descending 12345) == [1, 2, 3, 4, 5] diff --git a/src/Util/Eff.md b/src/Util/Eff.md index 1baa453..8441eb9 100644 --- a/src/Util/Eff.md +++ b/src/Util/Eff.md @@ -36,7 +36,7 @@ data Level : Type where Other : (n : Nat) -> {auto _ : n `GT` 4} -> Level ``` - +``` Convert a `Level` into a colorized tag diff --git a/src/Years/Y2015.md b/src/Years/Y2015.md index f745517..c2a0326 100644 --- a/src/Years/Y2015.md +++ b/src/Years/Y2015.md @@ -6,7 +6,7 @@ import Structures.Dependent.FreshList import Runner ``` - +``` # Days diff --git a/src/Years/Y2015/Day1.md b/src/Years/Y2015/Day1.md index f8820d3..49369d9 100644 --- a/src/Years/Y2015/Day1.md +++ b/src/Years/Y2015/Day1.md @@ -3,7 +3,7 @@ Pretty simple, basic warmup problem, nothing really novel is on display here except the effectful part computations. - +``` ## Solver Functions @@ -76,8 +76,8 @@ part2 x = do pure $ findBasement 1 0 input ``` - +``` diff --git a/src/Years/Y2015/Day10.md b/src/Years/Y2015/Day10.md index 201e0c5..d07edf8 100644 --- a/src/Years/Y2015/Day10.md +++ b/src/Years/Y2015/Day10.md @@ -3,13 +3,13 @@ This day doesn't really add anything new, but we will show off our new views for viewing integers as lists of digits. - +``` ```idris import Data.String @@ -22,9 +22,9 @@ import Util import Util.Digits ``` - +``` # Solver Functions @@ -118,8 +118,8 @@ part2 digits = do pure $ count (const True) output ``` - +``` diff --git a/src/Years/Y2015/Day11.md b/src/Years/Y2015/Day11.md index 43d7908..0feff8f 100644 --- a/src/Years/Y2015/Day11.md +++ b/src/Years/Y2015/Day11.md @@ -10,13 +10,13 @@ implement the one we need for today's task as a throw away data structure just for this module, we will be using the `refined`[^1] library's implementation for the sake of getting on with it. - +``` ```idris import Data.Vect @@ -55,13 +55,13 @@ record PasswordChar where %name PasswordChar pc ``` - +``` A function to fallible convert `Char`s into refined `PasswordChar`s, this will return `Just` if the `Char` satisfies the predicate, and `Nothing` otherwise, @@ -227,12 +227,12 @@ part2 password = do pure $ passwordToString next_password ``` - +``` ## References -[^1]: https://github.com/stefan-hoeck/idris2-refined/ +[^1]: diff --git a/src/Years/Y2015/Day2.md b/src/Years/Y2015/Day2.md index 22081b2..9ab3ead 100644 --- a/src/Years/Y2015/Day2.md +++ b/src/Years/Y2015/Day2.md @@ -2,13 +2,13 @@ This day provides us our first little taste of effectful parsing - +``` ```idris import Data.List @@ -16,9 +16,9 @@ import Data.List1 import Data.String ``` - +``` ## Box structure @@ -130,8 +130,8 @@ part2 : (boxes : List Box) -> Eff (PartEff String) Integer part2 boxes = pure . sum . map totalRibbon $ boxes ``` - +``` diff --git a/src/Years/Y2015/Day3.md b/src/Years/Y2015/Day3.md index 195d1d9..daa922d 100644 --- a/src/Years/Y2015/Day3.md +++ b/src/Years/Y2015/Day3.md @@ -3,13 +3,13 @@ This day provides a gentle introduction to `mutual` blocks and mutually recursive functions. - +``` ```idris import Data.SortedSet @@ -18,9 +18,9 @@ import Data.String import Util ``` - +``` ## Parsing and data structures @@ -152,8 +152,8 @@ part2 movements = do pure . length $ locations ``` - +``` diff --git a/src/Years/Y2015/Day4.md b/src/Years/Y2015/Day4.md index f907fa1..78d0abe 100644 --- a/src/Years/Y2015/Day4.md +++ b/src/Years/Y2015/Day4.md @@ -3,13 +3,13 @@ This day introduces us to a little bit of FFI, linking to openssl to use it's `MD5` functionality. - +``` ```idris import Data.String @@ -196,8 +196,8 @@ part2 seed = do pure number ``` - +``` diff --git a/src/Years/Y2015/Day5.md b/src/Years/Y2015/Day5.md index e41bd96..d1b3ccb 100644 --- a/src/Years/Y2015/Day5.md +++ b/src/Years/Y2015/Day5.md @@ -6,13 +6,13 @@ specifically `String`'s [`AsList`](https://www.idris-lang.org/docs/idris2/current/base_docs/docs/Data.String.html#Data.String.AsList) view, which lets us treat `String`s as if they were lazy lists or iterators. - +``` ```idris import Data.String @@ -20,9 +20,9 @@ import Data.String import Util ``` - +``` ## Nice Strings @@ -213,8 +213,8 @@ part2 _ = do pure x ``` - +``` diff --git a/src/Years/Y2015/Day6.md b/src/Years/Y2015/Day6.md index 131be48..c15596d 100644 --- a/src/Years/Y2015/Day6.md +++ b/src/Years/Y2015/Day6.md @@ -1,16 +1,14 @@ -# \[Year 2015 Day 6\](https://adventofcode.com/2015/day/ - -6. +# [Year 2015 Day 6](https://adventofcode.com/2015/day/6) Introduction to the advent of code classic 2d grid problem. - +``` ```idris import Util @@ -23,9 +21,9 @@ import Data.String import Data.IORef ``` - +``` ## Parsing and data structures @@ -77,12 +75,12 @@ The three types of action that can be performed on a light. data Action = On | Off | Toggle ``` - +``` The range of coordinates that a command affects @@ -92,11 +90,11 @@ record Range (rows, cols : Nat) where top_left, bottom_right : Coord rows cols ``` - +``` Helper function to extract a range of values from our Grid. @@ -121,11 +119,11 @@ record Command (rows, cols : Nat) where range : Range rows cols ``` - +``` ### Parsing @@ -336,8 +334,8 @@ part2 commands = do pure brightness ``` - +``` diff --git a/src/Years/Y2015/Day7.md b/src/Years/Y2015/Day7.md index 18f6d01..9e663f6 100644 --- a/src/Years/Y2015/Day7.md +++ b/src/Years/Y2015/Day7.md @@ -1,6 +1,4 @@ -# \[Year 2015 Day 7\](https://adventofcode.com/2015/day/ - -7. +# [Year 2015 Day 7](https://adventofcode.com/2015/day/7) This day provides us a gentle introduction to dependent maps. @@ -15,13 +13,13 @@ Ensuring that the input contains only one gate outputting for each wire is done through throwing a runtime error in the parsing function if a second gate outputting to a given wire is found in the input. - +``` ```idris import Data.Bits @@ -33,9 +31,9 @@ import Data.SortedMap.Dependent import Decidable.Equality ``` - +``` ## Parsing and data structures @@ -254,8 +252,8 @@ part2 (circut, value) = do pure value ``` - +``` diff --git a/src/Years/Y2015/Day8.md b/src/Years/Y2015/Day8.md index 6b285b9..621cae2 100644 --- a/src/Years/Y2015/Day8.md +++ b/src/Years/Y2015/Day8.md @@ -3,7 +3,7 @@ This day provides a more in depth introduction to writing effectful parsers, making use of state and non-determinism in our parsers. - +``` ```idris import Data.String @@ -344,8 +344,8 @@ part2 inputs = do pure difference ``` - +``` diff --git a/src/Years/Y2015/Day9.md b/src/Years/Y2015/Day9.md index c689b78..d30a9b0 100644 --- a/src/Years/Y2015/Day9.md +++ b/src/Years/Y2015/Day9.md @@ -6,13 +6,13 @@ meeting the problem criteria, and then figure out the length in a separate step. This isn't a particularly efficient solution, but its good enough for this small problem size. - +``` ```idris import Data.String @@ -70,10 +70,10 @@ DistanceMap : Type DistanceMap = SortedMap Location (List LP) ``` - +``` Perform simple, pattern matching based parsing of a location pair. @@ -287,8 +287,8 @@ part2 (distance_map, pairs) = do pure len ``` - +```