From 3569b6bccb62f8227c2438d8cd5d854ea772f81c Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Sat, 2 Jan 2016 15:55:29 -0800 Subject: [PATCH] rkt-ize --- aoc-racket.scrbl | 32 ++++++++++++++++++-------------- day1.scrbl => day1.rkt | 21 +++++++-------------- day10.scrbl => day10.rkt | 3 +++ day11.scrbl => day11.rkt | 3 +++ day12.scrbl => day12.rkt | 3 +++ day13.scrbl => day13.rkt | 3 +++ day2.scrbl => day2.rkt | 3 +++ day3.scrbl => day3.rkt | 3 +++ day4.scrbl => day4.rkt | 3 +++ day5.scrbl => day5.rkt | 3 +++ day6.scrbl => day6.rkt | 3 +++ day7.scrbl => day7.rkt | 3 +++ day8.scrbl => day8.rkt | 3 +++ day9.scrbl => day9.rkt | 3 +++ main.rkt | 3 +++ 15 files changed, 64 insertions(+), 28 deletions(-) rename day1.scrbl => day1.rkt (84%) rename day10.scrbl => day10.rkt (97%) rename day11.scrbl => day11.rkt (98%) rename day12.scrbl => day12.rkt (97%) rename day13.scrbl => day13.rkt (98%) rename day2.scrbl => day2.rkt (95%) rename day3.scrbl => day3.rkt (98%) rename day4.scrbl => day4.rkt (97%) rename day5.scrbl => day5.rkt (97%) rename day6.scrbl => day6.rkt (98%) rename day7.scrbl => day7.rkt (99%) rename day8.scrbl => day8.rkt (96%) rename day9.scrbl => day9.rkt (98%) create mode 100644 main.rkt diff --git a/aoc-racket.scrbl b/aoc-racket.scrbl index a48e0a7..06c4ce9 100644 --- a/aoc-racket.scrbl +++ b/aoc-racket.scrbl @@ -5,20 +5,24 @@ @author[(author+email "Matthew Butterick" "mb@mbtype.com")] -@defmodule[aoc-racket] +@defmodule[aoc-racket] + +@italic{Dedicated to curious characters everywhere, especially those learning Racket.} @local-table-of-contents[] -@include-section[(submod "day1.scrbl" doc)] -@include-section[(submod "day2.scrbl" doc)] -@include-section[(submod "day3.scrbl" doc)] -@include-section[(submod "day4.scrbl" doc)] -@include-section[(submod "day5.scrbl" doc)] -@include-section[(submod "day6.scrbl" doc)] -@include-section[(submod "day7.scrbl" doc)] -@include-section[(submod "day8.scrbl" doc)] -@include-section[(submod "day9.scrbl" doc)] -@include-section[(submod "day10.scrbl" doc)] -@include-section[(submod "day11.scrbl" doc)] -@include-section[(submod "day12.scrbl" doc)] -@include-section[(submod "day13.scrbl" doc)] \ No newline at end of file +@include-section[(submod "day1.rkt" doc)] +@include-section[(submod "day2.rkt" doc)] +@include-section[(submod "day3.rkt" doc)] +@include-section[(submod "day4.rkt" doc)] +@include-section[(submod "day5.rkt" doc)] +@include-section[(submod "day6.rkt" doc)] +@include-section[(submod "day7.rkt" doc)] +@include-section[(submod "day8.rkt" doc)] +@include-section[(submod "day9.rkt" doc)] +@include-section[(submod "day10.rkt" doc)] +@include-section[(submod "day11.rkt" doc)] +@include-section[(submod "day12.rkt" doc)] +@include-section[(submod "day13.rkt" doc)] + +@index-section[] diff --git a/day1.scrbl b/day1.rkt similarity index 84% rename from day1.scrbl rename to day1.rkt index 79e9c67..2f08774 100644 --- a/day1.scrbl +++ b/day1.rkt @@ -3,6 +3,8 @@ @aoc-title[1] +@defmodule[aoc-racket/day1] + @link["http://adventofcode.com/day/1"]{The puzzle}. Our @link-rp["day1-input.txt"]{input} is a string of parentheses that controls an elevator. A left parenthesis @litchar{(} means go up one floor, and a right parenthesis @litchar{)} means go down. @chunk[ @@ -22,6 +24,7 @@ The building has an indefinite number of floors in both directions. So the ultim @chunk[ (require racket rackunit) + (provide (all-defined-out)) (define up-char #\() (define down-char #\)) @@ -35,11 +38,7 @@ The building has an indefinite number of floors in both directions. So the ultim @chunk[ (define (q1 str) - (displayln (format "ups = ~a" (get-ups str))) - (displayln (format "downs = ~a" (get-downs str))) - (define destination (get-destination str)) - (displayln (format "destination = ~a" destination)) - destination)] + (get-destination str))] @subsection{Alternate approach: numerical conversion} @@ -53,9 +52,7 @@ Rather than counting matches with @racket[regexp-match*], we could also convert -1))) (define (q1-alt str) - (define destination (apply + (elevator-string->ints str))) - (displayln (format "destination = ~a" destination)) - destination)] + (apply + (elevator-string->ints str)))] @section[#:tag "q2"]{At what point does the elevator enter the basement?} @@ -77,15 +74,13 @@ We could characterize this as a problem of tracking @italic{cumulative values} o #:break (in-basement? movements-so-far)) (cons (get-destination (~a c)) movements-so-far))) - (define basement-position (length relative-movements)) - (displayln (format "basement entered at position = ~a" basement-position)) - basement-position)] + (length relative-movements))] @subsection{Alternate approaches: @tt{for/first} or @tt{for/or}} When you need to stop a loop the first time a condition occurs, you can also consider @racket[for/first] or @racket[for/or]. The difference is that @racket[for/first] ends after the first evaluation of the body, but @racket[for/or] evaluates the body every time, and ends the first time the body is not @racket[#f]. -The two are similar. The choice comes down to readability and efficiency — meaning, if each iteration of the loop is expensive, you probably will want to cache intermediate values, which means you might as well use @racket[for/fold]. +The two are similar. The choice comes down to readability and efficiency — meaning, if each iteration of the loop is expensive, you'll probably want to cache intermediate values, which means you might as well use @racket[for/fold]. @chunk[ (define (q2-for/first str) @@ -94,7 +89,6 @@ The two are similar. The choice comes down to readability and efficiency — me (for/first ([idx (in-range (length ints))] #:when (negative? (apply + (take ints idx)))) idx))) - (displayln (format "basement entered at position = ~a" basement-position)) basement-position) (define (q2-for/or str) @@ -102,7 +96,6 @@ The two are similar. The choice comes down to readability and efficiency — me (let ([ints (elevator-string->ints str)]) (for/or ([idx (in-range (length ints))]) (and (negative? (apply + (take ints idx))) idx)))) - (displayln (format "basement entered at position = ~a" basement-position)) basement-position)] diff --git a/day10.scrbl b/day10.rkt similarity index 97% rename from day10.scrbl rename to day10.rkt index 3d2be63..731d15c 100644 --- a/day10.scrbl +++ b/day10.rkt @@ -3,6 +3,8 @@ @aoc-title[10] +@defmodule[aoc-racket/day10] + @link["http://adventofcode.com/day/10"]{The puzzle}. Our @link-rp["day10-input.txt"]{input} is a short numeric key. @chunk[ @@ -21,6 +23,7 @@ The second part of the puzzle is just going to change the number of iterations. @chunk[ (require racket rackunit) + (provide (all-defined-out)) (define (look-and-say iterations input-key) (for/fold ([start input-key]) diff --git a/day11.scrbl b/day11.rkt similarity index 98% rename from day11.scrbl rename to day11.rkt index a14b02c..2de7b80 100644 --- a/day11.scrbl +++ b/day11.rkt @@ -3,6 +3,8 @@ @aoc-title[11] +@defmodule[aoc-racket/day11] + @link["http://adventofcode.com/day/11"]{The puzzle}. Our @link-rp["day11-input.txt"]{input} is a short alphabetic key that represents a password. @chunk[ @@ -34,6 +36,7 @@ The @racket[three-consecutive-letters?] test works by converting the letters to @chunk[ (require racket rackunit) + (provide (all-defined-out)) (define (increment-password password) (define (increment-letter c) diff --git a/day12.scrbl b/day12.rkt similarity index 97% rename from day12.scrbl rename to day12.rkt index 99f1433..e050093 100644 --- a/day12.scrbl +++ b/day12.rkt @@ -3,6 +3,8 @@ @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[ @@ -24,6 +26,7 @@ If you're new to Racket, notice the @italic{recursive descent} pattern used in @ @chunk[ (require racket rackunit json) + (provide (all-defined-out)) (define (string->jsexpr str) (read-json (open-input-string str))) diff --git a/day13.scrbl b/day13.rkt similarity index 98% rename from day13.scrbl rename to day13.rkt index 6fce99f..33434e0 100644 --- a/day13.scrbl +++ b/day13.rkt @@ -3,6 +3,8 @@ @aoc-title[13] +@defmodule[aoc-racket/day13] + @link["http://adventofcode.com/day/13"]{The puzzle}. Our @link-rp["day13-input.txt"]{input} is a list of descriptions of ``happiness units'' that would be gained or lost among eight people sitting next to each other at a dinner table. @chunk[ @@ -23,6 +25,7 @@ Those wrinkles noted, we'll proceed as we did in @secref{Day_9}. We'll parse the @chunk[ (require racket rackunit) + (provide (all-defined-out)) (define happiness-scores (make-hash)) diff --git a/day2.scrbl b/day2.rkt similarity index 95% rename from day2.scrbl rename to day2.rkt index 02c9e80..0450fea 100644 --- a/day2.scrbl +++ b/day2.rkt @@ -3,6 +3,8 @@ @aoc-title[2] +@defmodule[aoc-racket/day2] + @link["http://adventofcode.com/day/2"]{The puzzle}. Our @link-rp["day2-input.txt"]{input} is a list of strings that represent dimensions of rectangular boxes. @chunk[ @@ -22,6 +24,7 @@ Then we have a traditional setup for the devastating one-two punch of @racket[ma @chunk[ (require racket rackunit) + (provide (all-defined-out)) (define (string->boxes str) (for/list ([ln (in-list (string-split str "\n"))]) (map string->number (string-split ln "x"))))] diff --git a/day3.scrbl b/day3.rkt similarity index 98% rename from day3.scrbl rename to day3.rkt index fe26815..dc522dd 100644 --- a/day3.scrbl +++ b/day3.rkt @@ -3,6 +3,8 @@ @aoc-title[3] +@defmodule[aoc-racket/day3] + @link["http://adventofcode.com/day/3"]{The puzzle}. Our @link-rp["day3-input.txt"]{input} is a string made of the characters @litchar{^v<>} that represent north, south, west, and east. Taken together, the string represents a path through an indefinitely large grid. In essence, this a two-dimensional version of the elevator problem in @secref{Day_1}. @@ -25,6 +27,7 @@ Once the whole cell path is computed, the answer is found by removing duplicate @chunk[ (require racket rackunit) + (provide (all-defined-out)) ] @chunk[ diff --git a/day4.scrbl b/day4.rkt similarity index 97% rename from day4.scrbl rename to day4.rkt index 9768b64..8bf5d94 100644 --- a/day4.scrbl +++ b/day4.rkt @@ -4,6 +4,8 @@ @aoc-title[4] +@defmodule[aoc-racket/day4] + @link["http://adventofcode.com/day/4"]{The puzzle}. Our @link-rp["day4-input.txt"]{input} is a string of eight characters that represents part of a key for making an MD5 hash. @chunk[ @@ -21,6 +23,7 @@ Whether or not you already know what an MD5 hash is, you can search the Racket d @chunk[ (require racket rackunit openssl/md5) + (provide (all-defined-out)) ] @chunk[ diff --git a/day5.scrbl b/day5.rkt similarity index 97% rename from day5.scrbl rename to day5.rkt index f1d0fb0..e465867 100644 --- a/day5.scrbl +++ b/day5.rkt @@ -3,6 +3,8 @@ @aoc-title[5] +@defmodule[aoc-racket/day5] + @link["http://adventofcode.com/day/5"]{The puzzle}. Our @link-rp["day5-input.txt"]{input} is a list of random-looking but not really random text strings. @chunk[ @@ -26,6 +28,7 @@ This is a job for @racket[regexp-match]. There's nothing tricky here (except for @chunk[ (require racket rackunit) + (provide (all-defined-out)) ] @chunk[ diff --git a/day6.scrbl b/day6.rkt similarity index 98% rename from day6.scrbl rename to day6.rkt index 33da754..7d7f4bb 100644 --- a/day6.scrbl +++ b/day6.rkt @@ -3,6 +3,8 @@ @aoc-title[6] +@defmodule[aoc-racket/day6] + @link["http://adventofcode.com/day/6"]{The puzzle}. Our @link-rp["day6-input.txt"]{input} is a list of instructions for turning on (or off) the bulbs in a @racket[(* 1000 1000)] grid of lights. @chunk[ @@ -47,6 +49,7 @@ We'll define our functions for setting and counting the lights separately, since @chunk[ (require racket rackunit) + (provide (all-defined-out)) (define (set-lights lights arglist) (match-define (list bulb-func x1 y1 x2 y2) arglist) diff --git a/day7.scrbl b/day7.rkt similarity index 99% rename from day7.scrbl rename to day7.rkt index 7e8144c..6cd5f15 100644 --- a/day7.scrbl +++ b/day7.rkt @@ -3,6 +3,8 @@ @aoc-title[7] +@defmodule[aoc-racket/day7] + @link["http://adventofcode.com/day/7"]{The puzzle}. Our @link-rp["day7-input.txt"]{input} describes an electrical circuit, with each line of the file describing the signal provided to a particular wire. @chunk[ @@ -45,6 +47,7 @@ One gotcha when using syntax transformers is that identifiers introduced by a tr @chunk[ (require racket rackunit (for-syntax racket/base racket/file racket/string)) + (provide (all-defined-out)) (define-syntax (convert-input-to-wire-functions stx) (syntax-case stx () diff --git a/day8.scrbl b/day8.rkt similarity index 96% rename from day8.scrbl rename to day8.rkt index a9c40b0..45f0324 100644 --- a/day8.scrbl +++ b/day8.rkt @@ -3,6 +3,8 @@ @aoc-title[8] +@defmodule[aoc-racket/day8] + @link["http://adventofcode.com/day/8"]{The puzzle}. Our @link-rp["day8-input.txt"]{input} consists of a list of seemingly random strings within quotation marks. @chunk[ @@ -19,6 +21,7 @@ The literal length of the string is trivial — use @racket[string-length]. The @chunk[ (require racket rackunit) + (provide (all-defined-out)) ] @chunk[ diff --git a/day9.scrbl b/day9.rkt similarity index 98% rename from day9.scrbl rename to day9.rkt index 09e1a71..315bd8c 100644 --- a/day9.scrbl +++ b/day9.rkt @@ -3,6 +3,8 @@ @aoc-title[9] +@defmodule[aoc-racket/day9] + @link["http://adventofcode.com/day/9"]{The puzzle}. Our @link-rp["day9-input.txt"]{input} consists of a list of distances between fictional cities, e.g., @italic{AlphaCentauri to Straylight = 133}. @chunk[ @@ -23,6 +25,7 @@ In the second part, we'll loop through every possible path between the cities wi @chunk[ (require racket rackunit) + (provide (all-defined-out)) (define distances (make-hash)) diff --git a/main.rkt b/main.rkt new file mode 100644 index 0000000..b362aff --- /dev/null +++ b/main.rkt @@ -0,0 +1,3 @@ +#lang racket/base + +;; nothing at the top level \ No newline at end of file