Compare commits

..

45 commits

Author SHA1 Message Date
90c48b3672 json: delimited arrays 2025-01-26 21:09:58 -05:00
ef690db972 core: Properly restore state in delimited 2025-01-26 21:09:30 -05:00
93d4d876d9 core: Factor parseExactChar into the effect 2025-01-26 21:06:22 -05:00
08a2f263bb json: parse char result 2025-01-26 20:51:24 -05:00
40251a1455 numbers: ParseCharResult refactor 2025-01-26 20:51:10 -05:00
b1a4e1a941 core: Remove type argument from ParseCharResult 2025-01-26 20:51:00 -05:00
2e4ab42aa0 json: Notes 2025-01-26 20:06:53 -05:00
da44cf72cf core: Notes 2025-01-26 20:04:14 -05:00
da182e813f json: Use debuging runner in tests 2025-01-26 19:51:46 -05:00
06c4c8a9cf core: Debug wrapper for handleParserIO 2025-01-26 19:49:46 -05:00
5a47d5548c json: Clean up json smoke test 2025-01-26 15:48:28 -05:00
4fb5707b25 json: Refactor string parser 2025-01-26 15:48:28 -05:00
91e1d2c9b1 json: More refactor 2025-01-26 15:48:28 -05:00
a3c7729ab2 json: Smoke test 2025-01-26 15:48:28 -05:00
a8c3901665 json: Show Fix 2025-01-26 15:48:28 -05:00
77dcc4d953 json: oneOfM refactor 2025-01-26 15:48:28 -05:00
aa1ae93165 json: object refactor 2025-01-26 15:48:28 -05:00
19ce8ac798 json: Bool and null 2025-01-26 15:48:28 -05:00
370bb18c06 json: number 2025-01-26 15:48:28 -05:00
3ad023ef6a json: Janky string 2025-01-26 15:48:28 -05:00
38e259fd13 json: Object and array 2025-01-26 15:48:28 -05:00
79d56aeddd json: Parser types 2025-01-26 15:48:28 -05:00
b70ed0e147 json: Define types, add sop 2025-01-26 15:48:28 -05:00
b018967cb1 json: create module 2025-01-26 15:48:28 -05:00
906ffb7877 numbers: Fix readme 2025-01-26 15:48:28 -05:00
aacabb8b22 numbers: make double non base-sensitive 2025-01-26 15:48:28 -05:00
026476dd91 numbers: Double Parser 2025-01-26 15:48:28 -05:00
9220d4bbac numbers: Integer parser 2025-01-26 15:48:28 -05:00
1cc6bea78e numbers: Nat parser 2025-01-26 15:48:28 -05:00
82b16a0e63 numbers: Nat unit tests 2025-01-26 15:48:28 -05:00
2b78275a4b numbers: Basic module structure 2025-01-26 15:48:28 -05:00
46b591283d numbers: Create numbers module 2025-01-26 15:48:28 -05:00
72ea53becf core: oneOfM refactor 2025-01-26 15:48:28 -05:00
59fba4584d core: nom and surround 2025-01-26 15:48:28 -05:00
3029432699 core: export exactString 2025-01-25 05:09:41 -05:00
59f1eb31d0 core: exact string 2025-01-25 04:39:50 -05:00
994da7065c core: runParserState 2025-01-25 00:36:35 -05:00
1658e15487 core: runFirstIO 2025-01-25 00:36:35 -05:00
38c69c0ae3 core: parseTheseChars 2025-01-25 00:36:35 -05:00
7dba492535 core: parseExactChar 2025-01-24 22:39:22 -05:00
40dd87a4f3 core: ParseCharE 2025-01-24 22:39:22 -05:00
fa5eb61d59 core: spelling 2025-01-24 22:21:29 -05:00
9b12ebcf00 core: Add replaceError method 2025-01-24 22:21:29 -05:00
5e5ede87b4 core: Add show for ParserError 2025-01-24 22:21:29 -05:00
222ae17180 core: Beginnings of parser module 2025-01-24 07:11:04 -05:00
27 changed files with 152 additions and 298 deletions

2
.gitignore vendored
View file

@ -4,5 +4,3 @@ inputs/
support/*.o
support/advent-support
tmp/
book/
index.html

View file

@ -6,9 +6,6 @@ Idris files.
## Authors Note
This entire book is a single literate code base, the source code is available at
<https://git.stranger.systems/Idris/advent>.
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.
@ -25,7 +22,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>.
https://git.stranger.systems/Idris/advent.rss
## Index of non-day modules

View file

@ -1,13 +0,0 @@
[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"

View file

@ -1,101 +0,0 @@
#!/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/'<style>' .* '</style>'//;
$output ~~ s:g/'<br />'//;
$output ~~ s:g/'<code'/<pre><code/;
$output ~~ s:g/'</code>'/<\/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(*.&not-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 <mdbook build>;
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;
}

View file

@ -12,9 +12,9 @@ import Decidable.Equality
import Control.WellFounded
```
```idris hide
<!-- idris
import System
```
-->
```idris
%default total
@ -89,9 +89,9 @@ Iterable (LazyList a) a where
## Immutable arrays
```idris hide
<!-- idris
namespace Immutable
```
-->
Immutable arrays created from vectors that provide constant time indexing and
slicing operations.

View file

@ -76,7 +76,7 @@ data Error : Type where
A `Show` implementation for `Error` is provided, hidden in this document for
brevity.
```idris hide
<!-- idris
Show Error where
show (OptionsError errs) =
let errs = unlines . map (" " ++) . lines . joinBy "\n" $ errs
@ -98,7 +98,7 @@ Show Error where
show (SolveError year day part err) =
let err = unlines . map (" " ++) . lines . show $ err
in "Error solving day \{show day} part \{show part} of year \{show year}: \n" ++ err
```
-->
## Extract the year and day

View file

@ -27,7 +27,7 @@ data ParseError : Type where
-> (rest : List ParseError) -> ParseError
```
```idris hide
<!-- idris
export
Show ParseError where
show (MkParseError state message) =
@ -44,7 +44,7 @@ Show ParseError where
position = show state.position.index
first = "Error at line \{line}, column \{col} (\{position}): \{message}"
in "\{first}\n\{rest}"
```
-->
## 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
liftString : Parser (List Char) -> Parser String
liftString x = do
parseString : Parser (List Char) -> Parser String
parseString x = do
xs <- x
pure $ pack xs
export
liftString' : Parser (List1 Char) -> Parser String
liftString' x = liftString $ map forget x
parseString' : Parser (List1 Char) -> Parser String
parseString' x = parseString $ map forget x
```
Attempt to parse a specified character
```idris
export
charExact : Char -> Parser Char
charExact c = do
result <- charExact' c
parseExactChar : Char -> Parser Char
parseExactChar c = do
result <- parseExactChar' 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
theseChars : List Char -> Parser Char
theseChars cs = do
parseTheseChars : List Char -> Parser Char
parseTheseChars cs = do
pnote "Parsing one of: \{show cs}"
result <- charPredicate (\x => any (== x) cs)
result <- parseChar (\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 <- charPredicate (== c)
GotChar next <- parseChar (== 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
_ <- charExact before
_ <- parseExactChar before
Right val <- tryEither x
| Left err => do
load starting_state
throw err
Just _ <- tryMaybe $ charExact after
Just _ <- tryMaybe $ parseExactChar after
| _ => do
load starting_state
throw $ MkParseError starting_state "Unmatched delimiter \{show before}"

View file

@ -9,7 +9,7 @@ import public Parser.Numbers
import Structures.Dependent.DList
```
```idris hide
<!-- idris
import System
import Derive.Prelude
import Generics.Derive
@ -19,7 +19,7 @@ import Generics.Derive
%hide Generics.Derive.Show
%language ElabReflection
```
-->
## JSON components
@ -54,7 +54,7 @@ data JSONValue : JSONType -> Type where
%name JSONValue value, value2, value3
```
```idris hide
<!-- idris
Show (JSONValue t) where
show (VObject xs) =
let xs = dMap (\_,(key, value) => "\"\{key}\":\{show value}") xs
@ -80,7 +80,7 @@ Eq (JSONValue t) where
VNull == VNull = True
%hide Language.Reflection.TT.WithFC.value
```
-->
## Parsers
@ -109,7 +109,12 @@ Define a `whitespace` character class based on the json specifications
whitespace : Parser Char
whitespace = do
pnote "Whitespace character"
theseChars [' ', '\n', '\r', '\t']
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"
```
Convenience function
@ -157,12 +162,12 @@ object = do
keyValue : Parser (t : JSONType ** (String, JSONValue t))
keyValue = do
VString key <- surround whitespace string
_ <- charExact ':'
_ <- parseExactChar ':'
(typ ** val) <- value
pure (typ ** (key, val))
restKeyValue : Parser (t : JSONType ** (String, JSONValue t))
restKeyValue = do
_ <- charExact ','
_ <- parseExactChar ','
keyValue
pairs : Parser (List1 (t : JSONType ** (String, JSONValue t)))
pairs = do
@ -189,7 +194,7 @@ array = do
pure $ VArray Nil
restValue : Parser (t : JSONType ** JSONValue t)
restValue = do
_ <- charExact ','
_ <- parseExactChar ','
value
values : Parser (List1 (t : JSONType ** JSONValue t))
values = do
@ -206,13 +211,13 @@ array = do
```idris
string = do
pnote "JSON String"
str <- liftString $ delimited '"' '"' (many stringCharacter)
str <- parseString $ delimited '"' '"' (many stringCharacter)
pure $ VString str
where
-- TODO: Handle control characters properly
stringCharacter : Parser Char
stringCharacter = do
result <- charPredicate (not . (== '"'))
result <- parseChar (not . (== '"'))
case result of
GotChar char => pure char
GotError err =>

View file

@ -9,9 +9,9 @@ import Data.Vect
import Control.Eff
```
```idris hide
<!-- idris
import System
```
-->
## Base Abstraction
@ -63,7 +63,7 @@ nat b = do
where
parseDigit : Parser Nat
parseDigit = do
GotChar char <- charPredicate (hasDigit b)
GotChar char <- parseChar (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 $ charExact '-'
negative <- map isJust . tryMaybe $ parseExactChar '-'
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 <- charPredicate (hasDigit base10)
GotChar char <- parseChar (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 $ charExact '-'
sign <- tryMaybe $ parseExactChar '-'
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 <- charExact '.'
decimal <- parseExactChar '.'
error <- replaceError "Expected digit"
digits <- map forget $ atLeastOne error parseDigit
pure $ pack digits
exponent : Parser String
exponent = do
e <- theseChars ['e', 'E']
sign <- theseChars ['+', '-']
e <- parseTheseChars ['e', 'E']
sign <- parseTheseChars ['+', '-']
error <- replaceError "Expected digit"
digits <- map forget $ atLeastOne error parseDigit
pure . pack $ sign :: digits

View file

@ -51,7 +51,7 @@ record Index (length : Int64) where
{auto 0 prf : IsIndex length index}
```
```idris hide
<!-- idris
export
Eq (Index i) where
x == y = x.index == y.index
@ -63,7 +63,7 @@ Ord (Index i) where
export
Show (Index i) where
show (MkIndex index) = show 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)
```
```idris hide
<!-- idris
export
Show (ParserInternal Id) where
show pi =
@ -165,7 +165,7 @@ Show (ParserInternal Id) where
pos = pi.position.index
eof = show pi.end_of_input
in "Position: \{pos}(\{line}, \{col}}) Value: \{show current} EoF: \{eof}"
```
-->
### More Barbie Functionality
@ -216,7 +216,7 @@ data ParserState : Type -> Type where
Note : Lazy String -> ParserState ()
```
```idris hide
<!-- idris
Show (ParserState t) where
show Save = "Saving state"
show (Load pi) = "Loading state \{show pi}"
@ -224,7 +224,7 @@ Show (ParserState t) where
show (ParseExactChar char) = "Parsing char \{show char}"
show ParseEoF = "Parsing EoF"
show (Note _) = "Note"
```
-->
### 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
charPredicate : Has ParserState fs => (predicate : Char -> Bool)
parseChar : Has ParserState fs => (predicate : Char -> Bool)
-> Eff fs ParseCharResult
charPredicate predicate = send $ ParseChar predicate
parseChar predicate = send $ ParseChar predicate
||| Parse a char by exact value
export
charExact' : Has ParserState fs => (chr : Char) -> Eff fs ParseCharResult
charExact' chr = send $ ParseExactChar chr
parseExactChar' : Has ParserState fs => (chr : Char) -> Eff fs ParseCharResult
parseExactChar' 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]: https://github.com/stefan-hoeck/idris2-barbies

View file

@ -1 +0,0 @@
../README.md

View file

@ -1,35 +0,0 @@
# 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)

View file

@ -29,9 +29,9 @@ repeatN (S times') f seed = repeatN times' f (f seed)
## Either
```idris hide
<!-- idris
namespace Either
```
-->
### mapLeft
@ -47,9 +47,9 @@ Applies a function to the contents of a `Left` if the value of the given
## List
```idris hide
<!-- idris
namespace List
```
-->
### contains
@ -94,12 +94,12 @@ Define some operations for pairs of numbers, treating them roughly like vectors
### Addition and Subtraction
```idris hide
<!-- idris
export infixl 8 >+<
export infixl 8 >-<
namespace Pair
```
-->
```idris
public export
@ -115,9 +115,9 @@ namespace Pair
Extend `Data.SortedSet`
```idris hide
<!-- idris
namespace Set
```
-->
### length
@ -133,9 +133,9 @@ Count the number of elements in a sorted set
Extend `Data.String`
```idris hide
<!-- idris
namespace String
```
-->
### isSubstr

View file

@ -6,11 +6,11 @@ module Util.Digits
import Data.Monoid.Exponentiation
```
```idris hide
<!-- idris
import System
%default total
```
-->
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.
```idris hide
<!-- idris
-- This mutual block isn't strictly required, but is useful for literate purposes
mutual
```
-->
## Primitive functionality
@ -50,14 +50,14 @@ most significant digit.
For a clarifying example:
```idris hide
<!-- idris
-- @@test Ascending Digits Example
ascendingExample : IO Bool
ascendingExample = do
putStrLn "Expecting: \{show [5, 4, 3, 2, 1]}"
putStrLn "Got: \{show . ascList $ ascending 12345}"
pure $
```
-->
```idris
ascList (ascending 12345) == [5, 4, 3, 2, 1]
@ -121,14 +121,14 @@ least significant digit.
For a clarifying example:
```idris hide
<!-- idris
-- @@test Descending Digits Example
descendingExample : IO Bool
descendingExample = do
putStrLn "Expecting: \{show [1, 2, 3, 4, 5]}"
putStrLn "Got: \{show . decList $ descending 12345}"
pure $
```
-->
```idris
decList (descending 12345) == [1, 2, 3, 4, 5]

View file

@ -36,7 +36,7 @@ data Level : Type where
Other : (n : Nat) -> {auto _ : n `GT` 4} -> Level
```
```idris hide
<!-- idris
export
levelToNat : Level -> Nat
levelToNat Err = 0
@ -67,7 +67,7 @@ export infixl 8 >+
export
(>+) : Level -> Nat -> Level
(>+) x k = natToLevel (k + levelToNat x)
```
-->
Convert a `Level` into a colorized tag

View file

@ -6,7 +6,7 @@ import Structures.Dependent.FreshList
import Runner
```
```idris hide
<!-- idris
import Years.Y2015.Day1
import Years.Y2015.Day2
import Years.Y2015.Day3
@ -18,7 +18,7 @@ import Years.Y2015.Day8
import Years.Y2015.Day9
import Years.Y2015.Day10
import Years.Y2015.Day11
```
-->
# Days

View file

@ -3,7 +3,7 @@
Pretty simple, basic warmup problem, nothing really novel is on display here
except the effectful part computations.
```idris hide
<!-- idris
module Years.Y2015.Day1
import Control.Eff
@ -11,7 +11,7 @@ import Control.Eff
import Runner
%default total
```
-->
## Solver Functions
@ -76,8 +76,8 @@ part2 x = do
pure $ findBasement 1 0 input
```
```idris hide
<!-- idris
public export
day1 : Day
day1 = Both 1 part1 part2
```
-->

View file

@ -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 hide
<!-- idris
module Years.Y2015.Day10
import Control.Eff
import Runner
```
-->
```idris
import Data.String
@ -22,9 +22,9 @@ import Util
import Util.Digits
```
```idris hide
<!-- idris
%default total
```
-->
# Solver Functions
@ -118,8 +118,8 @@ part2 digits = do
pure $ count (const True) output
```
```idris hide
<!-- idris
public export
day10 : Day
day10 = Both 10 part1 part2
```
-->

View file

@ -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 hide
<!-- idris
module Years.Y2015.Day11
import Control.Eff
import Runner
```
-->
```idris
import Data.Vect
@ -55,13 +55,13 @@ record PasswordChar where
%name PasswordChar pc
```
```idris hide
<!-- idris
Show PasswordChar where
show (MkPC char) = singleton char
Eq PasswordChar where
x == y = x.char == y.char
```
-->
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
```
```idris hide
<!-- idris
public export
day11 : Day
day11 = Both 11 part1 part2
```
-->
## References
[^1]: <https://github.com/stefan-hoeck/idris2-refined/>
[^1]: https://github.com/stefan-hoeck/idris2-refined/

View file

@ -2,13 +2,13 @@
This day provides us our first little taste of effectful parsing
```idris hide
<!-- idris
module Years.Y2015.Day2
import Control.Eff
import Runner
```
-->
```idris
import Data.List
@ -16,9 +16,9 @@ import Data.List1
import Data.String
```
```idris hide
<!-- idris
%default total
```
-->
## Box structure
@ -130,8 +130,8 @@ part2 : (boxes : List Box) -> Eff (PartEff String) Integer
part2 boxes = pure . sum . map totalRibbon $ boxes
```
```idris hide
<!-- idris
public export
day2 : Day
day2 = Both 2 part1 part2
```
-->

View file

@ -3,13 +3,13 @@
This day provides a gentle introduction to `mutual` blocks and mutually
recursive functions.
```idris hide
<!-- idris
module Years.Y2015.Day3
import Control.Eff
import Runner
```
-->
```idris
import Data.SortedSet
@ -18,9 +18,9 @@ import Data.String
import Util
```
```idris hide
<!-- idris
%default total
```
-->
## Parsing and data structures
@ -152,8 +152,8 @@ part2 movements = do
pure . length $ locations
```
```idris hide
<!-- idris
public export
day3 : Day
day3 = Both 3 part1 part2
```
-->

View file

@ -3,13 +3,13 @@
This day introduces us to a little bit of FFI, linking to openssl to use it's
`MD5` functionality.
```idris hide
<!-- idris
module Years.Y2015.Day4
import Control.Eff
import Runner
```
-->
```idris
import Data.String
@ -196,8 +196,8 @@ part2 seed = do
pure number
```
```idris hide
<!-- idris
public export
day4 : Day
day4 = Both 4 part1 part2
```
-->

View file

@ -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 hide
<!-- idris
module Years.Y2015.Day5
import Control.Eff
import Runner
```
-->
```idris
import Data.String
@ -20,9 +20,9 @@ import Data.String
import Util
```
```idris hide
<!-- idris
%default total
```
-->
## Nice Strings
@ -213,8 +213,8 @@ part2 _ = do
pure x
```
```idris hide
<!-- idris
public export
day5 : Day
day5 = Both 5 part1 part2
```
-->

View file

@ -1,14 +1,16 @@
# [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 hide
<!-- idris
module Years.Y2015.Day6
import Control.Eff
import Runner
```
-->
```idris
import Util
@ -21,9 +23,9 @@ import Data.String
import Data.IORef
```
```idris hide
<!-- idris
%default total
```
-->
## Parsing and data structures
@ -75,12 +77,12 @@ The three types of action that can be performed on a light.
data Action = On | Off | Toggle
```
```idris hide
<!-- idris
Show Action where
show On = "on"
show Off = "off"
show Toggle = "toggle"
```
-->
The range of coordinates that a command affects
@ -90,11 +92,11 @@ record Range (rows, cols : Nat) where
top_left, bottom_right : Coord rows cols
```
```idris hide
<!-- idris
Show (Range rows cols) where
show (MkRange top_left bottom_right) =
"\{show top_left} -> \{show bottom_right}"
```
-->
Helper function to extract a range of values from our Grid.
@ -119,11 +121,11 @@ record Command (rows, cols : Nat) where
range : Range rows cols
```
```idris hide
<!-- idris
Show (Command rows cols) where
show (MkCmd action range) =
"{\{show action}: \{show range}}"
```
-->
### Parsing
@ -334,8 +336,8 @@ part2 commands = do
pure brightness
```
```idris hide
<!-- idris
public export
day6 : Day
day6 = Both 6 part1 part2
```
-->

View file

@ -1,4 +1,6 @@
# [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.
@ -13,13 +15,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 hide
<!-- idris
module Years.Y2015.Day7
import Control.Eff
import Runner
```
-->
```idris
import Data.Bits
@ -31,9 +33,9 @@ import Data.SortedMap.Dependent
import Decidable.Equality
```
```idris hide
<!-- idris
%default total
```
-->
## Parsing and data structures
@ -252,8 +254,8 @@ part2 (circut, value) = do
pure value
```
```idris hide
<!-- idris
public export covering
day7 : Day
day7 = Both 7 part1 part2
```
-->

View file

@ -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 hide
<!-- idris
module Years.Y2015.Day8
import Control.Eff
@ -11,7 +11,7 @@ import Control.Eff
import Data.Primitives.Interpolation
import Runner
```
-->
```idris
import Data.String
@ -344,8 +344,8 @@ part2 inputs = do
pure difference
```
```idris hide
<!-- idris
public export
day8 : Day
day8 = Both 8 part1 part2
```
-->

View file

@ -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 hide
<!-- idris
module Years.Y2015.Day9
import Control.Eff
import Runner
```
-->
```idris
import Data.String
@ -70,10 +70,10 @@ DistanceMap : Type
DistanceMap = SortedMap Location (List LP)
```
```idris hide
<!-- idris
Show l => Show (LocationPair l) where
show (MkLP [x, y] distance) = "\{show x} <-> \{show y}: \{show distance}"
```
-->
Perform simple, pattern matching based parsing of a location pair.
@ -287,8 +287,8 @@ part2 (distance_map, pairs) = do
pure len
```
```idris hide
<!-- idris
public export
day9 : Day
day9 = Both 9 part1 part2
```
-->