Skip to content

Instantly share code, notes, and snippets.

@christianberg
Last active December 4, 2020 07:57
Show Gist options
  • Save christianberg/b32b1fd83b455089cecc15a19474f44a to your computer and use it in GitHub Desktop.
Save christianberg/b32b1fd83b455089cecc15a19474f44a to your computer and use it in GitHub Desktop.
Advent of Code in jq

The one-line solution for part 2 of Day 3 of Advent of Code:

jq -sR '[([1,1],[3,1],[5,1],[7,1],[1,2]) as $slope | ./"\n" | [.,([range(length)]|map(.%$slope[1]))] | transpose | map(select(.[1]==0)|.[0]) | (.[0] | length) as $w| [.,([range(0;length*$slope[0];$slope[0])]|map(.%$w))] | transpose | map(.[0][.[1]:.[1]+1] | select(.=="#")) | length] | reduce .[] as $i (1; . * $i)' < input.txt

And an annotated version. This is the same code as above, with more whitespace, longer variable names, and comments.

[
  ([1,1],[3,1],[5,1],[7,1],[1,2]) as $slope |      ## Loop through all possible slope values, assigning it to the $slope variable.
  ./"\n" |                                         ## `.` is the entire input file (because we call `jq -sR`). Here we split it into lines.
  [                                                ## Create a new array
    .,                                             ## The first element consists of the input (an array of lines).
    (                                              ## The second element is an array of flags to decide if we care about the input line.
      [range(length)] |                            ## For this we generate line numbers (from 0 to length of the input)
      map(. % $slope[1])                           ## and calculate the remainder of dividing them by the second slope element.
    )
  ] |
  transpose |                                      ## Flip the array, so we have pairs of [input_line, flag].
  map(
    select(.[1] == 0) |                            ## Keep only the lines we care about (for all but the last slope value, that's all lines)
    .[0]                                           ## and keep only the line (discarding the flag).
  ) |
  (.[0] | length) as $width |                      ## Store the width (length of first line) in $width
  [                                                ## Create a new array (again)
    .,                                             ## with the (remaining) input as first element (again).
    (                                              ## The second element is a list of indices on our path
      [range(0; length * $slope[0]; $slope[0])] |  ## calculated by starting from 0 and increasing by the first element of $slope each time
      map(. % $width)                              ## and taking the remainder of the division by width, to account for the repeating pattern.
    )
  ] |
  transpose |                                      ## Flip the array, so we have pairs of [input_line, index].
  map(
    .[0][.[1]:.[1]+1] |                            ## Now lookup the content of that grid square
    select(. == "#")                               ## and only keep it if it's a tree.
  ) |
  length                                           ## Count the remaining elements (i.e. trees) for that slope value.
] |                                                ## The square brackets collect the results for each slope in an array,
reduce .[] as $i (1; . * $i)                       ## which we finally reduce with multiplication.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment