My attempt at solving Advent of Code 2023.
Go to file
2023-12-05 18:04:21 +01:00
.dir-locals.el Day 4: Scratchcards 2023-12-05 12:49:56 +01:00
.gitignore Cube Conundrum part 1 2023-12-02 12:18:23 +01:00
chicken.org Day 5 Part 2: Missing code 2023-12-05 18:04:21 +01:00
README.org Add symlink 2023-12-01 23:34:38 +01:00

Advent Of Code with Chicken Scheme

Prelude

I don't know why I am spending my time this way, but I am trying to get through this year's Advent of Code. I decided to use Chicken Scheme, and I am trying to use as few (if any) extensions, for an extra challenge.

Day 1: Trebuchet?!

Part One

Quest

Something is wrong with global snow production, and you've been selected to take a look. The Elves have even given you a map; on it, they've used stars to mark the top fifty locations that are likely to be having problems.

You've been doing this long enough to know that to restore snow operations, you need to check all fifty stars by December 25th.

Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck!

You try to ask why they can't just use a weather machine ("not powerful enough") and where they're even sending you ("the sky") and why your map looks mostly blank ("you sure ask a lot of questions") and hang on did you just say the sky ("of course, where do you think snow comes from") when you realize that the Elves are already loading you into a trebuchet ("please hold still, we need to strap you in").

As they're making the final adjustments, they discover that their calibration document (your puzzle input) has been amended by a very young Elf who was apparently just excited to show off her art skills. Consequently, the Elves are having trouble reading the values on the document.

The newly-improved calibration document consists of lines of text; each line originally contained a specific calibration value that the Elves now need to recover. On each line, the calibration value can be found by combining the first digit and the last digit (in that order) to form a single two-digit number.

For example:

1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet

In this example, the calibration values of these four lines are 12, 38, 15, and 77. Adding these together produces 142.

Consider your entire calibration document. What is the sum of all of the calibration values?

