This post describes my solution for Day 2 of the Advent of Code.

## Problem Description

First, the problem description (copied from the website):

**Day 2: I Was Told There Would Be No Math**

The elves are running low on wrapping paper, and so they need to submit an order for more. They have a list of the dimensions (length l, width w, and height h) of each present, and only want to order exactly as much as they need.

Fortunately, every present is a box (a perfect right rectangular prism), which makes calculating the required wrapping paper for each gift a little easier: find the surface area of the box, which is 2 x l x w + 2 x w x h + 2 x h x l. The elves also need a little extra paper for each present: the area of the smallest side.

For example:

- A present with dimensions 2x3x4 requires 2 x 6 + 2 x 12 + 2 x 8 = 52 square feet of wrapping paper plus 6 square feet of slack, for a total of 58 square feet.

- A present with dimensions 1x1x10 requires 2 x 1 + 2 x 10 + 2 x 10 = 42 square feet of wrapping paper plus 1 square foot of slack, for a total of 43 square feet.

All numbers in the elves’ list are in feet. How many total square feet of wrapping paper should they order?

## Solution

Once again, we’ll be working in Scheme.

For this problem, I decided to create a “box” data type. In addition to the automatically generated accessors (thanks SRFI-9!), I wrote several procedures to perform calculations on boxes, namely:

`SURFACE-AREA`

: Calculate the box’s surface area.`SMALLEST-SIDE`

: Determine which of the box’s sides has the smallest surface area (the extra material makes it easier to wrap).

`WRAPPING-PAPER`

is just a “wrapper” (pun intended) around the first two.

`LINE->BOX`

, `READ-BOXES`

, and `SUM-BOXES`

are all about parsing the input file contents and shuffling them into the box data type that we use to do the actual calculation. The only part that required a bit of thought was the line with `STRING-TOKENIZE`

in `LINE->BOX`

. In Perl I’d use `my @params = split /x/, $line`

without even thinking, but I was less familiar with Scheme’s facility for solving this problem, so it took a few minutes to puzzle out the right part of Scheme’s “API”. (`STRING-TOKENIZE`

was helpfully provided by SRFI-13.)

Abstract data types FTW! I’ll be using them more as the month’s challenges progress.

;; ,open srfi-9 srfi-13 sort (define-record-type box (make-box l w h) box? (l box-length set-box-length!) (w box-width set-box-width!) (h box-height set-box-height!)) (define (surface-area box) ;; Box -> Int (let ((l (box-length box)) (w (box-width box)) (h (box-height box))) (+ (* 2 l w) (* 2 w h) (* 2 h l)))) (define (smallest-side box) ;; Box -> Int (define (smallest-two xs) ;; List -> List (let ((sorted (sort-list xs <))) (list (first sorted) (second sorted)))) (let ((l (box-length box)) (w (box-width box)) (h (box-height box))) (apply * (smallest-two (list l w h))))) (define (wrapping-paper box) ;; Box -> Int (let ((minimum (surface-area box)) (extra (smallest-side box))) (+ minimum extra))) (define (line->box line) ;; String -> Box (define (line->lon s) ;; String -> List<Number> (let ((xs (string-tokenize s (char-set-complement (char-set #\x))))) (map string->number xs))) (let* ((dims (line->lon line))) (let ((l (first dims)) (w (second dims)) (h (third dims))) (make-box l w h)))) (define (read-boxes file) ;; Pathname -> List<Box> (with-input-from-file file (lambda () (let loop ((line (read-line)) (ys '())) (if (eof-object? line) ys (loop (read-line) (cons (line->box line) ys))))))) (define (sum-boxes boxes) ;; List<Box> -> Int (let ((xs (map wrapping-paper boxes))) (apply + xs))) ;; eof