127 KiB
Advent of Code
- Day 1: Not Quite Lisp
- Day 2: I Was Told There Would Be No Math
- Day 3: Perfectly Spherical Houses in a Vacuum
- Day 4: The Ideal Stocking Stuffer
- Day 5: Doesn't He Have Intern-Elves For This?
- Day 6: Probably a Fire Hazard
- Day 7: Some Assembly Required
- Day 8: Matchsticks
- Day 9: All in a Single Night
- Day 10: Elves Look, Elves Say
- Day 11: Corporate Policy
Day 1: Not Quite Lisp
Santa was hoping for a white Christmas, but his weather machine's "snow" function is powered by stars, and he's fresh out! To save Christmas, he needs you to collect fifty stars by December 25th.
Collect stars by helping Santa solve 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!
Here's an easy puzzle to warm you up.
Santa is trying to deliver presents in a large apartment building, but
he can't find the right floor - the directions he got are a little
confusing. He starts on the ground floor (floor 0
) and then follows
the instructions one character at a time.
An opening parenthesis, (
, means he should go up one floor, and a
closing parenthesis, )
, means he should go down one floor.
The apartment building is very tall, and the basement is very deep; he will never find the top or bottom floors.
For example:
(())
and()()
both result in floor 0.(((
and(()(()(
both result in floor 3.))(((((
also results in floor 3.())
and))(
both result in floor -1 (the first basement level).)))
and)())())
both result in floor -3.
To what floor do the instructions take Santa?
((((()(()(((((((()))(((()((((()())(())()(((()((((((()((()(()(((()(()((())))()((()()())))))))))()((((((())((()))(((((()(((((((((()()))((()(())()((())((()(()))((()))()))()(((((()(((()()))()())((()((((())()())()((((())()(()(()(((()(())(()(())(((((((())()()(((())(()(()(()(())))(()((((())((()))(((()(()()(((((()()(()(((()(((((())()))()((()(()))()((()((((())((((())(()(((())()()(()()()()()(())((((())((())(()()))()((((())))((((()())()((((())((()())((())(())(((((()((((()(((()((((())(()(((()()))()))((((((()((())()())))(((()(()))(()()(()(((()(()))((()()()())((()()()(((())())()())())())((()))(()(()))(((((()(()(())((()(())(())()((((()())()))((((())(())((())())((((()(((())(())((()()((((()((((((()(())()()(()(()()((((()))(())()())()))(())))(())))())()()(())(()))()((()(()(())()()))(()())))))(()))(()()))(())(((((()(()(()()((())()())))))((())())((())(()(())((()))(())(((()((((((((()()()(()))()()(((()))()((()()(())(())())()(()(())))(((((()(())(())(()))))())()))(()))()(()(((((((()((((())))())())())())()((((((((((((((()()((((((()()()())())()())())())(())(())))())((()())((()(()))))))()))))))))))))))))())((())((())()()))))))(((()((()(()()))((())(()()))()()())))(())))))))(()(((())))())()())))()()(())()))()(()))())((()()))))(()))))()))(()()(())))))))()(((()))))()(()))(())())))))()))((()))((()))())(())))))))))((((())()))()))()))())(())()()(())))())))(()())()))((()()(())))(())((((((()(())((()(((()(()()(())))()))))))()))()(()((()))()(()))(()(((())((((())())(())(()))))))))())))))))())())))))())))))()()(((())()(()))))))))())))))(())()()()))()))()))(()(())()()())())))))))())()(()(()))))()()()))))())(()))))()()))))()())))))(((())()()))(()))))))))))()()))))()()()))))(()())())()()())()(()))))()(()))(())))))))(((((())(())())()()))()()))(())))))()(()))))(())(()()))()())()))()))()))()))))())()()))())())))(()))(()))))))())()(((())()))))))))()))()())))())))())))()))))))))))()()))(()()))))))(())()(()))))())(()))))(()))))(()())))))())())()()))))())()))))))))(()))))()))))))()(()())))))))()))())))())))())))())))))))())(()()))))))(()())())))()())()))))))))))))))())))()(())))()))())()()(())(()()))(())))())()())(()(()(()))))())))))))))))())(()))()))()))))(())()())()())))))))))))()()))))))))))))())())))))(()())))))))))))())(())))()))))))))())())(()))()))(())))()))()()(())()))))))()((((())()))())())))))()))()))))((()())()))))())))(())))))))))))))))))()))))()()())()))()()))))())()))((()())))())))(()))(()())))))))()))()))))(())))))))(())))))())()()(()))())()))()()))))())()()))))())()))())))))))(()))))()())()))))))))(()))())))(()))()))))(())()))())())(())())())))))))((((())))))()))()))()())()(())))()))()))()())(()())()()(()())()))))())())))))(()))()))))())(()()(())))))(())()()((())())))))(())(())))))))())))))))))()(())))))))()())())())()(()))))))))(()))))))))())()()))()(()))))))()))))))())))))))(())))()()(())()())))))(((())))()((())()))())))(()()))())(())())))()(((()())))))()(()()())))()()(()()(()()))())()(()()()))())()()))()())(()))))())))))())))(())()()))))(()))))(())(()))(())))))()()))()))))())()))()()(())())))((()))())()))))))()()))))((()(()))))()()))))))())))))())(()((()())))))))))))()())())))()))(()))))))(()))(())()())))(()))))))))())()()()()))))(()())))))))((())))()))(()))(())(())()())()))))))))(())))())))(()))()()))(()()))(()))())))()(())))())((()((()(())))((())))()))))((((())())()())))(())))()))))))())(()()((())))())()(()())))))(()())()))())))))))((())())))))))(()(()))())()()(()()(((()(((()())))))()))))))()(())(()()((()()(())()()))())()())()))()())())())))))))(((())))))))()()))))))(((())()))(()()))(()()))))(()(()()((((())()())((()()))))(()(())))))()((()()()())()()((()((()()))(()))(((()()()))(((())))()(((())()))))))((()(())())))(()())(((((()(()))(()((()))(()())()))))(()(()))()(()))(())(((())(()()))))()()))(((()))))(()()()()))())))((()()()(())()))()))))()()))()))))))((((((()()()))))())((()()(((()))))(()(())(()()())())())))()(((()()))(())((())))(()))(()()()())((())())())(()))))()))()((()(())()(()()(())(()))(())()))(())(()))))(())(())())(()()(()((()()((())))((()))()((())))(((()()()()((((()))(()()))()()()(((())((())())(()()(()()()))()((())(())()))())(((()()(())))()((()()())()())(()(())())(((())(())())((())(())()(((()()))(())))((())(()())())(())((()()()((((((())))((()(((((())()))()))(())(()()))()))(())()()))(())((()()())()()(()))())()((())))()((()()())((((()())((())())())((()((()))()))((())((()()(()((()()(((())(()()))))((()((())()(((())(()((())())((())(()((((((())())()(()())()(())(((())((((((()(())(()((()()()((()()(()()()())))()()(((((()()))()((((((()))()(()(()(()(((()())((()))())()((()))(())))()))()()))())()()))())((((())(()(()))(((((((())(((()(((((()(((()()((((())(((())())))(()()()(()(()))()))((((((()))((()(((()(())((()((((()((((((())(((((())))(((()(()))))(((()(((())()((())(()((()))(((()()(((())((((()(()(((((()))(((()(((((((()(()()()(()(()(()()())(())(((((()(())())()())(()(()(()))()(()()()())(()()(()((()))()((())())()(()))((())(()))()(()))()(((()(()(()((((((()()()()())()(((((()()(((()()()((()(((((()))((((((((()()()(((((()))))))(()()()(())(()))(()()))))(())()))(((((()(((((()()(()(()())(((()))((((()((()(()(()((()(()((())))()(((()((()))((()))(((((((((()((()((()(())))()((((()((()()))((())(((()(((((()()(()(()()((()(()()()(((((((())())()())))))((((()()(()))()))(()((())()(()(((((((((()()(((()(()())(()((()())((())())((((()(((()(((()((((()((()((((()(()((((((())((((((((((((()()(()()((((((((((((((()((()()))()((((((((((((())((((()(()())((()(()(()))()(((((()()(((()()))()())(())((()(((((()((())(((((()((()(((((()))()()((((())()((((())(((((((((()(())(()(())))())(()((())(((())(())(())())(()(()(())()()((()((())()(((()(((((()(())))()(((()((())))((()()()(((()(((()((()(()(())(()((()())(()(()(((()(((((((((())(()((((()()))(()((((()()()()(((()((((((((()(()()((((((()(()()(()((()((((((((((()()(((((((()())(())))(((()()))(((((()((()()())(()()((((())((()((((()))))(())((()(()()(((()(()(((()((((()(((((()))())())(()((())()))(((()())((())((())((((()((()((((((())(()((((()()))((((((())()(()))((()(((())((((((((((()()(((((()(((((()((()()()((((())))(()))()((()(())()()((()((((((((((()((())(())(((((()(()(()()))((((()((((()()((()(((()(((((((((()(()((()((()))((((((()(((())()()((()(((((((()())))()()(()((()((()()(((()(()()()()((((()((())((((()(((((((((()(((()()(((()(()(((()(((()((())()(()((()(()(()(()))()(((()))(()((((()((())((((())((((((())(()))(()((((())((()(()((((((((()()((((((()(()(()()()(())((()((()()(((()(((((((()()((()(((((((()))(((((()(((()(()()()(()(((()((()()((())(()(((((((((()(()((()((((((()()((())()))(((((()((())()())()(((((((((((()))((((()()()()())(()()(()(()()))()))(()))(()(((()()))())(()(()))()()((())(()())()())()(()))()))(()()(()((((((())((()(((((((((((()(())()((()(()((()((()(()((()((((((((((()()())((())()(())))((())()())()(((((()(()())((((()((()(())(()))(((())()((()))(((((())(()))()()(()))(((())((((()((((()(())))(((((((()))))())()())(())((())()(()()((()(()))()(()()(()()((()())((())((()()))((((()))()()))(()()(())()()(((((()(())((()((((()))()))(()())())(((()()(()()))(())))))(()))((())(((((()((((()))()((((()))()((())(((())))(((()())))((()(()()((
(defun day1/parse-directions (directions)
(seq-map
(lambda (char)
(cond ((eq char ?\() 1)
((eq char ?\)) -1)
(t 0)))
directions))
(seq-reduce #'+
(day1/parse-directions input)
0)
74
Part 2
Now, given the same instructions, find the position of the first
character that causes him to enter the basement (floor -1
). The
first character in the instructions has position 1
, the second
character has position 2
, and so on.
For example:
)
causes him to enter the basement at character position1
.()())
causes him to enter the basement at character position5
.
What is the position of the character that causes Santa to first enter the basement?
(defun day1/steps-until (predicate reduce-fn sequence initial-value)
(car (seq-reduce
(lambda (acc next)
(let ((counter (car acc))
(value (cdr acc)))
(if (funcall predicate value) acc
(cons (+ 1 counter)
(funcall reduce-fn value next)))))
sequence
(cons 0 initial-value))))
(day1/steps-until
(lambda (floor) (= floor -1))
#'+
(day1/parse-directions input)
0)
1795
Day 2: I Was Told There Would Be No Math
The elves are running low on wrapping paper, and so they need to submit an order for more. They have a list of the dimensions (length l, width w, and height h) of each present, and only want to order exactly as much as they need.
Fortunately, every present is a box (a perfect right rectangular
prism), which makes calculating the required wrapping paper for each
gift a little easier: find the surface area of the box, which is
2*l*w + 2*w*h + 2*h*l
. The elves also need a little extra paper for
each present: the area of the smallest side.
For example:
- A present with dimensions 2x3x4 requires 2*6 + 2*12 + 2*8 = 52 square feet of wrapping paper plus 6 square feet of slack, for a total of 58 square feet.
- A present with dimensions 1x1x10 requires 2*1 + 2*10 + 2*10 = 42 square feet of wrapping paper plus 1 square foot of slack, for a total of 43 square feet.
All numbers in the elves' list are in feet. How many total square feet of wrapping paper should they order?
20x3x11 15x27x5 6x29x7 30x15x9 19x29x21 10x4x15 1x26x4 1x5x18 10x15x23 10x14x20 3x5x18 29x23x30 7x4x10 22x24x29 30x1x2 19x2x5 11x9x22 23x15x10 11x11x10 30x28x5 22x5x4 6x26x20 16x12x30 10x20x5 25x14x24 16x17x22 11x28x26 1x11x10 1x24x15 13x17x21 30x3x13 20x25x17 22x12x5 22x20x24 9x2x14 6x18x8 27x28x24 11x17x1 1x4x12 5x20x13 24x23x23 22x1x25 18x19x5 5x23x13 8x16x4 20x21x9 1x7x11 8x30x17 3x30x9 6x16x18 22x25x27 9x20x26 16x21x23 5x24x17 15x17x15 26x15x10 22x16x3 20x24x24 8x18x10 23x19x16 1x21x24 23x23x9 14x20x6 25x5x5 16x3x1 29x29x20 11x4x26 10x23x24 29x25x16 27x27x22 9x7x22 6x21x18 25x11x19 14x13x3 15x28x17 14x3x12 29x8x19 30x14x20 20x23x4 8x16x5 4x11x18 20x8x24 21x13x21 14x26x29 27x4x17 27x4x25 5x28x6 23x24x11 29x22x5 30x20x6 23x2x10 11x4x7 27x23x6 10x20x19 8x20x22 5x29x22 16x13x2 2x11x14 6x12x4 3x13x6 16x5x18 25x3x28 21x1x5 20x16x19 28x30x27 26x7x18 25x27x24 11x19x7 21x19x17 2x12x27 20x5x14 8x5x8 6x24x8 7x28x20 3x20x28 5x20x30 13x29x1 26x29x5 19x28x25 5x19x11 11x20x22 4x23x1 19x25x12 3x10x6 3x14x10 28x16x12 23x12x2 23x12x19 20x28x10 9x10x25 16x21x16 1x18x20 9x4x26 3x25x8 17x16x28 9x28x16 27x3x12 17x24x12 13x21x10 7x17x13 6x10x9 7x29x25 11x19x30 1x24x5 20x16x23 24x28x21 6x29x19 25x2x19 12x5x26 25x29x12 16x28x22 26x26x15 9x13x5 10x29x7 1x24x16 22x2x2 6x16x13 3x12x28 4x12x13 14x27x21 14x23x26 7x5x18 8x30x27 15x9x18 26x16x5 3x29x17 19x7x18 16x18x1 26x15x30 24x30x21 13x20x7 4x12x10 27x20x11 28x29x21 20x14x30 28x12x3 19x1x8 4x8x6 21x14x2 27x19x21 17x24x14 15x18x11 18x7x26 25x28x29 27x26x9 18x12x17 24x28x25 13x24x14 26x9x28 9x3x30 9x2x9 8x1x29 18x30x10 18x14x5 26x8x30 12x1x1 30x5x28 26x17x21 10x10x10 20x7x27 13x17x6 21x13x17 2x16x8 7x9x9 15x26x4 11x28x25 10x6x19 21x6x29 15x5x6 28x9x16 14x3x10 12x29x5 22x19x19 25x15x22 30x6x28 11x23x13 20x25x14 26x1x13 6x14x15 16x25x17 28x4x13 10x24x25 4x13x10 9x15x16 15x24x6 22x9x19 11x11x8 4x19x12 24x5x4 27x12x13 7x27x16 2x6x9 29x27x15 18x26x23 19x16x15 14x5x25 9x16x30 4x6x4 13x10x10 1x8x29 23x5x17 19x20x20 11x27x24 27x15x5 15x11x12 21x11x3 1x13x22 17x8x8 13x14x14 17x22x7 9x5x8 2x6x3 25x9x15 11x8x13 9x25x12 3x16x12 12x16x8 16x24x17 4x6x26 22x29x11 14x17x19 28x2x27 24x22x19 22x20x30 23x28x4 16x12x14 22x24x22 29x1x28 26x29x16 3x25x30 27x3x13 22x24x26 25x3x2 7x24x2 10x5x3 28x8x29 25x6x4 12x17x14 24x3x5 23x27x7 26x23x30 11x10x19 23x7x11 26x14x15 14x3x25 12x24x14 2x14x12 9x12x16 9x2x28 3x8x2 22x6x9 2x30x2 25x1x9 20x11x2 14x11x12 7x14x12 24x8x26 13x21x23 18x17x23 13x6x17 20x20x19 13x17x29 7x24x24 23x8x6 19x10x28 3x8x21 15x20x18 11x27x1 11x24x28 13x20x11 18x19x22 27x22x12 28x3x2 13x4x29 26x5x6 14x29x25 7x4x7 5x17x7 2x8x1 22x30x24 22x21x28 1x28x13 11x20x4 25x29x19 9x23x4 30x6x11 25x18x10 28x10x24 3x5x20 19x28x10 27x19x2 26x20x4 19x21x6 2x12x30 8x26x27 11x27x10 14x13x17 4x3x21 2x20x21 22x30x3 2x23x2 3x16x12 22x28x22 3x23x29 8x25x15 9x30x4 10x11x1 24x8x20 10x7x27 7x22x4 27x13x17 5x28x5 30x15x13 10x8x17 8x21x5 8x17x26 25x16x4 9x7x25 13x11x20 6x30x9 15x14x12 30x1x23 5x20x24 22x7x6 26x11x23 29x7x5 13x24x28 22x20x10 18x3x1 15x19x23 28x28x20 7x26x2 9x12x20 15x4x6 1x17x21 3x22x17 9x4x20 25x19x5 9x11x22 14x1x17 14x5x16 30x5x18 19x6x12 28x16x22 13x4x25 29x23x18 1x27x3 12x14x4 10x25x19 15x19x30 11x30x4 11x22x26 13x25x2 17x13x27 11x30x24 15x1x14 17x18x4 26x11x3 16x22x28 13x20x9 1x18x3 25x11x12 20x21x1 22x27x4 8x28x23 7x13x27 17x9x26 27x27x20 11x20x12 26x21x11 29x14x12 27x25x1 28x29x25 21x23x28 5x18x18 19x5x4 7x6x30 27x8x11 12x24x12 16x25x22 26x11x29 25x22x17 15x23x23 17x9x6 30x10x16 21x3x5 18x27x2 28x21x14 16x18x17 4x18x2 9x1x14 9x1x9 5x27x12 8x16x30 3x19x19 16x26x24 1x6x9 15x14x3 11x7x19 8x19x3 17x26x26 6x18x11 19x12x4 29x20x16 20x17x23 6x6x5 20x30x19 18x25x18 2x26x2 3x1x1 14x25x18 3x1x6 11x14x18 17x23x27 25x29x9 6x25x20 20x10x9 17x5x18 29x14x8 14x25x26 10x15x29 23x19x11 22x2x2 4x5x5 13x23x25 19x13x19 20x18x6 30x7x28 26x18x17 29x18x10 30x29x1 12x26x24 18x17x26 29x28x15 3x12x20 24x10x8 30x15x6 28x23x15 14x28x11 10x27x19 14x8x21 24x1x23 1x3x27 6x15x6 8x25x26 13x10x25 6x9x8 10x29x29 26x23x5 14x24x1 25x6x22 17x11x18 1x27x26 18x25x23 20x15x6 2x21x28 2x10x13 12x25x14 2x14x23 30x5x23 29x19x21 29x10x25 14x22x16 17x11x26 12x17x30 8x17x7 20x25x28 20x11x30 15x1x12 13x3x24 16x23x23 27x3x3 26x3x27 18x5x12 12x26x7 19x27x12 20x10x28 30x12x25 3x14x10 21x26x1 24x26x26 7x21x30 3x29x12 29x28x5 5x20x7 27x11x2 15x20x4 16x15x15 19x13x7 7x17x15 27x24x15 9x17x28 20x21x14 14x29x29 23x26x13 27x23x21 18x13x6 26x16x21 18x26x27 9x3x12 30x18x24 12x11x29 5x15x1 1x16x3 14x28x11 2x18x1 19x18x19 18x28x21 2x3x14 22x16x5 28x18x28 24x16x18 7x4x10 19x26x19 24x17x7 25x9x6 25x17x7 20x22x20 3x3x7 23x19x15 21x27x21 1x23x11 9x19x4 22x4x18 6x15x5 15x25x2 23x11x20 27x16x6 27x8x5 10x10x19 22x14x1 7x1x29 8x11x17 27x9x27 28x9x24 17x7x3 26x23x8 7x6x30 25x28x2 1x30x25 3x18x18 28x27x15 14x14x1 10x25x29 18x12x9 20x28x16 26x27x22 8x26x1 21x2x12 25x16x14 21x19x5 12x9x22 16x5x4 5x4x16 25x29x3 4x29x13 15x16x29 8x11x24 30x11x20 17x21x14 12x24x10 10x12x6 3x26x30 15x14x25 20x12x21 13x11x16 15x13x3 5x17x29 6x3x23 9x26x11 30x1x8 14x10x30 18x30x10 13x19x19 16x19x17 28x7x10 28x29x4 3x21x10 4x28x24 7x28x9 2x4x9 25x27x13 6x12x15 4x18x20 20x1x16 5x13x24 11x11x10 12x9x23 1x9x30 17x28x24 9x5x27 21x15x16 17x4x14 8x14x4 13x10x7 17x12x14 9x19x19 2x7x21 8x24x23 19x5x12 11x23x21 13x3x1 5x27x15 12x25x25 13x21x16 9x17x11 1x15x21 4x26x17 11x5x15 23x10x15 12x17x21 27x15x1 4x29x14 5x24x25 10x10x12 18x12x9 11x24x23 24x23x3 28x12x15 29x9x14 11x25x8 5x12x2 26x26x29 9x21x2 8x8x25 1x16x30 17x29x20 9x22x13 7x18x16 3x3x23 26x25x30 15x23x24 20x23x5 20x16x10 23x7x8 20x18x26 8x27x6 30x23x23 7x7x24 21x11x15 1x30x25 26x27x22 30x28x13 20x13x13 3x1x15 16x7x1 7x25x15 12x7x18 16x9x23 16x12x18 29x5x2 17x7x7 21x17x5 9x9x17 26x16x10 29x29x23 17x26x10 5x19x17 1x10x1 14x21x20 13x6x4 13x13x3 23x4x18 4x16x3 16x30x11 2x11x2 15x30x15 20x30x22 18x12x16 23x5x16 6x14x15 9x4x11 30x23x21 20x7x12 7x18x6 15x6x5 18x22x19 16x10x22 26x20x25 9x25x25 29x21x10 9x21x24 7x18x21 14x3x15 18x19x19 4x29x17 14x10x9 2x26x14 13x3x24 4x4x17 6x27x24 2x18x3 14x25x2 30x14x17 11x6x14 4x10x18 15x4x2 27x7x10 13x24x1 7x12x6 25x22x26 19x2x18 23x29x2 2x15x4 12x6x9 16x14x29 9x17x3 21x9x12 23x18x22 10x8x4 29x2x7 19x27x15 4x24x27 25x20x14 8x23x19 1x24x19 6x20x10 15x8x5 18x28x5 17x23x22 9x16x13 30x24x4 26x3x13 12x22x18 29x17x29 26x4x16 15x7x20 9x15x30 12x7x18 28x19x18 11x23x23 24x20x1 20x3x24 1x26x1 14x10x6 5x27x24 13x21x12 20x20x5 6x28x9 11x26x11 26x29x12 21x4x11 20x11x17 22x27x20 19x11x21 2x11x11 13x5x7 12x10x25 21x28x1 15x30x17 28x19x1 4x19x12 11x4x12 4x10x30 11x18x5 22x20x12 3x7x27 20x26x4 13x27x26 23x14x13 4x19x7 26x27x16 20x5x20 18x5x8 19x21x1 22x8x1 29x4x1 24x10x15 24x9x20 10x3x8 29x30x3 2x8x24 16x7x18 2x11x23 23x15x16 21x12x6 24x28x9 6x1x13 14x29x20 27x24x13 16x26x8 5x6x17 21x8x1 28x19x21 1x14x16 18x2x9 29x28x10 22x26x27 18x26x23 22x24x2 28x26x1 27x29x12 30x13x11 1x25x5 13x30x18 3x13x22 22x10x11 2x7x7 18x17x8 9x22x26 30x18x16 10x2x3 7x27x13 3x20x16 9x21x16 1x18x15 21x30x30 4x25x23 3x11x7 5x6x12 27x1x20 13x15x24 23x29x2 13x5x24 22x16x15 28x14x3 29x24x9 2x20x4 30x10x4 23x7x20 22x12x21 3x19x11 4x28x28 5x4x7 28x12x25 2x16x26 23x20x7 5x21x29 9x21x16 9x6x10 9x6x4 24x14x29 28x11x6 10x22x1 21x30x20 13x17x8 2x25x24 19x21x3 28x8x14 6x29x28 27x10x28 30x11x12 17x2x10 14x19x17 2x11x4 26x1x2 13x4x4 23x20x18 2x17x21 28x7x15 3x3x27 24x17x30 28x28x20 21x5x29 13x12x19 24x29x29 19x10x6 19x12x14 21x4x17 27x16x1 4x17x30 23x23x18 23x15x27 26x2x11 12x8x8 15x23x26 30x17x15 17x17x15 24x4x30 9x9x10 14x25x20 25x11x19 20x7x1 9x21x3 7x19x9 10x6x19 26x12x30 21x9x20 15x11x6 30x21x9 10x18x17 22x9x8 8x30x26 28x12x27 17x17x7 11x13x8 5x3x21 24x1x29 1x28x2 18x28x10 8x29x14 26x26x27 17x10x25 22x30x3 27x9x13 21x21x4 30x29x16 22x7x20 24x10x2 16x29x17 28x15x17 19x19x22 9x8x6 26x23x24 25x4x27 16x12x2 11x6x18 19x14x8 9x29x13 23x30x19 10x16x1 4x21x28 23x25x25 19x9x16 30x11x12 24x3x9 28x19x4 18x12x9 7x1x25 28x7x1 24x3x12 30x24x22 27x24x26 9x30x30 29x10x8 4x6x18 10x1x15 10x4x26 23x20x16 6x3x14 30x8x16 25x14x20 11x9x3 15x23x25 8x30x22 22x19x18 25x1x12 27x25x7 25x23x3 13x20x8 5x30x7 18x19x27 20x23x3 1x17x21 21x21x27 13x1x24 7x30x20 21x9x18 23x26x6 22x9x29 17x6x21 28x28x29 19x25x26 9x27x21 5x26x8 11x19x1 10x1x18 29x4x8 21x2x22 14x12x8
(defun day2/surface-area (w h l)
"Calculate the surface area of a box."
(+ (* 2 l w)
(* 2 w h)
(* 2 h l)))
(defun day2/slack (w h l)
"Find the area of the smallest side of a box.
The smallest side is the side with the smallest area."
(min (* l w)
(* w h)
(* h l)))
(defun day2/wrapping-paper (w h l)
"Find the area of wrapping paper needed to wrap a box."
(+ (day2/surface-area w h l)
(day2/slack w h l)))
(ert-deftest day2/wrapping-paper ()
(should (eq 58 (day2/wrapping-paper 2 3 4)))
(should (eq 43 (day2/wrapping-paper 1 1 10))))
(defun day2/parse-dimensions (dimension-string)
"Parse a string representing the dimensions of a box separated
by the character 'x' into a list of integers."
(seq-map #'string-to-int
(split-string dimension-string "x")))
(defun day2/sum-list (input)
(seq-reduce
#'+
(seq-map (lambda (dimension-string)
(let ((dimensions (day2/parse-dimensions dimension-string)))
(eval (cons 'day2/wrapping-paper dimensions))))
(split-string input))
0))
(ert-deftest day2/sum-list ()
(let ((test-data (string-join '("2x3x4" "1x1x10") "\n")))
(should (eq (+ 58 43)
(day2/sum-list test-data)))))
(day2/sum-list input)
1606483
Part 2
The elves are also running low on ribbon. Ribbon is all the same width, so they only have to worry about the length they need to order, which they would again like to be exact.
The ribbon required to wrap a present is the shortest distance around its sides, or the smallest perimeter of any one face. Each present also requires a bow made out of ribbon as well; the feet of ribbon required for the perfect bow is equal to the cubic feet of volume of the present. Don't ask how they tie the bow, though; they'll never tell.
For example:
- A present with dimensions
2x3x4
requires2+2+3+3 = 10
feet of ribbon to wrap the present plus2*3*4 = 24
feet of ribbon for the bow, for a total of34
feet. - A present with dimensions
1x1x10
requires1+1+1+1 = 4
feet of ribbon to wrap the present plus1*1*10 = 10
feet of ribbon for the bow, for a total of14
feet.
How many total feet of ribbon should they order?
(defun day2/smallest-perimeter (w h l)
(min (* 2 (+ l w))
(* 2 (+ w h))
(* 2 (+ h l))))
(defun day2/volume (w h l)
(* w h l))
(defun day2/ribbon (w h l)
(+ (day2/smallest-perimeter w h l)
(day2/volume w h l)))
(ert-deftest day2/ribbon ()
(should (eq 34 (day2/ribbon 2 3 4)))
(should (eq 14 (day2/ribbon 1 1 10))))
(defun day2/sum-ribbon (input)
(seq-reduce
#'+
(seq-map (lambda (dimension-string)
(let ((dimensions (day2/parse-dimensions dimension-string)))
(eval (cons 'day2/ribbon dimensions))))
(split-string input))
0))
(day2/sum-ribbon input)
3842356
Day 3: Perfectly Spherical Houses in a Vacuum
Santa is delivering presents to an infinite two-dimensional grid of houses.
He begins by delivering a present to the house at his starting
location, and then an elf at the North Pole calls him via radio and
tells him where to move next. Moves are always exactly one house to
the north (^
), south (v
), east (>
), or west (<
). After each
move, he delivers another present to the house at his new location.
However, the elf back at the north pole has had a little too much eggnog, and so his directions are a little off, and Santa ends up visiting some houses more than once. How many houses receive at least one present?
For example:
>
delivers presents to2
houses: one at the starting location, and one to the east.^>v<
delivers presents to4
houses in a square, including twice to the house at his starting/ending location.^v^v^v^v^v
delivers a bunch of presents to some very lucky children at only2
houses.
>^^v^<>v<<<v<v^>>v^^^<v<>^^><^<<^vv>>>^<<^>><vv<<v^<^^><>>><>v<><>^^<^^^<><>>vv>vv>v<<^>v<>^>v<v^<>v>><>^v<<<<v^vv^><v>v^>>>vv>v^^^<^^<>>v<^^v<>^<vv^^<^><<>^>><^<>>><><vv><>v<<<><><>v><<>^^^^v>>^>^<v<<vv^^<v<^<^>^^v^^^^^v<><^v><<><^v^>v<<>^<>^^v^<>v<v^>v>^^<vv^v><^<>^v<><^><v^><><><<<<>^vv^>^vvvvv><><^<vv^v^v>v<<^<^^v^<>^<vv><v<v^v<<v<<^^>>^^^v^>v<><^vv<<^<>v<v><><v^^><v<>^^>^^>v^>^<<<<v><v<<>v><^v>^>><v^^<^>v<vvvv<>>>>>^v^^>v<v<^<vv>^>^vv^>vv^^v<<^<^^<>v>vv^v>><>>>v^>^>^^v<>^<v<<>^vv>v^<<v>v<<><v>^vvv<v<vvv^v<vv<v^^^>v><<^<>><v^^>^v^>>^v<^<><v<>>v^<>>v<>>v^^^><^>>vvvv>^v<^><<>>^<>^>vv><v<<>>^^>v^^^><^<<^^v>v<^<<>v>^^vvv^v^>v^<>^^<>v^v>v>v<v^>vv>^^v<>v>>^<>><>v>v^<<vvvv<vvv><v^<^>^v<>>^><v>><>^<v>v<v>vv^>>vvv<>v>v<v^>>^>>v<<>^<>^<>>>^v<<<^<^v>vv^>><<><v^>^v^^^v<>^^vv><>><>>^>v^<v<>v<>>^<<^v>^^^<>^v^><>v<<v>vv^>vv<<>>><<^v^<>v<vv>>>^^<>^><<^>vv>>^<<v^^vv<>>><v>v><^<v<<>>>^^<>>^<^v><>vv^^^v>vvv>^><<>^^>^<<v^<v<^v<<>vvv<^<<>^>^v<vv<^>vvv>v>vv^<v^><>>^vv<^^^vv><^vv<v^<><v^vvv><<^>^^><v<<vv^>v<vv<v>^<>^v<<>v<v^v^>^>^>v<<^vvv<<<v>^^>^<<<<>vv>>^<>^>>>v<v>^^<v^<v<>>>vv>^^v<<>>>^^v><<<v<v<^v<>^^><v<^v<<v^><><^<><v<^^v>>><v^^v<<v^><^<><<v^>><^<>v>v^<><^<v>^v^>^>^vv^>^^<<vv^>vv<^vvv<>>^^<^>v^>^>^<v^><v<v>>>v<<<><^v<<><^<vv^v^^^>v<^^<v^vvv<v<><v<vv<^vv<>vv<v^<>>vvvvv<<>^v^v>vv>>>vvv^^<^<^<><>v<v>><^v><^<<<>><<<v>^>v<>^>^v>>^<>v^<^>><<>^<v>^>^^^>^^<v>>>><>^v^v><<<<vv^<vv<>vv>v<>v^<v^>v><>>>v^<><^vvv>vv^<^<<^<^^v>^>>>v<^<^v^^<^<^>>><v>vv>^<<><>^>>v>^<<>><^<>v<>vv^^>^>vvv^v<<^<^^<vv<>^vvv<^^v^vv^>>v<^>^^<v^<>v<^<^vv>v<<vv>vv>^>vvv>>>^^>v<>^v>v^<^>>v>^^v>>>>v^<v>v<^>v<v<<>>^v<^^<v><^<>>^<<vv^>>v<<v>^v<>><^>vv<v<^>>^^<vvvvvvvvv>>>v<v<>v^<>>^vv<v^^v<<^vvv^<<^><>vv<><<>>v>vv^><>>^^v^>>v^v^><<<>>^^<^v<<^<>>>>^<^>v^><<^>v<^v<^>>^^<<<<><^<^v^v<>>^v<^<<vv^<><^^vv><v^v^v>^>>^>^vv^>^v<v^v<<vvv^><>>^v^^><>v>vv><^>>vv<vvv<<<<^<>vvv^v<v>^<v<^>^<^<v<><>v^^^^<<vv<^^vv<v>><<v^><>>><v^>^v><^>^><vv^<><^<v>><<^vv<>>v^<<v<>v><v<><><vv>^>>v^<^<v>^><>>><^><v^v<>>>^^<^>v<v>vvv<>^<<><v^^>^>>v<^v>^>v>>>vv>v>>v^^^<^<vvv^<>^>^<v^<v^v>v>^>vv>vvv<>v<^>v>^^>>^<vv^^v>v^^^^^v^vv><^<><>^>vv<^>>^vvvv^^^>^<vv>^v<<^><^^>^<>^^>^<<v<^>>>^><<^^>v^v>>^>vvvv>^^v><v>>vv><<<vv<^>v>^^^<v>v^vvv<^><<^>^<>^><<<<<v^<<vv^v>^<>v<v>^>^>><>v^v<^vv^^>vv<<v^v>vv^vvv<<<<>^v<v^^v^v>v<<v>^^<>^vv^^>^>^v^vv^>>v^vv^^<vv><<v^v^^v><vv<^vvv<vv^^<<v>v^v^^^^v<^<^>v>^>v>^vv^v^^<v<^vvvv<<<>^<^^^<^^<>^<><vv<^^<<^>>><v^vvvv>^<>>^^>v^^v^<<v^^^<<<><^<v^v^^v<v^<>v><<v<>^v>v<^><^>vv^^<vvv<^v>>v>^<><v^><^^^<v^>>vv<<<<<^<>^v^v>^vv^<>v>v<^>vv<<^vv>vv<v<><>>v>><v<^<^^>><<v^v<<^><v<^<vv<v<<vv^>^<<><^^>^<^>>^<vv>><v<<vvv<^^v^>^^<^v>^v<v<>v><v^v^<<^<><<v<<^v>v<<>>^>v>>v>>v<^<<^<^>>>v>^^^v><^>^^>>v<<>^v><v>vvv^vv<<<>vvv<<>^>>>v<v<v^<^<^>^<^>v^^v<^^<v<>v<>>^^>^v^>v<<<<^<>v^><<<v>>>><<v^<^vv>v>><>>^<<<^<^^>v<>>v<>vv<<^<<><<^>v^^^vv^>vvvv>>v>v^><<v<>vv^<<><<vvv>^>>>^<<<^<^<<v>^>v<>>v>>vv^^><<<<^^^v>><<^><v><v^^><v<<v^^v^^v>>v<><><<>^><v><^<vv>><^v<>v<vvv<>^>><v>>v<^><<v>^<>^v><^><^^<v>^><^^v^<<><>>^>v^<^v^vv<><^>vv^>v^vvv^<>>^><^<^<>^<<v^v<^v><>^v<v>>^>>^v^vv>><vv><v^^<<^v^<>^v<<>^><^>><v>>v<<<v^^vv<>^^v>>><><><<v^<<<v^<^^><v^>v^^vv<v^<>>vv^<^v<>^v>>v^v>v<^^vv><>^v<<>v^<>v^>>v>vvv<^><><^^>^vv^>>v^>^<^^<><>><<>^^^><^v^v><<<><<^v^vv>v>><^>>><v^>v<v><><v^v<>v^^>>v<<>v>v<v<v<^^<><>v^^<>>v<^v<v>v<><v<v>^<<>v>vv^^<>>^^^<>^^>^v>v>>>^v^v><v^^<><v>^^v^v<^<^^><<v<^<^<>^<>><<>^>>^>^^><v><>v<><>><<<>>>>vv>>>^>>^v<^>v^^^v<<vv>><<<^<<<>>>>>^>vv<^v^<>^<v^>^v><v>vvv<>>>^v^^^v<<<<>>^^<vv<^<^^>^<>v<^<<<>><>>v<^<>^<vvv<^<>><><<v>^^^>^^<<v<v^>^^v^>><<^vv><v>^v>>^<v>v>^^>^v>^vvv<>v^v^^<><vv>vv^>>><>v<^><v<v^<><<<>^v>^v<<<^>^>^>v^v<<><vvv<<v^^<><v>^>>><vv>><v>>v^<vv>>vv<<^v^v<<><^v<vv>>>vv<>>>>^vv>v^<>vv>v^v<v^><v<^^^^^>vv<><<vvv^<v><^<vv><^^^vv^<>^^^^<^><^<>v^<v^v<<^v<<^^<>>^<v^^>>>vv<vvv<>v<<>><^vvv^<<^^<<>>>^<>>>v^^><>><<>><v^v>>>>>><>>><v^<<vvv^>v<>>v^<>vv<><^^^^v^<<^<v^vv><<^^>v<^vvv^v>>v>^>>v>^^><<v^<>v<>vv<^v^vv><v><<vv^v>>v^>>v<^^^>^><<v<>^><>v>>>vvv<v<vv<^>>^v<v>^<^^^^^v><>v><>v^v^v<v^vv^v>vvvv<>vv<<<vv<v<<>^<^>^^v^<<>^<v><^><v<v<><<>v^<<^<><vv>v<<^v>>^v<><v>^>>^^><>v^<^<vvv^>^>^<<<<>vv>^v^v<^^^<vv>><>^^<<v<^<^^>>>v^v<<^^^<v<v<^<>^v<v><v^vv^^v^^v^^<vv<>^<><vv^<^v^<<^><<vvv>^^<^^^<^v>^>^vv><<<^v<v>vv>v<>v^v<v^>v^>>>v^v<>^v<<>^vv>v>v>v^<^>v^^<^>^^^^vv>^^><^>vv^>>^^v>><<<<^><>v<>^<v<vv^>^^><<^><v>v^>^^<^>>><>><v^v<v^<v<vv^v^<<^<vvv>>><vv<^^>>^>^><<v^<>>v>v^v^^><<>vv^v>v^<v><^<>^^<^>v>^<><<<v>^<^<^>^>^>^^v^<<^^v^^<^<>><^>v>>^^<>^^^<<<<v^>^v<^vv>^<<<v<><<v<>vv>>>v><>>><>>v<<<vv><>^v>v<^>><^><><v<>^v^>^v>^v<<><<^<>>v>^><>^>><>><^<v^><v^^<><v><^^>^v^^<>v^<v^<^v<v^^^^^v^<<^>^^^<^v><>^^<<<><<<<<^^>v^vvvv>v<>>vv<^>^v^>v<^vv^v<<><<v>v^v>^^><><^<v^>v><vv><>>><<>^vv<>v>>v<^v>>>v<v>v>v>^vv<<>^^vv<v<^v^<v<v>vv<>^<^<vv<v^<^v^^><<>^>><^v>vv^^v<<^^><<>v^^<><><v^^<v^v>^>^>^>v<^<v>^v^^>v<>vvv<^v<v^v><<v^><<^^><^<<v^v^>v<>^>v><><v>^<v<v>^<^^^>^v<<><<><>vv>v^<>v^><v^v<v><><<v>v<vv><<v>>v>^<<<>vv>>vvv>^^vv^v^^<^^<>v^^<>v>>^^>^>^>v>><^>><>>^<<>><^>v<<<<<<<^v^v<v^<v^^>^<><<v<^>v^>v^vv<<^^vv^>>>>^<>v<^v<>v<vv<^>>v^vv>vv><vv<<^>v>><vv>>>vv^<<<<vv^>v<<<<^^>^^v^><<^<v^>v^>^^<v<>vvv^>^<>vvv<v<^^>v^<<v>><>v<v<>^^<vvv>^>vv><><<<^^vv<v^<v<>v<>><<v><^vv^>^<^>^^^<<<v>vv^<^<<>^>^<vv>v><v<<^><^>^^<vv^v^^>>>>vv^><^^vv><>^<v^v>v<vv>v><<<v>v<v>^><v^^><v>v<^v^>>^^<v^>^^>vv>>vv^><^vv^vv<<^>vv>^v<v><vv><v<vvvvv>^^v^v><v>>>^vv<>v>^^^^<^>><>^v^^^>v<^^<<^^v<vv<>vvv<^>><><^>>^><^<>v<v<<><<v><v^v<>><^>v><<v^<v>v<^<vv^v^v^>vvv^^>v>^<vv^>v^v^<>v>^>>vv>><^^<v<<>^vv<><><<^v<v>v<<vv><>><^v<v>>v^>vvv^v^<<^><v<>^vv^>v^<v<^>>v<v><v><v>>^<<<v^<><<>v>^>^^<v<>>^<>^>^><<<^<<^<<^>^v>>><vvv>><<<<v>>>>>>>^<^v<^>v<>vv<><>v>>^>>^>vv^^><<^<v<v>>^^<<^>v<^>>vv>^<>v><^>v<vv>>>>>>^v<^<<<v^><vv<<>>vv<<><v<><<<v<^<v<>>v<^^^^v^^<^^^<^<vv><<^>><>v<<>v<v<>>>><>v^vv>^>^>>vv^v<v<<><^v>vv^><v<<>v^v<^>vv<<^^v><^>>^^vv<^<>>v^^>><v>^v>>>^>>v>v<>v<^vv><>^<<^>vv>>><><>v^><>v^>v>v><^v<><v<v>^v<<^vv^><^^>><^^^<<<^>v>^v>>><^>><^>>>^^^<^>vv<><<<v^>^<^^>>^^^v^v^v>v<v>>>><^>>>v>^vv<<^^^<^^vv>v<<><v<<^^>v>><<v^^><^>^<^>^v^>v><^<^vv>v>><>^<<vv<<v>v<vv<v>^>^>><^^<v>^v^v<><<>vvv<^<v>^><>^>vvv>>>^><<>><v^^<^<<^v>>^v<v<vv>vv^v^>v<<vvv<^^v^v>^<^>>^>v<^>^v<<><<<^>^<^^^>vv<^^^^vv<v<^^v<<<<v<^v^<><v<<^><<>vv>>><^<^<>>>^>^>>^<<<<<^^v>^>^<>vvv^^<^><^>^^v>^vv^><v^<^<<v^<vvv<<^v<><^><^>>>v>^v>^>^v<vv^v>><v><^><v^^>v^>^<><<><>v<v^>vvv^>^>>v<>^><^>^><vvv>^^v^v>v<>^v^><^>>v>v^><<<^>>^<>^<>>v><>>v^>^>^^<>>v^>^<vvvv<^vvvv^>>vv^<v^v>^vv<>v<>^<v<v>v>^^><^>vv^<^v^<<^<^<><vv<^v<^v><>>>^v^<<^><^>vv<v>v<^>vv^>v<<<>^<><v<^^^>v><^^<>^<^<v^vv^<<^>><<v^v<^vvv<<<>>vvvv^v^^^>v<>>><<>vvv<<^^^>v>v>>v<<v<v^v^>^^v>^><^<><<v^<v<v^^^><>v^^^<v>vv<>^>^^vv>^<<^v<^v><v>>>^>>><^<<>^v>>^>vv<<<v<>^<v><v^<^<>v>v^^v^>><<^v<<<<>v>v>v^^<^><>^^<<<v>vv<>>>^>>v<><v^>^<><vv>v>v^v<v^<^>>^>><<^^<^^v<vv<>><<<v<^<<^^^>vvv^<vvv<^>vv><>><<<^<v^v^^<<^vvv^^<^<><<>^<^<>>vvv<>^<>v^v<><>>v^v><<>>>vvv>v<>^>>^><^>vv<<>>v<<^><>v>>^^<v>^>^<<>><^<<vv<^<vv^vv><>>>><^<v>^>vv<v><>^<>vvvvv^vv<<v<>>>^<<><>^^vvv>>>vv<<^^><^v^^v<>^^>^><^>v^^^^v<^<<vv<vv<>vv^^>v^vv>v><>>vv>^<^<v^v^>>v^v^^v>^>vv^>v<vvvv<^v<^v>^v>^^v<<^>^^<<>^><^v>>>vv^>^^>vvvv>>v<^<v>^>>>v^<><^<^^<v>vv^^><v>v^<>^^^>>><^^v>v>^<<>^<v^>vvv^>^^^><v<^>>v<v>>^v><<><<>v<^<<>^><>^>vv>^<v>^^v<<^v^vvv^^>^vv^<^>^>^^v>v^>^<<><<^>v>>vv^vv><v>>^<<^<v^^<^<v^^vv^><^^<^^><v^^>v^^^<^<>^<>>^v<^vvv^^v^<><^>>>>>v><><<<>vv<^v>><<>vvv<><<vv<<<^>v^^>>^>^v>><><^^v<>><>>v^>^<vv><<<>><><<v>^^<>>v<><^<vv>vv<^v>^<<<<v<^<<^^>>^<><^>><<>^>v>^^^v>>^<^^v><v^v>^><<><>>^>>^<<v<>^v<>^>^<v>>vv>^vvv<<v<<^>^>^<<^^<>^^^^vvv<>^vv<vvvvv^^>^^<^>>><>v^<><^<<^>v^^v<>>^vv<>v^^<>>v^vvvvv<<v^<v^^>>><vvvvv>><^>vv>v^v^<v<^>^^><^>^^^^v<><^v<<>v^>v>>vv<<>^<v^^>vvv>^^<v^<>vv^><>><v^^v<>^>>^>v><>>^^v>^>^>>>^>v<^v>v>^<^^^^^>>v<v<>>v<<^>^<v<<>^^>><<^><>v<>^^^vv<>^^>><<^^>v>vv>vv>v^>^v>v^^<>>><<v><v<<>>v><>vvv^^v>^^>^vvvv^>^<>^vvvv><v><v<>>><>^<^vv<>^v<^v<>^vvv<<>><vvv^>>^><<vv^<v^>^<v<<^^>^^<^^v^>v<>v^v><>><v^^>>^vvv><^vv>v^<^<^v>>v^^>^vvv^<v^^v^^>v<^<>>^<>>>^^<><^^vv<>^vv^<>>>>^^<<^^<>vv^^><>^^<v<<v>^<v^^>^v<><><>vvv>^v^>>vv<<^v<<>><v>^><^>>>^<^<^^>vv^<<^<>>^^><><<v>^^<v>>v<<vvvv>^v^vv>><^^<<^>>v>v<^^^<^><^^vv>^vv<^<vv<>v><^<><v><^^^>>^<><^<v>>>>v^<v>>>>>v<><^^>v<^<^>><v<>^>vv>^^v^v^<<v<><<<^v^><<^<><<<<v<^>><<<>v>>vv><vv<><<^<^<><vv>^^^^<>v<<<<v>vv<>vv^^^>><>vv^><>>^vv<<><^^vv<>v^>>^<<>^<v^<^>v<
(defun day3/make-coord (x y)
(cons x y))
(defun day3/coord-x (coord)
(car coord))
(defun day3/coord-y (coord)
(cdr coord))
(defun day3/add-coords (a b)
(day3/make-coord
(+ (day3/coord-x a)
(day3/coord-x b))
(+ (day3/coord-y a)
(day3/coord-y b))))
(defun day3/arrow-to-coord (arrow)
(cond ((eq arrow ?>) (day3/make-coord 1 0))
((eq arrow ?<) (day3/make-coord -1 0))
((eq arrow ?^) (day3/make-coord 0 1))
((eq arrow ?v) (day3/make-coord 0 -1))
(t (day3/make-coord 0 0))))
(defun day3/make-map ()
(make-hash-table :test #'equal))
(defun day3/map-visit (map coord)
(puthash coord
(+ 1 (gethash coord map 0))
map))
(defun day3/deliver (directions)
(let ((map (day3/make-map)))
(day3/map-visit map (day3/make-coord 0 0))
(cdr (seq-reduce
(lambda (acc next)
(let* ((loc (car acc))
(map (cdr acc))
(next-loc (day3/add-coords loc
(day3/arrow-to-coord next))))
(day3/map-visit map next-loc)
(cons next-loc map)))
directions
(cons (day3/make-coord 0 0)
map)))))
(defun day3/map-count-visited (map)
(hash-table-count map))
(ert-deftest day3/map-count-visited ()
(should (eq 2 (day3/map-count-visited
(day3/deliver ">"))))
(should (eq 4 (day3/map-count-visited
(day3/deliver "^>v<"))))
(should (eq 2 (day3/map-count-visited
(day3/deliver "^v^v^v^v^v")))))
(day3/map-count-visited
(day3/deliver input))
2592
Part 2
The next year, to speed up the process, Santa creates a robot version of himself, Robo-Santa, to deliver presents with him.
Santa and Robo-Santa start at the same location (delivering two presents to the same starting house), then take turns moving based on instructions from the elf, who is eggnoggedly reading from the same script as the previous year.
This year, how many houses receive at least one present?
For example:
^v
delivers presents to3
houses, because Santa goes north, and then Robo-Santa goes south.^>v<
now delivers presents to3
houses, and Santa and Robo-Santa end up back where they started.^v^v^v^v^v
now delivers presents to11
houses, with Santa going one direction and Robo-Santa going the other.
(require 'dash)
(defun day3/alternate (count sequence)
(->> (-zip (seq-into sequence 'list)
(number-sequence 1 (seq-length sequence)))
(-group-by (lambda (x) (mod (cdr x) count)))
(-map (lambda (x) (-map #'car (cdr x))))))
(defun day3/map-visit-n (map coord times)
(puthash coord
(+ times (gethash coord map 0))
map))
(defun day3/map-visits (map coord)
(gethash coord map 0))
(defun day3/map-locations (map)
(hash-table-keys map))
(defun day3/map-merge (a &rest maps)
(-map (lambda (map)
(-map (lambda (coord)
(day3/map-visit-n a coord (day3/map-visits map coord)))
(day3/map-locations map)))
maps)
a)
(defun day3/deliver-with-robosanta (directions)
(let* ((alternated (day3/alternate 2 (string-to-list directions)))
(santa-directions (car alternated))
(robot-directions (cadr alternated)))
(day3/map-merge
(day3/deliver santa-directions)
(day3/deliver robot-directions))))
(ert-deftest day3/deliver-with-robosanta ()
(should (eq 3 (day3/map-count-visited
(day3/deliver-with-robosanta "^v"))))
(should (eq 3 (day3/map-count-visited
(day3/deliver-with-robosanta "^>v<"))))
(should (eq 11 (day3/map-count-visited
(day3/deliver-with-robosanta "^v^v^v^v^v")))))
(day3/map-count-visited
(day3/deliver-with-robosanta input))
2360
Day 4: The Ideal Stocking Stuffer
Santa needs help mining some AdventCoins (very similar to bitcoins) to use as gifts for all the economically forward-thinking little girls and boys.
To do this, he needs to find MD5 hashes which, in hexadecimal, start
with at least five zeroes. The input to the MD5 hash is some secret
key (your puzzle input, given below) followed by a number in decimal.
To mine AdventCoins, you must find Santa the lowest positive number
(no leading zeroes: 1
, 2
, 3
, …) that produces such a hash.
For example:
- If your secret key is
abcdef
, the answer is609043
, because the MD5 hash ofabcdef609043
starts with five zeroes (000001dbbfa...
), and it is the lowest such number to do so. - If your secret key is
pqrstuv
, the lowest number it combines with to make an MD5 hash starting with five zeroes is1048970
; that is, the MD5 hash ofpqrstuv1048970
looks like000006136ef...
.
ckczppom
(defun day4/mine-hash (key n)
(md5 (format "%s%d" key n)))
(defun day4/adventcoin-hash-p (hash)
(string-equal
"00000"
(substring hash 0 5)))
(defun day4/first-adventcoin (secret)
(loop for x from 0
while (not (day4/adventcoin-hash-p (day4/mine-hash secret x)))
count x))
(ert-deftest day4/first-adventcoin ()
(should (eq 609043 (day4/first-adventcoin "abcdef")))
(should (eq 1048970 (day4/first-adventcoin "pqrstuv"))))
(day4/first-adventcoin (string-trim input))
117946
Part 2
Now find one that starts with six zeroes.
(defun day4/adventcoin-hash-6-p (n hash)
(string-equal
"000000"
(substring hash 0 6)))
(defun day4/first-adventcoin-n (n secret)
(loop for x from 0
while (not (day4/adventcoin-hash-6-p n (day4/mine-hash secret x)))
count x))
(day4/first-adventcoin-n 6 (string-trim input))
3938038
Day 5: Doesn't He Have Intern-Elves For This?
Santa needs help figuring out which strings in his text file are naughty or nice.
A nice string is one with all of the following properties:
- It contains at least three vowels (
aeiou
only), likeaei
,xazegov
, oraeiouaeiouaeiou
. - It contains at least one letter that appears twice in a row, like
xx
,abcdde
(dd
), oraabbccdd
(aa
,bb
,cc
, ordd
). - It does not contain the strings
ab
,cd
,pq
, orxy
, even if they are part of one of the other requirements.
For example:
ugknbfddgicrmopn
is nice because it has at least three vowels (u...i...o...
), a double letter (...dd...
), and none of the disallowed substrings.aaa
is nice because it has at least three vowels and a double letter, even though the letters used by different rules overlap.jchzalrnumimnmhp
is naughty because it has no double letter.haegwjzuvuyypxyu
is naughty because it contains the stringxy
.- =dvszwmarrgswjxmb- is naughty because it contains only one vowel.
How many strings are nice?
sszojmmrrkwuftyv isaljhemltsdzlum fujcyucsrxgatisb qiqqlmcgnhzparyg oijbmduquhfactbc jqzuvtggpdqcekgk zwqadogmpjmmxijf uilzxjythsqhwndh gtssqejjknzkkpvw wrggegukhhatygfi vhtcgqzerxonhsye tedlwzdjfppbmtdx iuvrelxiapllaxbg feybgiimfthtplui qxmmcnirvkzfrjwd vfarmltinsriqxpu oanqfyqirkraesfq xilodxfuxphuiiii yukhnchvjkfwcbiq bdaibcbzeuxqplop ivegnnpbiyxqsion ybahkbzpditgwdgt dmebdomwabxgtctu ibtvimgfaeonknoh jsqraroxudetmfyw dqdbcwtpintfcvuz tiyphjunlxddenpj fgqwjgntxagidhah nwenhxmakxqkeehg zdoheaxqpcnlhnen tfetfqojqcdzlpbm qpnxkuldeiituggg xwttlbdwxohahwar hjkwzadmtrkegzye koksqrqcfwcaxeof wulwmrptktliyxeq gyufbedqhhyqgqzj txpunzodohikzlmj jloqfuejfkemcrvu amnflshcheuddqtc pdvcsduggcogbiia yrioavgfmeafjpcz uyhbtmbutozzqfvq mwhgfwsgyuwcdzik auqylgxhmullxpaa lgelzivplaeoivzh uyvcepielfcmswoa qhirixgwkkccuzlp zoonniyosmkeejfg iayfetpixkedyana ictqeyzyqswdskiy ejsgqteafvmorwxe lhaiqrlqqwfbrqdx ydjyboqwhfpqfydc dwhttezyanrnbybv edgzkqeqkyojowvr rmjfdwsqamjqehdq ozminkgnkwqctrxz bztjhxpjthchhfcd vrtioawyxkivrpiq dpbcsznkpkaaclyy vpoypksymdwttpvz hhdlruwclartkyap bqkrcbrksbzcggbo jerbbbnxlwfvlaiw dwkasufidwjrjfbf kkfxtjhbnmqbmfwf vmnfziwqxmioukmj rqxvcultipkecdtu fhmfdibhtjzkiqsd hdpjbuzzbyafqrpd emszboysjuvwwvts msyigmwcuybfiooq druyksfnbluvnwoh fvgstvynnfbvxhsx bmzalvducnqtuune lzwkzfzttsvpllei olmplpvjamynfyfd padcwfkhystsvyfb wjhbvxkwtbfqdilb hruaqjwphonnterf bufjobjtvxtzjpmj oiedrjvmlbtwyyuy sgiemafwfztwsyju nsoqqfudrtwszyqf vonbxquiiwxnazyl yvnmjxtptujwqudn rrnybqhvrcgwvrkq taktoxzgotzxntfu quffzywzpxyaepxa rfvjebfiddcfgmwv iaeozntougqwnzoh scdqyrhoqmljhoil bfmqticltmfhxwld brbuktbyqlyfpsdl oidnyhjkeqenjlhd kujsaiqojopvrygg vebzobmdbzvjnjtk uunoygzqjopwgmbg piljqxgicjzgifso ikgptwcjzywswqnw pujqsixoisvhdvwi trtuxbgigogfsbbk mplstsqclhhdyaqk gzcwflvmstogdpvo tfjywbkmimyyqcjd gijutvhruqcsiznq ibxkhjvzzxgavkha btnxeqvznkxjsgmq tjgofgauxaelmjoq sokshvyhlkxerjrv ltogbivktqmtezta uduwytzvqvfluyuf msuckpthtgzhdxan fqmcglidvhvpirzr gwztkqpcwnutvfga bsjfgsrntdhlpqbx xloczbqybxmiopwt orvevzyjliomkkgu mzjbhmfjjvaziget tlsdxuhwdmghdyjb atoecyjhwmznaewi pyxpyvvipbqibiox ajbfmpqqobfsmesj siknbzefjblnohgd eqfhgewbblwdfkmc opylbscrotckkrbk lbwxbofgjkzdxkle ceixfjstaptdomvm hnkrqxifjmmjktie aqykzeuzvvetoygd fouahjimfcisxima prkzhutbqsyrhjzx qqwliakathnsbzne sayhgqtlcqqidqhj ygduolbysehdudra zricvxhdzznuxuce ucvzakslykpgsixd udirhgcttmyspgsb yuwzppjzfsjhhdzi gtqergjiuwookwre xvxexbjyjkxovvwf mlpaqhnnkqxrmwmm ezuqbrjozwuqafhb mcarusdthcbsonoq weeguqeheeiigrue pngtfugozxofaqxv copphvbjcmfspenv jiyahihykjjkdaya gdqnmesvptuyrfwp vbdscfywqmfxbohh crtrfuxyjypzubrg seihvevtxywxhflp fvvpmgttnapklwou qmqaqsajmqwhetpk zetxvrgjmblxvakr kpvwblrizaabmnhz mwpvvzaaicntrkcp clqyjiegtdsswqfm ymrcnqgcpldgfwtm nzyqpdenetncgnwq cmkzevgacnmdkqro kzfdsnamjqbeirhi kpxrvgvvxapqlued rzskbnfobevzrtqu vjoahbfwtydugzap ykbbldkoijlvicbl mfdmroiztsgjlasb quoigfyxwtwprmdr ekxjqafwudgwfqjm obtvyjkiycxfcdpb lhoihfnbuqelthof eydwzitgxryktddt rxsihfybacnpoyny bsncccxlplqgygtw rvmlaudsifnzhcqh huxwsyjyebckcsnn gtuqzyihwhqvjtes zreeyomtngvztveq nwddzjingsarhkxb nuqxqtctpoldrlsh wkvnrwqgjooovhpf kwgueyiyffudtbyg tpkzapnjxefqnmew ludwccvkihagvxal lfdtzhfadvabghna njqmlsnrkcfhtvbb cajzbqleghhnlgap vmitdcozzvqvzatp eelzefwqwjiywbcz uyztcuptfqvymjpi aorhnrpkjqqtgnfo lfrxfdrduoeqmwwp vszpjvbctblplinh zexhadgpqfifcqrz ueirfnshekpemqua qfremlntihbwabtb nwznunammfexltjc zkyieokaaogjehwt vlrxgkpclzeslqkq xrqrwfsuacywczhs olghlnfjdiwgdbqc difnlxnedpqcsrdf dgpuhiisybjpidsj vlwmwrikmitmoxbt sazpcmcnviynoktm pratafauetiknhln ilgteekhzwlsfwcn ywvwhrwhkaubvkbl qlaxivzwxyhvrxcf hbtlwjdriizqvjfb nrmsononytuwslsa mpxqgdthpoipyhjc mcdiwmiqeidwcglk vfbaeavmjjemfrmo qzcbzmisnynzibrc shzmpgxhehhcejhb wirtjadsqzydtyxd qjlrnjfokkqvnpue dxawdvjntlbxtuqc wttfmnrievfestog eamjfvsjhvzzaobg pbvfcwzjgxahlrag omvmjkqqnobvnzkn lcwmeibxhhlxnkzv uiaeroqfbvlazegs twniyldyuonfyzqw wgjkmsbwgfotdabi hnomamxoxvrzvtew ycrcfavikkrxxfgw isieyodknagzhaxy mgzdqwikzullzyco mumezgtxjrrejtrs nwmwjcgrqiwgfqel wjgxmebfmyjnxyyp durpspyljdykvzxf zuslbrpooyetgafh kuzrhcjwbdouhyme wyxuvbciodscbvfm kbnpvuqwmxwfqtqe zddzercqogdpxmft sigrdchxtgavzzjh lznjolnorbuddgcs ycnqabxlcajagwbt bnaudeaexahdgxsj rlnykxvoctfwanms jngyetkoplrstfzt tdpxknwacksotdub yutqgssfoptvizgr lzmqnxeqjfnsxmsa iqpgfsfmukovsdgu qywreehbidowtjyz iozamtgusdctvnkw ielmujhtmynlwcfd hzxnhtbnmmejlkyf ftbslbzmiqkzebtd bcwdqgiiizmohack dqhfkzeddjzbdlxu mxopokqffisxosci vciatxhtuechbylk khtkhcvelidjdena blatarwzfqcapkdt elamngegnczctcck xeicefdbwrxhuxuf sawvdhjoeahlgcdr kmdcimzsfkdfpnir axjayzqlosrduajb mfhzreuzzumvoggr iqlbkbhrkptquldb xcvztvlshiefuhgb pkvwyqmyoazocrio ajsxkdnerbmhyxaj tudibgsbnpnizvsi cxuiydkgdccrqvkh cyztpjesdzmbcpot nnazphxpanegwitx uphymczbmjalmsct yyxiwnlrogyzwqmg gmqwnahjvvdyhnfa utolskxpuoheugyl mseszdhyzoyavepd ycqknvbuvcjfgmlc sknrxhxbfpvpeorn zqxqjetooqcodwml sesylkpvbndrdhsy fryuxvjnsvnjrxlw mfxusewqurscujnu mbitdjjtgzchvkfv ozwlyxtaalxofovd wdqcduaykxbunpie rlnhykxiraileysk wgoqfrygttlamobg kflxzgxvcblkpsbz tmkisflhativzhde owsdrfgkaamogjzd gaupjkvkzavhfnes wknkurddcknbdleg lltviwincmbtduap qwzvspgbcksyzzmb ydzzkumecryfjgnk jzvmwgjutxoysaam icrwpyhxllbardkr jdopyntshmvltrve afgkigxcuvmdbqou mfzzudntmvuyhjzt duxhgtwafcgrpihc tsnhrkvponudumeb sqtvnbeiigdzbjgv eczmkqwvnsrracuo mhehsgqwiczaiaxv kaudmfvifovrimpd lupikgivechdbwfr mwaaysrndiutuiqx aacuiiwgaannunmm tjqjbftaqitukwzp lrcqyskykbjpaekn lirrvofbcqpjzxmr jurorvzpplyelfml qonbllojmloykjqe sllkzqujfnbauuqp auexjwsvphvikali usuelbssqmbrkxyc wyuokkfjexikptvv wmfedauwjgbrgytl sfwvtlzzebxzmuvw rdhqxuechjsjcvaf kpavhqkukugocsxu ovnjtumxowbxduts zgerpjufauptxgat pevvnzjfwhjxdoxq pmmfwxajgfziszcs difmeqvaghuitjhs icpwjbzcmlcterwm ngqpvhajttxuegyh mosjlqswdngwqsmi frlvgpxrjolgodlu eazwgrpcxjgoszeg bbtsthgkjrpkiiyk tjonoglufuvsvabe xhkbcrofytmbzrtk kqftfzdmpbxjynps kmeqpocbnikdtfyv qjjymgqxhnjwxxhp dmgicrhgbngdtmjt zdxrhdhbdutlawnc afvoekuhdboxghvx hiipezngkqcnihty bbmqgheidenweeov suprgwxgxwfsgjnx adeagikyamgqphrj zzifqinoeqaorjxg adhgppljizpaxzld lvxyieypvvuqjiyc nljoakatwwwoovzn fcrkfxclcacshhmx ownnxqtdhqbgthch lmfylrcdmdkgpwnj hlwjfbvlswbzpbjr mkofhdtljdetcyvp synyxhifbetzarpo agnggugngadrcxoc uhttadmdmhidpyjw ohfwjfhunalbubpr pzkkkkwrlvxiuysn kmidbxmyzkjrwjhu egtitdydwjxmajnw civoeoiuwtwgbqqs dfptsguzfinqoslk tdfvkreormspprer zvnvbrmthatzztwi ffkyddccrrfikjde hrrmraevdnztiwff qaeygykcpbtjwjbr purwhitkmrtybslh qzziznlswjaussel dfcxkvdpqccdqqxj tuotforulrrytgyn gmtgfofgucjywkev wkyoxudvdkbgpwhd qbvktvfvipftztnn otckgmojziezmojb inxhvzbtgkjxflay qvxapbiatuudseno krpvqosbesnjntut oqeukkgjsfuqkjbb prcjnyymnqwqksiz vuortvjxgckresko orqlyobvkuwgathr qnpyxlnazyfuijox zwlblfkoklqmqzkw hmwurwtpwnrcsanl jzvxohuakopuzgpf sfcpnxrviphhvxmx qtwdeadudtqhbely dbmkmloasqphnlgj olylnjtkxgrubmtk nxsdbqjuvwrrdbpq wbabpirnpcsmpipw hjnkyiuxpqrlvims enzpntcjnxdpuqch vvvqhlstzcizyimn triozhqndbttglhv fukvgteitwaagpzx uhcvukfbmrvskpen tizcyupztftzxdmt vtkpnbpdzsaluczz wodfoyhoekidxttm otqocljrmwfqbxzu linfbsnfvixlwykn vxsluutrwskslnye zbshygtwugixjvsi zdcqwxvwytmzhvoo wrseozkkcyctrmei fblgtvogvkpqzxiy opueqnuyngegbtnf qxbovietpacqqxok zacrdrrkohfygddn gbnnvjqmkdupwzpq qgrgmsxeotozvcak hnppukzvzfmlokid dzbheurndscrrtcl wbgdkadtszebbrcw fdmzppzphhpzyuiz bukomunhrjrypohj ohodhelegxootqbj rsplgzarlrknqjyh punjjwpsxnhpzgvu djdfahypfjvpvibm mlgrqsmhaozatsvy xwktrgyuhqiquxgn wvfaoolwtkbrisvf plttjdmguxjwmeqr zlvvbwvlhauyjykw cigwkbyjhmepikej masmylenrusgtyxs hviqzufwyetyznze nzqfuhrooswxxhus pdbdetaqcrqzzwxf oehmvziiqwkzhzib icgpyrukiokmytoy ooixfvwtiafnwkce rvnmgqggpjopkihs wywualssrmaqigqk pdbvflnwfswsrirl jeaezptokkccpbuj mbdwjntysntsaaby ldlgcawkzcwuxzpz lwktbgrzswbsweht ecspepmzarzmgpjm qmfyvulkmkxjncai izftypvwngiukrns zgmnyjfeqffbooww nyrkhggnprhedows yykzzrjmlevgffah mavaemfxhlfejfki cmegmfjbkvpncqwf zxidlodrezztcrij fseasudpgvgnysjv fupcimjupywzpqzp iqhgokavirrcvyys wjmkcareucnmfhui nftflsqnkgjaexhq mgklahzlcbapntgw kfbmeavfxtppnrxn nuhyvhknlufdynvn nviogjxbluwrcoec tyozixxxaqiuvoys kgwlvmvgtsvxojpr moeektyhyonfdhrb kahvevmmfsmiiqex xcywnqzcdqtvhiwd fnievhiyltbvtvem jlmndqufirwgtdxd muypbfttoeelsnbs rypxzbnujitfwkou ubmmjbznskildeoj ofnmizdeicrmkjxp rekvectjbmdnfcib yohrojuvdexbctdh gwfnfdeibynzjmhz jfznhfcqdwlpjull scrinzycfhwkmmso mskutzossrwoqqsi rygoebkzgyzushhr jpjqiycflqkexemx arbufysjqmgaapnl dbjerflevtgweeoj snybnnjlmwjvhois fszuzplntraprmbj mkvaatolvuggikvg zpuzuqygoxesnuyc wnpxvmxvllxalulm eivuuafkvudeouwy rvzckdyixetfuehr qgmnicdoqhveahyx miawwngyymshjmpj pvckyoncpqeqkbmx llninfenrfjqxurv kzbjnlgsqjfuzqtp rveqcmxomvpjcwte bzotkawzbopkosnx ktqvpiribpypaymu wvlzkivbukhnvram uohntlcoguvjqqdo ajlsiksjrcnzepkt xsqatbldqcykwusd ihbivgzrwpmowkop vfayesfojmibkjpb uaqbnijtrhvqxjtb hhovshsfmvkvymba jerwmyxrfeyvxcgg hncafjwrlvdcupma qyvigggxfylbbrzt hiiixcyohmvnkpgk mmitpwopgxuftdfu iaxderqpceboixoa zodfmjhuzhnsqfcb sthtcbadrclrazsi bkkkkcwegvypbrio wmpcofuvzemunlhj gqwebiifvqoeynro juupusqdsvxcpsgv rbhdfhthxelolyse kjimpwnjfrqlqhhz rcuigrjzarzpjgfq htxcejfyzhydinks sxucpdxhvqjxxjwf omsznfcimbcwaxal gufmtdlhgrsvcosb bssshaqujtmluerz uukotwjkstgwijtr kbqkneobbrdogrxk ljqopjcjmelgrakz rwtfnvnzryujwkfb dedjjbrndqnilbeh nzinsxnpptzagwlb lwqanydfirhnhkxy hrjuzfumbvfccxno okismsadkbseumnp sfkmiaiwlktxqvwa hauwpjjwowbunbjj nowkofejwvutcnui bqzzppwoslaeixro urpfgufwbtzenkpj xgeszvuqwxeykhef yxoldvkyuikwqyeq onbbhxrnmohzskgg qcikuxakrqeugpoa lnudcqbtyzhlpers nxduvwfrgzaailgl xniuwvxufzxjjrwz ljwithcqmgvntjdj awkftfagrfzywkhs uedtpzxyubeveuek bhcqdwidbjkqqhzl iyneqjdmlhowwzxx kvshzltcrrururty zgfpiwajegwezupo tkrvyanujjwmyyri ercsefuihcmoaiep ienjrxpmetinvbos jnwfutjbgenlipzq bgohjmrptfuamzbz rtsyamajrhxbcncw tfjdssnmztvbnscs bgaychdlmchngqlp kfjljiobynhwfkjo owtdxzcpqleftbvn ltjtimxwstvzwzjj wbrvjjjajuombokf zblpbpuaqbkvsxye gwgdtbpnlhyqspdi abipqjihjqfofmkx nlqymnuvjpvvgova avngotmhodpoufzn qmdyivtzitnrjuae xfwjmqtqdljuerxi csuellnlcyqaaamq slqyrcurcyuoxquo dcjmxyzbzpohzprl uqfnmjwniyqgsowb rbmxpqoblyxdocqc ebjclrdbqjhladem ainnfhxnsgwqnmyo eyytjjwhvodtzquf iabjgmbbhilrcyyp pqfnehkivuelyccc xgjbyhfgmtseiimt jwxyqhdbjiqqqeyy gxsbrncqkmvaryln vhjisxjkinaejytk seexagcdmaedpcvh lvudfgrcpjxzdpvd fxtegyrqjzhmqean dnoiseraqcoossmc nwrhmwwbykvwmgep udmzskejvizmtlce hbzvqhvudfdlegaa cghmlfqejbxewskv bntcmjqfwomtbwsb qezhowyopjdyhzng todzsocdkgfxanbz zgjkssrjlwxuhwbk eibzljqsieriyrzr wamxvzqyycrxotjp epzvfkispwqynadu dwlpfhtrafrxlyie qhgzujhgdruowoug girstvkahaemmxvh baitcrqmxhazyhbl xyanqcchbhkajdmc gfvjmmcgfhvgnfdq tdfdbslwncbnkzyz jojuselkpmnnbcbb hatdslkgxtqpmavj dvelfeddvgjcyxkj gnsofhkfepgwltse mdngnobasfpewlno qssnbcyjgmkyuoga glvcmmjytmprqwvn gwrixumjbcdffsdl lozravlzvfqtsuiq sicaflbqdxbmdlch inwfjkyyqbwpmqlq cuvszfotxywuzhzi igfxyoaacoarlvay ucjfhgdmnjvgvuni rvvkzjsytqgiposh jduinhjjntrmqroz yparkxbgsfnueyll lyeqqeisxzfsqzuj woncskbibjnumydm lltucklragtjmxtl ubiyvmyhlesfxotj uecjseeicldqrqww xxlxkbcthufnjbnm lhqijovvhlffpxga fzdgqpzijitlogjz efzzjqvwphomxdpd jvgzvuyzobeazssc hejfycgxywfjgbfw yhjjmvkqfbnbliks sffvfyywtlntsdsz dwmxqudvxqdenrur asnukgppdemxrzaz nwqfnumblwvdpphx kqsmkkspqvxzuket cpnraovljzqiquaz qrzgrdlyyzbyykhg opoahcbiydyhsmqe hjknnfdauidjeydr hczdjjlygoezadow rtflowzqycimllfv sfsrgrerzlnychhq bpahuvlblcolpjmj albgnjkgmcrlaicl pijyqdhfxpaxzdex eeymiddvcwkpbpux rqwkqoabywgggnln vckbollyhgbgmgwh ylzlgvnuvpynybkm hpmbxtpfosbsjixt ocebeihnhvkhjfqz tvctyxoujdgwayze efvhwxtuhapqxjen rusksgefyidldmpo nkmtjvddfmhirmzz whvtsuadwofzmvrt iiwjqvsdxudhdzzk gucirgxaxgcassyo rmhfasfzexeykwmr hynlxcvsbgosjbis huregszrcaocueen pifezpoolrnbdqtv unatnixzvdbqeyox xtawlpduxgacchfe bdvdbflqfphndduf xtdsnjnmzccfptyt nkhsdkhqtzqbphhg aqcubmfkczlaxiyb moziflxpsfubucmv srdgnnjtfehiimqx pwfalehdfyykrohf sysxssmvewyfjrve brsemdzosgqvvlxe bimbjoshuvflkiat hkgjasmljkpkwwku sbnmwjvodygobpqc bbbqycejueruihhd corawswvlvneipyc gcyhknmwsczcxedh kppakbffdhntmcqp ynulzwkfaemkcefp pyroowjekeurlbii iwksighrswdcnmxf glokrdmugreygnsg xkmvvumnfzckryop aesviofpufygschi csloawlirnegsssq fkqdqqmlzuxbkzbc uzlhzcfenxdfjdzp poaaidrktteusvyf zrlyfzmjzfvivcfr qwjulskbniitgqtx gjeszjksbfsuejki vczdejdbfixbduaq knjdrjthitjxluth jweydeginrnicirl bottrfgccqhyycsl eiquffofoadmbuhk lbqfutmzoksscswf xfmdvnvfcnzjprba uvugkjbkhlaoxmyx wadlgtpczgvcaqqv inzrszbtossflsxk dbzbtashaartczrj qbjiqpccefcfkvod hluujmokjywotvzy thwlliksfztcmwzh arahybspdaqdexrq nuojrmsgyipdvwyx hnajdwjwmzattvst sulcgaxezkprjbgu rjowuugwdpkjtypw oeugzwuhnrgiaqga wvxnyymwftfoswij pqxklzkjpcqscvde tuymjzknntekglqj odteewktugcwlhln exsptotlfecmgehc eeswfcijtvzgrqel vjhrkiwmunuiwqau zhlixepkeijoemne pavfsmwesuvebzdd jzovbklnngfdmyws nbajyohtzfeoiixz ciozmhrsjzrwxvhz gwucrxieqbaqfjuv uayrxrltnohexawc flmrbhwsfbcquffm gjyabmngkitawlxc rwwtggvaygfbovhg xquiegaisynictjq oudzwuhexrwwdbyy lengxmguyrwhrebb uklxpglldbgqsjls dbmvlfeyguydfsxq zspdwdqcrmtmdtsc mqfnzwbfqlauvrgc amcrkzptgacywvhv ndxmskrwrqysrndf mwjyhsufeqhwisju srlrukoaenyevykt tnpjtpwawrxbikct geczalxmgxejulcv tvkcbqdhmuwcxqci tiovluvwezwwgaox zrjhtbgajkjqzmfo vcrywduwsklepirs lofequdigsszuioy wxsdzomkjqymlzat iabaczqtrfbmypuy ibdlmudbajikcncr rqcvkzsbwmavdwnv ypxoyjelhllhbeog fdnszbkezyjbttbg uxnhrldastpdjkdz xfrjbehtxnlyzcka omjyfhbibqwgcpbv eguucnoxaoprszmp xfpypldgcmcllyzz aypnmgqjxjqceelv mgzharymejlafvgf tzowgwsubbaigdok ilsehjqpcjwmylxc pfmouwntfhfnmrwk csgokybgdqwnduwp eaxwvxvvwbrovypz nmluqvobbbmdiwwb lnkminvfjjzqbmio mjiiqzycqdhfietz towlrzriicyraevq obiloewdvbrsfwjo lmeooaajlthsfltw ichygipzpykkesrw gfysloxmqdsfskvt saqzntehjldvwtsx pqddoemaufpfcaew mjrxvbvwcreaybwe ngfbrwfqnxqosoai nesyewxreiqvhald kqhqdlquywotcyfy liliptyoqujensfi nsahsaxvaepzneqq zaickulfjajhctye gxjzahtgbgbabtht koxbuopaqhlsyhrp jhzejdjidqqtjnwe dekrkdvprfqpcqki linwlombdqtdeyop dvckqqbnigdcmwmx yaxygbjpzkvnnebv rlzkdkgaagmcpxah cfzuyxivtknirqvt obivkajhsjnrxxhn lmjhayymgpseuynn bbjyewkwadaipyju lmzyhwomfypoftuu gtzhqlgltvatxack jfflcfaqqkrrltgq txoummmnzfrlrmcg ohemsbfuqqpucups imsfvowcbieotlok tcnsnccdszxfcyde qkcdtkwuaquajazz arcfnhmdjezdbqku srnocgyqrlcvlhkb mppbzvfmcdirbyfw xiuarktilpldwgwd ypufwmhrvzqmexpc itpdnsfkwgrdujmj cmpxnodtsswkyxkr wayyxtjklfrmvbfp mfaxphcnjczhbbwy sjxhgwdnqcofbdra pnxmujuylqccjvjm ivamtjbvairwjqwl deijtmzgpfxrclss bzkqcaqagsynlaer tycefobvxcvwaulz ctbhnywezxkdsswf urrxxebxrthtjvib fpfelcigwqwdjucv ngfcyyqpqulwcphb rltkzsiipkpzlgpw qfdsymzwhqqdkykc balrhhxipoqzmihj rnwalxgigswxomga ghqnxeogckshphgr lyyaentdizaumnla exriodwfzosbeoib speswfggibijfejk yxmxgfhvmshqszrq hcqhngvahzgawjga qmhlsrfpesmeksur eviafjejygakodla kvcfeiqhynqadbzv fusvyhowslfzqttg girqmvwmcvntrwau yuavizroykfkdekz jmcwohvmzvowrhxf kzimlcpavapynfue wjudcdtrewfabppq yqpteuxqgbmqfgxh xdgiszbuhdognniu jsguxfwhpftlcjoh whakkvspssgjzxre ggvnvjurlyhhijgm krvbhjybnpemeptr pqedgfojyjybfbzr jzhcrsgmnkwwtpdo yyscxoxwofslncmp gzjhnxytmyntzths iteigbnqbtpvqumi zjevfzusnjukqpfw xippcyhkfuounxqk mcnhrcfonfdgpkyh pinkcyuhjkexbmzj lotxrswlxbxlxufs fmqajrtoabpckbnu wfkwsgmcffdgaqxg qfrsiwnohoyfbidr czfqbsbmiuyusaqs ieknnjeecucghpoo cevdgqnugupvmsge gjkajcyjnxdrtuvr udzhrargnujxiclq zqqrhhmjwermjssg ggdivtmgoqajydzz wnpfsgtxowkjiivl afbhqawjbotxnqpd xjpkifkhfjeqifdn oyfggzsstfhvticp kercaetahymeawxy khphblhcgmbupmzt iggoqtqpvaebtiol ofknifysuasshoya qxuewroccsbogrbv apsbnbkiopopytgu zyahfroovfjlythh bxhjwfgeuxlviydq uvbhdtvaypasaswa qamcjzrmesqgqdiz hjnjyzrxntiycyel wkcrwqwniczwdxgq hibxlvkqakusswkx mzjyuenepwdgrkty tvywsoqslfsulses jqwcwuuisrclircv xanwaoebfrzhurct ykriratovsvxxasf qyebvtqqxbjuuwuo telrvlwvriylnder acksrrptgnhkeiaa yemwfjhiqlzsvdxf banrornfkcymmkcc ytbhxvaeiigjpcgm crepyazgxquposkn xlqwdrytzwnxzwzv xtrbfbwopxscftps kwbytzukgseeyjla qtfdvavvjogybxjg ytbmvmrcxwfkgvzw nbscbdskdeocnfzr sqquwjbdxsxhcseg ewqxhigqcgszfsuw cvkyfcyfmubzwsee dcoawetekigxgygd ohgqnqhfimyuqhvi otisopzzpvnhctte bauieohjejamzien ewnnopzkujbvhwce aeyqlskpaehagdiv pncudvivwnnqspxy ytugesilgveokxcg zoidxeelqdjesxpr ducjccsuaygfchzj smhgllqqqcjfubfc nlbyyywergronmir prdawpbjhrzsbsvj nmgzhnjhlpcplmui eflaogtjghdjmxxz qolvpngucbkprrdc ixywxcienveltgho mwnpqtocagenkxut iskrfbwxonkguywx ouhtbvcaczqzmpua srewprgddfgmdbao dyufrltacelchlvu czmzcbrkecixuwzz dtbeojcztzauofuk prrgoehpqhngfgmw baolzvfrrevxsyke zqadgxshwiarkzwh vsackherluvurqqj surbpxdulvcvgjbd wqxytarcxzgxhvtx vbcubqvejcfsgrac zqnjfeapshjowzja hekvbhtainkvbynx knnugxoktxpvoxnh knoaalcefpgtvlwm qoakaunowmsuvkus ypkvlzcduzlezqcb ujhcagawtyepyogh wsilcrxncnffaxjf gbbycjuscquaycrk aduojapeaqwivnly ceafyxrakviagcjy nntajnghicgnrlst vdodpeherjmmvbje wyyhrnegblwvdobn xlfurpghkpbzhhif xyppnjiljvirmqjo kglzqahipnddanpi omjateouxikwxowr ocifnoopfglmndcx emudcukfbadyijev ooktviixetfddfmh wtvrhloyjewdeycg cgjncqykgutfjhvb nkwvpswppeffmwad hqbcmfhzkxmnrivg mdskbvzguxvieilr anjcvqpavhdloaqh erksespdevjylenq fadxwbmisazyegup iyuiffjmcaahowhj ygkdezmynmltodbv fytneukxqkjattvh woerxfadbfrvdcnz iwsljvkyfastccoa movylhjranlorofe drdmicdaiwukemep knfgtsmuhfcvvshg ibstpbevqmdlhajn tstwsswswrxlzrqs estyydmzothggudf jezogwvymvikszwa izmqcwdyggibliet nzpxbegurwnwrnca kzkojelnvkwfublh xqcssgozuxfqtiwi tcdoigumjrgvczfv ikcjyubjmylkwlwq kqfivwystpqzvhan bzukgvyoqewniivj iduapzclhhyfladn fbpyzxdfmkrtfaeg yzsmlbnftftgwadz
(defun day5/vowels (string)
(seq-filter
(apply-partially 'seq-contains "aeiou")
string))
(defun day5/has-doubles? (string)
(string-match-p "\\([a-z]\\)\\1" string))
(defun day5/naughty? (string)
(-any
(lambda (naughty-pattern)
(s-contains? naughty-pattern string))
'("ab" "cd" "pq" "xy")))
(defun day5/nice? (string)
(and (<= 3 (length (day5/vowels string)))
(day5/has-doubles? string)
(not (day5/naughty? string))))
(ert-deftest day5/nice? ()
(should (day5/nice? "ugknbfddgicrmopn"))
(should (day5/nice? "aaa"))
(should-not (day5/nice? "jchzalrnumimnmhp"))
(should-not (day5/nice? "haegwjzuvuyypxyu"))
(should-not (day5/nice? "dvszwmarrgswjxmb")))
(length
(-filter #'day5/nice?
(split-string input)))
255
Part 2
Realizing the error of his ways, Santa has switched to a better model of determining whether a string is naughty or nice. None of the old rules apply, as they are all clearly ridiculous.
Now, a nice string is one with all of the following properties:
- It contains a pair of any two letters that appears at least twice in
the string without overlapping, like
xyxy
(xy
) oraabcdefgaa
(aa
), but not likeaaa
(aa
, but it overlaps). - It contains at least one letter which repeats with exactly one
letter between them, like
xyx
,abcdefeghi
(efe
), or evenaaa
.
For example:
qjhvhtzxzqqjkmpb
is nice because is has a pair that appears twice (qj
) and a letter that repeats with exactly one letter between them (zxz
).xxyxx
is nice because it has a pair that appears twice and a letter that repeats with one between, even though the letters used by each rule overlap.uurcxstgmygtbstg
is naughty because it has a pair (tg
) but no repeat with a single letter between them.ieodomkazucvgmuy
is naughty because it has a repeating letter with one between (odo
), but no pair that appears twice.
How many strings are nice under these new rules?
(defun day5/double-pair? (string)
(string-match-p "\\([a-z][a-z]\\).*\\1"
string))
(ert-deftest day5/double-pair? ()
(should (day5/double-pair? "xyxy"))
(should (day5/double-pair? "aabcdefgaa"))
(should-not (day5/double-pair? "aaa")))
(defun day5/letter-sandwich? (string)
(string-match-p "\\([a-z]\\)[a-z]\\1"
string))
(ert-deftest day5/letter-sandwich? ()
(should (day5/letter-sandwich? "xyx"))
(should (day5/letter-sandwich? "abcdefeghi"))
(should (day5/letter-sandwich? "aaa")))
(defun day5/nice?? (string)
(and (day5/double-pair? string)
(day5/letter-sandwich? string)))
(ert-deftest day5/nice?? ()
(should (day5/nice?? "qjhvhtzxzqqjkmpb"))
(should (day5/nice?? "xxyxx"))
(should-not (day5/nice?? "uurcxstgmygtbstg"))
(should-not (day5/nice?? "ieodomkazucvgmuy")))
(length
(-filter #'day5/nice??
(split-string input)))
55
Day 6: Probably a Fire Hazard
Because your neighbors keep defeating you in the holiday house decorating contest year after year, you've decided to deploy one million lights in a 1000x1000 grid.
Furthermore, because you've been especially nice this year, Santa has mailed you instructions on how to display the ideal lighting configuration.
Lights in your grid are numbered from 0 to 999 in each direction; the
lights at each corner are at 0,0
, 0,999
, 999,999
, and 999,0
.
The instructions include whether to turn on
, turn off
, or toggle
various inclusive ranges given as coordinate pairs. Each coordinate
pair represents opposite corners of a rectangle, inclusive; a
coordinate pair like 0,0
through 2,2
therefore refers to 9 lights
in a 3x3 square. The lights all start turned off.
To defeat your neighbors this year, all you have to do is set up your lights by doing the instructions Santa sent you in order.
For example:
turn on 0,0 through 999,999
would turn on (or leave on) every light.toggle 0,0 through 999,0
would toggle the first line of 1000 lights, turning off the ones that were on, and turning on the ones that were off.turn off 499,499 through 500,500
would turn off (or leave off) the middle four lights.
After following the instructions, how many lights are lit?
turn on 887,9 through 959,629 turn on 454,398 through 844,448 turn off 539,243 through 559,965 turn off 370,819 through 676,868 turn off 145,40 through 370,997 turn off 301,3 through 808,453 turn on 351,678 through 951,908 toggle 720,196 through 897,994 toggle 831,394 through 904,860 toggle 753,664 through 970,926 turn off 150,300 through 213,740 turn on 141,242 through 932,871 toggle 294,259 through 474,326 toggle 678,333 through 752,957 toggle 393,804 through 510,976 turn off 6,964 through 411,976 turn off 33,572 through 978,590 turn on 579,693 through 650,978 turn on 150,20 through 652,719 turn off 782,143 through 808,802 turn off 240,377 through 761,468 turn off 899,828 through 958,967 turn on 613,565 through 952,659 turn on 295,36 through 964,978 toggle 846,296 through 969,528 turn off 211,254 through 529,491 turn off 231,594 through 406,794 turn off 169,791 through 758,942 turn on 955,440 through 980,477 toggle 944,498 through 995,928 turn on 519,391 through 605,718 toggle 521,303 through 617,366 turn off 524,349 through 694,791 toggle 391,87 through 499,792 toggle 562,527 through 668,935 turn off 68,358 through 857,453 toggle 815,811 through 889,828 turn off 666,61 through 768,87 turn on 27,501 through 921,952 turn on 953,102 through 983,471 turn on 277,552 through 451,723 turn off 64,253 through 655,960 turn on 47,485 through 734,977 turn off 59,119 through 699,734 toggle 407,898 through 493,955 toggle 912,966 through 949,991 turn on 479,990 through 895,990 toggle 390,589 through 869,766 toggle 593,903 through 926,943 toggle 358,439 through 870,528 turn off 649,410 through 652,875 turn on 629,834 through 712,895 toggle 254,555 through 770,901 toggle 641,832 through 947,850 turn on 268,448 through 743,777 turn off 512,123 through 625,874 turn off 498,262 through 930,811 turn off 835,158 through 886,242 toggle 546,310 through 607,773 turn on 501,505 through 896,909 turn off 666,796 through 817,924 toggle 987,789 through 993,809 toggle 745,8 through 860,693 toggle 181,983 through 731,988 turn on 826,174 through 924,883 turn on 239,228 through 843,993 turn on 205,613 through 891,667 toggle 867,873 through 984,896 turn on 628,251 through 677,681 toggle 276,956 through 631,964 turn on 78,358 through 974,713 turn on 521,360 through 773,597 turn off 963,52 through 979,502 turn on 117,151 through 934,622 toggle 237,91 through 528,164 turn on 944,269 through 975,453 toggle 979,460 through 988,964 turn off 440,254 through 681,507 toggle 347,100 through 896,785 turn off 329,592 through 369,985 turn on 931,960 through 979,985 toggle 703,3 through 776,36 toggle 798,120 through 908,550 turn off 186,605 through 914,709 turn off 921,725 through 979,956 toggle 167,34 through 735,249 turn on 726,781 through 987,936 toggle 720,336 through 847,756 turn on 171,630 through 656,769 turn off 417,276 through 751,500 toggle 559,485 through 584,534 turn on 568,629 through 690,873 toggle 248,712 through 277,988 toggle 345,594 through 812,723 turn off 800,108 through 834,618 turn off 967,439 through 986,869 turn on 842,209 through 955,529 turn on 132,653 through 357,696 turn on 817,38 through 973,662 turn off 569,816 through 721,861 turn on 568,429 through 945,724 turn on 77,458 through 844,685 turn off 138,78 through 498,851 turn on 136,21 through 252,986 turn off 2,460 through 863,472 turn on 172,81 through 839,332 turn on 123,216 through 703,384 turn off 879,644 through 944,887 toggle 227,491 through 504,793 toggle 580,418 through 741,479 toggle 65,276 through 414,299 toggle 482,486 through 838,931 turn off 557,768 through 950,927 turn off 615,617 through 955,864 turn on 859,886 through 923,919 turn on 391,330 through 499,971 toggle 521,835 through 613,847 turn on 822,787 through 989,847 turn on 192,142 through 357,846 turn off 564,945 through 985,945 turn off 479,361 through 703,799 toggle 56,481 through 489,978 turn off 632,991 through 774,998 toggle 723,526 through 945,792 turn on 344,149 through 441,640 toggle 568,927 through 624,952 turn on 621,784 through 970,788 toggle 665,783 through 795,981 toggle 386,610 through 817,730 toggle 440,399 through 734,417 toggle 939,201 through 978,803 turn off 395,883 through 554,929 turn on 340,309 through 637,561 turn off 875,147 through 946,481 turn off 945,837 through 957,922 turn off 429,982 through 691,991 toggle 227,137 through 439,822 toggle 4,848 through 7,932 turn off 545,146 through 756,943 turn on 763,863 through 937,994 turn on 232,94 through 404,502 turn off 742,254 through 930,512 turn on 91,931 through 101,942 toggle 585,106 through 651,425 turn on 506,700 through 567,960 turn off 548,44 through 718,352 turn off 194,827 through 673,859 turn off 6,645 through 509,764 turn off 13,230 through 821,361 turn on 734,629 through 919,631 toggle 788,552 through 957,972 toggle 244,747 through 849,773 turn off 162,553 through 276,887 turn off 569,577 through 587,604 turn off 799,482 through 854,956 turn on 744,535 through 909,802 toggle 330,641 through 396,986 turn off 927,458 through 966,564 toggle 984,486 through 986,913 toggle 519,682 through 632,708 turn on 984,977 through 989,986 toggle 766,423 through 934,495 turn on 17,509 through 947,718 turn on 413,783 through 631,903 turn on 482,370 through 493,688 turn on 433,859 through 628,938 turn off 769,549 through 945,810 turn on 178,853 through 539,941 turn off 203,251 through 692,433 turn off 525,638 through 955,794 turn on 169,70 through 764,939 toggle 59,352 through 896,404 toggle 143,245 through 707,320 turn off 103,35 through 160,949 toggle 496,24 through 669,507 turn off 581,847 through 847,903 turn on 689,153 through 733,562 turn on 821,487 through 839,699 turn on 837,627 through 978,723 toggle 96,748 through 973,753 toggle 99,818 through 609,995 turn on 731,193 through 756,509 turn off 622,55 through 813,365 turn on 456,490 through 576,548 turn on 48,421 through 163,674 turn off 853,861 through 924,964 turn off 59,963 through 556,987 turn on 458,710 through 688,847 toggle 12,484 through 878,562 turn off 241,964 through 799,983 turn off 434,299 through 845,772 toggle 896,725 through 956,847 turn on 740,289 through 784,345 turn off 395,840 through 822,845 turn on 955,224 through 996,953 turn off 710,186 through 957,722 turn off 485,949 through 869,985 turn on 848,209 through 975,376 toggle 221,241 through 906,384 turn on 588,49 through 927,496 turn on 273,332 through 735,725 turn on 505,962 through 895,962 toggle 820,112 through 923,143 turn on 919,792 through 978,982 toggle 489,461 through 910,737 turn off 202,642 through 638,940 turn off 708,953 through 970,960 toggle 437,291 through 546,381 turn on 409,358 through 837,479 turn off 756,279 through 870,943 turn off 154,657 through 375,703 turn off 524,622 through 995,779 toggle 514,221 through 651,850 toggle 808,464 through 886,646 toggle 483,537 through 739,840 toggle 654,769 through 831,825 turn off 326,37 through 631,69 turn off 590,570 through 926,656 turn off 881,913 through 911,998 turn on 996,102 through 998,616 turn off 677,503 through 828,563 turn on 860,251 through 877,441 turn off 964,100 through 982,377 toggle 888,403 through 961,597 turn off 632,240 through 938,968 toggle 731,176 through 932,413 turn on 5,498 through 203,835 turn on 819,352 through 929,855 toggle 393,813 through 832,816 toggle 725,689 through 967,888 turn on 968,950 through 969,983 turn off 152,628 through 582,896 turn off 165,844 through 459,935 turn off 882,741 through 974,786 turn off 283,179 through 731,899 toggle 197,366 through 682,445 turn on 106,309 through 120,813 toggle 950,387 through 967,782 turn off 274,603 through 383,759 turn off 155,665 through 284,787 toggle 551,871 through 860,962 turn off 30,826 through 598,892 toggle 76,552 through 977,888 turn on 938,180 through 994,997 toggle 62,381 through 993,656 toggle 625,861 through 921,941 turn on 685,311 through 872,521 turn on 124,934 through 530,962 turn on 606,379 through 961,867 turn off 792,735 through 946,783 turn on 417,480 through 860,598 toggle 178,91 through 481,887 turn off 23,935 through 833,962 toggle 317,14 through 793,425 turn on 986,89 through 999,613 turn off 359,201 through 560,554 turn off 729,494 through 942,626 turn on 204,143 through 876,610 toggle 474,97 through 636,542 turn off 902,924 through 976,973 turn off 389,442 through 824,638 turn off 622,863 through 798,863 turn on 840,622 through 978,920 toggle 567,374 through 925,439 turn off 643,319 through 935,662 toggle 185,42 through 294,810 turn on 47,124 through 598,880 toggle 828,303 through 979,770 turn off 174,272 through 280,311 turn off 540,50 through 880,212 turn on 141,994 through 221,998 turn on 476,695 through 483,901 turn on 960,216 through 972,502 toggle 752,335 through 957,733 turn off 419,713 through 537,998 toggle 772,846 through 994,888 turn on 881,159 through 902,312 turn off 537,651 through 641,816 toggle 561,947 through 638,965 turn on 368,458 through 437,612 turn on 290,149 through 705,919 turn on 711,918 through 974,945 toggle 916,242 through 926,786 toggle 522,272 through 773,314 turn on 432,897 through 440,954 turn off 132,169 through 775,380 toggle 52,205 through 693,747 toggle 926,309 through 976,669 turn off 838,342 through 938,444 turn on 144,431 through 260,951 toggle 780,318 through 975,495 turn off 185,412 through 796,541 turn on 879,548 through 892,860 turn on 294,132 through 460,338 turn on 823,500 through 899,529 turn off 225,603 through 483,920 toggle 717,493 through 930,875 toggle 534,948 through 599,968 turn on 522,730 through 968,950 turn off 102,229 through 674,529
(defun day6/make-light ()
nil)
(defun day6/turn-on-light (light)
t)
(defun day6/turn-off-light (light)
nil)
(defun day6/toggle-light (light)
(not light))
(defun day6/lit? (light)
light)
(defun day6/make-grid (size)
(let ((table (make-hash-table :size (* size size))))
(-each (number-sequence 0 (- (* size size) 1))
(lambda (pos) (puthash pos (day6/make-light) table)))
(cons size
table)))
(defun day6/grid-size (grid)
(car grid))
(defun day6/grid-table (grid)
(cdr grid))
(defun day6/grid-lights (grid)
(hash-table-values (day6/grid-table grid)))
(defun day6/grid-location (grid x y)
(+ x (* y (day6/grid-size grid))))
(ert-deftest day6/grid-location ()
(should (eq 99 (let ((grid (day6/make-grid 100)))
(day6/grid-location grid 99 0))))
(should (eq 100 (let ((grid (day6/make-grid 100)))
(day6/grid-location grid 0 1)))))
(defun day6/grid-light (grid location)
(gethash location (day6/grid-table grid)))
(defun day6/grid-do (grid fun location)
(puthash location
(funcall fun (day6/grid-light grid location))
(day6/grid-table grid)))
(defun day6/change-range (grid light-fun x1 y1 x2 y2)
(loop for x from x1 to x2
do (loop for y from y1 to y2
do (let* ((location (day6/grid-location grid x y)))
(day6/grid-do grid light-fun location)))))
(defun day6/lit-count (grid)
(length (-filter #'day6/lit? (day6/grid-lights grid))))
(ert-deftest day6/lit-count ()
(should (eq 1000000
(let ((grid (day6/make-grid 1000)))
(day6/change-range grid #'day6/turn-on-light
0 0 999 999)
(day6/lit-count grid))))
(should (eq 4
(let ((grid (day6/make-grid 1000)))
(day6/change-range grid #'day6/turn-on-light
499 499 500 500)
(day6/lit-count grid)))))
(defun day6/parse-instruction (instruction)
(if (string-match (concat "\\(turn \\(on\\|off\\)\\|toggle\\) "
"\\([0-9]+\\),\\([0-9]+\\)"
" through "
"\\([0-9]+\\),\\([0-9]+\\)")
instruction)
(list (cond ((string-equal "turn on" (match-string 1 instruction))
#'day6/turn-on-light)
((string-equal "turn off" (match-string 1 instruction))
#'day6/turn-off-light)
((string-equal "toggle" (match-string 1 instruction))
#'day6/toggle-light))
(string-to-int (match-string 3 instruction))
(string-to-int (match-string 4 instruction))
(string-to-int (match-string 5 instruction))
(string-to-int (match-string 6 instruction)))))
(ert-deftest day6/parse-instruction ()
(should (equal '(day6/turn-on-light 887 9 959 629)
(day6/parse-instruction "turn on 887,9 through 959,629")))
(should (equal '(day6/turn-off-light 539 243 559 965)
(day6/parse-instruction "turn off 539,243 through 559,965")))
(should (equal '(day6/toggle-light 720 196 897 994)
(day6/parse-instruction "toggle 720,196 through 897,994"))))
(defun day6/run-instruction (grid instruction)
(let ((parsed-instruction (day6/parse-instruction instruction)))
(eval (append '(day6/change-range grid)
`(',(first parsed-instruction))
(rest parsed-instruction)))))
(let ((grid (day6/make-grid 1000)))
(-each (split-string input "\n" t)
(apply-partially 'day6/run-instruction grid))
(day6/lit-count grid))
377891
Part 2
You just finish implementing your winning light pattern when you realize you mistranslated Santa's message from Ancient Nordic Elvish.
The light grid you bought actually has individual brightness controls; each light can have a brightness of zero or more. The lights all start at zero.
The phrase turn on
actually means that you should increase the
brightness of those lights by 1
.
The phrase turn off
actually means that you should decrease the
brightness of those lights by 1
, to a minimum of zero.
The phrase toggle
actually means that you should increase the
brightness of those lights by 2
.
What is the total brightness of all lights combined after following Santa's instructions?
For example:
turn on 0,0 through 0,0
would increase the total brightness by1
.toggle 0,0 through 999,999
would increase the total brightness by2000000
.
(defun day6.2/make-light ()
0)
(defun day6.2/turn-on-light (light)
(+ 1 light))
(defun day6.2/turn-off-light (light)
(if (>= 0 light) 0
(- light 1)))
(defun day6.2/toggle-light (light)
(+ 2 light))
(defun day6.2/parse-instruction (instruction)
(if (string-match (concat "\\(turn \\(on\\|off\\)\\|toggle\\) "
"\\([0-9]+\\),\\([0-9]+\\)"
" through "
"\\([0-9]+\\),\\([0-9]+\\)")
instruction)
(list (cond ((string-equal "turn on" (match-string 1 instruction))
#'day6.2/turn-on-light)
((string-equal "turn off" (match-string 1 instruction))
#'day6.2/turn-off-light)
((string-equal "toggle" (match-string 1 instruction))
#'day6.2/toggle-light))
(string-to-int (match-string 3 instruction))
(string-to-int (match-string 4 instruction))
(string-to-int (match-string 5 instruction))
(string-to-int (match-string 6 instruction)))))
(defun day6.2/run-instruction (grid instruction)
(let ((parsed-instruction (day6.2/parse-instruction instruction)))
(eval (append '(day6/change-range grid)
`(',(first parsed-instruction))
(rest parsed-instruction)))))
(defun day6.2/make-grid (size)
(let ((table (make-hash-table :size (* size size))))
(-each (number-sequence 0 (- (* size size) 1))
(lambda (pos) (puthash pos (day6.2/make-light) table)))
(cons size
table)))
(defun day6.2/total-brightness (grid)
(-reduce #'+
(day6/grid-lights grid)))
(let ((grid (day6.2/make-grid 1000)))
(-each (split-string input "\n" t)
(apply-partially 'day6.2/run-instruction grid))
(day6.2/total-brightness grid))
14110788
Day 7: Some Assembly Required
This year, Santa brought little Bobby Tables a set of wires and bitwise logic gates! Unfortunately, little Bobby is a little under the recommended age range, and he needs help assembling the circuit.
Each wire has an identifier (some lowercase letters) and can carry a
16-bit signal (a number from 0
to 65535
). A signal is provided to
each wire by a gate, another wire, or some specific value. Each wire
can only get a signal from one source, but can provide its signal to
multiple destinations. A gate provides no signal until all of its
inputs have a signal.
The included instructions booklet describes how to connect the parts
together: x AND y -> z
means to connect wires x
and y
to an
AND
gate, and then connect its output to wire z
.
For example:
123 -> x
means that the signal123
is provided to wirex
.x AND y -> z
means that the bitwise AND of wirex
and wirey
is provided to wirez
.p LSHIFT 2 -> q
means that the value from wirep
is left-shifted by2
and then provided to wireq
.NOT e -> f
means that thebitwise complement
of the value from wiree
is provided to wiref
.
Other possible gates include OR
(bitwise OR) and RSHIFT
(right-shift). If, for some reason, you'd like to emulate the
circuit instead, almost all programming languages (for example, C,
JavaScript, or Python) provide operators for these gates.
For example, here is a simple circuit:
123 -> x 456 -> y x AND y -> d x OR y -> e x LSHIFT 2 -> f y RSHIFT 2 -> g NOT x -> h NOT y -> i
After it is run, these are the signals on the wires:
d: 72 e: 507 f: 492 g: 114 h: 65412 i: 65079 x: 123 y: 456
In little Bobby's kit's instructions booklet (provided as your puzzle input), what signal is ultimately provided to wire a?
af AND ah -> ai NOT lk -> ll hz RSHIFT 1 -> is NOT go -> gp du OR dt -> dv x RSHIFT 5 -> aa at OR az -> ba eo LSHIFT 15 -> es ci OR ct -> cu b RSHIFT 5 -> f fm OR fn -> fo NOT ag -> ah v OR w -> x g AND i -> j an LSHIFT 15 -> ar 1 AND cx -> cy jq AND jw -> jy iu RSHIFT 5 -> ix gl AND gm -> go NOT bw -> bx jp RSHIFT 3 -> jr hg AND hh -> hj bv AND bx -> by er OR es -> et kl OR kr -> ks et RSHIFT 1 -> fm e AND f -> h u LSHIFT 1 -> ao he RSHIFT 1 -> hx eg AND ei -> ej bo AND bu -> bw dz OR ef -> eg dy RSHIFT 3 -> ea gl OR gm -> gn da LSHIFT 1 -> du au OR av -> aw gj OR gu -> gv eu OR fa -> fb lg OR lm -> ln e OR f -> g NOT dm -> dn NOT l -> m aq OR ar -> as gj RSHIFT 5 -> gm hm AND ho -> hp ge LSHIFT 15 -> gi jp RSHIFT 1 -> ki hg OR hh -> hi lc LSHIFT 1 -> lw km OR kn -> ko eq LSHIFT 1 -> fk 1 AND am -> an gj RSHIFT 1 -> hc aj AND al -> am gj AND gu -> gw ko AND kq -> kr ha OR gz -> hb bn OR by -> bz iv OR jb -> jc NOT ac -> ad bo OR bu -> bv d AND j -> l bk LSHIFT 1 -> ce de OR dk -> dl dd RSHIFT 1 -> dw hz AND ik -> im NOT jd -> je fo RSHIFT 2 -> fp hb LSHIFT 1 -> hv lf RSHIFT 2 -> lg gj RSHIFT 3 -> gl ki OR kj -> kk NOT ak -> al ld OR le -> lf ci RSHIFT 3 -> ck 1 AND cc -> cd NOT kx -> ky fp OR fv -> fw ev AND ew -> ey dt LSHIFT 15 -> dx NOT ax -> ay bp AND bq -> bs NOT ii -> ij ci AND ct -> cv iq OR ip -> ir x RSHIFT 2 -> y fq OR fr -> fs bn RSHIFT 5 -> bq 0 -> c 14146 -> b d OR j -> k z OR aa -> ab gf OR ge -> gg df OR dg -> dh NOT hj -> hk NOT di -> dj fj LSHIFT 15 -> fn lf RSHIFT 1 -> ly b AND n -> p jq OR jw -> jx gn AND gp -> gq x RSHIFT 1 -> aq ex AND ez -> fa NOT fc -> fd bj OR bi -> bk as RSHIFT 5 -> av hu LSHIFT 15 -> hy NOT gs -> gt fs AND fu -> fv dh AND dj -> dk bz AND cb -> cc dy RSHIFT 1 -> er hc OR hd -> he fo OR fz -> ga t OR s -> u b RSHIFT 2 -> d NOT jy -> jz hz RSHIFT 2 -> ia kk AND kv -> kx ga AND gc -> gd fl LSHIFT 1 -> gf bn AND by -> ca NOT hr -> hs NOT bs -> bt lf RSHIFT 3 -> lh au AND av -> ax 1 AND gd -> ge jr OR js -> jt fw AND fy -> fz NOT iz -> ja c LSHIFT 1 -> t dy RSHIFT 5 -> eb bp OR bq -> br NOT h -> i 1 AND ds -> dt ab AND ad -> ae ap LSHIFT 1 -> bj br AND bt -> bu NOT ca -> cb NOT el -> em s LSHIFT 15 -> w gk OR gq -> gr ff AND fh -> fi kf LSHIFT 15 -> kj fp AND fv -> fx lh OR li -> lj bn RSHIFT 3 -> bp jp OR ka -> kb lw OR lv -> lx iy AND ja -> jb dy OR ej -> ek 1 AND bh -> bi NOT kt -> ku ao OR an -> ap ia AND ig -> ii NOT ey -> ez bn RSHIFT 1 -> cg fk OR fj -> fl ce OR cd -> cf eu AND fa -> fc kg OR kf -> kh jr AND js -> ju iu RSHIFT 3 -> iw df AND dg -> di dl AND dn -> do la LSHIFT 15 -> le fo RSHIFT 1 -> gh NOT gw -> gx NOT gb -> gc ir LSHIFT 1 -> jl x AND ai -> ak he RSHIFT 5 -> hh 1 AND lu -> lv NOT ft -> fu gh OR gi -> gj lf RSHIFT 5 -> li x RSHIFT 3 -> z b RSHIFT 3 -> e he RSHIFT 2 -> hf NOT fx -> fy jt AND jv -> jw hx OR hy -> hz jp AND ka -> kc fb AND fd -> fe hz OR ik -> il ci RSHIFT 1 -> db fo AND fz -> gb fq AND fr -> ft gj RSHIFT 2 -> gk cg OR ch -> ci cd LSHIFT 15 -> ch jm LSHIFT 1 -> kg ih AND ij -> ik fo RSHIFT 3 -> fq fo RSHIFT 5 -> fr 1 AND fi -> fj 1 AND kz -> la iu AND jf -> jh cq AND cs -> ct dv LSHIFT 1 -> ep hf OR hl -> hm km AND kn -> kp de AND dk -> dm dd RSHIFT 5 -> dg NOT lo -> lp NOT ju -> jv NOT fg -> fh cm AND co -> cp ea AND eb -> ed dd RSHIFT 3 -> df gr AND gt -> gu ep OR eo -> eq cj AND cp -> cr lf OR lq -> lr gg LSHIFT 1 -> ha et RSHIFT 2 -> eu NOT jh -> ji ek AND em -> en jk LSHIFT 15 -> jo ia OR ig -> ih gv AND gx -> gy et AND fe -> fg lh AND li -> lk 1 AND io -> ip kb AND kd -> ke kk RSHIFT 5 -> kn id AND if -> ig NOT ls -> lt dw OR dx -> dy dd AND do -> dq lf AND lq -> ls NOT kc -> kd dy AND ej -> el 1 AND ke -> kf et OR fe -> ff hz RSHIFT 5 -> ic dd OR do -> dp cj OR cp -> cq NOT dq -> dr kk RSHIFT 1 -> ld jg AND ji -> jj he OR hp -> hq hi AND hk -> hl dp AND dr -> ds dz AND ef -> eh hz RSHIFT 3 -> ib db OR dc -> dd hw LSHIFT 1 -> iq he AND hp -> hr NOT cr -> cs lg AND lm -> lo hv OR hu -> hw il AND in -> io NOT eh -> ei gz LSHIFT 15 -> hd gk AND gq -> gs 1 AND en -> eo NOT kp -> kq et RSHIFT 5 -> ew lj AND ll -> lm he RSHIFT 3 -> hg et RSHIFT 3 -> ev as AND bd -> bf cu AND cw -> cx jx AND jz -> ka b OR n -> o be AND bg -> bh 1 AND ht -> hu 1 AND gy -> gz NOT hn -> ho ck OR cl -> cm ec AND ee -> ef lv LSHIFT 15 -> lz ks AND ku -> kv NOT ie -> if hf AND hl -> hn 1 AND r -> s ib AND ic -> ie hq AND hs -> ht y AND ae -> ag NOT ed -> ee bi LSHIFT 15 -> bm dy RSHIFT 2 -> dz ci RSHIFT 2 -> cj NOT bf -> bg NOT im -> in ev OR ew -> ex ib OR ic -> id bn RSHIFT 2 -> bo dd RSHIFT 2 -> de bl OR bm -> bn as RSHIFT 1 -> bl ea OR eb -> ec ln AND lp -> lq kk RSHIFT 3 -> km is OR it -> iu iu RSHIFT 2 -> iv as OR bd -> be ip LSHIFT 15 -> it iw OR ix -> iy kk RSHIFT 2 -> kl NOT bb -> bc ci RSHIFT 5 -> cl ly OR lz -> ma z AND aa -> ac iu RSHIFT 1 -> jn cy LSHIFT 15 -> dc cf LSHIFT 1 -> cz as RSHIFT 3 -> au cz OR cy -> da kw AND ky -> kz lx -> a iw AND ix -> iz lr AND lt -> lu jp RSHIFT 5 -> js aw AND ay -> az jc AND je -> jf lb OR la -> lc NOT cn -> co kh LSHIFT 1 -> lb 1 AND jj -> jk y OR ae -> af ck AND cl -> cn kk OR kv -> kw NOT cv -> cw kl AND kr -> kt iu OR jf -> jg at AND az -> bb jp RSHIFT 2 -> jq iv AND jb -> jd jn OR jo -> jp x OR ai -> aj ba AND bc -> bd jl OR jk -> jm b RSHIFT 1 -> v o AND q -> r NOT p -> q k AND m -> n as RSHIFT 2 -> at
(defun day7/parse-expression (expression-string)
(cond ((s-numeric? expression-string)
(string-to-int expression-string))
((s-contains? " " expression-string)
(let ((expression (-map #'day7/parse-expression
(split-string expression-string))))
(cond ((= 1 (length expression)) ;; single term
(car expression))
((= 3 (length expression)) ;; re-order infix operation
(list (cadr expression)
(car expression)
(caddr expression)))
(t expression))))
(t (intern (downcase expression-string)))))
(ert-deftest day7/parse-expression ()
(should (equal 123
(day7/parse-expression "123")))
(should (equal 'x
(day7/parse-expression "x")))
(should (equal 'ab
(day7/parse-expression "ab")))
(should (equal '(and x y)
(day7/parse-expression "x AND y"))))
(defun day7/parse-connection (connection-string)
(string-match "\\(.*?\\) -> \\(.*\\)"
connection-string)
(cons (day7/parse-expression (match-string 2 connection-string))
(day7/parse-expression (match-string 1 connection-string))))
(ert-deftest day7/parse-connection ()
(should (equal '(x . 123)
(day7/parse-connection "123 -> x")))
(should (equal '(d . (and x y))
(day7/parse-connection "x AND y -> d"))))
(defun day7/make-circuit (connection-strings)
(let ((expressions (-map #'day7/parse-connection
connection-strings))
(circuit (make-hash-table :size (length connection-strings))))
(-each expressions
(lambda (expr) (puthash (car expr)
(cdr expr)
circuit)))
circuit))
(defun day7/circuit-get (circuit wire)
(or (gethash wire circuit)
(error (format "Unknown wire: %s" wire))))
(defun day7/circuit-put (circuit wire value)
(puthash wire value circuit))
(defun day7/truncate-to-16bit (num)
(string-to-number
(substring (format "%04x" num) -4)
16))
(defun day7/and (a b)
(logand a b))
(defun day7/or (a b)
(logior a b))
(defun day7/not (n)
(day7/truncate-to-16bit (lognot n)))
(defun day7/rshift (n count)
(lsh n (- count)))
(defun day7/lshift (n count)
(day7/truncate-to-16bit (lsh n count)))
(defun day7/evaluate (circuit expr)
(cond ((numberp expr) (day7/truncate-to-16bit expr))
((symbolp expr)
;; Evaluate and store the result in the circuit table for
;; future lookups
(let ((result (day7/evaluate circuit
(day7/circuit-get circuit expr))))
(day7/circuit-put circuit expr result)
result))
((listp expr)
(let ((op (cond ((eq 'and (car expr)) #'day7/and)
((eq 'or (car expr)) #'day7/or)
((eq 'not (car expr)) #'day7/not)
((eq 'lshift (car expr)) #'day7/lshift)
((eq 'rshift (car expr)) #'day7/rshift)))
(args (-map (apply-partially 'day7/evaluate circuit)
(cdr expr))))
(apply op args)))
(t expr))
)
(ert-deftest day7/evaluate ()
(let* ((sample-input (list "123 -> x"
"456 -> y"
"x AND y -> d"
"x OR y -> e"
"x LSHIFT 2 -> f"
"y RSHIFT 2 -> g"
"NOT x -> h"
"NOT y -> i"))
(circuit (day7/make-circuit sample-input)))
(should (eq 72 (day7/evaluate circuit 'd)))
(should (eq 507 (day7/evaluate circuit 'e)))
(should (eq 492 (day7/evaluate circuit 'f)))
(should (eq 114 (day7/evaluate circuit 'g)))
(should (eq 65412 (day7/evaluate circuit 'h)))
(should (eq 65079 (day7/evaluate circuit 'i)))
(should (eq 123 (day7/evaluate circuit 'x)))
(should (eq 456 (day7/evaluate circuit 'y)))))
(let* ((connection-strings (split-string input "\n" t))
(circuit (day7/make-circuit connection-strings)))
(day7/evaluate circuit 'a))
956
Part 2
Now, take the signal you got on wire a
, override wire b
to that
signal, and reset the other wires (including wire a
). What new
signal is ultimately provided to wire a
?
(let* ((connection-strings (split-string input "\n" t))
(circuit (day7/make-circuit connection-strings)))
(day7/circuit-put circuit 'b 956)
(day7/evaluate circuit 'a))
40149
Day 8: Matchsticks
Space on the sleigh is limited this year, and so Santa will be bringing his list as a digital copy. He needs to know how much space it will take up when stored.
It is common in many programming languages to provide a way to escape special characters in strings. For example, C, JavaScript, Perl, Python, and even PHP handle special characters in very similar ways.
However, it is important to realize the difference between the number of characters in the code representation of the string literal and the number of characters in the in-memory string itself.
For example:
""
is2
characters of code (the two double quotes), but the string contains zero characters."abc"
is5
characters of code, but 3 characters in the string data."aaa\"aaa"
is10
characters of code, but the string itself contains six"a"
characters and a single, escaped quote character, for a total of7
characters in the string data."\x27"
is6
characters of code, but the string itself contains just one - an apostrophe ('
), escaped using hexadecimal notation.
Santa's list is a file that contains many double-quoted string
literals, one on each line. The only escape sequences used are \\
(which represents a single backslash), \"
(which represents a lone
double-quote character), and \x
plus two hexadecimal characters
(which represents a single character with that ASCII code).
Disregarding the whitespace in the file, what is the number of characters of code for string literals minus the number of characters in memory for the values of the strings in total for the entire file?
For example, given the four strings above, the total number of
characters of string code (2 + 5 + 10 + 6 = 23)
minus the total
number of characters in memory for string values (0 + 3 + 7 + 1 =
11)
is 23 - 11 = 12
.
"qxfcsmh" "ffsfyxbyuhqkpwatkjgudo" "byc\x9dyxuafof\\\xa6uf\\axfozomj\\olh\x6a" "jtqvz" "uzezxa\"jgbmojtwyfbfguz" "vqsremfk\x8fxiknektafj" "wzntebpxnnt\"vqndz\"i\x47vvjqo\"" "higvez\"k\"riewqk" "dlkrbhbrlfrp\\damiauyucwhty" "d\"" "qlz" "ku" "yy\"\"uoao\"uripabop" "saduyrntuswlnlkuppdro\\sicxosted" "tj" "zzphopswlwdhebwkxeurvizdv" "xfoheirjoakrpofles\"nfu" "q\xb7oh\"p\xce\"n" "qeendp\"ercwgywdjeylxcv" "dcmem" "\"i\x13r\"l" "ikso\xdcbvqnbrjduh\"uqudzki\xderwk" "wfdsn" "pwynglklryhtsqbno" "hcoj\x63iccz\"v\"ttr" "zf\x23\\hlj\\kkce\\d\\asy\"yyfestwcdxyfj" "xs" "m\"tvltapxdvtrxiy" "bmud" "k\"a" "b\"oas" "\"yexnjjupoqsxyqnquy\"uzfdvetqrc" "vdw\xe3olxfgujaj" "qomcxdnd\"\\cfoe\"" "fpul" "m\"avamefphkpv" "vvdnb\\x\\uhnxfw\"dpubfkxfmeuhnxisd" "hey\\" "ldaeigghlfey" "eure\"hoy\xa5iezjp\\tm" "yygb\"twbj\\r\"\x10gmxuhmp\"" "weirebp\x39mqonbtmfmd" "ltuz\\hs\"e" "ysvmpc" "g\x8amjtt\"megl\"omsaihifwa" "yimmm" "iiyqfalh" "cwknlaaf" "q\x37feg\xc6s\"xx" "uayrgeurgyp\\oi" "xhug\"pt\"axugllbdiggzhvy" "kdaarqmsjfx\xc3d" "\"vkwla" "d\"" "tmroz\"bvfinxoe\\mum\"wmm" "\"n\"bbswxne\\p\\yr\"qhwpdd" "skzlkietklkqovjhvj\xfe" "pbg\\pab\"bubqaf\"obzcwxwywbs\\dhtq" "xxjidvqh\"lx\\wu\"ij" "daef\x5fe\x5b\\kbeeb\x13qnydtboof" "ogvazaqy\"j\x73" "y" "n\"tibetedldy\\gsamm\"nwu" "wldkvgdtqulwkad" "dpmxnj" "twybw\"cdvf\"mjdajurokbce" "ru\"\\lasij\"i" "roc\\vra\\lhrm" "pbkt\x60booz\"fjlkc" "j\x4dytvjwrzt" "\\uiwjkniumxcs" "cbhm\"nexccior\"v\"j\"nazxilmfp\x47" "qdxngevzrlgoq" "\"lrzxftytpobsdfyrtdqpjbpuwmm\x9e" "mdag\x0asnck\xc2ggj\"slb\"fjy" "wyqkhjuazdtcgkcxvjkpnjdae" "aixfk\xc0iom\x21vueob" "dkiiakyjpkffqlluhaetires" "ysspv\"lysgkvnmwbbsy" "gy\"ryexcjjxdm\"xswssgtr" "s" "ddxv" "qwt\"\x27puilb\"pslmbrsxhrz" "qdg\xc9e\\qwtknlvkol\x54oqvmchn\\" "lvo" "b" "fk\"aa\"\"yenwch\\\\on" "srig\x63hpwaavs\\\x80qzk\"xa\"\xe6u\\wr" "yxjxuj\"ghyhhxfj\"\xa6qvatre" "yoktqxjxkzrklkoeroil" "\"jfmik\"" "smgseztzdwldikbqrh\"" "jftahgctf\"hoqy" "tcnhicr\"znpgckt\"ble" "vqktnkodh\"lo\"a\\bkmdjqqnsqr" "ztnirfzqq" "s" "xx" "iqj\"y\\hqgzflwrdsusasekyrxbp\\ad" "\\xzjhlaiynkioz\"\"bxepzimvgwt" "s\x36rbw" "mniieztwrisvdx" "atyfxioy\x2b\\" "irde\x85\x5cvbah\\jekw\"ia" "bdmftlhkwrprmpat\"prfaocvp" "w\\k" "umbpausy" "zfauhpsangy" "p\"zqyw" "wtztypyqvnnxzvlvipnq\"zu" "deicgwq\\oqvajpbov\\or\"kgplwu" "mbzlfgpi\\\\zqcidjpzqdzxityxa" "lfkxvhma" "\xf2yduqzqr\"\\fak\"p\"n" "mpajacfuxotonpadvng" "anb\\telzvcdu\\a\xf2flfq" "lrs\"ebethwpmuuc\"\x86ygr" "qmvdbhtumzc\"ci" "meet" "yopg\x0fdxdq\"h\\ugsu\xffmolxjv" "uhy" "fzgidrtzycsireghazscvmwcfmw\\t" "cqohkhpgvpru" "bihyigtnvmevx\"xx" "xz" "zofomwotzuxsjk\"q\"mc\"js\"dnmalhxd" "\\ktnddux\\fqvt\"ibnjntjcbn" "ia" "htjadnefwetyp\xd5kbrwfycbyy" "\"\\hkuxqddnao" "meqqsz\x83luecpgaem" "cvks\x87frvxo\"svqivqsdpgwhukmju" "sgmxiai\\o\"riufxwjfigr\xdf" "fgywdfecqufccpcdn" "faghjoq\x28abxnpxj" "zuppgzcfb\"dctvp\"elup\"zxkopx" "xqs\x45xxdqcihbwghmzoa" "anbnlp\\cgcvm\"hc" "xf\"fgrngwzys" "nrxsjduedcy\x24" "\x71sxl\"gj\"sds\"ulcruguz\\t\\ssvjcwhi" "jhj\"msch" "qpovolktfwyiuyicbfeeju\x01" "nkyxmb\"qyqultgt\"nmvzvvnxnb" "ycsrkbstgzqb\"uv\\cisn" "s" "ueptjnn\"\"sh" "lp\"z\"d\"mxtxiy" "yzjtvockdnvbubqabjourf\"k\"uoxwle" "\x82\"wqm\"" "\xb5cwtuks\x5fpgh" "wd" "tbvf" "ttbmzdgn" "vfpiyfdejyrlbgcdtwzbnm" "uc" "otdcmhpjagqix" "\\\xb1qso\"s" "scowax" "behpstjdh\xccqlgnqjyz\"eesn" "r\xe1cbnjwzveoomkzlo\\kxlfouhm" "jgrl" "kzqs\\r" "ctscb\x7fthwkdyko\"\x62pkf\"d\xe6knmhurg" "tc\"kw\x3ftt" "bxb\x5ccl" "jyrmfbphsldwpq" "jylpvysl\"\"juducjg" "en\\m\"kxpq\"wpb\\\"" "madouht\"bmdwvnyqvpnawiphgac\"" "vuxpk\"ltucrw" "aae\x60arr" "ttitnne\"kilkrgssnr\xfdurzh" "oalw" "pc\"\"gktkdykzbdpkwigucqni\"nxiqx" "dbrsaj" "bgzsowyxcbrvhtvekhsh\"qgd" "kudfemvk\"\"\"hkbrbil\"chkqoa" "zjzgj\\ekbhyfzufy" "\\acos\"fqekuxqzxbmkbnn\x1ejzwrm" "elxahvudn\"txtmomotgw" "\x2eoxmwdhelpr\"cgi\xf7pzvb" "eapheklx" "hfvma\"mietvc\"tszbbm\"czex" "h\"iiockj\\\xc1et" "d\"rmjjftm" "qlvhdcbqtyrhlc\\" "yy\"rsucjtulm\"coryri\"eqjlbmk" "tv" "r\"bfuht\\jjgujp\"" "kukxvuauamtdosngdjlkauylttaokaj" "srgost\"\"rbkcqtlccu\x65ohjptstrjkzy" "yxwxl\\yjilwwxffrjjuazmzjs" "dxlw\\fkstu\"hjrtiafhyuoh\"sewabne" "\x88sj\"v" "rfzprz\xec\"oxqclu\"krzefp\\q" "cfmhdbjuhrcymgxpylllyvpni" "ucrmjvmimmcq\x88\xd9\"lz" "lujtt\"" "gvbqoixn\"pmledpjmo\"flydnwkfxllf" "dvxqlbshhmelsk\x8big\"l" "mx\x54lma\x8bbguxejg" "\x66jdati\xeceieo" "\"iyyupixei\x54ff" "xohzf\"rbxsoksxamiu" "vlhthspeshzbppa\x4drhqnohjop\"\"mfjd" "f\"tvxxla\"vurian\"\"idjq\x3aptm\xc3olep" "gzqz" "kbq\\wogye\\altvi\\hbvmodny" "j\xd8" "ofjozdhkblvndl" "hbitoupimbawimxlxqze" "ypeleimnme" "xfwdrzsc\\oxqamawyizvi\\y" "enoikppx\xa1ixe\"yo\"gumye" "fb" "vzf" "zxidr" "cu\x31beirsywtskq" "lxpjbvqzztafwezd" "\\jyxeuo\x18bv" "b\"vawc\"p\\\\giern\"b" "odizunx\"\"t\\yicdn\"x\"sdiz" "\"\"tebrtsi" "ctyzsxv\xa6pegfkwsi\"tgyltaakytccb" "htxwbofchvmzbppycccliyik\xe5a" "ggsslefamsklezqkrd" "rcep\"fnimwvvdx\"l" "zyrzlqmd\x12egvqs\\llqyie" "\x07gsqyrr\\rcyhyspsvn" "butg\"" "gb" "gywkoxf\"jsg\\wtopxvumirqxlwz" "rj\"ir\"wldwveair\x2es\"dhjrdehbqnzl" "ru\"elktnsbxufk\\ejufjfjlevt\\lrzd" "\"widsvok" "oy\"\x81nuesvw" "ay" "syticfac\x1cfjsivwlmy\"pumsqlqqzx" "m" "rjjkfh\x78cf\x2brgceg\"jmdyas\"\\xlv\xb6p" "tmuvo\"\x3ffdqdovjmdmkgpstotojkv\"as" "jd\\ojvynhxllfzzxvbn\"wrpphcvx" "pz" "\"twr" "n\\hdzmxe\"mzjjeadlz" "fb\"rprxuagvahjnri" "rfmexmjjgh\\xrnmyvnatrvfruflaqjnd" "obbbde\"co\"qr\"qpiwjgqahqm\\jjp\"" "vpbq\"\"y\"czk\\b\x52ed\"lnzepobp" "syzeajzfarplydipny\"y\"\xe8ad" "mpyodwb" "\x47rakphlqqptd" "wa\"oj\"aiy" "a" "ropozx" "q\x51nbtlwa" "etukvgx\\jqxlkq" "\"tp\"rah\"pg\"s\"bpdtes\\tkasdhqd" "dn\"qqpkikadowssb\xcah\"dzpsf\\ect\"jdh" "pxunovbbrrn\\vullyn\"bno\"\"\"myfxlp\"" "qaixyazuryvkmoulhcqaotegfj\\mpzm" "bvfrbicutzbjwn\\oml\"cf\"d\"ezcpv\"j" "rmbrdtneudemigdhelmb" "aq\\aurmbhy" "wujqvzw" "gf\"tssmvm\"gm\"hu\x9a\xb7yjawsa" "hrhqqxow\xe2gsydtdspcfqy\"zw\\ou" "ianwwf\\yko\\tdujhhqdi" "xylz\"zpvpab" "lwuopbeeegp" "aoop\x49jhhcexdmdtun" "\\\\mouqqcsgmz" "tltuvwhveau\x43b\"ymxjlcgiymcynwt" "gsugerumpyuhtjljbhrdyoj" "lnjm\xb8wg\"ajh" "zmspue\"nfttdon\\b\"eww" "\"w\x67jwaq\x7ernmyvs\\rmdsuwydsd\"th" "ogtgvtlmcvgllyv" "z\"fqi\"rvddoehrciyl" "yustxxtot\"muec\"xvfdbzunzvveq" "mqslw" "txqnyvzmibqgjs\xb6xy\x86nfalfyx" "kzhehlmkholov" "plpmywcnirrjutjguosh\\" "pydbnqofv\"dn\\m" "aegqof" "eambmxt\\dxagoogl\\zapfwwlmk" "afbmqitxxqhddlozuxcpjxgh" "vgts" "bfdpqtoxzzhmzcilehnflna" "s\"idpz" "\xcfhgly\"nlmztwybx\"ecezmsxaqw" "aackfgndqcqiy" "\x22unqdlsrvgzfaohoffgxzfpir\"s" "abh\"ydv\"kbpdhrerl" "bdzpg" "ekwgkywtmzp" "wtoodejqmrrgslhvnk\"pi\"ldnogpth" "njro\x68qgbx\xe4af\"\\suan"
(defun day8/hex-replacements (string-literal)
(-map (lambda (escaped-hex)
(let ((hex-code (string-to-number (substring escaped-hex 2) 16)))
(cons escaped-hex (char-to-string hex-code))))
(-map #'car (s-match-strings-all "\\\\x[0-9,a-f][0-9,a-f]" string-literal))))
(defun day8/parse-string (string-literal)
(let ((contents (substring string-literal 1 -1)))
(-reduce-from
(lambda (acc replacement)
(s-replace (car replacement)
(cdr replacement)
acc))
contents
(append '(("\\\"" . "\"")
("\\\\" . "\\"))
(day8/hex-replacements contents)))))
(ert-deftest day8/parse-string ()
(should (string-equal ""
(day8/parse-string "\"\"")))
(should (string-equal "abc"
(day8/parse-string "\"abc\"")))
(should (string-equal "aaa\"aaa"
(day8/parse-string "\"aaa\\\"aaa\"")))
(should (string-equal "'"
(day8/parse-string "\"\\x27\""))))
(let* ((code-strings (split-string input "\n" t))
(string-values (-map #'day8/parse-string code-strings)))
(- (-sum (-map #'length code-strings))
(-sum (-map #'length string-values))))
1350
Part 2
Now, let's go the other way. In addition to finding the number of characters of code, you should now encode each code representation as a new string and find the number of characters of the new encoded representation, including the surrounding double quotes.
For example:
""
encodes to"\"\""
, an increase from2
characters to6
."abc"
encodes to"\"abc\""
, an increase from5
characters to9
."aaa\"aaa"
encodes to"\"aaa\\\"aaa\""
, an increase from10
characters to16
."\x27"
encodes to"\"\\x27\""
, an increase from6
characters to11
.
Your task is to find the total number of characters to represent the
newly encoded strings minus the number of characters of code in each
original string literal. For example, for the strings above, the
total encoded length (6 + 9 + 16 + 11 = 42
) minus the characters in
the original code representation (23
, just like in the first part of
this puzzle) is 42 - 23 = 19
.
(defun day8/encode-string (string-literal)
(format "\"%s\""
(-reduce-from
(lambda (acc replacement)
(s-replace (car replacement)
(cdr replacement)
acc))
string-literal
'(("\\" . "\\\\")
("\"" . "\\\"")))))
(ert-deftest day8/encode-string ()
(should (string-equal "\"\\\"\\\"\""
(day8/encode-string "\"\"")))
(should (string-equal "\"\\\"abc\\\"\""
(day8/encode-string "\"abc\"")))
(should (string-equal "\"\\\"aaa\\\\\\\"aaa\\\"\""
(day8/encode-string "\"aaa\\\"aaa\"")))
(should (string-equal "\"\\\"\\\\x27\\\"\""
(day8/encode-string "\"\\x27\""))))
(let* ((code-strings (split-string input "\n" t))
(encoded-values (-map #'day8/encode-string code-strings)))
(- (-sum (-map #'length encoded-values))
(-sum (-map #'length code-strings))))
2085
Day 9: All in a Single Night
Every year, Santa manages to deliver all of his presents in a single night.
This year, however, he has some new locations to visit; his elves have provided him the distances between every pair of locations. He can start and end at any two (different) locations he wants, but he must visit each location exactly once. What is the shortest distance he can travel to achieve this?
For example, given the following distances:
London to Dublin = 464 London to Belfast = 518 Dublin to Belfast = 141
The possible routes are therefore:
Dublin -> London -> Belfast = 982 London -> Dublin -> Belfast = 605 London -> Belfast -> Dublin = 659 Dublin -> Belfast -> London = 659 Belfast -> Dublin -> London = 605 Belfast -> London -> Dublin = 982
The shortest of these is London -> Dublin -> Belfast = 605
, and so
the answer is 605
in this example.
What is the distance of the shortest route?
Tristram to AlphaCentauri = 34 Tristram to Snowdin = 100 Tristram to Tambi = 63 Tristram to Faerun = 108 Tristram to Norrath = 111 Tristram to Straylight = 89 Tristram to Arbre = 132 AlphaCentauri to Snowdin = 4 AlphaCentauri to Tambi = 79 AlphaCentauri to Faerun = 44 AlphaCentauri to Norrath = 147 AlphaCentauri to Straylight = 133 AlphaCentauri to Arbre = 74 Snowdin to Tambi = 105 Snowdin to Faerun = 95 Snowdin to Norrath = 48 Snowdin to Straylight = 88 Snowdin to Arbre = 7 Tambi to Faerun = 68 Tambi to Norrath = 134 Tambi to Straylight = 107 Tambi to Arbre = 40 Faerun to Norrath = 11 Faerun to Straylight = 66 Faerun to Arbre = 144 Norrath to Straylight = 115 Norrath to Arbre = 135 Straylight to Arbre = 127
(defun day9/make-map ()
(make-hash-table :test #'equal))
(defun day9/store-distance (map a b distance)
(puthash (cons a b) distance map))
(defun day9/distance (map a b)
(gethash (cons a b) map
(gethash (cons b a) map 0)))
(defun day9/parse-distance (distance-string)
(if (string-match "\\(.*?\\) to \\(.*?\\) = \\([0-9]+\\)"
distance-string)
(cons (cons (match-string-no-properties 1 distance-string)
(match-string-no-properties 2 distance-string))
(string-to-number (match-string-no-properties 3 distance-string)))))
(ert-deftest day9/parse-distance ()
(should (equal '(("London" . "Dublin") . 464)
(day9/parse-distance "London to Dublin = 464"))))
(defun day9/build-map (input)
(let ((map (day9/make-map)))
(-each (-map #'day9/parse-distance
(split-string input "\n" t))
(lambda (distance)
(day9/store-distance map
(caar distance)
(cdar distance)
(cdr distance))))
map))
(defun day9/trip-distance (map trip)
(let ((start (first trip))
(steps (rest trip)))
(if (null steps) 0
(+ (day9/distance map start (first steps))
(day9/trip-distance map steps)))))
(defun day9/trip-distance< (min current map trip)
(let ((start (first trip))
(steps (rest trip)))
(cond ((and min (> current min)) nil)
((null steps) current)
(t (let ((distance (day9/distance map start (first steps))))
(day9/trip-distance< min (+ distance current) map
steps))))))
(lexical-let ((example example))
(ert-deftest day9/trip-distance ()
(let ((map (day9/build-map example)))
(should (eq 982 (day9/trip-distance map
'("Dublin"
"London"
"Belfast")))))))
(defun day9/permutations (lst)
(if (not lst) '(nil)
(mapcan
(lambda (e)
(mapcar (lambda (perm) (cons e perm))
(day9/permutations (-remove-item e lst))))
lst)))
(defun day9/trips (map)
"Don't include reversed location permutations"
(cl-loop for perm in (day9/permutations (day9/locations map))
with unique-perms = (make-hash-table :test 'equal)
unless (gethash (reverse perm) unique-perms)
do (puthash perm t unique-perms)
finally return (hash-table-keys unique-perms)))
(defun day9/locations (map)
(-distinct
(append (-map #'car (hash-table-keys map))
(-map #'cdr (hash-table-keys map)))))
(lexical-let ((example example))
(ert-deftest day9/locations ()
(let ((map (day9/build-map example)))
(should (seq-empty-p
(-difference '("Dublin" "London" "Belfast")
(day9/locations map)))))))
(defun day9/min-trip-distance (map)
(cl-loop for path in (day9/trips map)
with min-distance
do (let ((distance (day9/trip-distance< min-distance 0 map path)))
(if (and (null min-distance) distance)
(setf min-distance distance))
(if (and min-distance distance
(< distance min-distance))
(setf min-distance distance)))
finally return min-distance))
(day9/min-trip-distance
(day9/build-map input))
251
Part 2
The next year, just to show off, Santa decides to take the route with the longest distance instead.
He can still start and end at any two (different) locations he wants, and he still must visit each location exactly once.
For example, given the distances above, the longest route would be
982
via (for example) Dublin -> London -> Belfast
.
What is the distance of the longest route?
(defun day9/trip-distance> (max current map trip)
(let ((start (first trip))
(steps (rest trip)))
(cond ((null steps) current)
(t (let ((distance (day9/distance map start (first steps))))
(day9/trip-distance> max (+ distance current) map
steps))))))
(defun day9/max-trip-distance (map)
(cl-loop for path in (day9/trips map)
with max-distance
do (let ((distance (day9/trip-distance> max-distance 0 map path)))
(if (and (null max-distance) distance)
(setf max-distance distance))
(if (and max-distance distance
(< max-distance distance))
(setf max-distance distance)))
finally return max-distance))
(day9/max-trip-distance
(day9/build-map input))
898
Day 10: Elves Look, Elves Say
Today, the Elves are playing a game called look-and-say. They take
turns making sequences by reading aloud the previous sequence and
using that reading as the next sequence. For example, 211
is read as
"one two, two ones", which becomes 1221
(1
2
, 2
=1=s).
Look-and-say sequences are generated iteratively, using the previous
value as input for the next step. For each step, take the previous
value, and replace each run of digits (like 111
) with the number of
digits (3
) followed by the digit itself (1
).
For example:
1
becomes11
(1
copy of digit1
).11
becomes21
(2
copies of digit1
).21
becomes1211
(one2
followed by one1
).1211
becomes111221
(one1
, one2
, and two =1=s).111221
becomes312211
(three1=s, two =2=s, and one =1
).
Starting with the digits in your puzzle input, apply this process 40 times. What is the length of the result?
3113322113
(defun day10/say-sequence (seq)
(let ((partitioned ))
(mapconcat
(lambda (chars)
(format "%d%s" (length chars) (char-to-string (car chars))))
(-partition-by #'identity (seq-into seq 'list))
"")))
(ert-deftest day10/say-sequence ()
(should (string-equal "11" (day10/say-sequence "1")))
(should (string-equal "21" (day10/say-sequence "11")))
(should (string-equal "1211" (day10/say-sequence "21")))
(should (string-equal "111221" (day10/say-sequence "1211")))
(should (string-equal "312211" (day10/say-sequence "111221"))))
(defun day10/say-sequence-n (times seq)
(-reduce-from
(lambda (acc next)
(day10/say-sequence acc))
seq
(number-sequence 1 times)))
(ert-deftest day10/say-sequence-n ()
(should (string-equal "312211" (day10/say-sequence-n 5 "1"))))
(length (day10/say-sequence-n 40 (string-trim input)))
329356
Part 2
Neat, right? You might also enjoy hearing John Conway talking about this sequence (that's Conway of Conway's Game of Life fame).
Now, starting again with the digits in your puzzle input, apply this process 50 times. What is the length of the new result?
(length (day10/say-sequence-n 50 (string-trim input)))
4666278
Day 11: Corporate Policy
Santa's previous password expired, and he needs help choosing a new one.
To help him remember his new password after the old one expires, Santa has devised a method of coming up with a password based on the previous one. Corporate policy dictates that passwords must be exactly eight lowercase letters (for security reasons), so he finds his new password by incrementing his old password string repeatedly until it is valid.
Incrementing is just like counting with numbers: xx, xy, xz, ya, yb, and so on. Increase the rightmost letter one step; if it was z, it wraps around to a, and repeat with the next letter to the left until one doesn't wrap around.
Unfortunately for Santa, a new Security-Elf recently started, and he has imposed some additional password requirements:
- Passwords must include one increasing straight of at least three letters, like abc, bcd, cde, and so on, up to xyz. They cannot skip letters; abd doesn't count.
- Passwords may not contain the letters i, o, or l, as these letters can be mistaken for other characters and are therefore confusing.
- Passwords must contain at least two different, non-overlapping pairs of letters, like aa, bb, or zz.
For example:
- hijklmmn meets the first requirement (because it contains the straight hij) but fails the second requirement requirement (because it contains i and l).
- abbceffg meets the third requirement (because it repeats bb and ff) but fails the first requirement.
- abbcegjk fails the third requirement, because it only has one double letter (bb).
- The next password after abcdefgh is abcdffaa.
- The next password after ghijklmn is ghjaabcc, because you eventually skip all the passwords that start with ghi…, since i is not allowed.
Given Santa's current password (your puzzle input), what should his next password be?
cqjxjnds
(defun day11/inc-password (password)
(cl-loop with carry = t
for char across (s-reverse password)
for new-char = (if carry (+ 1 char)
char)
if (> new-char ?z)
concat "a" into next-password
and do (setq carry t)
else
concat (char-to-string new-char) into next-password
and do (setq carry nil)
finally return (s-reverse
(if carry (s-concat next-password "a")
next-password))))
(ert-deftest day11/inc-password ()
(should (equal "xy" (day11/inc-password "xx")))
(should (equal "xz" (day11/inc-password "xy")))
(should (equal "ya" (day11/inc-password "xz")))
(should (equal "aaa" (day11/inc-password "zz"))))
(defun day11/includes-straight? (password)
(if password
(cl-loop with chars = (string-to-list password)
with straight = 1
for current = (car chars)
for next = (cadr chars)
while (and next (< straight 3))
do (if (eq next (+ 1 current))
(setq straight (+ 1 straight))
(setq straight 1))
(setq chars (rest chars))
finally return (eq straight 3))))
(defun day11/no-confusing-letters? (password)
(not (string-match-p "[iol]" password)))
(defun day11/two-different-pairs? (password)
(->> password
string-to-list
(-partition-by #'identity)
(-filter (lambda (x) (>= (length x) 2)))
(-map #'car)
-distinct
length
(<= 2)))
(defun day11/valid-password? (password)
(and (day11/no-confusing-letters? password)
(day11/two-different-pairs? password)
(day11/includes-straight? password)))
(ert-deftest day11/valid-password? ()
(should-not (day11/valid-password? "hijklmmn"))
(should-not (day11/valid-password? "abbceffg"))
(should-not (day11/valid-password? "abbcefgk"))
(should (day11/valid-password? "abcdffaa"))
(should (day11/valid-password? "ghjaabcc")))
(defun day11/next (next-fn predicate value)
(cl-loop with v = value
do (setq v (funcall next-fn v))
until (funcall predicate v)
finally return v))
(defun day11/next-password (password)
(day11/next
#'day11/inc-password
#'day11/valid-password?
password))
(ert-deftest day11/next-password ()
(should (equal "abcdffaa"
(day11/next-password "abcdefgh")))
(should (equal "ghjaabcc"
(day11/next-password "ghijklmn"))))
day11/next-password
(defun day11/to-decimal (password)
(cl-loop with p = ""
for times from 0
until (equal password p)
do (setq p (day11/inc-password p))
finally return times))
(ert-deftest day11/to-decimal ()
(should (eq 1 (day11/to-decimal "a")))
(should (eq 27 (day11/to-decimal "aa")))
(should (eq 731 (day11/to-decimal "abc"))))
day11/to-decimal
Password | Decimal |
---|---|
a | 1 |
aa | 27 |
aaa | 703 |
aaaa | 18279 |
aa | ba | 26 |
aaa | baa | 676 |
aaaa | baaa | 17576 |
string | e | decimal | 26^e | 𝚫 |
---|---|---|---|---|
z | 1 | 26 | 26 | 0 |
zz | 2 | 702 | 676 | 26 |
zzz | 3 | 18278 | 17576 | 702 |
(defun day11/max (pos)
(1- (cl-loop for x from 0 to pos
sum (expt 26 x))))
(cl-loop for x from 0 to 5
collect (list x (day11/max x)))
0 | 0 |
1 | 26 |
2 | 702 |
3 | 18278 |
4 | 475254 |
5 | 12356630 |
(cl-loop for pos from 0
sum (expt 26 pos) into maximum
until (> maximum 702)
finally return pos)
2
731 = abc = (0 1 2)
(defun day11/from-decimal (n)
(cl-loop with remaining = n
with max-pos = (cl-loop for pos from 0
sum (expt 26 pos) into maximum
until (> maximum n)
finally return (1- pos))
for pos downfrom max-pos to 0
for value-at-pos = (if (= 0 (% remaining (expt 26 pos))) (1- (/ remaining (expt 26 pos)))
(/ remaining (expt 26 pos)))
for digit = (if (= 0 pos) value-at-pos
(1- value-at-pos))
;; collect (list pos digit)
concat (char-to-string (+ ?a digit))
do (setq remaining (- remaining (* value-at-pos (expt 26 pos))))
))
(ert-deftest day11/from-decimal ()
(should (equal "a" (day11/from-decimal 1)))
(should (equal "z" (day11/from-decimal 26)))
(should (equal "xz" (day11/from-decimal 650)))
(should (equal "abc" (day11/from-decimal 731)))
(should (equal "zzz" (day11/from-decimal 18278))))
(defun day11/to-decimal (password)
(cl-loop for chars = (string-to-list password) then (rest chars)
while chars
sum (* (1+ (- (first chars) ?a))
(expt 26 (1- (length chars))))))
(defun day11/inc-password (password)
(-> password
day11/to-decimal
1+
day11/from-decimal))
day11/inc-password
(defun day11/from-decimal (n)
(cl-loop with remaining = n
;; How many digits long should this number be? This will
;; also be used as the max exponent of 26 to work down
;; from.
with max-exp = (cl-loop for pos from 0
sum (expt 26 pos) into maximum
while (< (1- maximum) n)
maximize pos)
for exp downfrom max-exp to 0
for exp-val = (expt 26 exp)
if (<= 27 (/ remaining exp-val))
;; Too big, let the remaining digits absorb it
collect 26 into values
and do (setq remaining (- remaining (* 26 exp-val)))
else if (and (> exp 0) (= 0 (% remaining 26)))
;; Perfectly divisible! Except, oh no, we don't have zeros.
;; Drop it a by multiple and carry the remainder through to
;; the next iteration.
collect (/ (- remaining exp-val) exp-val) into values
and do (setq remaining exp-val)
else
collect (/ remaining exp-val) into values
and do (setq remaining (% remaining exp-val))
finally return (->> values
(-map '1-)
(-map (apply-partially '+ ?a))
(apply 'string))))
(day11/from-decimal 18279)
aaaa
Boo, next-password is still too slow. Slower, maybe.
(defun day11/from-decimal (n)
(->>
(-reduce-from
(lambda (acc exp-val)
(let ((values (car acc))
(remaining (cdr acc)))
(cond ((<= 27 (/ remaining exp-val))
(cons (cons 26 values)
(- remaining (* 26 exp-val))))
((and (> exp-val 1) (= 0 (% remaining 26)))
(cons (cons (/ (- remaining exp-val) exp-val) values)
exp-val))
(t
(cons (cons (/ remaining exp-val) values)
(% remaining exp-val))))
))
(cons nil n)
(reverse (cl-loop for pos from 0
sum (expt 26 pos) into maximum
while (< (1- maximum) n)
collect (expt 26 pos))))
car
reverse
(-map '1-)
(-map (apply-partially '+ ?a))
(apply 'string)))
(day11/from-decimal 18279)
aaaa