Puzzle Solution

    (import (chicken string)
            (chicken irregex))
    (let ((lines (string-split input "\n")))
      (foldl + 0
             (map
              (lambda (line)
                (let ((digits (irregex-extract '(/ #\0 #\9) line)))
                  (if (= 0 (length digits))
                      0
                      (let ((first-digit (car digits))
                            (last-digit (car (reverse digits))))
                        (string->number (string-append first-digit last-digit))))))
              lines)))
54159

Part Two

Quest

Your calculation isn't quite right. It looks like some of the digits are actually spelled out with letters: one, two, three, four, five, six, seven, eight, and nine also count as valid "digits".

Equipped with this new information, you now need to find the real first and last digit on each line. For example:

two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen

In this example, the calibration values are 29, 83, 13, 24, 42, 14, and 76. Adding these together produces 281.

What is the sum of all of the calibration values?

Puzzle Solution

  (import (chicken string)
          (chicken irregex))

  (define (extract-digits input-string)
    (irregex-extract '(or (/ #\0 #\9)
                          "one"
                          "two"
                          "three"
                          "four"
                          "five"
                          "six"
                          "seven"
                          "eight"
                          "nine"
                          ; Duplicates
                          "twone"
                          "eightwo"
                          "nineight"
                          "eighthree"
                          "threeight"
                          "fiveight"
                          "oneight"
                          "sevenine")
                     input-string))

  (define (translate-code digit)
    (case (string->symbol digit)
      ((|0|)       "0")
      ((|1| one)   "1")
      ((|2| two)   "2")
      ((|3| three) "3")
      ((|4| four)  "4")
      ((|5| five)  "5")
      ((|6| six)   "6")
      ((|7| seven) "7")
      ((|8| eight) "8")
      ((|9| nine)  "9")
      ; Again, duplicates
      ((twone)     "21")
      ((eightwo)   "82")
      ((nineight)  "98")
      ((eighthree) "83")
      ((threeight) "38")
      ((fiveight)  "58")
      ((oneight)   "18")
      ((sevenine)  "79")
      ))

  (let ((lines (string-split input "\n")))
    (foldl + 0
           (map
            (lambda (line)
              (let ((digits (string->list
                             (foldl string-append ""
                                    (map translate-code (extract-digits line))))))
                (if (= 0 (length digits))
                    0
                    (let ((first-digit (car digits))
                          (last-digit (car (reverse digits))))
                      (string->number (string first-digit last-digit))))))
                lines)))
53866

Puzzle Input

Jump to day 2.

  (define (calc-part-2)
    (let ((seeds (map (cut make-entity #:seed <>)
                      (expand-seeds (input->seeds-list input))))
          (mapping-alist (input->mapping-alist input)))
      (foldl (lambda (min new)
               (if (fx< new min)
                   new min))
             most-positive-fixnum
             (map (compose entity-id
                           (cut map-entity-forward-fully <> mapping-alist))
                  seeds))))

Day 2: Cube Conundrum

Part One

Quest

You're launched high into the atmosphere! The apex of your trajectory just barely reaches the surface of a large island floating in the sky. You gently land in a fluffy pile of leaves. It's quite cold, but you don't see much snow. An Elf runs over to greet you.

The Elf explains that you've arrived at Snow Island and apologizes for the lack of snow. He'll be happy to explain the situation, but it's a bit of a walk, so you have some time. They don't get many visitors up here; would you like to play a game in the meantime?

As you walk, the Elf shows you a small bag and some cubes which are either red, green, or blue. Each time you play this game, he will hide a secret number of cubes of each color in the bag, and your goal is to figure out information about the number of cubes.

To get information, once a bag has been loaded with cubes, the Elf will reach into the bag, grab a handful of random cubes, show them to you, and then put them back in the bag. He'll do this a few times per game.

You play several games and record the information from each game (your puzzle input). Each game is listed with its ID number (like the 11 in Game 11: ...) followed by a semicolon-separated list of subsets of cubes that were revealed from the bag (like 3 red, 5 green, 4 blue).

For example, the record of a few games might look like this:

Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green

In game 1, three sets of cubes are revealed from the bag (and then put back again). The first set is 3 blue cubes and 4 red cubes; the second set is 1 red cube, 2 green cubes, and 6 blue cubes; the third set is only 2 green cubes.

The Elf would first like to know which games would have been possible if the bag contained only 12 red cubes, 13 green cubes, and 14 blue cubes?

In the example above, games 1, 2, and 5 would have been possible if the bag had been loaded with that configuration. However, game 3 would have been impossible because at one point the Elf showed you 20 red cubes at once; similarly, game 4 would also have been impossible because the Elf showed you 15 blue cubes at once. If you add up the IDs of the games that would have been possible, you get 8.

Determine which games would have been possible if the bag had been loaded with only 12 red cubes, 13 green cubes, and 14 blue cubes. What is the sum of the IDs of those games?

Puzzle Solution

I decided to make the code for this as readable as possible. I've split the process into multiple parts:

Record Splitting

Here, I am turning the input data into an alist with the game number as key, and the draws as value of the entries, by using irregex matches.

    ;; Records
    (define record-pattern
      '(: bol
          "Game "
          (submatch-named game-no (+ (/ #\0 #\9)))
          ":"
          (submatch-named draws (*? any))
          eol))

    (define (record-kons from-index match seed)
      (cons
       (cons (string->number (irregex-match-substring match 'game-no))
             (draws-fold (irregex-match-substring match 'draws)))
       seed))

    (define (record-fold input)
      (irregex-fold record-pattern record-kons '() input))
Draw Splitting

Next, as already called inside record-kons, the list of draws has to be split and processed into individual draws. Here, I simply split them.

    ;; Draws
    (define draws-pattern
      '(: " " (* (~ #\;))))

    (define (draws-kons from-index match seed)
      (cons
       (draw-fold (irregex-match-substring match))
       seed))

    (define (draws-fold line)
      (irregex-fold draws-pattern draws-kons '() line))
Draw Processing

And as the last pre-processing step, I take apart the individual draws, and assign each amount to its respective colour keyword.

    ;; Draw
    (define draw-pattern
      '(: " "
          (submatch-named amount (+ (/ #\0 #\9)))
          " "
          (submatch-named colour (or "red" "green" "blue"))
          (? ",")))

    (define (draw-kons from-index match seed)
      (cons
       (cons (string->keyword (irregex-match-substring match 'colour))
             (string->number (irregex-match-substring match 'amount)))
       seed))

    (define (draw-fold draw)
      (irregex-fold draw-pattern draw-kons '() draw))
Main Program

I check the possibility of a game by folding over its draws, starting with a #t (true) value; basically, it is nothing more than a recursive and statement.

      ;; Game success check
      (define (game-possible? draws)
        (foldl (lambda (seed draw)
                 (and seed
                      (>= 12 (alist-ref #:red draw eqv? 0))
                      (>= 13 (alist-ref #:green draw eqv? 0))
                      (>= 14 (alist-ref #:blue draw eqv? 0))))
               #t draws))

Then, I put everything together in a main function, preprocessing the input and summing up all game ids for which game-possible? returns #t.

      ;; Main function
      (define (sum-of-valid-games input)
        (let ((games (record-fold input)))
          (foldl
           (lambda (seed game)
             (let ((game-id (car game))
                   (draws (cdr game)))
               (if (game-possible? draws)
                   (+ seed game-id)
                   seed)))
           0 games)))

And now, everything can be put together:

(import (chicken string)
      (chicken keyword)
      (chicken irregex))

<<day2-part1-draw-processing>>
<<day2-part1-draw-splitting>>
<<day2-part1-record-splitting>>
<<day2-part1-success-check>>
<<day2-part1-main-function>>
2406

Part Two

Quest

The Elf says they've stopped producing snow because they aren't getting any water! He isn't sure why the water stopped; however, he can show you how to get to the water source to check it out for yourself. It's just up ahead!

As you continue your walk, the Elf poses a second question: in each game you played, what is the fewest number of cubes of each color that could have been in the bag to make the game possible?

Again consider the example games from earlier:

Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
  • In game 1, the game could have been played with as few as 4 red, 2 green, and 6 blue cubes. If any color had even one fewer cube, the game would have been impossible.
  • Game 2 could have been played with a minimum of 1 red, 3 green, and 4 blue cubes.
  • Game 3 must have been played with at least 20 red, 13 green, and 6 blue cubes.
  • Game 4 required at least 14 red, 3 green, and 15 blue cubes.
  • Game 5 needed no fewer than 6 red, 3 green, and 2 blue cubes in the bag.

The power of a set of cubes is equal to the numbers of red, green, and blue cubes multiplied together. The power of the minimum set of cubes in game 1 is 48. In games 2-5 it was 12, 1560, 630, and 36, respectively. Adding up these five powers produces the sum 2286.

For each game, find the minimum set of cubes that must have been present. What is the sum of the power of these sets?

Puzzle Solution

Most code can be reused from the first part; only the success check and the main function have to be rewritten to accommodate the new requirements.

The success check gets replaced by a function that multiplies the maxima together.

  (define (powercalc draws)
    (* (apply max (map (lambda (draw)
                         (alist-ref #:red draw eqv? 1))
                       draws))
       (apply max (map (lambda (draw)
                         (alist-ref #:green draw eqv? 1))
                       draws))
       (apply max (map (lambda (draw)
                         (alist-ref #:blue draw eqv? 1))
                       draws))))

And the main function gets modified to sum everything up.

  (define (game-set-power input)
    (let ((games (record-fold input)))
      (foldl + 0
             (map (lambda (game)
                    (powercalc (cdr game)))
                  games))))

The full thing put together:

  (import (chicken string)
          (chicken keyword)
          (chicken irregex))

  <<day2-part1-draw-processing>>
  <<day2-part1-draw-splitting>>
  <<day2-part1-record-splitting>>
  <<day2-part2-powercalc>>
  <<day2-part2-main-function>>
78375

Puzzle Input

Jump to day 3.

Game 1: 2 blue, 4 green; 7 blue, 1 red, 14 green; 5 blue, 13 green, 1 red; 1 red, 7 blue, 11 green
Game 2: 6 blue, 3 green; 4 red, 1 green, 7 blue; 2 green
Game 3: 4 blue, 3 red; 2 blue, 4 red, 7 green; 1 blue, 6 red, 7 green; 5 green, 10 blue; 9 green, 1 blue, 6 red; 8 blue, 1 red, 12 green
Game 4: 15 blue, 4 green, 5 red; 2 red, 2 green, 5 blue; 3 green, 13 blue; 17 blue, 1 green, 5 red
Game 5: 11 green, 4 red, 3 blue; 8 blue, 6 green; 8 green, 2 red, 9 blue; 4 red, 16 blue; 8 blue, 10 red, 6 green; 9 blue, 3 red, 10 green
Game 6: 4 green, 9 red, 2 blue; 7 red, 2 green, 15 blue; 13 red, 2 green, 6 blue; 5 green, 7 blue, 6 red; 19 red, 15 blue, 4 green
Game 7: 12 blue, 5 red; 5 green, 6 blue; 5 red, 15 blue; 5 blue, 5 red, 5 green; 1 green, 11 blue, 2 red
Game 8: 6 red, 11 green; 5 red, 2 blue, 7 green; 7 red, 6 green
Game 9: 5 red, 1 blue, 11 green; 4 green, 1 blue; 8 green, 2 red; 1 green, 2 red, 2 blue; 3 green, 2 red
Game 10: 7 blue, 4 red, 11 green; 13 green, 1 red, 1 blue; 7 blue, 6 green
Game 11: 4 blue, 7 red, 2 green; 1 green, 14 red, 3 blue; 2 green, 5 red, 3 blue
Game 12: 6 green, 6 blue, 1 red; 1 green, 3 red, 2 blue; 2 blue, 6 red, 7 green
Game 13: 6 red, 10 green, 13 blue; 3 red, 12 green, 9 blue; 11 blue, 1 green; 4 red, 3 blue, 13 green; 12 green, 10 blue, 6 red; 13 blue, 3 green, 3 red
Game 14: 8 green, 1 blue, 17 red; 7 green, 11 blue, 19 red; 19 red, 9 blue, 2 green; 8 green, 20 red, 12 blue; 16 red, 3 green, 11 blue
Game 15: 3 red, 1 green, 5 blue; 9 blue, 4 green; 6 blue, 5 green, 9 red
Game 16: 13 blue, 1 red; 2 blue, 2 green; 1 green; 10 blue, 8 red; 4 red, 3 green, 9 blue
Game 17: 10 blue, 2 red; 3 green, 4 red; 6 blue, 1 red, 6 green; 5 green, 7 blue, 5 red
Game 18: 3 red, 1 green; 2 red, 5 blue; 5 blue, 2 red
Game 19: 7 green, 4 blue, 1 red; 1 green, 4 blue, 4 red; 6 blue, 8 green; 4 green, 2 blue, 1 red; 1 red, 1 blue, 2 green
Game 20: 13 green, 1 red, 1 blue; 12 green, 1 blue; 5 green, 1 blue, 2 red; 16 green, 3 red; 2 red, 9 green
Game 21: 8 red, 2 green, 2 blue; 5 red, 3 blue; 2 blue, 5 red, 2 green; 7 blue
Game 22: 9 red, 12 blue, 7 green; 7 red, 13 blue, 4 green; 9 blue, 13 red, 1 green; 3 blue, 4 red, 5 green
Game 23: 7 green, 12 red; 6 red, 7 green, 4 blue; 1 blue, 11 red, 5 green; 4 green, 2 blue, 6 red; 12 green, 6 red, 3 blue
Game 24: 11 red, 4 blue; 9 blue, 6 green, 17 red; 8 green, 2 red; 16 blue, 6 red, 2 green
Game 25: 7 red, 4 blue; 7 blue, 4 green; 10 blue, 4 red, 2 green; 6 green, 4 blue, 1 red; 10 blue, 2 red, 4 green
Game 26: 7 green, 8 red, 6 blue; 5 red, 3 green, 2 blue; 13 blue, 6 green, 5 red; 10 blue, 4 red, 8 green; 2 red, 2 blue, 1 green; 8 blue, 1 green, 4 red
Game 27: 7 green, 3 blue, 13 red; 1 green, 17 red, 1 blue; 16 red, 3 blue, 3 green; 5 green, 3 red, 5 blue; 13 red, 4 green, 8 blue; 6 blue, 2 green, 15 red
Game 28: 8 blue, 5 red, 18 green; 1 green, 6 red; 7 blue, 18 green, 5 red; 16 green, 3 red, 7 blue; 6 blue, 18 green; 8 blue, 8 green, 7 red
Game 29: 4 blue, 1 red; 6 blue, 1 red; 17 blue, 1 green
Game 30: 1 red, 2 green, 5 blue; 2 blue, 7 green, 6 red; 11 blue, 4 red, 2 green; 5 green, 6 blue, 4 red; 5 red, 8 blue, 7 green
Game 31: 10 green, 9 blue; 5 green, 9 blue, 1 red; 1 red, 8 blue
Game 32: 3 red, 5 green; 5 red, 5 blue, 14 green; 2 red, 2 green; 11 green, 3 red, 5 blue
Game 33: 7 blue, 10 green, 8 red; 18 blue, 15 green, 4 red; 6 red, 1 green; 18 blue, 8 red, 11 green
Game 34: 3 green; 2 red, 5 green; 5 blue, 3 green; 3 blue, 5 green, 1 red
Game 35: 1 blue, 5 green, 6 red; 3 green, 2 red, 3 blue; 4 red, 9 blue, 3 green; 1 green, 12 blue, 1 red
Game 36: 14 green, 3 blue, 16 red; 1 green, 2 red, 4 blue; 4 blue, 9 green, 18 red; 4 blue, 4 green, 14 red; 4 blue, 11 green
Game 37: 7 green, 2 blue, 3 red; 8 green, 9 red, 2 blue; 4 blue, 15 green, 18 red
Game 38: 11 red, 1 blue, 6 green; 6 green, 2 blue, 1 red; 6 blue, 17 red, 2 green; 17 red, 9 blue, 3 green; 7 red, 7 blue, 3 green; 3 green, 7 red, 7 blue
Game 39: 1 blue, 2 green; 1 blue, 2 green, 7 red; 1 blue, 4 red, 2 green; 1 blue, 12 red
Game 40: 1 blue, 4 red, 15 green; 12 green, 1 blue, 15 red; 15 red, 8 green
Game 41: 5 blue, 5 green, 1 red; 9 red, 8 green, 9 blue; 10 red, 10 blue, 4 green; 3 blue, 17 red, 3 green; 3 blue, 4 red, 2 green
Game 42: 2 blue, 10 red, 17 green; 6 red, 10 green, 10 blue; 3 blue, 6 green, 8 red; 9 green, 2 blue, 8 red; 13 green, 5 blue; 4 red, 18 green, 11 blue
Game 43: 8 red, 3 blue, 6 green; 2 red, 8 green, 10 blue; 5 blue, 9 red, 9 green; 1 green, 15 red, 8 blue
Game 44: 11 green, 19 red, 14 blue; 1 red, 19 green, 9 blue; 7 green, 8 red, 10 blue; 14 green, 8 blue, 15 red; 7 green, 3 red, 2 blue
Game 45: 4 green, 9 blue, 4 red; 7 blue, 13 green, 2 red; 12 green, 10 blue, 10 red
Game 46: 10 red, 2 green, 1 blue; 10 red, 10 green, 1 blue; 1 blue, 13 green; 1 blue, 2 green, 10 red; 1 blue, 7 red, 11 green; 10 red, 5 green
Game 47: 3 blue, 2 green, 12 red; 5 blue, 7 red; 5 green, 14 red; 12 red, 7 green, 5 blue
Game 48: 5 red, 1 blue, 3 green; 7 red, 8 green, 4 blue; 4 blue, 5 green, 17 red; 1 blue, 12 red
Game 49: 2 green, 7 red, 1 blue; 11 green, 5 red; 4 red, 1 blue, 1 green; 11 green, 1 blue, 7 red
Game 50: 10 red, 3 blue, 6 green; 1 blue, 5 red, 3 green; 6 blue, 11 red, 12 green; 10 green
Game 51: 18 blue, 1 green, 1 red; 15 blue; 13 blue, 11 green, 4 red; 8 red, 1 green, 18 blue; 10 green, 7 blue, 8 red
Game 52: 13 green, 15 blue; 6 blue, 4 red, 8 green; 6 red, 13 green, 11 blue; 2 red, 7 green, 13 blue; 12 green, 2 blue, 3 red; 6 red, 11 green, 1 blue
Game 53: 2 red, 2 green; 3 green, 1 blue, 1 red; 1 blue, 4 green, 7 red; 4 red, 1 blue; 4 red, 5 green, 2 blue
Game 54: 8 blue, 2 red, 5 green; 6 green, 2 blue, 3 red; 1 blue, 8 green, 4 red
Game 55: 6 green, 6 blue, 3 red; 13 green, 1 red; 2 blue, 1 red, 1 green; 14 green, 1 blue, 1 red; 1 blue, 2 red, 9 green; 9 green, 2 blue, 4 red
Game 56: 4 green, 6 blue, 1 red; 5 red, 3 blue; 6 red, 1 blue; 9 green, 5 blue, 7 red
Game 57: 5 red, 5 green, 8 blue; 11 red, 3 blue, 8 green; 7 green, 9 blue, 11 red; 3 green, 2 blue, 12 red
Game 58: 3 green, 3 red; 4 red, 1 green; 1 red, 6 green; 5 green; 5 red, 1 blue, 3 green; 3 red, 1 blue
Game 59: 2 green, 2 blue; 7 red, 18 green; 2 blue, 7 red, 16 green; 7 red, 10 green
Game 60: 3 blue, 4 red; 4 blue, 3 red, 3 green; 16 green
Game 61: 1 blue, 2 red, 8 green; 9 blue, 4 green, 12 red; 10 green, 2 red; 5 blue, 11 red, 1 green; 10 green, 3 blue, 8 red; 5 red, 2 green
Game 62: 15 red, 10 blue, 7 green; 4 blue, 9 red, 4 green; 4 red, 2 blue, 2 green; 11 green, 2 red; 8 blue, 2 green; 2 green, 8 red, 8 blue
Game 63: 2 green, 3 blue, 1 red; 7 blue, 5 red; 7 blue
Game 64: 3 green, 5 blue, 6 red; 9 green, 4 red; 13 red, 1 blue, 5 green; 4 blue, 13 red, 8 green
Game 65: 7 green, 1 blue; 1 red, 14 blue, 4 green; 8 blue, 6 red; 14 green, 4 red
Game 66: 6 red, 11 green, 7 blue; 1 blue, 6 red; 13 red, 7 blue, 3 green; 8 red, 6 blue, 15 green; 7 green, 6 blue, 4 red; 4 red, 1 blue, 20 green
Game 67: 4 blue, 9 green; 15 red, 16 green, 3 blue; 1 green, 14 red, 3 blue; 3 red, 2 blue, 3 green; 4 green, 3 blue, 12 red
Game 68: 5 green, 3 blue, 2 red; 4 green, 8 blue, 11 red; 6 red, 6 blue, 4 green; 8 red, 5 blue, 7 green; 6 blue, 6 green, 11 red; 2 blue, 3 green, 3 red
Game 69: 15 blue, 16 green, 5 red; 10 blue, 3 red, 13 green; 4 red, 5 blue, 2 green; 1 red; 11 green, 5 red, 15 blue
Game 70: 8 red, 9 blue, 12 green; 3 red, 2 blue, 14 green; 10 blue, 1 red, 18 green; 1 blue, 7 red, 16 green; 3 green, 4 red, 16 blue; 10 green, 6 red
Game 71: 12 blue, 7 red, 16 green; 2 red, 9 blue, 15 green; 1 red, 11 blue, 11 green; 15 red, 16 blue, 2 green
Game 72: 1 blue, 11 red, 6 green; 1 red, 2 blue, 5 green; 4 green, 2 red; 2 green, 12 red
Game 73: 1 blue, 1 red; 2 red, 4 blue, 2 green; 1 blue, 2 green, 10 red; 8 red
Game 74: 12 red, 1 green, 4 blue; 1 red, 5 blue, 1 green; 11 green, 16 red, 7 blue; 7 red, 1 blue, 1 green; 12 red, 11 green, 12 blue; 11 green, 6 red
Game 75: 12 green, 8 red, 3 blue; 7 red, 10 green; 1 green, 7 blue, 1 red
Game 76: 4 green, 1 red, 3 blue; 7 blue, 3 green, 3 red; 4 blue, 2 red, 3 green; 4 blue, 1 green
Game 77: 2 green, 12 blue, 10 red; 5 blue, 7 red; 2 red, 6 green; 1 blue, 2 red, 6 green
Game 78: 2 green, 4 blue, 4 red; 8 green, 10 red, 10 blue; 5 green, 8 blue, 10 red; 6 green, 2 red
Game 79: 3 green, 2 blue, 11 red; 8 red, 11 green, 1 blue; 1 blue, 16 red; 5 red, 7 green, 16 blue; 12 red, 7 green, 9 blue; 4 red, 20 blue, 12 green
Game 80: 3 red, 5 green; 2 blue, 4 green; 2 red, 12 green, 4 blue; 10 green, 1 blue, 1 red; 4 blue, 3 red
Game 81: 1 blue, 1 green, 1 red; 5 green, 3 red, 1 blue; 1 blue, 6 green; 1 green; 1 red, 5 green, 2 blue; 1 blue, 1 red, 3 green
Game 82: 7 green, 10 blue, 3 red; 10 green, 12 red, 12 blue; 18 red, 8 green, 14 blue; 3 red, 3 green, 10 blue; 3 red, 1 blue, 5 green; 1 green, 8 blue
Game 83: 9 red, 3 blue; 14 blue, 8 red, 3 green; 14 blue, 5 green, 4 red
Game 84: 2 blue, 3 red, 6 green; 11 green, 2 red, 1 blue; 17 green, 3 blue, 3 red; 1 red, 1 blue; 1 red, 2 blue, 19 green
Game 85: 3 green, 2 blue, 3 red; 4 red, 5 blue, 8 green; 15 green, 1 red, 9 blue; 12 green, 3 blue, 2 red
Game 86: 15 green, 7 red, 10 blue; 2 blue, 2 red, 1 green; 4 red, 1 green, 9 blue; 7 red, 14 blue, 5 green
Game 87: 1 green, 3 blue, 1 red; 2 blue, 1 green; 1 blue, 2 green, 1 red
Game 88: 2 green, 6 blue, 5 red; 5 blue, 2 red; 3 red, 13 blue; 9 blue, 10 red, 1 green
Game 89: 6 green, 10 red, 2 blue; 7 red, 1 blue, 8 green; 4 blue, 3 red, 5 green; 4 green, 4 blue, 10 red
Game 90: 8 red, 7 blue; 4 green, 3 red, 1 blue; 5 blue, 2 green
Game 91: 15 green, 14 red; 12 red, 16 green, 2 blue; 8 red, 10 green; 1 green, 6 red; 8 green, 12 red
Game 92: 4 blue, 4 green, 9 red; 1 blue, 17 green; 1 green; 15 green, 3 blue, 12 red; 11 red, 1 blue, 7 green; 7 blue, 13 red, 8 green
Game 93: 10 blue, 12 red; 10 blue, 11 green, 8 red; 1 blue, 11 green, 7 red; 10 blue, 15 red, 5 green; 11 red, 8 green, 9 blue; 10 green, 3 blue
Game 94: 1 blue, 2 red; 4 red, 1 green, 5 blue; 3 red, 2 green; 2 green, 2 blue; 1 red, 5 blue, 1 green; 4 blue, 1 red, 2 green
Game 95: 1 red, 1 blue, 3 green; 2 green, 6 blue; 1 green, 13 blue, 1 red; 3 green, 15 blue
Game 96: 16 blue, 7 green, 5 red; 5 green, 5 blue, 6 red; 3 green, 17 blue, 10 red; 13 blue, 2 red, 1 green
Game 97: 12 red; 1 blue, 6 red, 1 green; 9 red, 2 blue, 1 green; 1 green, 2 blue, 1 red; 15 red, 1 blue; 1 blue
Game 98: 11 red, 6 blue, 13 green; 4 blue, 2 red, 12 green; 2 blue, 8 green, 10 red
Game 99: 2 red, 1 blue; 4 green; 7 green, 1 blue, 1 red; 5 green, 2 red; 1 blue, 2 red, 9 green; 2 green, 3 red
Game 100: 7 red, 11 blue; 10 red, 5 blue, 1 green; 7 red, 1 green, 13 blue; 9 red; 9 red, 19 blue; 9 red, 9 blue

Day 3: Gear Ratios

Part One

Quest

You and the Elf eventually reach a gondola lift station; he says the gondola lift will take you up to the water source, but this is as far as he can bring you. You go inside.

It doesn't take long to find the gondolas, but there seems to be a problem: they're not moving.

"Aaah!"

You turn around to see a slightly-greasy Elf with a wrench and a look of surprise. "Sorry, I wasn't expecting anyone! The gondola lift isn't working right now; it'll still be a while before I can fix it." You offer to help.

The engineer explains that an engine part seems to be missing from the engine, but nobody can figure out which one. If you can add up all the part numbers in the engine schematic, it should be easy to work out which part is missing.

The engine schematic (your puzzle input) consists of a visual representation of the engine. There are lots of numbers and symbols you don't really understand, but apparently any number adjacent to a symbol, even diagonally, is a "part number" and should be included in your sum. (Periods (.) do not count as a symbol.)

Here is an example engine schematic:

467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..

In this schematic, two numbers are not part numbers because they are not adjacent to a symbol: 114 (top right) and 58 (middle right). Every other number is adjacent to a symbol and so is a part number; their sum is 4361.

Of course, the actual engine schematic is much larger. What is the sum of all of the part numbers in the engine schematic?

Puzzle Solution

Records
(define-record part-number number line start-col end-col)
(define-record part-symbol sym line start-col end-col)
(define-record buffer-char char line col)
Indexing the Input
(define (index-input input #!optional (indexed-input '()) (line-index 0) (col-index 0))
  (if (= 0 (length input))
      (reverse indexed-input)
      (let ((next-char (car input))
            (new-rest-input (cdr input)))
        (if (eqv? #\newline next-char)
            (index-input new-rest-input
                         indexed-input
                         (+ line-index 1)
                         0)
            (index-input new-rest-input
                         (cons (make-buffer-char next-char line-index col-index)
                               indexed-input)
                         line-index
                         (+ col-index 1))))))
Tokenizing the Indexed Input
(define (number-char? c)
  (case (buffer-char-char c)
    ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) #t)
    (else #f)))
(define (finalize-token buffer)
  (let* ((rev-buffer (reverse buffer))
         (line (buffer-char-line (car buffer)))
         (start-col (buffer-char-col (car buffer)))
         (end-col (buffer-char-col (car rev-buffer))))
    (if (number-char? (car buffer))
        (make-part-number (string->number
                           (apply string (map buffer-char-char buffer)))
                          line start-col end-col)
        (make-part-symbol (string->symbol
                           (apply string (map buffer-char-char buffer)))
                          line start-col end-col))))
(define (compatible-with-buffer? buffer char)
  (and
   (not (eqv? #\. (buffer-char-char char)))
   (or (= 0 (length buffer))
       (and (number-char? (car buffer))
            (number-char? char))
       (and (not (number-char? (car buffer)))
            (not (number-char? char))))))
(define (tokenize-indexed-input indexed-input #!optional (token-buffer '()) (part-nums '()) (part-syms '()))
  (if (= 0 (length indexed-input))
      (values (reverse part-nums)
              (reverse part-syms))
      (let ((next-char (car indexed-input)))
        (cond
           ((compatible-with-buffer? token-buffer (car indexed-input))
            (tokenize-indexed-input (cdr indexed-input)
                                    (cons (car indexed-input) token-buffer)
                                    part-nums part-syms))
           ((= 0 (length token-buffer))
            (tokenize-indexed-input
              (cdr indexed-input)
              (if (eqv? #\. (buffer-char-char (car indexed-input)))
                token-buffer (list (car indexed-input)))
              part-nums part-syms))
           (else
            (let ((token (finalize-token (reverse token-buffer))))
              (tokenize-indexed-input
               (cdr indexed-input)
               (if (eqv? #\. (buffer-char-char next-char)) '() (list (car indexed-input)))
               (if (part-number? token) (cons token part-nums) part-nums)
               (if (part-symbol? token) (cons token part-syms) part-syms))))))))
Checking for Part Neighbours
(define (neighbours? part-num part-sym)
  (let ((part-num-line (part-number-line part-num))
        (col-min (- (part-number-start-col part-num) 1))
        (col-max (+ (part-number-end-col part-num) 1)))
    (and (>= (part-symbol-line part-sym) (- part-num-line 1))
         (<= (part-symbol-line part-sym) (+ part-num-line 1))
         (>= (part-symbol-start-col part-sym) col-min)
         (<= (part-symbol-start-col part-sym) col-max)
         (>= (part-symbol-end-col part-sym) col-min)
         (<= (part-symbol-end-col part-sym) col-max))))
Folding Everything Together
(define (is-real-part-number? part-num part-syms)
  (and (< 0 (length part-syms))
       (or (neighbours? part-num (car part-syms))
           (is-real-part-number? part-num (cdr part-syms)))))
(define (fold-part-numbers part-nums part-syms)
  (foldl (lambda (output input)
           (if (is-real-part-number? input part-syms)
               (+ output (part-number-number input))
               output))
         0 part-nums))
(let-values (((part-nums part-syms) (tokenize-indexed-input (index-input (string->list input)))))
  (fold-part-numbers part-nums part-syms))
509115

Part Two

Quest

The engineer finds the missing part and installs it in the engine! As the engine springs to life, you jump in the closest gondola, finally ready to ascend to the water source.

You don't seem to be going very fast, though. Maybe something is still wrong? Fortunately, the gondola has a phone labeled "help", so you pick it up and the engineer answers.

Before you can explain the situation, she suggests that you look out the window. There stands the engineer, holding a phone in one hand and waving with the other. You're going so slowly that you haven't even left the station. You exit the gondola.

The missing part wasn't the only issue - one of the gears in the engine is wrong. A gear is any * symbol that is adjacent to exactly two part numbers. Its gear ratio is the result of multiplying those two numbers together.

This time, you need to find the gear ratio of every gear and add them all up so that the engineer can figure out which gear needs to be replaced.

Consider the same engine schematic again:

467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..

In this schematic, there are two gears. The first is in the top left; it has part numbers 467 and 35, so its gear ratio is 16345. The second gear is in the lower right; its gear ratio is 451490. (The * adjacent to 617 is not a gear because it is only adjacent to one part number.) Adding up all of the gear ratios produces 467835.

What is the sum of all of the gear ratios in your engine schematic?

Puzzle Solution

Gather Symbol Neighbours
  (define (gather-neighbours part-sym part-nums)
    (foldl (lambda (output input)
             (if (neighbours? input part-sym)
                 (cons input output)
                 output))
           (list) part-nums))
Put Everything Together
  (define (filter-gear-candidates part-syms)
    (foldl (lambda (output input)
             (if (eqv? '* (part-symbol-sym input))
                 (cons input output) output))
           (list) part-syms))
  (define (calc-gear-ratio gears)
    (foldl (lambda (output input)
             (if (= 2 (length input))
                 (+ output (apply * (map part-number-number input)))
                 output))
           0 gears))
  (let-values (((part-nums part-syms) (tokenize-indexed-input (index-input (string->list input)))))
    (let ((gear-candidates (map (lambda (x) (gather-neighbours x part-nums)) (filter-gear-candidates part-syms))))
      (calc-gear-ratio gears)))
75220503

Puzzle Input

Jump to day 4.

.....664...998........343...............851............................2............414.....................3....................948.164....
......*..................*617....885...*....................-......250.........536..........470...#..................../4......=.....*......
...407...570..218................-.....654........776.....920.........*753...........566......*..347.....61.-979..786........935...42.......
.......%....*...$..311.102..........................*.907.....723...............622-....*..354..............................................
.....266..............*....987.554...........&....288...#......#.......................69......41..........486..-...........................
.849................................&........781...........978......724*..196..../767................725..../...892.....*355.....815.390....
....*......@.....*988......%........704...............*......&...........*...................826.....................243.......#....*.......
...796......729.9.........490..721....................438.=....272..54&...926..481..............*..523......&.785...........766.......*493..
........281.........706...........=.666.......505.........579.*................./...669.........73...*...639...*.......479.........514......
...........*...386.......375..................................525.926..$120............&.580.........457........325.......*829..............
.....758..662.......937....%...661.24......749*323...444.............*.............583....*.........................................223.....
.......*........665....*...........*................@.................154......965..*....119.......620*............347.................*470.
........391.........183.........75..783../....................209.312............*...362........./.....667..........*....77.................
...379=..........................$......261..228........907......*.......+591...178.........227.704........@771..667..........268......543..
.......................#.....................*..........*....................................-........*581...........101........*.....*.....
................471...545..135........432..178....$225..143...973#..322............2.................................*...........239...985..
......728*612...*.........*.....65....................................*...........*................&..............527....255+../............
..255.........435.304....854...................-............=........261......&...749....+......196....694......................779..271.374
......604.........*.....................708.....922.......76..82*554......991..19........456............*..582.........597@.................
.................374..*........*707........................................*....................609...52....%.................483...........
..../..................739......................$..........649...973.*511.861..20%.................=.....................148....*......343..
...978.................................282&...401......961....-.*.........................................499%.........../.....347..........
.................+..174..315.-819.................841.....*66......820.836......8....60....456........*........434..........................
....62%.......908......./.................770....../..................*.....852......&.....*........317...%......@.......+.......691........
........793......../......411......963.......*594..................@........@......*.......45.............729...........306.148....*..@.....
626.......$......35..........*........*...........................77.134........584.....23....35................589........./...482..853....
.......................366..668.........................238...........*..265.........*..........*...........&......*...471..................
..741.............679.................@.807...76....185*...........211..%.........507....178..583....*.561...521..620...*....865.$247.494...
.....*.....383.....%..183..876......179..$..................254.........................$..........697.*..............935...*...............
...50..390..*.........*.........917.........904/..50+.........................96...............960......701...............464....*.......947
.........*..53........270..........*647.342......................778............$..$684..+279...*....#.........................393..........
......151.......490...........352*.........*........................#............................594.732.........11....#....................
........................$.........306....805..................832...................859..../.#53.........953*228...*....217.................
......37....349....391.739.......................................*286..........558......516.......647........................%........847...
..346.../....*......&.......855.........732....586...353.................43....*..............598.&...798.719.........671.....881...........
..........561................=..........................*..........52....*.....727............./.....$....*..........*......................
999*..........746...158........534............927.....587.....521......511...........448%...89...........52..557......211..356.344...116....
........*.....................%........732....*..............*...............................*..................*806.......$.....*..*.......
.....575.515.......922..........410.......*................564...............+503...........297................................132.667......
.../.............-..#.....69*82....*.......842......248..&.......630.@........................................500...........................
..916.........944...................586.................647.......*...21....&419..........=....699.......766...%.......152.......315*101....
......*436...........987#.....*....................188.............81.............87..-..109......*.........-..........*....349.............
...553..........570-.......442.197.......115...590....*.......284.......478...459..#.6.........946...............945-..192............292...
22.......+..............................%......../...865........*......*........*..........900......950.......................*449...$......
.......780..........435...*................................371...588...727.....213.....496.............-.845*..../173......688..............
713........923..../.*......289....38.....408.552.141*476..*..................................619....6........238...................633......
...*821.......*..57.8............../..46*......*..........38.........%..................$...*.......*....201......=.............61...-..%86.
...........361......../12..39.51............903..................380..659........905+.28....256.............*......215.....=.../............
...-..577.......553...............749.246.........34....................................................311..282........894.................
.960.....@...........661.....558...&......239*..........482......574=..269..........289..../...............*.................323............
...........292................%.................#........../............*......452/.-......132.....=..342.721..335.....426....*.....516.....
................967.......=.......900...........925..........476.252/...861.....................891.....*.........*315.&.....130...=........
..955..........=........584.......*...-................600............$..........940.=348...............733...754...........................
.....*..123.....................76...36...430-......&...............524.........*............706..............#.....*.....849*......162*129.
..543.....*........903..290.........................42.......................649...$............+...78.*648......180.979......353...........
...........91.642.../....*........443/.........206...........#.......219............134............*..............................798..344..
......759................144..............................455........*...906...............195......924....502.405....802.400.......*.......
.812..............-..........394.............$771.245..............116........................*.+.........#....../...*.....*...448...883....
..................784................................*.....&.................809.......616..109.496.................89.....592...*..........
...596........671......527..483.197......-965.231.918.......921.452-.538.......*..763.........................162............../..479../685.
......*....46...#......*......*.@.............................................839.*......172.....................*374........927............
.....383............649.....783..........=981.........44..159.....94...............769......*..............#..........*.............748*993.
..................................................607.+...*......*.......................755..810........539.......728.98.....425...........
......32......35....99...233..............275.337.&......437..630...........423.84...........-............................163........578....
................+.....*.....+.....334.......*.-................................*..................110.....358....115..566....*648.......*...
....................471............*......384....81...190.606..=714....673.198.......57..#761........=..........*.....*..................618
..........847.755..................963..........*........*................*......251*....................#592.222....107...991..557.........
....236-.....*.................569.....311....584.............*958..........923%........................................./.......*....=.....
................../.835...................*........157*324.840......../415...................408...........212......-..573.549.770.995......
............312.34..............&.377...287.461..................+.................33*555...*................@.315.720......%...............
.......614.*.................309.....*........*..758............811..........................259.................+..................-627....
.........*.....*.....757.................684.527..*.......408.........999...............524..............570...............995..............
...835..415.345.822...............495.....*.......138...........966....*..................#...............*....560.........*................
...#.................806..954......*.......51...........+.......*.....910..436.477..............*150.....510...*.....#....537...........434.
......................*...-........871.743.........643...234...844............*....705..959..360................454..402..........984.......
....................491.................+..675...........................$........*........-................................487...*...876...
....191........%559.......................*........250..................965......556..&...........521.......365.......994%.%....923.....$...
.....*........................238..257...631..........*....*.....&...........346......366...150....*........*...............................
.....532....584....800.......*.................603.452..155.42..272..267.295*.....52...........*....672..743...830.....395.......862........
...............#....*.....347...................*......................@.......................487...................................671*973
......=340.......&..667...................*......413.........................576*888......706.......487..502..........22....................
................649..........&./426....286.............149........690..............................&..........765.....*..............321....
389........304/............200...................660...*.............*253...........129..#30.........................710.../................
...@..............408.............258*246....136.....614..531..-.....................*.........253&..........421...........939.....+.357....
.....%..............*...........................*............*..313..+418.47...931...329............974.........=...847..........166.*......
834..6.............346....505....164............833........66.....................*.......367..95......*211..............-............888...
.........535....=......+.....$.......770......+....................................5.......*.....*36..................547...+...............
.....115.*...471......863.............#.....75..364...........=842..974......722........581............$..........588.......557....760......
987..=...780...............$...................*......................................+......869.......591.......&................-.........
........................15.484..........640...768.@710.353.......=.585......&91....996..712..=...............548...680........661...939.....
...630...........186=...*......575.....*................#.....662..$.................................+......*.........+........../.....*....
.........116*235........138...*....................644....................*853...............210...719......503.....................453.....
.....................=.........480..%................=...........429...478.....695.....789..$..........19&............216...................
......506.........101...189.........232....951.........706....43...*.......943.........%...........935.......160..........+20..152.16.......
..............789...........654...............*648.............*...........*....=.............398...*........*................*.............
..............*.........509...@.....$...............746.....645...........607..336.................488....285....$..944......298.$..........
..........23...642.374.............913................*.327....................................................263.....*182......822........
......94....*......*.......942*.............596....285.....*..............177...........86...................................477......702...
..243..+.....220.838.637.......481....301..+...............717...................394......................782/.......*..........%.872.*.....
.........../.........%...../...........$...........239...........209......*........-...............153............100.700...........*..708..
............499.........235..........................*....939*......*..227.293.-.....805.785.........#..250.................423....954......
.......570........................................837..@......748..56..........782.....*....*..........*......552...........................
872%..*......%.......88*484....805....178...704........282............387...........562....614..559...750..*...........@.....417......762...
......745.....3...98....................*..*...............................@....329........................130.......134....$...........*...
.814.............%......829.268........220...441.316.............*740......607........*831..............*......................529.......410
......=...687...........*.....*................*...*..........369.....332..........798...............956.932......................=.........
.....856.*............858....283.........43.594...292................*....*.604*.........217....................44*.....676*.........752.571
..........489....................951...................83...........262.243........681....*.................373....493...........-...@......
349................................*..................@.....................444.......*......../951..810.......#.......184....227...........
.................958..574....313...312...909....204/....................674*...........146...........=...=..................................
.....*.438...512*.....*.....*...........*.............484&.25..........................................851...........534@.$720.719..........
...254.*...........167..@...7............22....681...........*684........7.696.135.207.......177............749*670............*.....681....
..........733...........659.........527............645*215.........850.....*..........*.........*....822........................787.........
..37*58.....*.................562....*........232..........610.321*.....148.......416............514.....703......54...................310..
..........638....223.........*........296............452....................152....#...678..........................*...+...692.........*...
..911...........*.........594.......*......589........*..........186........................219...........344.927.324.525..*............753.
.....*..144.247.493...............351.........*....994...........*......738..107.......235...*....937.......-.*...........171....634........
....756..*..../.....626..131+.@..............770..........70...11........*...............*..533...*...181......861..................*.......
.........755...................637./15.....................=.........217..407......146...........402.#..................11...436..535.......
..........................&592.............367.636...........830........*..........*..........................................+.........%...
..........420*.27....954..........314.............=...........*......791...$.......718........828.....9@..449...................868...110...
..................*..........835...&...417*...........895......747..........785.........128....*..80........*.....................*.........
........475@...285...700.............*.....846....561...*.723.............................&.436...*......728................&....389........
....................*.............610.266...........@.351.*..........308...931...490...............50........*487.....958.500...............
..................335...736.....................285.......294..510*....*........*.....103.....139.........920...........=...................
.............*...........*..........343............*..692..........57.741.....@..314...*.....*......*835......738.=............582.....295..
...437....215..........185...............58.......654...&.....603..........505.......97...224..@..........766.....508.....+317....#.........
...............................52.............1...........777........704........372.............23....652...=...........@...............620.
............83..481..917......*........36$...../......=...=.............*...471*.....171.680.............*.......635...28...127.....272.....
...262.183..*......*..=..56*.72...................812.317.......454.....1.............*.............................*.........*.......*.....
....*........299..246...........190#...........%...+..............*.224..............664......897....407.155*....407...........406..581.....
......691.................869..........439.....385....@.........26.....*........863.......402*.........-.............*28...332..............
........*.......159*638......*....38....*..209......578.963........592..875......*...................*.....$......596........-..............
......90................424.640.....*.272.................$..........*.........134...........624..158.907..964.................291..........
................410....&..........972.......................$..305..683..743........551.338.&..................................*............
...........................%..........213.................164.....*.......+..........*........751..............................10....710.387
......%................&....314........-..376.......833*.......494..821...........829......%.....#........582..............&............*...
......87...318......472...........%449.....=............720.........%.................257...29...........*.........-.....656................
..666........*....*.....920.....................................................&......*........................759..........875$...........
......138....366..797...........584.......247.........................427..206..843...618.....530......................................172..

Day 4: Scratchcards

Part One

Quest

The gondola takes you up. Strangely, though, the ground doesn't seem to be coming with you; you're not climbing a mountain. As the circle of Snow Island recedes below you, an entire new landmass suddenly appears above you! The gondola carries you to the surface of the new island and lurches into the station.

As you exit the gondola, the first thing you notice is that the air here is much warmer than it was on Snow Island. It's also quite humid. Is this where the water source is?

The next thing you notice is an Elf sitting on the floor across the station in what seems to be a pile of colorful square cards.

"Oh! Hello!" The Elf excitedly runs over to you. "How may I be of service?" You ask about water sources.

"I'm not sure; I just operate the gondola lift. That does sound like something we'd have, though - this is Island Island, after all! I bet the gardener would know. He's on a different island, though - er, the small kind surrounded by water, not the floating kind. We really need to come up with a better naming scheme. Tell you what: if you can help me with something quick, I'll let you borrow my boat and you can go visit the gardener. I got all these scratchcards as a gift, but I can't figure out what I've won."

The Elf leads you over to the pile of colorful cards. There, you discover dozens of scratchcards, all with their opaque covering already scratched off. Picking one up, it looks like each card has two lists of numbers separated by a vertical bar (|): a list of winning numbers and then a list of numbers you have. You organize the information into a table (your puzzle input).

As far as the Elf has been able to figure out, you have to figure out which of the numbers you have appear in the list of winning numbers. The first match makes the card worth one point and each match after the first doubles the point value of that card.

For example:

Card 1: 41 48 83 86 17 | 83 86  6 31 17  9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3:  1 21 53 59 44 | 69 82 63 72 16 21 14  1
Card 4: 41 92 73 84 69 | 59 84 76 51 58  5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11

In the above example, card 1 has five winning numbers (41, 48, 83, 86, and 17) and eight numbers you have (83, 86, 6, 31, 17, 9, 48, and 53). Of the numbers you have, four of them (48, 83, 17, and 86) are winning numbers! That means card 1 is worth 8 points (1 for the first match, then doubled three times for each of the three matches after the first).

Card 2 has two winning numbers (32 and 61), so it is worth 2 points. Card 3 has two winning numbers (1 and 21), so it is worth 2 points. Card 4 has one winning number (84), so it is worth 1 point. Card 5 has no winning numbers, so it is worth no points. Card 6 has no winning numbers, so it is worth no points.

So, in this example, the Elf's pile of scratchcards is worth 13 points.

Take a seat in the large pile of colorful cards. How many points are they worth in total?

Puzzle Solution

A Record For The Start

Records are always useful, so let's create one to represent an individual card. We want to store the card's id (it might be useful in part 2), the winning numbers, and the card's numbers.

Since it could potentially be relevant, I also add a slot for the matches.

UPDATE: I also added a slot for the number of copies of the scratch card - relevant for part 2.

(define-record scratchcard id winning-numbers card-numbers match-numbers copies)
Parsing The Input

We know the drill by now, we have to take apart the input strings, and parse them into an easy format for us - in our case, this is the scratchcard record.

For that, I first create the pattern for a card.

  (define card-irregex
    '(: bol
        (* whitespace)
        "Card"
        (+ whitespace)
        (submatch-named card-no (+ numeric))
        ": "
        (submatch-named winning-numbers-str (+ (or numeric whitespace)))
        " | "
        (submatch-named card-numbers-str (+ (or numeric whitespace)))
        eol))

The pattern is then used to extract every scratch card which is then being parsed in a fold statement.

  (define (input->cards input-str)
    (irregex-fold card-irregex
      (lambda (from-index match seed)
        (cons
         (make-scratchcard
          (string->number (irregex-match-substring match 'card-no))
          (map string->number
               (string-split (irregex-match-substring match 'winning-numbers-str)))
          (map string->number
               (string-split (irregex-match-substring match 'card-numbers-str)))
          '() 1)
         seed))
      '() input-str))
Processing The Cards

I compare every card number with every winning number on a card, and put every card number with at least one match into the special slot of the record. Note that this is a non-functional operation, and thus modifies the original record! That is also the reason why the procedure name ends with an !.

  (define (calc-card-matches card)
    (let ((winning-nums (scratchcard-winning-numbers card))
          (card-nums (scratchcard-card-numbers card)))
      (for-each (lambda (card-num)
                  (when (foldl (lambda (matches? winning-num)
                                 (or matches?
                                     (= card-num winning-num)))
                               #f winning-nums)
                    (scratchcard-match-numbers-set!
                     card (cons card-num (scratchcard-match-numbers card)))))
                card-nums)))

As a next step, I calculate the points for each card.

  (define (card-points card)
    (let ((match-nums (scratchcard-match-numbers card)))
      (foldl (lambda (points num)
               (if (= 0 points)
                   1
                   (* points 2)))
             0 match-nums)))

And now, we can put everything together and sum up the points:

  (foldl
   (lambda (sum card)
     (calc-card-matches card)
     (+ sum
        (card-points card)))
   0 (input->cards input))
23441

Part Two

Quest

Just as you're about to report your findings to the Elf, one of you realizes that the rules have actually been printed on the back of every card this whole time.

There's no such thing as "points". Instead, scratchcards only cause you to win more scratchcards equal to the number of winning numbers you have.

Specifically, you win copies of the scratchcards below the winning card equal to the number of matches. So, if card 10 were to have 5 matching numbers, you would win one copy each of cards 11, 12, 13, 14, and 15.

Copies of scratchcards are scored like normal scratchcards and have the same card number as the card they copied. So, if you win a copy of card 10 and it has 5 matching numbers, it would then win a copy of the same cards that the original card 10 won: cards 11, 12, 13, 14, and 15. This process repeats until none of the copies cause you to win any more cards. (Cards will never make you copy a card past the end of the table.)

This time, the above example goes differently:

Card 1: 41 48 83 86 17 | 83 86  6 31 17  9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3:  1 21 53 59 44 | 69 82 63 72 16 21 14  1
Card 4: 41 92 73 84 69 | 59 84 76 51 58  5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
  • Card 1 has four matching numbers, so you win one copy each of the next four cards: cards 2, 3, 4, and 5.
  • Your original card 2 has two matching numbers, so you win one copy each of cards 3 and 4.
  • Your copy of card 2 also wins one copy each of cards 3 and 4.
  • Your four instances of card 3 (one original and three copies) have two matching numbers, so you win four copies each of cards 4 and 5.
  • Your eight instances of card 4 (one original and seven copies) have one matching number, so you win eight copies of card 5.
  • Your fourteen instances of card 5 (one original and thirteen copies) have no matching numbers and win no more cards.
  • Your one instance of card 6 (one original) has no matching numbers and wins no more cards.

Once all of the originals and copies have been processed, you end up with 1 instance of card 1, 2 instances of card 2, 4 instances of card 3, 8 instances of card 4, 14 instances of card 5, and 1 instance of card 6. In total, this example pile of scratchcards causes you to ultimately have 30 scratchcards!

Process all of the original and copied scratchcards until no more scratchcards are won. Including the original set of scratchcards, how many total scratchcards do you end up with?

Puzzle Solution

  (define (card-alist cards)
    (foldl (lambda (alist card)
             (calc-card-matches card)
             (alist-update (scratchcard-id card)
                           card
                           alist))
           '() (reverse cards)))
  (define (generate-copies cardlist #!optional (index 1))
    (let ((index-card (alist-ref index cardlist)))
      (if index-card
          (let* ((matches (scratchcard-match-numbers index-card))
                 (copies  (scratchcard-copies index-card))
                 (copy-indexes (foldl (lambda (indexes match)
                                        (cons (+ 1 index (length indexes))
                                              indexes))
                                      (list) matches)))
            (for-each (lambda (card-id)
                        (let ((target-card (alist-ref card-id cardlist)))
                          (scratchcard-copies-set!
                           target-card
                           (+ (scratchcard-copies target-card) copies))))
                      copy-indexes)
            (generate-copies
             cardlist
             (+ index 1)))
        cardlist)))
  (define (count-scratchcards cardlist)
    (foldl + 0 (map (compose scratchcard-copies cdr) cardlist)))
  (let ((cardlist (card-alist (input->cards input))))
    (generate-copies cardlist)
    (count-scratchcards cardlist))
5923918

Puzzle Input

Jump to day 5.

Card   1: 33 56 23 64 92 86 94  7 59 13 | 86 92 64 43 10 70 16 55 79 33 56  8  7 25 82 14 31 96 94 13 99 29 69 75 23
Card   2: 61 66 75  1 27 38 93 90 34 43 | 94 46 62 49 35 88 45 70 15 22 20 86 56 38 64 98 50  6 79 11 13 93 92 60 16
Card   3: 57  7 33 56 85  6 88 34 80  8 | 92 42  7 60 61 51 40  6 67 35  3 25 87  2 98 75 97 54 10 68 73 83  4 62 56
Card   4: 79 85 94 74 15 62 84 88 76 56 | 56  9 22 57  4 92 62 79 84 64 72 55 34 88 66 15 45 18 76 73 85 94  8 78 74
Card   5: 57 94 99 25 52 67 69 31 26 78 | 94 52 31 83 70 45 40 67 89 11 81 24 25 61 26 72 50 12 27 69 91 57 55 34 78
Card   6:  5 96  3 19 98 25 13 59 94  8 | 36 55 22 76 86 19 10  8 59  9 87 40  2 71 13 98 12 77  3 70  5 25 34 41 88
Card   7: 35 52 84 36 72 53 76 88 41 14 | 57 34 14 39 44 71 51  1 67 30 16 77 23 66 45 74 37 55 38 69 33 31 98 72 36
Card   8:  7 70 72 13 23  1 48 18 40 94 | 48 70 93 99 20 23 17 40 72 35 21  7 71  3 42 59 87 55 18 41 94  1 13 22 90
Card   9: 40  2 46 38 86 16 62 78 29 13 | 26 46 47 29 99 51 25 57 66 86 62  2 22 70 41  3 78 13 74 15 16 90 43 40 38
Card  10: 35 71 99 87 81 58  5 83 55 73 | 90 34 71 10 96 38 39 29 69 93 35 51 86 12 76 91 80 36 17 59 64 68 58 15 82
Card  11: 35 89 27 73 65 46 39 86 81 90 | 86 90 50 35 73 31 92 65 18 81 30 37 21 76 89 56 64 71 49 12 27 82 16 32 29
Card  12: 15 77 35 41 38 93 63 30 39 18 | 90 69 65 93 13  4 64 51 72 57 96 91 75 14 58 94 28 38 63 97 86 84 50 15 21
Card  13: 10 82 16 85 74 38 95 51 54 94 | 66 29 85 73 54  8 51 14 56 74 46 42 10 67 16 59 23  7 95 48 94  6 82 68 88
Card  14: 77 53 62 72 97  7 36 96 67 28 | 30 24 28 44 39 77 15 88 92  4 60 66 11 21 20 42 55 53  6 12 95 87 37 58 85
Card  15: 89 74 36  8 27 73 90 60 48 56 | 56 45 74 78 39  7 15  6 89 88  8 76 90 16 22 36 17 10 99 79 71 59 46 96 49
Card  16: 82 64 99 10 32 65 20 78 29 31 | 49 59  4 78 22 18 95 82 54 72 39 41 35 14 98  1 84 92 58 64 28 83 50  7 65
Card  17: 25  1 40 66 84 24 19 17 10 46 | 22 40  8 87 17 38  6 95 36 51 15 93 18 73 56  9 13 57 63 10 78 37 48  1 84
Card  18: 18 14 27 40 80 47  9 65 22  5 | 90 59 72 36 33 31 93 55 75  3 56 37 27 87 10 23 47 19 99 85 35 48 18 62 69
Card  19: 63 16 71 14  1 89 61 55 62 44 | 32  5 64 82 94 77 11 90 54 47 49 29 97 78 57 68 92 33 44 28 59 30 72 18  8
Card  20: 60 21 85  8 35 66 70 36  2 58 | 10 37 36 64 72 98 60 19 55 45 30 33 31 94 90 49 71 57 81 17 91 29 68 86 39
Card  21:  4 25 18  6 56 62 97  1 83 30 | 42 66 83 75 14 50 26 24 90 36 46 87 49 84 53 65 80 17 92 70 19 95  9 27 32
Card  22: 53 91 82 19 43 83 65 46  4 85 | 97 67 90 39 16  1 54 64 10 77 99 71 28 94 30 45 84 95 21 35 13 61 29 11 33
Card  23: 65 66 83 69 23 16 13  3 29 68 |  6 54 27 65 16 68 13 69 29 14 91 23 37 61 39 74 66 77 83 11 26 40 92  3 49
Card  24: 43 97 61 35 69 20 65  3 23 79 |  3 69 20 80 98 92 18 61 91 96 86 88 19 25 43 97 17 79 47 55 11 35 23 77 65
Card  25: 94 30 47 27  2 80 76 75 82 67 | 28 12 96 27  2 20  4 29 58 18 93 75 62 38 30 72 94 80 76 91 47 14 67 82 46
Card  26: 51 47 45 64  9 53 16 80 61 94 | 88 28 84 45 61 51 70 18  4 21 94 62  5 53 32 10 20 86 47 46 43  9 66 83 80
Card  27: 31  5 15 38 10 61 33 92 26 47 | 60 49 54 69  1 99 85 29 95 34 84 81 36 11 57 67 14 55 90 51 17  7 37 35 48
Card  28: 25 69 85 59 82 16  6 17 49 62 | 80 17 62 69 16 46 87 29 59 64 97 85 45 30  6 82 47 75 25 43 72 14  2 23 49
Card  29: 58 97 36 33 62 27 74 38 68 23 | 51 20 85 47 44 67 48 25 39 36 17 61 52 22 79  6 64 57 95 56 71 33 98 34 42
Card  30: 74 96 56 34 64 54 26 22 62 59 | 32 74 61  7 34 47 83 94 27 26 66 54 87 75 56 65 49 13 64 70 96 62 53 22 59
Card  31: 26  6 14 82 12 60 16  4 92 87 | 16 33 76 55 54 39 27 26 17 83  6 18 94 77  3 40 81 92  1 69 25 19 71 99  2
Card  32: 15  3 33 16 13 65  8 44 40 96 | 22 15 46 89 16 50  6 33 53 24 96 40  8 35 97 13  3 55 43 14 65 66 34 60 44
Card  33: 41 61 28 60 85 69 87 62 91 18 | 49 88 84 73 20 45 75 99 27 25  3 65 66 30 50 54 97 57 76 96  2  6 39  5 18
Card  34: 12 72 20 48 49 77 38 86 68 92 |  6 56 30 68 95 87 42 16 59 10  7 22 82 74  2 71 19 48 50  1 40 37 24 80 72
Card  35: 97 86 21 45 10 30 63  8 36 91 | 33 31 67 77 29 24 10 79 21 25 12 71 30  1 68 56 46 94 51 64  8 14 45  4 41
Card  36: 90 75 80 95 49 87  2 88 50 42 | 77 85 53 76 52 72 32 42 79 65 50 25 19 14 37 11 35 63 29 75 49 98 96 54 95
Card  37: 19 84 30 59 86 49 31 40 14 50 | 20 92 36 43 82 18 86 47 73 30 84 19 99  5 48 34 68 63 61 46 53 75 16 28 45
Card  38: 39 47 28 13 75 89 76 93 15 14 | 36 94 51 97 49 16 66 60 72 30 52  5  3 17 23  7 58 14 63 87 54  8 56 13 35
Card  39: 70 22  9 80 89 51 43 64 57 37 | 23 39  5 27 98 11 29 73 72 10 63 79 59 58 46 96  2 86 50 19 67 41 95 66 82
Card  40: 94 95  1 39 64 63 54 19 17 38 | 44 53 12 92 11 34 42 67 93 36  6  3 29 60  7 62 85  4 33 83  2  9 10 82 51
Card  41: 69 12 36 48 67  7 52 89 63 73 | 11 61 81 93 47 20 27 31 66 64 45 38  2 59 46  5 73  7 87 22  6 52 36 10 54
Card  42: 17 93  3 90 91 59  6 57 54 65 | 22 17 99 16  6 77 38 46 43 59 41 47 12  2 86  4 40 56 80 82 11 98 23 20 85
Card  43:  1 68 36 70 24 83 86 94 52  7 | 38  9 64 12 10 60 92 81 77 98 59 23 79 91 65 28 13 15  6 69 24 40 19 16 99
Card  44:  3 45 25  7 57 67 62 36 40 44 | 51 23 88 52 68 11 89 84 59 54 10 77 73 96 46 44 17 85 91 12 80 74  5 27 39
Card  45: 14 68 88 27 44 83 37 22 65  7 | 78 61 91 48 92 21 52 49 77 74 46 24 33 28 36 89 53 39 93 23 72 95  2 63 67
Card  46: 20 59 75 43 98 38 85 46 74 57 |  3 34 11  7 98 64 52 89 43 41 87 57 19 56 37 68 20  2 99 91 23 17 74 48 78
Card  47: 87 20 73 47 82 37  3 68 29 65 | 15 53 58 25 62 13 31 59 11 63  2 89 30 71 35 36 82 37 75 67 17 12 34 90 19
Card  48: 63 11 55 53 44  7  3 41 60 40 | 73 61 87 91 46 60 51 31 11 32  7 44 41 78 55 14 59  3 63 53 74 94 62 65 40
Card  49: 30 62 35  9 40 51 68 55 79 97 | 53 87 77 97 63 11 52 67 51 35 68 79 99 98  5  9 40 37 19 49 30 16 55 75 62
Card  50: 66 80 74 99 63 84 35 26 83 67 | 43 92 52 67 63 84 16 21 88 23 31 22 24 49 59 99 75 47 66 80  1 83 91 95 70
Card  51: 68 99 70 39 79 10 81 27 46 80 | 70 17 46 68 61 50 43 48 79 81 12 32 65  1 27 39 80 99 58  8 19 10 41  4 73
Card  52: 37 86 40 43 66 14 63  2 19 50 | 96 50 27 43 64 83 13 92 63 86 37 19  2 40 58 66  3 31 59 14 62 61 67 54 53
Card  53: 78 33 11 45 12 22 19 38 87 74 |  2 50 63 33 97  8 58 99 48 22  4 45 11 60 74 21 69 78 87 29 12 39 19 18 38
Card  54: 11 51 64 21 19 87 70 80 55 95 | 11 69 53 94 24 96 87 59 95 76 23 19 68 47 51 74 70 55 32 77 80 64 21 36 78
Card  55: 92 99 88 93  1 26 13  4 61 11 | 71 92 99 61 76 56 46 89  4 67  3 45 22 81 19 33 50 26 93 28 13 72  1 11 88
Card  56: 11 65 76 35 97 63 16 57 92 53 | 96 30 65 82 76 59 63 97 35 40 16 98 86 79 41 11 78 95 10 88 29 28 64  5 74
Card  57: 32  5  1  8 43 15 25 79 96 71 | 25 49 31 90 39 77 27 83 15 56 41  5  1 26 58 33 34 79 62  8 96 32 92 43 71
Card  58: 65 20 54 93 18 31 97 99 94 86 | 89 46 12 27 23 42 43 88 75 73 35 49 95  9 37 66 50 62 51 48 11 17 26  1 41
Card  59: 62 38 28  4 59 53 16 89 52 35 | 27 47 52 12 35 86 59  8 39 31 81 55 95 79 37 89 58 14 30 80 68 87 43 84 56
Card  60:  8 89 16 22 75 94 34 67 78 62 | 84 81 29 51 10 70 91 95 32 34 46 12 67 66 68 99 74 87 92 78 90 13 76 18 27
Card  61: 27 92 80 94 87  2 75 26 22 79 | 36 34 76 84 22 48 52 86 79 46 81 80 87 78 27 95 70 51 35 49  9 89 75  8 67
Card  62: 89 10 56 52 80 76 46 31 69 24 | 73  6 53 98 17 65 44 16 83 45 92 41 94  3 81 99 26 61 43 67  2 93 36 28 29
Card  63: 38 74 68 99 88  4 42 87 58 31 | 39 99 22 11 16 50 52 53 85 34 67 76 55 42 45  8 89 43  2 20 75  4 97 28 70
Card  64: 22 38 75  7 35 62 49 30 10 32 |  1 54 59 40 12 74 46 51 37 21 72 57 97 82 31 25 87 47 29 43 67 88 19  9  8
Card  65: 21 69 41 76 88 73  4 77 34 93 | 92 53 25 78 81 84  8 49 77 41 28 70 12 88 91 45 29 15 86 46 32 96 57 34 54
Card  66: 42 60  7 35 31 50 13 61  9 19 | 53 18 80 69 78 88 24 56 29 62 49 95 64 81 11 42 17 40 34 28  6 98 70 54 91
Card  67: 36 50 47 89 18 54  9 25 92 91 | 87 59 85 42 62 37 26 21 52  4 90 19 75 23 67 33 35 49 69 79 14 80 46 97 98
Card  68: 92 43 44 34 29 75  6  1  8 31 | 88 85 55  9  1 95 14 97 67 42 22 72 89 19 90 35 74 96 58  5 57 51 47 37 69
Card  69: 59 43 21 14  5 85 20 12  1  7 | 40 11 63 87 72 34 83 86 94 31 66  3 24 98 82 39 65 35 51 77 67 18  2 47 90
Card  70: 24 83 87 85  3 48 99 11 21 33 | 76 92 16 81 61 86 83 14 57 44 74 41 98 63 96 38 89 65 32 11 48 51 53 23 19
Card  71: 57 77 65 66 16 50 49 39 55 87 |  3 45 97 44 31 14 25 70 13 72 16 41  2 66 88 69 57 26 54 95 80 10 65 28 86
Card  72:  3 80 44 10 43 90 71 20 17 85 | 86 53 46 72 74  3 91 99 19 55 94  2 65  4 36 26 29 16 95 48 11 24 90 76 78
Card  73: 71 11 88  6 54 78 97 30 91 92 | 52 86 23 91 78 54 97 66 11 44 30  8 93 71 16 92 21 83 84 88 34  6 33 26  9
Card  74: 87 88 97 95 33 72 21 39 60 66 | 65 68 95 84 97 32 72 21 43 74 23 55  1 96 92 87 25 66 60 16 33 59 39 98 88
Card  75: 40 81 51 37 56 61 25 84 82  4 | 82 84 43  7 23 61 14 38 63  5 27 85 48 71 56 99 30 96 29 40 18 37 77 13 16
Card  76: 40 46 25 27 39 47 33 37 36  7 | 13 39  9 80 34 38  8  7 60 48 92 71  5 40 10 41 37 21 67 29 25 43 69 28  2
Card  77: 25 10  9 74 66 52  6 22 41  3 | 32 24 86  5 47 22  6 23  3 69 56 40 28 52 54 17 95 53 68 39 60 74 71 99  4
Card  78: 59 18 58 51 88  8 92 27 82 79 | 97 86  8 11 79 28 88 70 48 80 42 37 87  2 92 95 55 59 82 40 50 27 51 68 63
Card  79: 51 97 54 22 64 44 80 27 96 47 | 93 72 29 23 96  1 54 66 51 24 22 62 87 97 35 27 44 77 79 64  3 37 47 45 80
Card  80: 64 67 54 24  8  4 35 89 15 23 | 67 12 13 77 45 15 54 92 89  9 96 95 25 24 99  4 81 52 46 35 69 64 23 79  8
Card  81: 34 25 84  7 23 12 54 30 20  1 | 49 26 82  7 13 75 89 58 53 67 93 46  8 97 32 86 11 72 28 54 98 56  1 45 55
Card  82: 87 24 17 63 67 65 43 97 38 95 |  8 40 49 43 15 36 88 11 83 29 46  7 62 31 51 23 69 67 66 39 54 72 35 80 65
Card  83: 12 57 85 81 48 97 45  5 72 11 | 68 98 58 29  8 22  9 30 49 51 67 47 74 13 40 65 94 44 91 34 92 82 14 33 61
Card  84: 95 33 18 64 24 92 27 29 57 53 | 56 19 14 79 60 36  6 12 75 71 26 87  4 58 54 16 52 31 98 17 85 40 61 41 77
Card  85: 42 71 23 49 53 96 88 48 60 95 | 66 18 98 88 58  7 12 11 89 37 13  1  6 28 45 47 30 31 55 57 17 97 77 99  4
Card  86: 44 31 35  2 49 88 26 98 43 42 | 19 46 70  1 92 12  3 11 30 74 33 38 95 17 24 75  9 28 83 32 40 65 62 10 29
Card  87: 98 23 88 50  4 73 92  5 11 24 | 85 14 59 94 41 69  5 99 46 22 27 61 77  7 60 95 58  6 30 24 44 92 10 88 23
Card  88: 39 61  4 84  2  6 33 53 85 42 |  3 77 16 69 11 76 48 80 95 15 12 10 83 78 19 57 30 56 52 46 58 88 55 35 13
Card  89: 27 97 32 38 46  3 62 40 58 89 |  6 91 80 72 21 56 24 50 82 54 74 97 60 73 47 96 13 38 84 12  9 69 14  3 41
Card  90: 80 50  8 55 93 29  3 87 84 27 | 38 83 96 69 76 28 18 87 32 45 89 48 82 91 70  6 25 24 73 42 19 49 34 51 93
Card  91: 10 40  8 20 83 79 47  2 69 12 | 31 79 74 71 87 57 41 36  7 22 76 42 82 72 16 78  3 67 43 52 26 85 39 25 14
Card  92: 72 76 71  8 20 13 48 25 81 47 | 33 94  7 85 64 93 53 31 10 21 92 50 70 23  1 99  2 12 18 97 66 45 57 51 55
Card  93: 50 21 56 54 41 32 77 19 93 13 | 36 88 97 56 53 99 68 26 13 21  9 86 77 41 50  3 16 75 98 48 24 62  8 32 93
Card  94: 52 39 66 88 19 43 80 53 33  3 | 66 34 43 41 65 92 80 50 72 86 94 69 52 53 39 67 83 16 25 19 99 93 11 33  6
Card  95: 22 38 17 63 68 51 79 72 81 61 | 79 63 38 71 81  1 78 13 68 33 21 51 12 57 53 67 97 22 62 72 61  2  9 17 73
Card  96: 83 96  2 47 21 68 50 78 19 29 | 77 66 37 59 36 96 74 16 80 84 65 87 90 58 89 48 42 47 68 85 35 49 56 40 19
Card  97: 72  8 69 10  3 33 79  4 99 65 | 26 99 96 10 31 33  8 58 38  4 40 69  6 97 80 79 98 65 20 57 73  3 81  5 72
Card  98: 43 67 24 40 95  3 27  1 89 39 | 24 87 37  1 26 72 19 95 43 89 32  3 27  5 55 40 25 71 69 67 39 74 56 93 35
Card  99: 68 24 93 30 34 20 27 89 37 50 | 93 77 86 17  4 30 60 37 98 24 68 34 14 39  8 31 18 50 48 10 20 12 27 78 70
Card 100: 68 45 61 38 58 50 27 87  9 96 |  3 23 52 54 76 49 34  8 81 78 11 38 33 15 26 40 37 67 94 51 24  5 30 97 31
Card 101: 23 16 99 80 29 13 81 67 27 22 | 94 53 95 19 66 31 96  3 60 28 38 30 35 47 44 68 75 82 56 18  5 50 36 78 64
Card 102: 17  2 85 30 78 23 93 46 88 92 | 18 44 84 92 13 62 48 46 53 31 52 17 93 78 29 51 99 39 30 23 91  5 81  2 33
Card 103: 35 21 66 81 40 75 50 88 14  6 | 16 25 61 81 13  6 17 77 38 66 98 41 45 54 23 19 99 21 49 32 51 35  8 47 65
Card 104: 29 37 46 77 92 53 81 20  9 96 | 94 81 75  8 24 78 68 48  4  5 98 16 30 57  3 10 14 70 36 33 91 64 47 18 87
Card 105: 15  2 31 71 99 30 26 61 79 32 | 21 49 58 16 67 94  5 75  4 69 96 51 28 53 17 89 25 85  1 12 83 82 10 33  6
Card 106: 51 24 14 80 10 38 53 55 41 32 | 69 66 91 73 65 12 36 75 45 90 46 58 80 57 74 28 39 37 95 22 30 62  7 32  1
Card 107: 26 78 66 42 54 69 51 95 17 52 | 64 69 20 75 87 30 11 42 60 47 85 46 80 36 40  7 94 68 33 21 31 83 89 10 82
Card 108: 82  2 99 56 80 38 54 47 20 29 | 23 56 40 97  5 81 37  4 69 48 91 64 58 73 32 61 54 78 77 43 67 14 17 68 15
Card 109: 97 80 18 44 73 53 15 50 47 48 | 30 41 82 36 43 86 95 56 33  4 89 47 28 59 27 31 92 12 93 32 60 74 99 26 75
Card 110:  4 58 43 91 66 59 69 73 37 94 | 35  3 65 27 77 52 44 38 86 79  2 32 56 84 10 60 18 24 49 64 61 78 93 99 22
Card 111: 52 86 22  5 18 14  7 92 65 56 | 50 86 28 52 14 48 56 93  5 22 80 76 65 25 92  2 78  7 45 49 70 47 18 15 53
Card 112: 10 36 28 87 20  7 93 15 65 53 | 27 93 36 83 87 46 24  1 86 43 28  7 89  4 32 20 38 14 15 67 57 29 69 40 10
Card 113: 27 38 49 70 32 56 22 11 43 10 | 25 75 85 29 63 83 35 95 65 15 84 49 87 27 74 43 11 13 46 10 72 56 22 70 57
Card 114: 91 82 29 32 44 84 51 67 94 11 | 51 69 55 28 89 74  8 96 93 35 42 33 73 44  3 31 36 68 38 11 94 46 29 12 82
Card 115: 88 46 87 97 52 18 20 96  2  3 | 17 36 23 42 67 93 72 24 10 89 87  8 66 48 25 50 61 32 59 52 84  2 35 99 65
Card 116: 50 23 72 60 40 77 97 90 98 70 |  3 76 97 92 72 11 28 60 30 29 35 45 70 62 84 55 57 87 22 14 38 69 51 25 86
Card 117: 31  4 58 33 86  7 47 25 62 87 | 44 36  7  4 73 84 25 58 65 14 23 96 55 31 27 87 77 17  9 15 47 22 98 69 62
Card 118: 71 33 83 75 28 82 56 94 21 42 |  1 21 43 28 13 86 19 82 58 48 89 94 71 91 41 95 27 79 73 93 75 31 66 30 83
Card 119: 38 69 51 58 93 60 13 66 90 71 | 44 94 98 53 49 69  9 74 24 57 71 45 12 78 18 56 88 68 85 42 35  1 47 17  2
Card 120: 44 82 72 71 73 16 39  5 93 81 | 57 21  8 33  3 69 54 47 26 70 53 10  5 44 77 31 29 87 24 19 93 37 80 65 84
Card 121: 90 63 79 82 91 85 98 70 14 28 | 66 71 82 27  2 29 44 73 76 18 47  3 55 64 34 25  6 88 81  8 30 19 75  1 31
Card 122: 80  4  6 16 18 20 23 35 50 90 | 50 25 27  1 70 12 60 19 96 37 57 82 69 89 45 87 23 26 75 90 48 42 30 78 54
Card 123: 32  6  8 96 56 86 73 18 71 92 | 35 64 83 21 15 95 49 80 33 93 11 45 29 78 68  5 60 63 86 67 57 91 42 51 97
Card 124: 72 84 64 25 99 28 40 98 96 59 | 31 50 67 35 94  3 10 95 85 38 46 45 80 42  6 62 97 52  7 92 83 44 55 65 21
Card 125: 13 63  2 53 48 38 88 14  5 58 | 49 50 91 75 40 66 34 71 24 52 28 26 55 19 25 73 98 56 11 41 96 21 85 67 29
Card 126: 55 36 33 58 17 53 39  6 21 52 | 88 30 68 84 61 14 17 97  7 19 99 54 45 56 52 35 92 50 85 36 24 70 27 29 75
Card 127: 96 37 56 99 84 12 10 70 93 55 | 85 77 82 60 74 20 51 27 92 12 59 98 91 81 56 31  6 53  4 10 89 84 90 69 55
Card 128: 63 44 56 61 88 65 33 85 81 55 | 58 28 88 75 33 89 20  8 61 37  6  9 19 92 46 17 35 94 29 62 76 41 55 57 80
Card 129: 86 99 43 13 11 17 67  9 50 33 | 47 67  6 69 11  5 13 98 96 89 57 40 61 79 33 80 15 42 62 92 59 86 10 65 44
Card 130:  4 71 54 22 81  7 25 19 29 50 | 91 16 36 54 51 19 50 80 83  7 81 64 61 30 85 72 79  9 13 12 67 59  4 31 20
Card 131: 87 91 50 20  3 77 14 47 97 76 | 71 87  8 34 78 27 32 61 33 89 62 52 72 17 60 16 42 51 64 49 66 86 22 30 59
Card 132: 68 17  4 26  8 14 41 57 21 31 | 98 31 75 47  9 48 30 65 36 40 70 57 77 72 76  3 21 42 68 24 96  7 23 17 10
Card 133: 46 32 98 75 52 49 80 60  9 47 | 87  3 69 96 29 80 54 98 53 49 66 88 35 75 58 40 93 73 42  2 30 90  1 76 22
Card 134: 23  8 93 17  5 21  9 19 13 82 | 71 37 95 91 65 43 27 44 36 24 98 99  2 74 20 88 49 17 76 80 46 57 79 94 81
Card 135: 81 28 19  5 22 75 18 74 51 13 | 32 66 55 62 17 60 96 70 23 37 34 67 14 84 24 76 16 47 94 56 38 65 25 97 98
Card 136: 72  8 16 42 50 75 57 39 82 41 | 86 82 57 11 62 92 79 78  1 41  3 64 15 12 46 31 89 45 63 91 81 47 96 27 10
Card 137: 64 70 10 41 33 73 22 62  9 21 | 25 47 90 79 14 97 80 34 33 40  4  6 64 28 83 91 73 63 37 44 98 42  5 12 62
Card 138: 87 14 61  6 27 82 35  8 54 56 | 95 36 51 60 98 78 30 83 19 58 72  4 88 10 77 69 96  8 87 74 27 92 65 75 35
Card 139:  4 16 59 44 74 86 33  5 95 60 | 14  2 34 29 44 26 12 70 66 47 67 52 85 71 95  7 11  4 30 77 40 96 36 98  6
Card 140: 12 86  6 69 88 43 13 55 81 10 | 19 71  6 51 72 46  2 97  3 67 56 74 90 42 86 28 32 52 98 17 38 76 77 49 10
Card 141: 29 72 27 68 17  7 45 64 49 26 | 35 11 29 26 66 14 41 52  6 42 92  5 99 39 24 59 75 12 83 51 78 58 28 81 93
Card 142: 41 63 11 16 15 59 97 34 40 23 | 39 85 37 84 30 20 77 60 36 19 42 61 11 67 10 21 99 87 32 66 48  1 28  5  9
Card 143: 47 14 63 53 73 40  7 50 15 21 | 69 96 26 94 38  9 10 79 78 48 82 66 59 57 12 37 74  1 92 98 88 42 31 39 23
Card 144: 36 88 96 60 86 29  1 57 37 46 | 99 47 22 57  3 60 29 87 86 36 58 30 40 37  1 33 88 49 46 11 96 80  9  8 82
Card 145: 54 66 15 59 79 52 73 14 23  8 | 50  8 20 14 92 72 98 80 85 77 42 49 59 58 18 91 90 17 21 97  1 19 53 84  2
Card 146: 36 80 57 90 97 28 76 52 77 45 | 41 14 46  8 84 91 20 57 52 99 37 67  3 55 10 87 25 18 43 77 97 80 78 85 74
Card 147: 64 12 80 55 49 67 78 28 20 10 | 20 43  1 78 83 39 80 38 24 54 75 49 94 22 26 67 71 97 64 28 12 45 10 55 89
Card 148: 57 96 75 17 53 63 60  8 95 27 |  8 60  2 82 19  5 24 98 27 93 80 86 63 97 17 53 99 59 70 14 78 96 95 57 75
Card 149: 50 95 82 20 27 47 80 48 13 49 | 87 77 20 82 88 74 94 48 13 99 30 65 47 27 11 49 80 61 71 50 34 62 85 18 95
Card 150: 52 14 22 54 43  3  1 99 73 39 | 42 97 89 92 58  8 60 80 82  5 28 17 35 79 40 50 61 56 53 75 95 25 83 31 15
Card 151: 44  9  3 78 73 55 32 59 70 24 | 75 23 91 37 81 66 24 59 70 38 25 55 54  9  3 73 32 44 89 39 78 64 83 12  7
Card 152: 37 29 16 15 24 41 40 99 21 87 | 37 78 68 17 95 60 69 44 55 21 66 96 82 65 87 29 23 36  4 20 15 52 94 75 74
Card 153: 72 80 39 77 71 29 83 10  7 93 | 10 51 52 12  1 22 65 62 33 32 34 11 13 55 72 57 76 96 85 95 90  3 64 47 31
Card 154: 89 66 34 86  8 75 50 98 56 71 | 74 39 16 68 56 27  5  2 58 97 75 34 90 91  8 71 95 66 50 98 60 92  6  9 35
Card 155: 23 84 27 71 33 15 96 25 14 57 | 11 31 46 14 77 88 27 60 59 93  3 96 48 71 33 15  5  6 23 79 89 82 57 25 84
Card 156: 10 25 83 53 73 33 56 29 95 24 | 22 29 11 32 41 74  4 43 46 38 78 16 91 12 73 54 62 10 25 47 52 65  7 28 63
Card 157: 97 31 12 42 32 23 29 72 98 99 | 64 41  3 57 25 76 46 80 75 47 73 87 91 95 82 55 31 35 51 60 16  8 78 77 66
Card 158: 90 46 61 13 33 59 12 25 30 49 | 29 57 31 46  1 64 93 43 94 21 87 83 23 67 91 52 92 85 71 78 36 79 62  5 58
Card 159: 75 92 63 61 69 53  1 74 51 27 |  3 87 65 74 10 59 54 42 22 95 26 24 67 91 33 55 92 77 98 79 43 82 13 12 27
Card 160: 50 38 97 82 73 27 91 79 74 41 | 69 71 34 94 55 40 23 84 10 25 14 67  7 46 48  6 37 91 12 66 16 17 26 22  9
Card 161: 57 19 25 38 12 76 89 95 10 33 | 31 63 68 46 42 79 94 60  7 44 36 56 91 23 35 85 41 87 71 58 82 54 11  9 81
Card 162: 17 54 37 84 85 46 99 51 86  7 | 32 38  4 66 49  7  9 23 76 35 51 85 52 30 45 19 89  6 82  5 58 91 87 72 50
Card 163: 44  4 10 46 38 87 52 83 85 16 | 79 42 21 58 75  3 25 56  7 50 69 57 27 84 38 39 89 70 59 78 93 85  8 96 72
Card 164: 76 26 66 23 89 37 87  9 34 81 | 84 43 14 21 13 20 95 97  3 33 18 88 81 78 16 86 58 48 90  6 61 11 68 62 64
Card 165: 15 54 48 34 18 25 85 23 82 43 | 79 49 95 24  9 96 58 27  2  8 77  3 90 71 86 78 31 80 28 81 26 69 57 29 17
Card 166: 23 94 29 56 27 33 51 55 79 98 | 85  7 89 74 69 15 19  2 97  5 27 88 43 80 86 62 78 76 67 63 30 20 65  1 37
Card 167: 69 37 95  7 53 80 16 82 11 27 | 22 75  5 93 47 62 76 49  2 89  9 50 21 85 34 90 38 86 45 42 18 25 33 98 99
Card 168: 95 12 30 74 21 24 80 64 17 67 | 86  8 98 19 37 48 75 56 16 31 20 40 29 83 79 73 71 27 59 43 65 61 57 78 81
Card 169: 80  8  4 83 15 47 93  2 41 25 | 69 80 93 30 75 16 25 74 61 15 56 67 47  4 85 44  2 87 19 92 70 95 41 94 81
Card 170: 91 25 44 98 29 80 63 26 72 88 |  7 57  3 38 17 44 70 75 88 92 54 14 80 26  8 40 98 55 39 32 72 29 61 63 86
Card 171: 74 37 39 87 31  6  8 38 76 32 | 67 83 34 96 68 64 69 82 54 74 63 12 25 85  9 35 50 87 59 33 60 11 20 32 84
Card 172: 45 96  3 16 97  2 98 27 51 34 | 63 82 10 95  6  5 14 24 57 69 98 23 51  3 43 91 79 35 20 36 48 44 90 84 70
Card 173: 83 69 34  6  8 44 42 33 28  5 | 86 32 56 57  3 19 91 43 80 29 78  8 93 47 73 34 85 77 48 65 83 11  2 15 26
Card 174: 22 30 18 86 72 57 26 29 38 69 | 37 21 80 26 61 68 52 33 15 74 69  9 66 81 17 40 99 78 23 65 43  1 95 79 24
Card 175: 91 47 88  2 62 39 21  4 48 49 | 14 65 12  4 51 21 42  6 79 17 57 10  7 55 98 70 47 49  5 90 18 67 58 62 54
Card 176: 76  7 72 24 57 19 70 41 67 87 | 37 59 36 95 90 28  8 58 93 97 40 57 18 80 69 66 13 54 87 27 86 62 76 84 19
Card 177: 61 23 95 38  1 85 28 51 49 53 |  6 34 38 33 16 39 64 57 10 11 80 78 60 18 12 27  5 75 28 36 25 63 88 74  8
Card 178: 22 69 42 55 54 52 58 11 89 70 | 54 75  5 88 74 97 64 59 94 82 16 76 58 20 23 90 28 47 67 38 66 51 42 83 52
Card 179: 51 45 20 68 69 24 54 52 73 89 | 88  3 64  5 72  1 39 17 53 79 97  8 83 49 50 77 70 76 90 18 59 15 29 61 10
Card 180: 68 10 39 93 62 32  1 20 90 99 | 40 31 38 23 63 27 94 85 87 36 53 67 56  5 72 13 22  6 89 25 35 64 41 57 65
Card 181: 43 76 19 35 75 71 27 13 23  5 | 56 21 87 50 30 46  2 47 85 16 44 73  3 68 38 59 92 17 65 48 22 32 42 52 83
Card 182: 77  3 61 97 96 84 27 48 52 40 |  9 54 65 43  7 20 29 86 73 67 87 82 42 14 55 33 39 71  1 81 69 31 92 74 75
Card 183: 10 52 76 84 82 14 93 34 60 73 | 81 34 75 67 23 82 68 47 73  1 52 45 25 10  6 37 84 93 21 60 79 89 76 14 18
Card 184: 39 91 94 34 71 86 36  2 65 74 | 46 37 91 79 74 59 65 66 34 30 40 73 36 16 64 57 92 71  2 78 94 89 77 86 39
Card 185: 76 22 70 57 85 51 44 43 84 14 | 80 22 29 66 75  1 97 72 21 38 76 13 27 33 69 65 74  7 11 84 53 98 77 17 82
Card 186: 59 49 71 34 66 23 52 79 32 28 | 59  2 32 93 70 96 86 71  1  3 10 28 49 51 66 79 61 24 23 19 46 52  7 34 42
Card 187:  3 31 77 49 45 15 47  6 20 25 | 25 67 88 20 49  6 46 45  9 98 24  2 59 70 77 99 22 13 31 53 91 15  3 74 47
Card 188: 84 19 66 65 53 61 38 25 83 91 | 24 64 43 66 11 72 53 94 86 39 28 97 18 70 68 52  5  7 30 55 38  9 85 34 31
Card 189: 86 22 88 18 87 28 63 92  5 16 | 33 90 71 18 88 39 28 22 26 14 68  1 52 93 56 87 49 77 92 19 86 63  5 16 72
Card 190: 67 83 94 44 66 25  9 98 21 51 | 55 97 76 81 85 68 40 94 66 41 51 45 69 44 50 37 63 83 87 39  2 96 98 95 13
Card 191: 92 89 36 65  6 72 46 23 84 19 | 94 51 99  1  3 88 77 35 90 68 72 87 44 25 69 37  2 42 59 22 58 73 61 43 33
Card 192: 52 49 74 40  2 89 54 87 21 79 | 50 58 54 24 79 27 74 72 62 67 46 89 52 38 83 40 49 29 26 77 87 12  5 21  2
Card 193: 32 59 96 29 80  7 54  3 39 83 | 83 21 80 98 13 54 87 43 29 96 62 75 53 68 88 65 59 33  3 32 67 39 10 77  7
Card 194: 40 12 79 91 84 54  1 74 56 38 | 31 78 38  9 25 46 10 99 54 11  2 97  5 84 37 77 27  1 50 91 43 72 12 96 56
Card 195: 80 34 51 81 55 65 49 71  8 44 | 81 71 83 92  8 51 80 53 30 55 44  2 43 16 24 69 18 57 31 49 65 47 91 79  3
Card 196: 12 22 77 95 49  1 48  8 84 47 | 61 64 63 42 55 13 96 70 73 41 92 10 58  6 86 30 14 23 91 66 87 72  9 27 51
Card 197: 90 30 14 35 11 20 99 79 56  2 | 75 59 40 15 80 36 97 44 17 77 20 10 50 29 33 39 55 32 85 71 43 26 35 24 82
Card 198: 92 98 86 34 64 32 74 17 26 53 | 32 75 97 22 66 89 74 17  8 31 69 52 41 53 34 77 45 46 68  2 96 86 95 93 21
Card 199: 32 31 52 80  2 47  1 13 89  9 | 28 32 87  9 96  7 20 12 73 60 46 78 24 69 55 58 64 14 38 97 16 92 52 79 82
Card 200:  1  8 31  4 53 15 45 22 73 13 | 22 10 73  9 81 74 83  2 11 53 15 45 46 21 62 43 69 50 32 67 41 48  5 25 24
Card 201: 45 37 26 53 80  1 20 35 68 33 |  6 51 77 11 41 53 56 18 25 27 13 42 48 14 79 16 81 59 99 29 86 78  3 15 17
Card 202: 86 56 57 83 11 19 52 69 36 17 | 65 72 11 95 73 49 25 75 15  5 84 35 18 71 44 99 26 52  9 60 45 22 14 19 94
Card 203: 76 23 26 70 12 48 60 11 72 64 | 90 56 99 59 64 62 15 84 71 11 85 93 98 33 46 86 53 39  5 60 81 43  3 78 14
Card 204: 23 75 70 14 95 84 61  9 66 77 | 79  8  1 64 50 41 32 93 58 15 33 10 28 72 82 16 77 65 25 43 39 49 13 23 83
Card 205:  2 99 53 15 32  6 16 69 21 14 | 96 98 24 66  6 47  4 54 45 46 42 13 75 11 80 18 34 35 93 79 65 37 40 92 91
Card 206: 74 30 29 66 68  2  3 34 79 87 | 63 45 88 78 98 27 97 32 38 75  9 11 71 93 55 69 56 20 12 82 81 41 80 23 94

Day 5: If You Give A Seed A Fertilizer

Part One

Quest

You take the boat and find the gardener right where you were told he would be: managing a giant "garden" that looks more to you like a farm.

"A water source? Island Island is the water source!" You point out that Snow Island isn't receiving any water.

"Oh, we had to stop the water because we ran out of sand to filter it with! Can't make snow with dirty water. Don't worry, I'm sure we'll get more sand soon; we only turned off the water a few days… weeks… oh no." His face sinks into a look of horrified realization.

"I've been so busy making sure everyone here has food that I completely forgot to check why we stopped getting more sand! There's a ferry leaving soon that is headed over in that direction - it's much faster than your boat. Could you please go check it out?"

You barely have time to agree to this request when he brings up another. "While you wait for the ferry, maybe you can help us with our food production problem. The latest Island Island Almanac just arrived and we're having trouble making sense of it."

The almanac (your puzzle input) lists all of the seeds that need to be planted. It also lists what type of soil to use with each kind of seed, what type of fertilizer to use with each kind of soil, what type of water to use with each kind of fertilizer, and so on. Every type of seed, soil, fertilizer and so on is identified with a number, but numbers are reused by each category - that is, soil 123 and fertilizer 123 aren't necessarily related to each other.

For example:

seeds: 79 14 55 13

seed-to-soil map:
50 98 2
52 50 48

soil-to-fertilizer map:
0 15 37
37 52 2
39 0 15

fertilizer-to-water map:
49 53 8
0 11 42
42 0 7
57 7 4

water-to-light map:
88 18 7
18 25 70

light-to-temperature map:
45 77 23
81 45 19
68 64 13

temperature-to-humidity map:
0 69 1
1 0 69

humidity-to-location map:
60 56 37
56 93 4

The almanac starts by listing which seeds need to be planted: seeds 79, 14, 55, and 13.

The rest of the almanac contains a list of maps which describe how to convert numbers from a source category into numbers in a destination category. That is, the section that starts with seed-to-soil map: describes how to convert a seed number (the source) to a soil number (the destination). This lets the gardener and his team know which soil to use with which seeds, which water to use with which fertilizer, and so on.

Rather than list every source number and its corresponding destination number one by one, the maps describe entire ranges of numbers that can be converted. Each line within a map contains three numbers: the destination range start, the source range start, and the range length.

Consider again the example seed-to-soil map:

50 98 2
52 50 48

The first line has a destination range start of 50, a source range start of 98, and a range length of 2. This line means that the source range starts at 98 and contains two values: 98 and 99. The destination range is the same length, but it starts at 50, so its two values are 50 and 51. With this information, you know that seed number 98 corresponds to soil number 50 and that seed number 99 corresponds to soil number 51.

The second line means that the source range starts at 50 and contains 48 values: 50, 51, …, 96, 97. This corresponds to a destination range starting at 52 and also containing 48 values: 52, 53, …, 98, 99. So, seed number 53 corresponds to soil number 55.

Any source numbers that aren't mapped correspond to the same destination number. So, seed number 10 corresponds to soil number 10.

So, the entire list of seed numbers and their corresponding soil numbers looks like this:

seed  soil
0     0
1     1
...   ...
48    48
49    49
50    52
51    53
...   ...
96    98
97    99
98    50
99    51

With this map, you can look up the soil number required for each initial seed number:

  • Seed number 79 corresponds to soil number 81.
  • Seed number 14 corresponds to soil number 14.
  • Seed number 55 corresponds to soil number 57.
  • Seed number 13 corresponds to soil number 13.

The gardener and his team want to get started as soon as possible, so they'd like to know the closest location that needs a seed. Using these maps, find the lowest location number that corresponds to any of the initial seeds. To do this, you'll need to convert each seed number through other categories until you can find its corresponding location number. In this example, the corresponding types are:

  • Seed 79, soil 81, fertilizer 81, water 81, light 74, temperature 78, humidity 78, location 82.
  • Seed 14, soil 14, fertilizer 53, water 49, light 42, temperature 42, humidity 43, location 43.
  • Seed 55, soil 57, fertilizer 57, water 53, light 46, temperature 82, humidity 82, location 86.
  • Seed 13, soil 13, fertilizer 52, water 41, light 34, temperature 34, humidity 35, location 35.

So, the lowest location number in this example is 35.

What is the lowest location number that corresponds to any of the initial seed numbers?

Puzzle Solution

Mapping Record
  (define-record entity type id)
  (define-record mapping-entry from-type to-type from-start from-end to-start to-end)
Data Extraction
Irregexes
  (define seed-irregex
    '(: (* whitespace)
        "seeds: "
        (submatch-named seed-numbers (+ (or numeric whitespace)))))
  (define mapping-irregex
    '(: (submatch-named mapping-from (+ alphabetic))
        "-to-"
        (submatch-named mapping-to (+ alphabetic))
        " map:"
        (submatch-named mapping-vals (+ (or numeric whitespace)))))
  (define mapping-nums-irregex
    '(: (* whitespace)
        (submatch-named to-range (+ numeric))
        (* whitespace)
        (submatch-named from-range (+ numeric))
        (* whitespace)
        (submatch-named range-size (+ numeric))))
Data Reading

A list of seed numbers:

  (define (input->seeds-list input)
    (let ((seeds-str (irregex-match-substring
                      (irregex-search seed-irregex input)
                      'seed-numbers)))
      (map string->number (string-split seeds-str))))

And a mapping from input type (e.g. #:soil) to the mappings to the next type:

  (define (input->mapping-alist input)
    (irregex-fold mapping-irregex
                  (lambda (from-index match seed)
                    (let ((map-from-key     (string->keyword (irregex-match-substring match 'mapping-from)))
                          (map-to-key       (string->keyword (irregex-match-substring match 'mapping-to)))
                          (mapping-vals-str (irregex-match-substring match 'mapping-vals)))
                      (cons
                       (cons
                        map-from-key
                        (irregex-fold mapping-nums-irregex
                                      (lambda (from-index match seed)
                                        (let ((from-start (string->number
                                                           (irregex-match-substring match 'from-range)))
                                              (to-start (string->number
                                                         (irregex-match-substring match 'to-range)))
                                              (range-size (string->number
                                                           (irregex-match-substring match 'range-size))))
                                          (cons
                                           (make-mapping-entry
                                            map-from-key map-to-key
                                            from-start (fx- (fx+ from-start range-size) 1)
                                            to-start (fx- (fx+ to-start range-size) 1))
                                           seed)))
                                      '() mapping-vals-str))
                       seed)))
                  '() input))
Processing The Data
  (define (map-entity-forward entity mapping-alist)
    (let ((maplist (alist-ref (entity-type entity) mapping-alist)))
      (if maplist
          (let ((default-target-type (mapping-entry-to-type (car maplist))))
            (or
             (foldl (lambda (new-entity mapping-entry)
                      (if (and (fx>= (entity-id entity)
                                     (mapping-entry-from-start mapping-entry))
                               (fx<= (entity-id entity)
                                     (mapping-entry-from-end mapping-entry)))
                          (make-entity (mapping-entry-to-type mapping-entry)
                                       (fx+ (mapping-entry-to-start mapping-entry)
                                            (fx- (entity-id entity)
                                                 (mapping-entry-from-start mapping-entry))))
                          new-entity))
                    #f maplist)
             (make-entity default-target-type (entity-id entity))))
          #f)))
  (define (map-entity-forward-fully entity mapping-alist)
    (let ((new-entity (map-entity-forward entity mapping-alist)))
      (if new-entity
          (map-entity-forward-fully new-entity mapping-alist)
          entity)))
Solution
  (let ((seeds (map (cut make-entity #:seed <>) (input->seeds-list input)))
        (mapping-alist (input->mapping-alist input)))
    (apply min (map (compose
                     entity-id
                     (cut map-entity-forward-fully <> mapping-alist))
                    seeds)))
1181555926

Part Two

Quest

Everyone will starve if you only plant such a small number of seeds. Re-reading the almanac, it looks like the seeds: line actually describes ranges of seed numbers.

The values on the initial seeds: line come in pairs. Within each pair, the first value is the start of the range and the second value is the length of the range. So, in the first line of the example above:

seeds: 79 14 55 13

This line describes two ranges of seed numbers to be planted in the garden. The first range starts with seed number 79 and contains 14 values: 79, 80, …, 91, 92. The second range starts with seed number 55 and contains 13 values: 55, 56, …, 66, 67.

Now, rather than considering four seed numbers, you need to consider a total of 27 seed numbers.

In the above example, the lowest location number can be obtained from seed number 82, which corresponds to soil 84, fertilizer 84, water 84, light 77, temperature 45, humidity 46, and location 46. So, the lowest location number is 46.

Consider all of the initial seed numbers listed in the ranges on the first line of the almanac. What is the lowest location number that corresponds to any of the initial seed numbers?

Puzzle Solution

All that is needed is to "expand" the seed numbers before continuing. Since we are dealing with such a huge number of seeds, I use delay-force to delay calculation of the later ones until they're actually needed.

(define (expand-seed existing-seeds start size)
  (let ((max (- (+ start size) 1)))
    (do ((seedlist (cons start existing-seeds)
                   (cons (+ (car seedlist) 1)
                         seedlist)))
        ((< (- max 2) (car seedlist))
         seedlist))))

(define (expand-seeds seed-nums #!optional (existing-seeds '()))
  (if (< 2 (length seed-nums))
      (expand-seeds (cddr seed-nums)
                    (delay-force (expand-seed existing-seeds
                                              (car seed-nums)
                                              (cadr seed-nums))))
      (expand-seed existing-seeds (car seed-nums) (cadr seed-nums))))

After that, it is almost identical to part 1, but we have to replace the foldl with a recursive function that handles the promises.

(define (fold-seeds seeds mapping-alist #!optional (minimum most-positive-fixnum))
  (let* ((seeds (if (promise? seeds) (force seeds) seeds))
         (seeds-available? (not (eqv? '() seeds))))
    (if seeds-available?
        (let ((location-entity-id ((compose entity-id
                                            (cut map-entity-forward-fully <> mapping-alist)
                                            (cut make-entity #:seed <>))
                                   (car seeds))))
          (fold-seeds (cdr seeds)
                      mapping-alist
                      (min minimum location-entity-id)))
        minimum)))
  (let ((seeds (expand-seeds (input->seeds-list input)))
        (mapping-alist (input->mapping-alist input)))
    (fold-seeds seeds mapping-alist))
1181555926

Puzzle Input

seeds: 364807853 408612163 302918330 20208251 1499552892 200291842 3284226943 16030044 2593569946 345762334 3692780593 17215731 1207118682 189983080 2231594291 72205975 3817565407 443061598 2313976854 203929368

seed-to-soil map:
2069473506 3732587455 1483883
3235691256 2348990120 6550341
3547561069 1392195671 747406227
3264251584 3734071338 283309485
391285622 257757572 195552540
1645243555 3166958320 377191689
335002083 512210869 56283539
3242241597 897735089 22009987
77244511 0 257757572
989159646 4172023334 122943962
605476380 3544150009 188437446
0 568494408 18343754
2700122696 4050276683 121746651
2022435244 2139601898 47038262
2227672101 919745076 95840269
1112103608 2633818373 533139947
826809686 2186640160 162349960
3100147259 762191092 135543997
18343754 453310112 58900757
2323512370 1015585345 282396986
2605909356 1297982331 94213340
2821869347 2355540461 278277912
793913826 4017380823 32895860
2070957389 605476380 156714712

soil-to-fertilizer map:
2700214958 2743391193 363795571
1484584575 1440072796 24660284
927520818 435059068 191969051
1588488926 1434420334 5652462
1423277199 141187887 5443857
1594141388 1350997453 83422881
1986188257 3933008893 120750463
1509244859 146631744 79093544
3712482038 4220862006 74105290
3948206286 1986188257 277570873
291046304 281588807 153470261
1119489869 918224946 303787330
1677564269 1321192605 29804848
2309878676 2336743687 390336282
3079951473 3306332300 449116691
444516565 1222012276 99180329
543696894 1464733080 383823924
3895169406 3771389935 53036880
3529068164 4053759356 167102650
0 627178642 291046304
3696170814 2727079969 16311224
3855550220 3824426815 39619186
2106938720 3107186764 199145536
1428721056 225725288 55863519
1707369117 0 64378064
1771747181 64378064 76809823
3064010529 3755448991 15940944
2306084256 2332949267 3794420
4225777159 2263759130 69190137
3786587328 3864046001 68962892
1588338403 627028119 150523

fertilizer-to-water map:
2299879115 39069388 7889905
514481680 504392888 101474410
3448524168 0 25428313
13641075 1832356728 472401611
0 25428313 13641075
1842445520 108629584 395763304
486042686 3445513487 28438994
2307769020 2304758339 1140755148
2238208824 46959293 61670291
615956090 605867298 1226489430

water-to-light map:
1318826171 2010420436 223477535
2278894745 2233897971 671603259
988189854 447584401 27746374
2132052210 300741866 146842535
0 1279660741 97125596
3531244480 3147213622 507810286
257581844 3816963790 101424269
1298609589 3918388059 20216582
3317726838 1072550929 21856732
3065323607 1254863909 4121973
97125596 1094407661 160456248
359006113 1057194484 15356445
374362558 1636971609 104335413
4039054766 475330775 9209679
1038424317 1376786337 260185272
878530050 3938604641 109659804
1784016098 3738041092 78922698
3152462764 0 165264074
1862938796 1741307022 269113414
497536930 676201364 380993120
3069445580 3655023908 83017184
2950498004 165264074 114825603
1015936228 1258985882 1835900
478697971 1260821782 18838959
1017772128 280089677 20652189
1542303706 2905501230 241712392
3339583570 484540454 191660910

light-to-temperature map:
2827696039 489007811 183207687
1480301347 3744628626 306791400
695239418 130668965 358338846
1297125534 2232912413 183175813
3979319170 1917264287 315648126
3010903726 948848843 968415444
130668965 2663473525 564570453
1053578264 4051420026 243547270
2303677395 672215498 276633345
1787092747 3228043978 516584648
2580310740 2416088226 247385299

temperature-to-humidity map:
4161466647 3871737509 133500649
2423686895 2864370860 72123408
1983529997 0 320533964
3184295196 2695571092 41928210
0 822932241 605870242
3557076981 3267347843 604389666
3226223406 2936494268 330853575
2495810303 2737499302 126871558
1108268519 1428802483 491674128
605870242 320533964 502398277
2622681861 2423686895 271884197
2894566058 4005238158 289729138
1599942647 1920476611 383587350

humidity-to-location map:
2945628300 1864953738 334378942
3467273713 3579654586 715312710
975015905 1356290883 508662855
1483678760 2498980024 1080674562
3443998409 2199332680 23275304
3280007242 2222607984 163991167
4182586423 2386599151 112380873
2564353322 975015905 381274978