Skip to content

Commit dbd65cd

Browse files
committed
Day 25
1 parent 2e9a52c commit dbd65cd

File tree

4 files changed

+96
-0
lines changed

4 files changed

+96
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ _Warning:_ I write long explanations. So... yeah.
3434
| 22 | [source](src/advent_2020_clojure/day22.clj) | [blog](docs/day22.md) |
3535
| 23 | [source](src/advent_2020_clojure/day23.clj) | [blog](docs/day23.md) |
3636
| 24 | [source](src/advent_2020_clojure/day24.clj) | [blog](docs/day24.md) |
37+
| 25 | [source](src/advent_2020_clojure/day25.clj) | [blog](docs/day25.md) |

docs/day25.md

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Day Twenty-Five: Combo Breaker
2+
3+
* [Problem statement](https://adventofcode.com/2020/day/25)
4+
* [Solution code](https://github.com/abyala/advent-2020-clojure/blob/master/src/advent_2020_clojure/day25.clj)
5+
6+
---
7+
8+
After 24 days of code hacking, our final puzzle is a little password hacking. True to form, the final day's
9+
puzzle is pretty simple, I assume because the coordinator of Advent Of Code wants to dissuade folks from
10+
banging our heads against the wall on Christmas day.
11+
12+
---
13+
14+
## Part 1
15+
16+
There's not much to say here. We're given a cryptographic transformation algorithm that our private keys
17+
operate on a number of times to generate some output. Two systems, a key card and a door, both apply the
18+
cryptographic transformation on a common, widely-known secret to generate their public keys, which we are
19+
given as input. Then both the card and the door use their own private key (the looping factor) on the other's
20+
public key to generate the answer, ostensibly the shared encryption key. Because both the card and the door
21+
should generate the same encryption key, we only have to calculate it for either the card or the door, but my
22+
test case asserts that the two are equal.
23+
24+
Because cracking the private key and generating the encryption key use the same transformation algorithm,
25+
I created `crypto-transform`, which generates an infinite sequence of transformation on its `subject-number`
26+
input. On each iteration, we take the previous value (starting with `1`), multiply it by the `subject-number`,
27+
and take the remainder after dividing by `20201227`.
28+
29+
```clojure
30+
(defn crypto-transform [subject-number]
31+
(iterate #(-> (* % subject-number) (rem 20201227)) 1))
32+
```
33+
34+
Then to crack the private key, we need to figure out how many loops through the transformation function it
35+
takes to generate the public key. We just use `keep-indexed` to find the first iteration when the output
36+
equals the public key, pulling out the index that represents the iteration number.
37+
38+
```clojure
39+
(defn crack-private-key [subject-number public-key]
40+
(->> (crypto-transform subject-number)
41+
(keep-indexed (fn [idx v] (when (= v public-key) idx)))
42+
first))
43+
```
44+
45+
Finally, given the two public keys, we can determine the encryption key, which is the goal of part 1.
46+
We start with the sequence of transformations of the second public key, looping the number of times equal
47+
to the first private key, which we get by calling `crack-private-key`. And again, the test code verifies
48+
this, rather than the application code, but `(part1 key1 key2)` equals `(part1 key2 key1)`.
49+
50+
```clojure
51+
(defn part1 [key1-pub key2-pub]
52+
(->> (crypto-transform key2-pub)
53+
(drop (crack-private-key 7 key1-pub))
54+
first))
55+
```
56+
57+
---
58+
59+
## Part 2
60+
61+
There is no part 2. By finishing the first 49th stars, we get the 50th for free. Congratulations to all
62+
who participated in Advent Of Code this year! And a huge thanks to [@ericwastl](https://twitter.com/ericwastl)
63+
for putting together yet another fantastic coding event!

src/advent_2020_clojure/day25.clj

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
(ns advent-2020-clojure.day25)
2+
3+
(defn crypto-transform [subject-number]
4+
(iterate #(-> (* % subject-number) (rem 20201227)) 1))
5+
6+
(defn crack-private-key [subject-number public-key]
7+
(->> (crypto-transform subject-number)
8+
(keep-indexed (fn [idx v] (when (= v public-key) idx)))
9+
first))
10+
11+
(defn part1 [key1-pub key2-pub]
12+
(->> (crypto-transform key2-pub)
13+
(drop (crack-private-key 7 key1-pub))
14+
first))
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
(ns advent-2020-clojure.day25-test
2+
(:require [clojure.test :refer :all]
3+
[advent-2020-clojure.day25 :refer :all]))
4+
5+
(def test-card-pub 5764801)
6+
(def test-door-pub 17807724)
7+
(def puzzle-card-pub 6930903)
8+
(def puzzle-door-pub 19716708)
9+
10+
(deftest part1-test
11+
(testing "Test data"
12+
(is (= 14897079
13+
(part1 test-card-pub test-door-pub)
14+
(part1 test-door-pub test-card-pub))))
15+
(testing "Puzzle data"
16+
(is (= 10548634
17+
(part1 puzzle-card-pub puzzle-door-pub)
18+
(part1 puzzle-door-pub puzzle-card-pub)))))

0 commit comments

Comments
 (0)