Racket solutions & explanations for the Advent of Code puzzles
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
aoc-racket/day12.rkt

86 lines
2.8 KiB

#lang scribble/lp2
@(require scribble/manual aoc-racket/helper)
@aoc-title[12]
@defmodule[aoc-racket/day12]
@link["http://adventofcode.com/day/12"]{The puzzle}. Our @link-rp["day12-input.txt"]{input} is, unfortunately, a @link["http://json.org/"]{JSON} file.
@chunk[<day12>
<day12-setup>
<day12-q1>
<day12-q2>
<day12-test>]
@isection{What's the sum of all the numbers in the document?}
I've never liked JavaScript, and spending more time with Racket has only deepened my antipathy. So I apologize if this solution is terse.
We need to parse the JSON file, extract the numbers, and add them.
To parse the file we'll use the @iracket[read-json] function from Racket's @racketmodname[json] library. This function converts the JSON into a JS-expression (see @iracket[jsexpr?]), which is a recursively nested data structure. If we had a simple recursively nested list, we could just @iracket[flatten] it and filter for the numbers. We'll do something similar here  recursively flatten the JS-expression and pull out the numbers.
If you're new to Racket, notice the @italic{recursive descent} pattern used in @racket[flatten-jsexpr]  it's a very common way of handling recursively structured data.
@chunk[<day12-setup>
(require racket rackunit json)
(provide (all-defined-out))
(define (string->jsexpr str)
(read-json (open-input-string str)))
]
@chunk[<day12-q1>
(define (flatten-jsexpr jsexpr)
(flatten
(let loop ([x jsexpr])
(cond
[(list? x)
(map loop x)]
[(hash? x)
(loop (flatten (hash->list x)))]
[else x]))))
(define (q1 input-str)
(define json-items (flatten-jsexpr (string->jsexpr input-str)))
(apply + (filter number? json-items)))]
@section{What's the sum of all the numbers, if hash tables with value @racket{red} are ignored?}
We'll just update our flattening function to skip over hash tables that have @racket{red} among the values.
@chunk[<day12-q2>
(define (flatten-jsexpr-2 jsexpr)
(flatten
(let loop ([x jsexpr])
(cond
[(list? x)
(map loop x)]
[(hash? x)
(if (member "red" (hash-values x))
empty
(loop (flatten (hash->list x))))]
[else x]))))
(define (q2 input-str)
(define json-items (flatten-jsexpr-2 (string->jsexpr input-str)))
(apply + (filter number? json-items))) ]
@section{Testing Day 12}
@chunk[<day12-test>
(module+ test
(define input-str (file->string "day12-input.txt"))
(check-equal? (q1 input-str) 191164)
(check-equal? (q2 input-str) 87842))]