|
#lang iracket/lang #:require racket
(require "../advent.rkt" threading)
|
Day 3 involves some two dimensional analysis, so we’ll use complex numbers as a convenient two dimensional index:
|
#lang iracket/lang #:require racket
(require "../advent.rkt" threading)
|
Our data today is as follows:
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
For today’s task, I found it helpful to make use of the parallel-combine
combinator from Hanson & Sussman’s “Software Design for Flexibility”. This combinator applies f
and g
to the input, in parallel, and combines their output using h
. Pictorially, it looks like this:
Day 1
For part 1, we’re given data as follows (Note: in both data examples, intraline spaces are only for emphasis):
1 abc 2
pqr 3 stu 8 vwx
a 1 b2c3d4e 5 f
treb 7 uchet
The task is to find the first and last numeric digit in each line, e.g. 1
and 2
, concatenate them together, e.g. 12
, and then sum all of those values.
It appears upgrading my Anaconda Python distribution killed my Emacs, so I figured I’d try upgrading to the latest version to see if that fixed things. It did :)
Since upgrading Emacs to 29.1 no longer required the manual configuration changes I had to make when upgrading to 28.2, I’ll document the procedure I used on MacOS Ventura 13.6.1
Table of Contents
My support code is unchanged, as of now, so last year’s blog post still does a good job of explaining it.
Advent of Code 2023 is starting on December 1. This will be my fourth year, after participating in 2022, 2021 and 2020.
My primary programming language is Racket, so I expect to code most of the solutions in it; however, the rest of my language stack includes Python, Javascript and C++, so I’ll code some of the solutions using them also.
I upgraded to Emacs 28.2 (MacOS Ventura), and it required a few tweaks, so I’m documenting that here for future reference.
|
#lang iracket/lang #:require racket
(require "../advent.rkt")
|
Tuning Trouble
Today’s puzzle has very similar parts! For both parts, our input is a single string, and the task is to determine how many characters we need to consume before finding a contiguous group of N unique characters. The only difference is the value of N
.
|
#lang iracket/lang #:require racket
(require "../advent.rkt")
|
Supply Stacks We’re given the following sample input:
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2
And, fortunately for us, the first part has lines padded with spaces to be of equal length - this makes parsing just a little bit easier :) Even so, the built-in parsers we have for AoC are insufficient, so we’ll just use a custom parser that reads the file into a string, splits it on "\n\n", and then maps the string-split
function over both parts - the stack lines and the command lines:
|
#lang iracket/lang #:require racket
(require "../advent.rkt")
|
Camp Cleanup
Before we get started with today’s puzzle, I have some cleanup of my own to do!
1. all-from-out
At the beginning of each day, the second line of the prelude above is:
(require "../advent.rkt")
This is Racket’s way of importing a module. Rather than also having to import common modules I typically use, such as the threading
module, e.g. (require "../advent.rkt" threading)
, I’d like to be able to just import my advent.rkt
module and get access to threading
as well. I learned a long time ago that the answer to the question, “Can Racket do <X>”, is almost always, “yes”, and this is no exception; it’s accomplished with the all-from-out
macro. My advent.rkt
module already had (require threading)
for it’s own purposes, so I just needed a directive to have it export all of the exports from threading
as if they were defined in advent.rkt
:
(provide (all-from-out threading))
2. A parsing fix
One of the parsers I got from Peter Norvig is the numbers
parser, and it allows parsing input such as 1,2 | -3,4
into a list of numbers, '(1 2 -3 4)
; however, today’s input was like 49-51,31-50
, and the numbers
parser would output '(49 -51 31 -50
. The -
chars were meant to be separators, not negative signs. The original numbers
parser used the regex pattern -?[0-9.]+
. Modifying the regex pattern to be ((?<![0-9])-)?[0-9.]+
instead, which uses a negative lookbehind pattern, correctly outputs '(49 51 31 50)
.
The negative lookbehind pattern (?<![0-9])
is used in front of the -
, so that the -
will only match if it’s not preceded by a numeric digit. This is a very handy regex technique.
Ok, with the modified numbers
parser in place, let’s parse today’s input!