Last active
December 11, 2016 23:15
-
-
Save kurtmilam/db400c3b127dd8b7b2a794cc61278b84 to your computer and use it in GitHub Desktop.
Advent of Code 2016, Puzzle #1: Using Ramda, doubly linked cyclical list and lenses
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Paste into the Ramda REPL at http://ramdajs.com/repl/ | |
// NESW - doubly linked list, cyclical | |
const compass = [[1, 1], [[0, 1], [[1, -1], [[0, -1]]]]] | |
compass[1][1][1][1] = compass | |
compass[1][2] = compass | |
compass[1][1][2] = compass[1] | |
compass[1][1][1][2] = compass[1][1] | |
compass[2] = compass[1][1][1] | |
const blocksLens = lensIndex( 2 ) // number of blocks to walk in current instruction | |
const compassLens = lensIndex( 3 ) // access our compass in the accumulator | |
// update the compass in the accumulator according to the direction we turned | |
const turn = | |
a => over( compassLens | |
, ifElse( always( equals( 'R', head( a ) ) ) | |
, view( lensIndex( 1 ) ) // turn right | |
, view( lensIndex( 2 ) ) // turn left | |
) | |
) | |
// shortcut to the compass value in the accumulator | |
const viewCardLens = compose( view( lensIndex( 0 ) ), view( compassLens ) ) | |
// create a lens to the x or y axis in the accumulator based on the current axis | |
const viewAxisLens = compose( lensIndex, view( lensIndex( 0 ) ), viewCardLens ) | |
// view the current compass sign (positive or negative) | |
const viewSignLens = compose( view( lensIndex( 1 ) ), viewCardLens ) | |
// add the current number of blocks * compass cardinal direction to previous blocks | |
const move = compose( add, converge( multiply, [ view( blocksLens ), viewSignLens ] ) ) | |
// update the number of blocks walked in the x or y axis | |
const setPosition = | |
a => converge( over, [ viewAxisLens, move ] )( a )( a ) | |
const go = | |
( a, v ) => compose( setPosition | |
, turn( v ) | |
, set( blocksLens, parseInt( tail( v ), 10 ) ) | |
)( a ) | |
// The accumulator is: [ x blocks, y blocks, current blocks, compass ] | |
compose( apply( ( a, b ) => add( Math.abs( a ), Math.abs( b ) ) ) | |
, take( 2 ) | |
, reduce( go, [ 0, 0, 0, compass ] ) | |
, split( ', ' ) | |
)( 'L3, R1, L4, L1, L2, R4, L3, L3, R2, R3, L5, R1, R3, L4, L1, L2, R2, R1, L4, L4, R2, L5, R3, R2, R1, L1, L2, R2, R2, L1, L1, R2, R1, L3, L5, R4, L3, R3, R3, L5, L190, L4, R4, R51, L4, R5, R5, R2, L1, L3, R1, R4, L3, R1, R3, L5, L4, R2, R5, R2, L1, L5, L1, L1, R78, L3, R2, L3, R5, L2, R2, R4, L1, L4, R1, R185, R3, L4, L1, L1, L3, R4, L4, L1, R5, L5, L1, R5, L1, R2, L5, L2, R4, R3, L2, R3, R1, L3, L5, L4, R3, L2, L4, L5, L4, R1, L1, R5, L2, R4, R2, R3, L1, L1, L4, L3, R4, L3, L5, R2, L5, L1, L1, R2, R3, L5, L3, L2, L1, L4, R4, R4, L2, R3, R1, L2, R1, L2, L2, R3, R3, L1, R4, L5, L3, R4, R4, R1, L2, L5, L3, R1, R4, L2, R5, R4, R2, L5, L3, R4, R1, L1, R5, L3, R1, R5, L2, R1, L5, L2, R2, L2, L3, R3, R3, R1' ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I packed the axis into the compass in revision 2.