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/*.o
support/advent-support support/advent-support
tmp/ tmp/
book/
index.html

View file

@ -6,9 +6,6 @@ Idris files.
## Authors Note ## 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 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 order, though can reasonably be read in any order if you have a good level of
familiarity with more advanced functional programming topics. 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 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 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: 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 ## 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 import Control.WellFounded
``` ```
```idris hide <!-- idris
import System import System
``` -->
```idris ```idris
%default total %default total
@ -89,9 +89,9 @@ Iterable (LazyList a) a where
## Immutable arrays ## Immutable arrays
```idris hide <!-- idris
namespace Immutable namespace Immutable
``` -->
Immutable arrays created from vectors that provide constant time indexing and Immutable arrays created from vectors that provide constant time indexing and
slicing operations. slicing operations.

View file

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

View file

@ -27,7 +27,7 @@ data ParseError : Type where
-> (rest : List ParseError) -> ParseError -> (rest : List ParseError) -> ParseError
``` ```
```idris hide <!-- idris
export export
Show ParseError where Show ParseError where
show (MkParseError state message) = show (MkParseError state message) =
@ -44,7 +44,7 @@ Show ParseError where
position = show state.position.index position = show state.position.index
first = "Error at line \{line}, column \{col} (\{position}): \{message}" first = "Error at line \{line}, column \{col} (\{position}): \{message}"
in "\{first}\n\{rest}" in "\{first}\n\{rest}"
``` -->
## Type Alias ## Type Alias
@ -219,23 +219,23 @@ Lift a parser producing a `List` or `List1` of `Char` into a parser producing a
```idris ```idris
-- TODO: Rename these -- TODO: Rename these
export export
liftString : Parser (List Char) -> Parser String parseString : Parser (List Char) -> Parser String
liftString x = do parseString x = do
xs <- x xs <- x
pure $ pack xs pure $ pack xs
export export
liftString' : Parser (List1 Char) -> Parser String parseString' : Parser (List1 Char) -> Parser String
liftString' x = liftString $ map forget x parseString' x = parseString $ map forget x
``` ```
Attempt to parse a specified character Attempt to parse a specified character
```idris ```idris
export export
charExact : Char -> Parser Char parseExactChar : Char -> Parser Char
charExact c = do parseExactChar c = do
result <- charExact' c result <- parseExactChar' c
case result of case result of
GotChar char => pure char GotChar char => pure char
GotError err => throwParseError "Got \{show err} Expected \{show c}" GotError err => throwParseError "Got \{show err} Expected \{show c}"
@ -246,10 +246,10 @@ Attempt to parse one of a list of chars
```idris ```idris
export export
theseChars : List Char -> Parser Char parseTheseChars : List Char -> Parser Char
theseChars cs = do parseTheseChars cs = do
pnote "Parsing one of: \{show cs}" pnote "Parsing one of: \{show cs}"
result <- charPredicate (\x => any (== x) cs) result <- parseChar (\x => any (== x) cs)
case result of case result of
GotChar char => pure char GotChar char => pure char
GotError err => throwParseError "Got \{show err} Expected one of \{show cs}" GotError err => throwParseError "Got \{show err} Expected one of \{show cs}"
@ -267,7 +267,7 @@ exactString str with (asList str)
pure "" pure ""
exactString input@(strCons c str) | (c :: x) = do exactString input@(strCons c str) | (c :: x) = do
pnote "Parsing exact string \{show input}" pnote "Parsing exact string \{show input}"
GotChar next <- charPredicate (== c) GotChar next <- parseChar (== c)
| GotError err => throwParseError "Got \{show err} expected \{show c}" | GotError err => throwParseError "Got \{show err} expected \{show c}"
| EndOfInput => throwParseError "End of input" | EndOfInput => throwParseError "End of input"
rest <- exactString str | x rest <- exactString str | x
@ -282,12 +282,12 @@ delimited : (before, after : Char) -> Parser a -> Parser a
delimited before after x = do delimited before after x = do
pnote "Parsing delimited by \{show before} \{show after}" pnote "Parsing delimited by \{show before} \{show after}"
starting_state <- save starting_state <- save
_ <- charExact before _ <- parseExactChar before
Right val <- tryEither x Right val <- tryEither x
| Left err => do | Left err => do
load starting_state load starting_state
throw err throw err
Just _ <- tryMaybe $ charExact after Just _ <- tryMaybe $ parseExactChar after
| _ => do | _ => do
load starting_state load starting_state
throw $ MkParseError starting_state "Unmatched delimiter \{show before}" throw $ MkParseError starting_state "Unmatched delimiter \{show before}"

View file

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

View file

@ -9,9 +9,9 @@ import Data.Vect
import Control.Eff import Control.Eff
``` ```
```idris hide <!-- idris
import System import System
``` -->
## Base Abstraction ## Base Abstraction
@ -63,7 +63,7 @@ nat b = do
where where
parseDigit : Parser Nat parseDigit : Parser Nat
parseDigit = do parseDigit = do
GotChar char <- charPredicate (hasDigit b) GotChar char <- parseChar (hasDigit b)
| GotError e => throwParseError "\{show e} is not a digit" | GotError e => throwParseError "\{show e} is not a digit"
| EndOfInput => throwParseError "End Of Input" | EndOfInput => throwParseError "End Of Input"
case digitValue b char of case digitValue b char of
@ -82,7 +82,7 @@ natBase10 = nat base10
export export
integer : Base -> Parser Integer integer : Base -> Parser Integer
integer b = do integer b = do
negative <- map isJust . tryMaybe $ charExact '-' negative <- map isJust . tryMaybe $ parseExactChar '-'
value <- map natToInteger $ nat b value <- map natToInteger $ nat b
if negative if negative
then pure $ negate value then pure $ negate value
@ -120,13 +120,13 @@ double = do
where where
parseDigit : Parser Char parseDigit : Parser Char
parseDigit = do parseDigit = do
GotChar char <- charPredicate (hasDigit base10) GotChar char <- parseChar (hasDigit base10)
| GotError e => throwParseError "\{show e} is not a digit" | GotError e => throwParseError "\{show e} is not a digit"
| EndOfInput => throwParseError "End Of Input" | EndOfInput => throwParseError "End Of Input"
pure char pure char
integer : Parser String integer : Parser String
integer = do integer = do
sign <- tryMaybe $ charExact '-' sign <- tryMaybe $ parseExactChar '-'
error <- replaceError "Expected digit" error <- replaceError "Expected digit"
digits <- map forget $ atLeastOne error parseDigit digits <- map forget $ atLeastOne error parseDigit
case sign of case sign of
@ -134,14 +134,14 @@ double = do
Just x => pure $ pack (x :: digits) Just x => pure $ pack (x :: digits)
fraction : Parser String fraction : Parser String
fraction = do fraction = do
decimal <- charExact '.' decimal <- parseExactChar '.'
error <- replaceError "Expected digit" error <- replaceError "Expected digit"
digits <- map forget $ atLeastOne error parseDigit digits <- map forget $ atLeastOne error parseDigit
pure $ pack digits pure $ pack digits
exponent : Parser String exponent : Parser String
exponent = do exponent = do
e <- theseChars ['e', 'E'] e <- parseTheseChars ['e', 'E']
sign <- theseChars ['+', '-'] sign <- parseTheseChars ['+', '-']
error <- replaceError "Expected digit" error <- replaceError "Expected digit"
digits <- map forget $ atLeastOne error parseDigit digits <- map forget $ atLeastOne error parseDigit
pure . pack $ sign :: digits pure . pack $ sign :: digits

View file

@ -51,7 +51,7 @@ record Index (length : Int64) where
{auto 0 prf : IsIndex length index} {auto 0 prf : IsIndex length index}
``` ```
```idris hide <!-- idris
export export
Eq (Index i) where Eq (Index i) where
x == y = x.index == y.index x == y = x.index == y.index
@ -63,7 +63,7 @@ Ord (Index i) where
export export
Show (Index i) where Show (Index i) where
show (MkIndex index) = show index show (MkIndex index) = show index
``` -->
Stores the location we are currently at in the string, and metadata about it for 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 providing good error messages. Parsing an empty input isn't very interesting, so
@ -156,7 +156,7 @@ positionPair pi =
in (linum, col) in (linum, col)
``` ```
```idris hide <!-- idris
export export
Show (ParserInternal Id) where Show (ParserInternal Id) where
show pi = show pi =
@ -165,7 +165,7 @@ Show (ParserInternal Id) where
pos = pi.position.index pos = pi.position.index
eof = show pi.end_of_input eof = show pi.end_of_input
in "Position: \{pos}(\{line}, \{col}}) Value: \{show current} EoF: \{eof}" in "Position: \{pos}(\{line}, \{col}}) Value: \{show current} EoF: \{eof}"
``` -->
### More Barbie Functionality ### More Barbie Functionality
@ -216,7 +216,7 @@ data ParserState : Type -> Type where
Note : Lazy String -> ParserState () Note : Lazy String -> ParserState ()
``` ```
```idris hide <!-- idris
Show (ParserState t) where Show (ParserState t) where
show Save = "Saving state" show Save = "Saving state"
show (Load pi) = "Loading state \{show pi}" show (Load pi) = "Loading state \{show pi}"
@ -224,7 +224,7 @@ Show (ParserState t) where
show (ParseExactChar char) = "Parsing char \{show char}" show (ParseExactChar char) = "Parsing char \{show char}"
show ParseEoF = "Parsing EoF" show ParseEoF = "Parsing EoF"
show (Note _) = "Note" show (Note _) = "Note"
``` -->
### Actions ### Actions
@ -243,14 +243,14 @@ load pi = send $ Load pi
||| predicate, updates the state if parsing succeeds, does not alter it in an ||| predicate, updates the state if parsing succeeds, does not alter it in an
||| error condition. ||| error condition.
export export
charPredicate : Has ParserState fs => (predicate : Char -> Bool) parseChar : Has ParserState fs => (predicate : Char -> Bool)
-> Eff fs ParseCharResult -> Eff fs ParseCharResult
charPredicate predicate = send $ ParseChar predicate parseChar predicate = send $ ParseChar predicate
||| Parse a char by exact value ||| Parse a char by exact value
export export
charExact' : Has ParserState fs => (chr : Char) -> Eff fs ParseCharResult parseExactChar' : Has ParserState fs => (chr : Char) -> Eff fs ParseCharResult
charExact' chr = send $ ParseExactChar chr parseExactChar' chr = send $ ParseExactChar chr
||| "Parse" the end of input, returning `True` if the parser state is currently ||| "Parse" the end of input, returning `True` if the parser state is currently
||| at the end of the input ||| at the end of the input
@ -366,4 +366,4 @@ runParserState s =
## Footnotes ## 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 ## Either
```idris hide <!-- idris
namespace Either namespace Either
``` -->
### mapLeft ### mapLeft
@ -47,9 +47,9 @@ Applies a function to the contents of a `Left` if the value of the given
## List ## List
```idris hide <!-- idris
namespace List namespace List
``` -->
### contains ### contains
@ -94,12 +94,12 @@ Define some operations for pairs of numbers, treating them roughly like vectors
### Addition and Subtraction ### Addition and Subtraction
```idris hide <!-- idris
export infixl 8 >+< export infixl 8 >+<
export infixl 8 >-< export infixl 8 >-<
namespace Pair namespace Pair
``` -->
```idris ```idris
public export public export
@ -115,9 +115,9 @@ namespace Pair
Extend `Data.SortedSet` Extend `Data.SortedSet`
```idris hide <!-- idris
namespace Set namespace Set
``` -->
### length ### length
@ -133,9 +133,9 @@ Count the number of elements in a sorted set
Extend `Data.String` Extend `Data.String`
```idris hide <!-- idris
namespace String namespace String
``` -->
### isSubstr ### isSubstr

View file

@ -6,11 +6,11 @@ module Util.Digits
import Data.Monoid.Exponentiation import Data.Monoid.Exponentiation
``` ```
```idris hide <!-- idris
import System import System
%default total %default total
``` -->
This module provides views and associated functionality for treating `Integers` This module provides views and associated functionality for treating `Integers`
as if they were lists of numbers. 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 [prim](https://github.com/stefan-hoeck/idris2-prim) if you find yourself needing
to prove properties about primitive types. to prove properties about primitive types.
```idris hide <!-- idris
-- This mutual block isn't strictly required, but is useful for literate purposes -- This mutual block isn't strictly required, but is useful for literate purposes
mutual mutual
``` -->
## Primitive functionality ## Primitive functionality
@ -50,14 +50,14 @@ most significant digit.
For a clarifying example: For a clarifying example:
```idris hide <!-- idris
-- @@test Ascending Digits Example -- @@test Ascending Digits Example
ascendingExample : IO Bool ascendingExample : IO Bool
ascendingExample = do ascendingExample = do
putStrLn "Expecting: \{show [5, 4, 3, 2, 1]}" putStrLn "Expecting: \{show [5, 4, 3, 2, 1]}"
putStrLn "Got: \{show . ascList $ ascending 12345}" putStrLn "Got: \{show . ascList $ ascending 12345}"
pure $ pure $
``` -->
```idris ```idris
ascList (ascending 12345) == [5, 4, 3, 2, 1] ascList (ascending 12345) == [5, 4, 3, 2, 1]
@ -121,14 +121,14 @@ least significant digit.
For a clarifying example: For a clarifying example:
```idris hide <!-- idris
-- @@test Descending Digits Example -- @@test Descending Digits Example
descendingExample : IO Bool descendingExample : IO Bool
descendingExample = do descendingExample = do
putStrLn "Expecting: \{show [1, 2, 3, 4, 5]}" putStrLn "Expecting: \{show [1, 2, 3, 4, 5]}"
putStrLn "Got: \{show . decList $ descending 12345}" putStrLn "Got: \{show . decList $ descending 12345}"
pure $ pure $
``` -->
```idris ```idris
decList (descending 12345) == [1, 2, 3, 4, 5] 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 Other : (n : Nat) -> {auto _ : n `GT` 4} -> Level
``` ```
```idris hide <!-- idris
export export
levelToNat : Level -> Nat levelToNat : Level -> Nat
levelToNat Err = 0 levelToNat Err = 0
@ -67,7 +67,7 @@ export infixl 8 >+
export export
(>+) : Level -> Nat -> Level (>+) : Level -> Nat -> Level
(>+) x k = natToLevel (k + levelToNat x) (>+) x k = natToLevel (k + levelToNat x)
``` -->
Convert a `Level` into a colorized tag Convert a `Level` into a colorized tag

View file

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

View file

@ -3,7 +3,7 @@
Pretty simple, basic warmup problem, nothing really novel is on display here Pretty simple, basic warmup problem, nothing really novel is on display here
except the effectful part computations. except the effectful part computations.
```idris hide <!-- idris
module Years.Y2015.Day1 module Years.Y2015.Day1
import Control.Eff import Control.Eff
@ -11,7 +11,7 @@ import Control.Eff
import Runner import Runner
%default total %default total
``` -->
## Solver Functions ## Solver Functions
@ -76,8 +76,8 @@ part2 x = do
pure $ findBasement 1 0 input pure $ findBasement 1 0 input
``` ```
```idris hide <!-- idris
public export public export
day1 : Day day1 : Day
day1 = Both 1 part1 part2 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 This day doesn't really add anything new, but we will show off our new views for
viewing integers as lists of digits. viewing integers as lists of digits.
```idris hide <!-- idris
module Years.Y2015.Day10 module Years.Y2015.Day10
import Control.Eff import Control.Eff
import Runner import Runner
``` -->
```idris ```idris
import Data.String import Data.String
@ -22,9 +22,9 @@ import Util
import Util.Digits import Util.Digits
``` ```
```idris hide <!-- idris
%default total %default total
``` -->
# Solver Functions # Solver Functions
@ -118,8 +118,8 @@ part2 digits = do
pure $ count (const True) output pure $ count (const True) output
``` ```
```idris hide <!-- idris
public export public export
day10 : Day day10 : Day
day10 = Both 10 part1 part2 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 for this module, we will be using the `refined`[^1] library's implementation for
the sake of getting on with it. the sake of getting on with it.
```idris hide <!-- idris
module Years.Y2015.Day11 module Years.Y2015.Day11
import Control.Eff import Control.Eff
import Runner import Runner
``` -->
```idris ```idris
import Data.Vect import Data.Vect
@ -55,13 +55,13 @@ record PasswordChar where
%name PasswordChar pc %name PasswordChar pc
``` ```
```idris hide <!-- idris
Show PasswordChar where Show PasswordChar where
show (MkPC char) = singleton char show (MkPC char) = singleton char
Eq PasswordChar where Eq PasswordChar where
x == y = x.char == y.char x == y = x.char == y.char
``` -->
A function to fallible convert `Char`s into refined `PasswordChar`s, this will A function to fallible convert `Char`s into refined `PasswordChar`s, this will
return `Just` if the `Char` satisfies the predicate, and `Nothing` otherwise, return `Just` if the `Char` satisfies the predicate, and `Nothing` otherwise,
@ -227,12 +227,12 @@ part2 password = do
pure $ passwordToString next_password pure $ passwordToString next_password
``` ```
```idris hide <!-- idris
public export public export
day11 : Day day11 : Day
day11 = Both 11 part1 part2 day11 = Both 11 part1 part2
``` -->
## References ## 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 This day provides us our first little taste of effectful parsing
```idris hide <!-- idris
module Years.Y2015.Day2 module Years.Y2015.Day2
import Control.Eff import Control.Eff
import Runner import Runner
``` -->
```idris ```idris
import Data.List import Data.List
@ -16,9 +16,9 @@ import Data.List1
import Data.String import Data.String
``` ```
```idris hide <!-- idris
%default total %default total
``` -->
## Box structure ## Box structure
@ -130,8 +130,8 @@ part2 : (boxes : List Box) -> Eff (PartEff String) Integer
part2 boxes = pure . sum . map totalRibbon $ boxes part2 boxes = pure . sum . map totalRibbon $ boxes
``` ```
```idris hide <!-- idris
public export public export
day2 : Day day2 : Day
day2 = Both 2 part1 part2 day2 = Both 2 part1 part2
``` -->

View file

@ -3,13 +3,13 @@
This day provides a gentle introduction to `mutual` blocks and mutually This day provides a gentle introduction to `mutual` blocks and mutually
recursive functions. recursive functions.
```idris hide <!-- idris
module Years.Y2015.Day3 module Years.Y2015.Day3
import Control.Eff import Control.Eff
import Runner import Runner
``` -->
```idris ```idris
import Data.SortedSet import Data.SortedSet
@ -18,9 +18,9 @@ import Data.String
import Util import Util
``` ```
```idris hide <!-- idris
%default total %default total
``` -->
## Parsing and data structures ## Parsing and data structures
@ -152,8 +152,8 @@ part2 movements = do
pure . length $ locations pure . length $ locations
``` ```
```idris hide <!-- idris
public export public export
day3 : Day day3 : Day
day3 = Both 3 part1 part2 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 This day introduces us to a little bit of FFI, linking to openssl to use it's
`MD5` functionality. `MD5` functionality.
```idris hide <!-- idris
module Years.Y2015.Day4 module Years.Y2015.Day4
import Control.Eff import Control.Eff
import Runner import Runner
``` -->
```idris ```idris
import Data.String import Data.String
@ -196,8 +196,8 @@ part2 seed = do
pure number pure number
``` ```
```idris hide <!-- idris
public export public export
day4 : Day day4 : Day
day4 = Both 4 part1 part2 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) [`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. view, which lets us treat `String`s as if they were lazy lists or iterators.
```idris hide <!-- idris
module Years.Y2015.Day5 module Years.Y2015.Day5
import Control.Eff import Control.Eff
import Runner import Runner
``` -->
```idris ```idris
import Data.String import Data.String
@ -20,9 +20,9 @@ import Data.String
import Util import Util
``` ```
```idris hide <!-- idris
%default total %default total
``` -->
## Nice Strings ## Nice Strings
@ -213,8 +213,8 @@ part2 _ = do
pure x pure x
``` ```
```idris hide <!-- idris
public export public export
day5 : Day day5 : Day
day5 = Both 5 part1 part2 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. Introduction to the advent of code classic 2d grid problem.
```idris hide <!-- idris
module Years.Y2015.Day6 module Years.Y2015.Day6
import Control.Eff import Control.Eff
import Runner import Runner
``` -->
```idris ```idris
import Util import Util
@ -21,9 +23,9 @@ import Data.String
import Data.IORef import Data.IORef
``` ```
```idris hide <!-- idris
%default total %default total
``` -->
## Parsing and data structures ## 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 data Action = On | Off | Toggle
``` ```
```idris hide <!-- idris
Show Action where Show Action where
show On = "on" show On = "on"
show Off = "off" show Off = "off"
show Toggle = "toggle" show Toggle = "toggle"
``` -->
The range of coordinates that a command affects 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 top_left, bottom_right : Coord rows cols
``` ```
```idris hide <!-- idris
Show (Range rows cols) where Show (Range rows cols) where
show (MkRange top_left bottom_right) = show (MkRange top_left bottom_right) =
"\{show top_left} -> \{show bottom_right}" "\{show top_left} -> \{show bottom_right}"
``` -->
Helper function to extract a range of values from our Grid. 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 range : Range rows cols
``` ```
```idris hide <!-- idris
Show (Command rows cols) where Show (Command rows cols) where
show (MkCmd action range) = show (MkCmd action range) =
"{\{show action}: \{show range}}" "{\{show action}: \{show range}}"
``` -->
### Parsing ### Parsing
@ -334,8 +336,8 @@ part2 commands = do
pure brightness pure brightness
``` ```
```idris hide <!-- idris
public export public export
day6 : Day day6 : Day
day6 = Both 6 part1 part2 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. 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 through throwing a runtime error in the parsing function if a second gate
outputting to a given wire is found in the input. outputting to a given wire is found in the input.
```idris hide <!-- idris
module Years.Y2015.Day7 module Years.Y2015.Day7
import Control.Eff import Control.Eff
import Runner import Runner
``` -->
```idris ```idris
import Data.Bits import Data.Bits
@ -31,9 +33,9 @@ import Data.SortedMap.Dependent
import Decidable.Equality import Decidable.Equality
``` ```
```idris hide <!-- idris
%default total %default total
``` -->
## Parsing and data structures ## Parsing and data structures
@ -252,8 +254,8 @@ part2 (circut, value) = do
pure value pure value
``` ```
```idris hide <!-- idris
public export covering public export covering
day7 : Day day7 : Day
day7 = Both 7 part1 part2 day7 = Both 7 part1 part2
``` -->

View file

@ -3,7 +3,7 @@
This day provides a more in depth introduction to writing effectful parsers, This day provides a more in depth introduction to writing effectful parsers,
making use of state and non-determinism in our parsers. making use of state and non-determinism in our parsers.
```idris hide <!-- idris
module Years.Y2015.Day8 module Years.Y2015.Day8
import Control.Eff import Control.Eff
@ -11,7 +11,7 @@ import Control.Eff
import Data.Primitives.Interpolation import Data.Primitives.Interpolation
import Runner import Runner
``` -->
```idris ```idris
import Data.String import Data.String
@ -344,8 +344,8 @@ part2 inputs = do
pure difference pure difference
``` ```
```idris hide <!-- idris
public export public export
day8 : Day day8 : Day
day8 = Both 8 part1 part2 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 This isn't a particularly efficient solution, but its good enough for this small
problem size. problem size.
```idris hide <!-- idris
module Years.Y2015.Day9 module Years.Y2015.Day9
import Control.Eff import Control.Eff
import Runner import Runner
``` -->
```idris ```idris
import Data.String import Data.String
@ -70,10 +70,10 @@ DistanceMap : Type
DistanceMap = SortedMap Location (List LP) DistanceMap = SortedMap Location (List LP)
``` ```
```idris hide <!-- idris
Show l => Show (LocationPair l) where Show l => Show (LocationPair l) where
show (MkLP [x, y] distance) = "\{show x} <-> \{show y}: \{show distance}" show (MkLP [x, y] distance) = "\{show x} <-> \{show y}: \{show distance}"
``` -->
Perform simple, pattern matching based parsing of a location pair. Perform simple, pattern matching based parsing of a location pair.
@ -287,8 +287,8 @@ part2 (distance_map, pairs) = do
pure len pure len
``` ```
```idris hide <!-- idris
public export public export
day9 : Day day9 : Day
day9 = Both 9 part1 part2 day9 = Both 9 part1 part2
``` -->