advent-of-code/advent-of-code.org
2016-01-05 02:40:56 -05:00

4756 lines
127 KiB
Org Mode

#+TITLE: Advent of Code
#+STARTUP: indent
#+OPTIONS: num:nil ^:nil d:nil
#+PROPERTY: header-args :cache yes
#+DRAWERS: HIDDEN
#+BEGIN_SRC emacs-lisp :exports results :results silent
(require 'ert) ; Require ert for unit tests
(require 'dash)
(require 'dash-functional)
#+END_SRC
* 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?
----------------------------------------------------------------------
:HIDDEN:
#+name: 1-input
#+BEGIN_EXAMPLE
((((()(()(((((((()))(((()((((()())(())()(((()((((((()((()(()(((()(()((())))()((()()())))))))))()((((((())((()))(((((()(((((((((()()))((()(())()((())((()(()))((()))()))()(((((()(((()()))()())((()((((())()())()((((())()(()(()(((()(())(()(())(((((((())()()(((())(()(()(()(())))(()((((())((()))(((()(()()(((((()()(()(((()(((((())()))()((()(()))()((()((((())((((())(()(((())()()(()()()()()(())((((())((())(()()))()((((())))((((()())()((((())((()())((())(())(((((()((((()(((()((((())(()(((()()))()))((((((()((())()())))(((()(()))(()()(()(((()(()))((()()()())((()()()(((())())()())())())((()))(()(()))(((((()(()(())((()(())(())()((((()())()))((((())(())((())())((((()(((())(())((()()((((()((((((()(())()()(()(()()((((()))(())()())()))(())))(())))())()()(())(()))()((()(()(())()()))(()())))))(()))(()()))(())(((((()(()(()()((())()())))))((())())((())(()(())((()))(())(((()((((((((()()()(()))()()(((()))()((()()(())(())())()(()(())))(((((()(())(())(()))))())()))(()))()(()(((((((()((((())))())())())())()((((((((((((((()()((((((()()()())())()())())())(())(())))())((()())((()(()))))))()))))))))))))))))())((())((())()()))))))(((()((()(()()))((())(()()))()()())))(())))))))(()(((())))())()())))()()(())()))()(()))())((()()))))(()))))()))(()()(())))))))()(((()))))()(()))(())())))))()))((()))((()))())(())))))))))((((())()))()))()))())(())()()(())))())))(()())()))((()()(())))(())((((((()(())((()(((()(()()(())))()))))))()))()(()((()))()(()))(()(((())((((())())(())(()))))))))())))))))())())))))())))))()()(((())()(()))))))))())))))(())()()()))()))()))(()(())()()())())))))))())()(()(()))))()()()))))())(()))))()()))))()())))))(((())()()))(()))))))))))()()))))()()()))))(()())())()()())()(()))))()(()))(())))))))(((((())(())())()()))()()))(())))))()(()))))(())(()()))()())()))()))()))()))))())()()))())())))(()))(()))))))())()(((())()))))))))()))()())))())))())))()))))))))))()()))(()()))))))(())()(()))))())(()))))(()))))(()())))))())())()()))))())()))))))))(()))))()))))))()(()())))))))()))())))())))())))())))))))())(()()))))))(()())())))()())()))))))))))))))())))()(())))()))())()()(())(()()))(())))())()())(()(()(()))))())))))))))))())(()))()))()))))(())()())()())))))))))))()()))))))))))))())())))))(()())))))))))))())(())))()))))))))())())(()))()))(())))()))()()(())()))))))()((((())()))())())))))()))()))))((()())()))))())))(())))))))))))))))))()))))()()())()))()()))))())()))((()())))())))(()))(()())))))))()))()))))(())))))))(())))))())()()(()))())()))()()))))())()()))))())()))())))))))(()))))()())()))))))))(()))())))(()))()))))(())()))())())(())())())))))))((((())))))()))()))()())()(())))()))()))()())(()())()()(()())()))))())())))))(()))()))))())(()()(())))))(())()()((())())))))(())(())))))))())))))))))()(())))))))()())())())()(()))))))))(()))))))))())()()))()(()))))))()))))))())))))))(())))()()(())()())))))(((())))()((())()))())))(()()))())(())())))()(((()())))))()(()()())))()()(()()(()()))())()(()()()))())()()))()())(()))))())))))())))(())()()))))(()))))(())(()))(())))))()()))()))))())()))()()(())())))((()))())()))))))()()))))((()(()))))()()))))))())))))())(()((()())))))))))))()())())))()))(()))))))(()))(())()())))(()))))))))())()()()()))))(()())))))))((())))()))(()))(())(())()())()))))))))(())))())))(()))()()))(()()))(()))())))()(())))())((()((()(())))((())))()))))((((())())()())))(())))()))))))())(()()((())))())()(()())))))(()())()))())))))))((())())))))))(()(()))())()()(()()(((()(((()())))))()))))))()(())(()()((()()(())()()))())()())()))()())())())))))))(((())))))))()()))))))(((())()))(()()))(()()))))(()(()()((((())()())((()()))))(()(())))))()((()()()())()()((()((()()))(()))(((()()()))(((())))()(((())()))))))((()(())())))(()())(((((()(()))(()((()))(()())()))))(()(()))()(()))(())(((())(()()))))()()))(((()))))(()()()()))())))((()()()(())()))()))))()()))()))))))((((((()()()))))())((()()(((()))))(()(())(()()())())())))()(((()()))(())((())))(()))(()()()())((())())())(()))))()))()((()(())()(()()(())(()))(())()))(())(()))))(())(())())(()()(()((()()((())))((()))()((())))(((()()()()((((()))(()()))()()()(((())((())())(()()(()()()))()((())(())()))())(((()()(())))()((()()())()())(()(())())(((())(())())((())(())()(((()()))(())))((())(()())())(())((()()()((((((())))((()(((((())()))()))(())(()()))()))(())()()))(())((()()())()()(()))())()((())))()((()()())((((()())((())())())((()((()))()))((())((()()(()((()()(((())(()()))))((()((())()(((())(()((())())((())(()((((((())())()(()())()(())(((())((((((()(())(()((()()()((()()(()()()())))()()(((((()()))()((((((()))()(()(()(()(((()())((()))())()((()))(())))()))()()))())()()))())((((())(()(()))(((((((())(((()(((((()(((()()((((())(((())())))(()()()(()(()))()))((((((()))((()(((()(())((()((((()((((((())(((((())))(((()(()))))(((()(((())()((())(()((()))(((()()(((())((((()(()(((((()))(((()(((((((()(()()()(()(()(()()())(())(((((()(())())()())(()(()(()))()(()()()())(()()(()((()))()((())())()(()))((())(()))()(()))()(((()(()(()((((((()()()()())()(((((()()(((()()()((()(((((()))((((((((()()()(((((()))))))(()()()(())(()))(()()))))(())()))(((((()(((((()()(()(()())(((()))((((()((()(()(()((()(()((())))()(((()((()))((()))(((((((((()((()((()(())))()((((()((()()))((())(((()(((((()()(()(()()((()(()()()(((((((())())()())))))((((()()(()))()))(()((())()(()(((((((((()()(((()(()())(()((()())((())())((((()(((()(((()((((()((()((((()(()((((((())((((((((((((()()(()()((((((((((((((()((()()))()((((((((((((())((((()(()())((()(()(()))()(((((()()(((()()))()())(())((()(((((()((())(((((()((()(((((()))()()((((())()((((())(((((((((()(())(()(())))())(()((())(((())(())(())())(()(()(())()()((()((())()(((()(((((()(())))()(((()((())))((()()()(((()(((()((()(()(())(()((()())(()(()(((()(((((((((())(()((((()()))(()((((()()()()(((()((((((((()(()()((((((()(()()(()((()((((((((((()()(((((((()())(())))(((()()))(((((()((()()())(()()((((())((()((((()))))(())((()(()()(((()(()(((()((((()(((((()))())())(()((())()))(((()())((())((())((((()((()((((((())(()((((()()))((((((())()(()))((()(((())((((((((((()()(((((()(((((()((()()()((((())))(()))()((()(())()()((()((((((((((()((())(())(((((()(()(()()))((((()((((()()((()(((()(((((((((()(()((()((()))((((((()(((())()()((()(((((((()())))()()(()((()((()()(((()(()()()()((((()((())((((()(((((((((()(((()()(((()(()(((()(((()((())()(()((()(()(()(()))()(((()))(()((((()((())((((())((((((())(()))(()((((())((()(()((((((((()()((((((()(()(()()()(())((()((()()(((()(((((((()()((()(((((((()))(((((()(((()(()()()(()(((()((()()((())(()(((((((((()(()((()((((((()()((())()))(((((()((())()())()(((((((((((()))((((()()()()())(()()(()(()()))()))(()))(()(((()()))())(()(()))()()((())(()())()())()(()))()))(()()(()((((((())((()(((((((((((()(())()((()(()((()((()(()((()((((((((((()()())((())()(())))((())()())()(((((()(()())((((()((()(())(()))(((())()((()))(((((())(()))()()(()))(((())((((()((((()(())))(((((((()))))())()())(())((())()(()()((()(()))()(()()(()()((()())((())((()()))((((()))()()))(()()(())()()(((((()(())((()((((()))()))(()())())(((()()(()()))(())))))(()))((())(((((()((((()))()((((()))()((())(((())))(((()())))((()(()()((
#+END_EXAMPLE
:END:
#+name: 1-solution
#+BEGIN_SRC emacs-lisp :var input=1-input :exports both
(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)
#+END_SRC
#+RESULTS[966acea0b884f9a83f09aae9b3c00803a516e3ca]: 1-solution
: 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 position =1=.
- =()())= causes him to enter the basement at character position =5=.
What is the position of the character that causes Santa to first enter the basement?
----------------------------------------------------------------------
#+name: 1.2-solution
#+BEGIN_SRC emacs-lisp :var input=1-input :exports both
(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)
#+END_SRC
#+RESULTS[048e5b88e35ca21b8be15e5cffaa117c4e1eca45]: 1.2-solution
: 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 [[https://en.wikipedia.org/wiki/Cuboid#Rectangular_cuboid][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?
----------------------------------------------------------------------
:HIDDEN:
#+name: 2-input
#+BEGIN_EXAMPLE
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
#+END_EXAMPLE
:END:
#+name: 2-solution
#+BEGIN_SRC emacs-lisp :var input=2-input :exports both
(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)
#+END_SRC
#+RESULTS[f343fb2890e11ccbcc408d25b441e9a808073e1f]: 2-solution
: 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= requires =2+2+3+3 = 10= feet of
ribbon to wrap the present plus =2*3*4 = 24= feet of ribbon for the
bow, for a total of =34= feet.
- A present with dimensions =1x1x10= requires =1+1+1+1 = 4= feet of
ribbon to wrap the present plus =1*1*10 = 10= feet of ribbon for the
bow, for a total of =14= feet.
How many total feet of ribbon should they order?
----------------------------------------------------------------------
#+BEGIN_SRC emacs-lisp :var input=2-input :exports both
(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)
#+END_SRC
#+RESULTS[c13958a4756029347386f7b48c44959c7b8e3dea]:
: 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 to =2= houses: one at the starting location,
and one to the east.
- =^>v<= delivers presents to =4= 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 only =2= houses.
----------------------------------------------------------------------
:HIDDEN:
#+name: 3-input
#+BEGIN_EXAMPLE
>^^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<
#+END_EXAMPLE
:END:
#+BEGIN_SRC emacs-lisp :var input=3-input :exports both
(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))
#+END_SRC
#+RESULTS[de0154066fa58bb3f337d9fc6135a1e7620998c1]:
: 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 to =3= houses, because Santa goes north, and
then Robo-Santa goes south.
- =^>v<= now delivers presents to =3= houses, and Santa and Robo-Santa
end up back where they started.
- =^v^v^v^v^v= now delivers presents to =11= houses, with Santa going
one direction and Robo-Santa going the other.
----------------------------------------------------------------------
#+BEGIN_SRC emacs-lisp :var input=3-input :exports both
(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))
#+END_SRC
#+RESULTS[25db54a0aebd3fd8cbb6d364a6a05908e4c1e208]:
: 2360
* Day 4: The Ideal Stocking Stuffer
Santa needs help [[https://en.wikipedia.org/wiki/Bitcoin#Mining][mining]] some AdventCoins (very similar to [[https://en.wikipedia.org/wiki/Bitcoin#Mining][bitcoins]]) to
use as gifts for all the economically forward-thinking little girls
and boys.
To do this, he needs to find [[https://en.wikipedia.org/wiki/MD5][MD5]] hashes which, in [[https://en.wikipedia.org/wiki/Hexadecimal][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 is =609043=, because the
MD5 hash of =abcdef609043= 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 is =1048970=; that is,
the MD5 hash of =pqrstuv1048970= looks like =000006136ef...=.
----------------------------------------------------------------------
:HIDDEN:
#+name: 4-input
#+BEGIN_EXAMPLE
ckczppom
#+END_EXAMPLE
:END:
#+BEGIN_SRC emacs-lisp :var input=4-input :exports both
(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))
#+END_SRC
#+RESULTS[461139efd69152ff32f7ba3996d41b323fd6c8bd]:
: 117946
** Part 2
Now find one that starts with *six zeroes*.
----------------------------------------------------------------------
#+BEGIN_SRC emacs-lisp :var input=4-input :exports both
(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))
#+END_SRC
#+RESULTS[637ec8d92dd6b49b39e0eb247af8265cd6938e5a]:
: 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), like =aei=,
=xazegov=, or =aeiouaeiouaeiou=.
- It contains at least one letter that appears twice in a row, like
=xx=, =abcdde= (=dd=), or =aabbccdd= (=aa=, =bb=, =cc=, or =dd=).
- It does not contain the strings =ab=, =cd=, =pq=, or =xy=, 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 string =xy=.
- =dvszwmarrgswjxmb- is naughty because it contains only one vowel.
How many strings are nice?
----------------------------------------------------------------------
:HIDDEN:
#+name: 5-input
#+BEGIN_EXAMPLE
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
#+END_EXAMPLE
:END:
#+BEGIN_SRC emacs-lisp :var input=5-input :exports both
(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)))
#+END_SRC
#+RESULTS[7332f2494e02290b4a00b217635390fb235e1de7]:
: 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=) or =aabcdefgaa=
(=aa=), but not like =aaa= (=aa=, but it overlaps).
- It contains at least one letter which repeats with exactly one
letter between them, like =xyx=, =abcdefeghi= (=efe=), or even
=aaa=.
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?
----------------------------------------------------------------------
#+BEGIN_SRC emacs-lisp :var input=5-input :exports both
(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)))
#+END_SRC
#+RESULTS[714e53b40cf4a27435a59eafbd8c488cb05bd539]:
: 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?
----------------------------------------------------------------------
:HIDDEN:
#+name: 6-input
#+BEGIN_EXAMPLE
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
#+END_EXAMPLE
:END:
#+BEGIN_SRC emacs-lisp :var input=6-input :exports both
(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))
#+END_SRC
#+RESULTS[2e528f53a45a3c7e0dcc549d5ac69918287ddd6e]:
: 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 by
=1=.
- =toggle 0,0 through 999,999= would increase the total brightness by
=2000000=.
----------------------------------------------------------------------
#+BEGIN_SRC emacs-lisp :var input=6-input :exports both
(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))
#+END_SRC
#+RESULTS[ceaf378dab9cbe4211307b258b4fe66d2a04482b]:
: 14110788
* Day 7: Some Assembly Required
This year, Santa brought little Bobby Tables a set of wires and
[[https://en.wikipedia.org/wiki/Bitwise_operation][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
[[https://en.wikipedia.org/wiki/16-bit][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 signal =123= is provided to wire =x=.
- =x AND y -> z= means that the [[https://en.wikipedia.org/wiki/Bitwise_operation#AND][bitwise AND]] of wire =x= and wire =y=
is provided to wire =z=.
- =p LSHIFT 2 -> q= means that the value from wire =p= is [[https://en.wikipedia.org/wiki/Logical_shift][left-shifted]]
by =2= and then provided to wire =q=.
- =NOT e -> f= means that the =bitwise complement= of the value from
wire =e= is provided to wire =f=.
Other possible gates include =OR= ([[https://en.wikipedia.org/wiki/Bitwise_operation#OR][bitwise OR]]) and =RSHIFT=
([[https://en.wikipedia.org/wiki/Logical_shift][right-shift]]). If, for some reason, you'd like to *emulate* the
circuit instead, almost all programming languages (for example, [[https://en.wikipedia.org/wiki/Bitwise_operations_in_C][C]],
[[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators][JavaScript]], or [[https://wiki.python.org/moin/BitwiseOperators][Python]]) provide operators for these gates.
For example, here is a simple circuit:
#+BEGIN_EXAMPLE
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
#+END_EXAMPLE
After it is run, these are the signals on the wires:
#+BEGIN_EXAMPLE
d: 72
e: 507
f: 492
g: 114
h: 65412
i: 65079
x: 123
y: 456
#+END_EXAMPLE
In little Bobby's kit's instructions booklet (provided as your puzzle
input), what signal is ultimately provided to *wire a*?
----------------------------------------------------------------------
:HIDDEN:
#+name: 7-input
#+BEGIN_EXAMPLE
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
#+END_EXAMPLE
:END:
#+BEGIN_SRC emacs-lisp :var input=7-input :exports both
(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))
#+END_SRC
#+RESULTS[0e096ea6071516679cc36a305883d2bdd808c930]:
: 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=?
----------------------------------------------------------------------
#+BEGIN_SRC emacs-lisp :var input=7-input :exports both
(let* ((connection-strings (split-string input "\n" t))
(circuit (day7/make-circuit connection-strings)))
(day7/circuit-put circuit 'b 956)
(day7/evaluate circuit 'a))
#+END_SRC
#+RESULTS[61e8544d7d4f32d111e9a666de842ecc4248e390]:
: 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:
- =""= is =2= characters of code (the two double quotes), but the
string contains zero characters.
- ="abc"= is =5= characters of code, but 3 characters in the string
data.
- ="aaa\"aaa"= is =10= characters of code, but the string itself
contains six ="a"= characters and a single, escaped quote character,
for a total of =7= characters in the string data.
- ="\x27"= is =6= 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=.
----------------------------------------------------------------------
:HIDDEN:
#+name: 8-input
#+BEGIN_EXAMPLE
"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"
#+END_EXAMPLE
:END:
#+BEGIN_SRC emacs-lisp :var input=8-input :exports both
(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))))
#+END_SRC
#+RESULTS[acaa7a9432ace3b411d0bfcd4c61620b43ce21c5]:
: 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 from =2= characters to =6=.
- ="abc"= encodes to ="\"abc\""=, an increase from =5= characters to
=9=.
- ="aaa\"aaa"= encodes to ="\"aaa\\\"aaa\""=, an increase from =10=
characters to =16=.
- ="\x27"= encodes to ="\"\\x27\""=, an increase from =6= characters
to =11=.
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=.
----------------------------------------------------------------------
#+BEGIN_SRC emacs-lisp :var input=8-input :exports both
(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))))
#+END_SRC
#+RESULTS[bb50e3c25f6d0d1247acdefae2e5c755c90fe7a7]:
: 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:
#+name: 9-example
#+BEGIN_EXAMPLE
London to Dublin = 464
London to Belfast = 518
Dublin to Belfast = 141
#+END_EXAMPLE
The possible routes are therefore:
#+BEGIN_EXAMPLE
Dublin -> London -> Belfast = 982
London -> Dublin -> Belfast = 605
London -> Belfast -> Dublin = 659
Dublin -> Belfast -> London = 659
Belfast -> Dublin -> London = 605
Belfast -> London -> Dublin = 982
#+END_EXAMPLE
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?
----------------------------------------------------------------------
:HIDDEN:
#+name: 9-input
#+BEGIN_EXAMPLE
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
#+END_EXAMPLE
:END:
#+BEGIN_SRC emacs-lisp :var example=9-example :var input=9-input :noweb yes
(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))
#+END_SRC
#+RESULTS[052969aa6870de45711d74f55a9ef7dbd058a865]:
: 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?
----------------------------------------------------------------------
#+BEGIN_SRC emacs-lisp :var input=9-input :exports both
(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))
#+END_SRC
#+RESULTS[60abd7588f60147684eafda03eae00b226d39891]:
: 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= becomes =11= (=1= copy of digit =1=).
- =11= becomes =21= (=2= copies of digit =1=).
- =21= becomes =1211= (one =2= followed by one =1=).
- =1211= becomes =111221= (one =1=, one =2=, and two =1=s).
- =111221= becomes =312211= (three =1=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*?
----------------------------------------------------------------------
:HIDDEN:
#+name: 10-input
#+BEGIN_EXAMPLE
3113322113
#+END_EXAMPLE
:END:
#+BEGIN_SRC emacs-lisp :var input=10-input :exports both
(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)))
#+END_SRC
#+RESULTS[a92ffee565329427383332212debc42eac7b4af2]:
: 329356
** Part 2
Neat, right? You might also enjoy hearing [[https://www.youtube.com/watch?v=ea7lJkEhytA][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*?
----------------------------------------------------------------------
#+BEGIN_SRC emacs-lisp :var input=10-input :exports both
(length (day10/say-sequence-n 50 (string-trim input)))
#+END_SRC
#+RESULTS[cc7bbc9c6f3abcff179e832a1ed20371b788b059]:
: 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?
----------------------------------------------------------------------
#+name: 11-input
#+BEGIN_EXAMPLE
cqjxjnds
#+END_EXAMPLE
#+BEGIN_SRC emacs-lisp :var input=11-input :exports both
(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"))))
#+END_SRC
#+RESULTS[e3f93fa2eb79838daab12a13d299d30da1851600]:
: day11/next-password
#+BEGIN_SRC emacs-lisp
(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"))))
#+END_SRC
#+RESULTS[61997d8c37066aa33ef1da62aae97535f27744b7]:
: day11/to-decimal
| Password | Decimal |
|----------+---------|
| a | 1 |
| aa | 27 |
| aaa | 703 |
| aaaa | 18279 |
#+TBLFM: $2='(day11/to-int $1)
| aa | ba | 26 |
| aaa | baa | 676 |
| aaaa | baaa | 17576 |
#+TBLFM: $3='(- (day11/to-int $2) (day11/to-int $1))::
| string | e | decimal | 26^e | 𝚫 |
|--------+---+---------+-------+-----|
| z | 1 | 26 | 26 | 0 |
| zz | 2 | 702 | 676 | 26 |
| zzz | 3 | 18278 | 17576 | 702 |
#+TBLFM: $4=26**$2::$5=$3-$4
#+BEGIN_SRC emacs-lisp
(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)))
#+END_SRC
#+RESULTS[db569313ecda73a8c067e54caa31f2498f8e9ccb]:
| 0 | 0 |
| 1 | 26 |
| 2 | 702 |
| 3 | 18278 |
| 4 | 475254 |
| 5 | 12356630 |
#+BEGIN_SRC emacs-lisp
(cl-loop for pos from 0
sum (expt 26 pos) into maximum
until (> maximum 702)
finally return pos)
#+END_SRC
#+RESULTS[65d9292c08875bd5e0ea2d66b830785b4b9b09c2]:
: 2
~731 = abc = (0 1 2)~
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
#+RESULTS[7cf5f534d09862a37d0bc5530b0de5cd8846d3fd]:
: day11/inc-password
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
#+RESULTS[72a1e01d5c29b04647e80c2160179c06c9dbfb06]:
: aaaa
Boo, next-password is *still* too slow. Slower, maybe.
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
#+RESULTS[9f4122c0cddc66017f1605d52b6ae732b3150cf3]:
: aaaa