Reformat markdown
This commit is contained in:
parent
5a313c952f
commit
b0e7c1aa91
14 changed files with 459 additions and 188 deletions
|
@ -1,6 +1,7 @@
|
|||
# Year 2015 Day 3
|
||||
|
||||
This day provides a gentle introduction to `mutual` blocks and mutually recursive functions.
|
||||
This day provides a gentle introduction to `mutual` blocks and mutually
|
||||
recursive functions.
|
||||
|
||||
<!-- idris
|
||||
module Years.Y2015.Day3
|
||||
|
@ -23,13 +24,16 @@ import Util
|
|||
|
||||
## Parsing and data structures
|
||||
|
||||
We'll do parsing a little more properly this time, turning the input into a list of movement commands
|
||||
We'll do parsing a little more properly this time, turning the input into a list
|
||||
of movement commands
|
||||
|
||||
```idris
|
||||
data Movement = North | East | South | West
|
||||
```
|
||||
|
||||
We need an effectful operation to parse a single char into a movement. We'll pattern match on the char, and include a catch-all case that throws an error in the event of an invalid char
|
||||
We need an effectful operation to parse a single char into a movement. We'll
|
||||
pattern match on the char, and include a catch-all case that throws an error in
|
||||
the event of an invalid char
|
||||
|
||||
```idris
|
||||
parseMovement : Has (Except String) fs => (x : Char) -> Eff fs Movement
|
||||
|
@ -40,7 +44,9 @@ parseMovement '<' = pure West
|
|||
parseMovement x = throw "Invalid Movement: \{show x}"
|
||||
```
|
||||
|
||||
We also need to be able to translate a `Movement` into a vector of length one pointing in the given direction in coordinate space. Somewhat arbitrarily, we chose 'North' to be positive x and 'East' to be positive y.
|
||||
We also need to be able to translate a `Movement` into a vector of length one
|
||||
pointing in the given direction in coordinate space. Somewhat arbitrarily, we
|
||||
chose 'North' to be positive x and 'East' to be positive y.
|
||||
|
||||
```idris
|
||||
vector : Movement -> (Integer, Integer)
|
||||
|
@ -54,11 +60,17 @@ vector West = (0, -1)
|
|||
|
||||
### Visited houses
|
||||
|
||||
This is a pretty simple task, we are just applying the movements to our current position, and adding our current position to the set of visited locations, so we'll handle this with a normal tail recursive function.
|
||||
This is a pretty simple task, we are just applying the movements to our current
|
||||
position, and adding our current position to the set of visited locations, so
|
||||
we'll handle this with a normal tail recursive function.
|
||||
|
||||
To keep the api nice, we wont ask for the set or the starting location in the top-level function, and instead have the top level function initialize the set and location before passing control to the inner tail-recursive variant.
|
||||
To keep the api nice, we wont ask for the set or the starting location in the
|
||||
top-level function, and instead have the top level function initialize the set
|
||||
and location before passing control to the inner tail-recursive variant.
|
||||
|
||||
Because the starting location gets a present, we'll add our location to the set before performing the movement, so we will need to add our final location to the set in the recursive base case.
|
||||
Because the starting location gets a present, we'll add our location to the set
|
||||
before performing the movement, so we will need to add our final location to the
|
||||
set in the recursive base case.
|
||||
|
||||
```idris
|
||||
visitedLocations : List Movement -> SortedSet (Integer, Integer)
|
||||
|
@ -73,13 +85,26 @@ visitedLocations xs = visitor xs empty (0, 0)
|
|||
|
||||
### Robo Santa
|
||||
|
||||
This one gets a bit more interesting, we'll adopt the same tail recursive approach, but instead use a `mutual` block and two mutually recursive functions to handle the alternation between santa and robo santa. The `visitSanta` function will pass control to `visitRobo` after executing its movement, and vise versa.
|
||||
This one gets a bit more interesting, we'll adopt the same tail recursive
|
||||
approach, but instead use a `mutual` block and two mutually recursive functions
|
||||
to handle the alternation between santa and robo santa. The `visitSanta`
|
||||
function will pass control to `visitRobo` after executing its movement, and vise
|
||||
versa.
|
||||
|
||||
We'll want to insert both present deliverer's locations in the recursive base case, this may result in a duplicate location, but that's okay because `SortedSet` will only hold at most one of each item inserted into it.
|
||||
We'll want to insert both present deliverer's locations in the recursive base
|
||||
case, this may result in a duplicate location, but that's okay because
|
||||
`SortedSet` will only hold at most one of each item inserted into it.
|
||||
|
||||
In idris, there is a general requirement that values be defined before their use, a common feature of dependently typed languages, resulting from the fact that just having the type signature of a function/value alone is not always enough to perform type checking, as functions can appear as part of types, requiring evaluation of the function and making automatic dependency analysis effectively impossible.
|
||||
In idris, there is a general requirement that values be defined before their
|
||||
use, a common feature of dependently typed languages, resulting from the fact
|
||||
that just having the type signature of a function/value alone is not always
|
||||
enough to perform type checking, as functions can appear as part of types,
|
||||
requiring evaluation of the function and making automatic dependency analysis
|
||||
effectively impossible.
|
||||
|
||||
Inside a `mutual` block, elaboration behaves differently, elaborating types first and then values in separate passes. This restricts what you can do a little, but enables mutually recursive functions.
|
||||
Inside a `mutual` block, elaboration behaves differently, elaborating types
|
||||
first and then values in separate passes. This restricts what you can do a
|
||||
little, but enables mutually recursive functions.
|
||||
|
||||
```idris
|
||||
visitedLocations' : List Movement -> SortedSet (Integer, Integer)
|
||||
|
@ -103,7 +128,9 @@ visitedLocations' xs = visitSanta xs empty (0, 0) (0, 0)
|
|||
|
||||
### Part 1
|
||||
|
||||
Similar to the previous day, we get our input, unpack it, and traverse our effectful movement parsing function over it, before feeding that into our solving function.
|
||||
Similar to the previous day, we get our input, unpack it, and traverse our
|
||||
effectful movement parsing function over it, before feeding that into our
|
||||
solving function.
|
||||
|
||||
```idris
|
||||
part1 : Eff (PartEff String) (Nat, List Movement)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue