Advent of Code 2022 literate Clojure. To run code blocks in this file, you’ll probably want to have a recent version of Emacs with Org-Mode 9 or later, and Cider installed to start up the Clojure REPL.
Some of the problems might be stand-alone and some might build on earlier
solutions. In the past each day has usually had a couple of variations on a
problem’s theme, e.g. a simpler and a tougher challenge. For this reason, I’m
not initially going to tangle the code into different packages. Just run
cider-jack-in to start the REPL and then evaluate the code in the *user*
namespace.
Santa’s reindeer typically eat regular reindeer food, but they need a lot of magical energy to deliver presents on Christmas. For that, their favorite snack is a special type of star fruit that only grows deep in the jungle. The Elves have brought you on their annual expedition to the grove where the fruit grows.
To supply enough magical energy, the expedition needs to retrieve a minimum of fifty stars by December 25th. Although the Elves assure you that the grove has plenty of fruit, you decide to grab any fruit you see along the way, just in case.
Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck!
The jungle must be too overgrown and difficult to navigate in vehicles or access from the air; the Elves’ expedition traditionally goes on foot. As your boats approach land, the Elves begin taking inventory of their supplies. One important consideration is food - in particular, the number of Calories each Elf is carrying (your puzzle input).
The Elves take turns writing down the number of Calories contained by the various meals, snacks, rations, etc. that they’ve brought with them, one item per line. Each Elf separates their own inventory from the previous Elf’s inventory (if any) by a blank line.
For example, suppose the Elves finish writing their items’ Calories and end up with the following list:
(def day1-data (slurp "resources/day1_input.txt"))
(def elf-inventory
(->> (clojure.string/split day1-data #"\n\n")
(map (fn [coll] (clojure.string/split-lines coll)))
(mapv #(mapv (fn [x] (Integer/parseInt x)) %))))This list represents the Calories of the food carried by five Elves, e.g:
- The first Elf is carrying food with 1000, 2000, and 3000 Calories, a total of 6000 Calories.
- The second Elf is carrying one food item with 4000 Calories.
- The third Elf is carrying food with 5000 and 6000 Calories, a total of 11000 Calories.
- The fourth Elf is carrying food with 7000, 8000, and 9000 Calories, a total of 24000 Calories.
- The fifth Elf is carrying one food item with 10000 Calories.
In case the Elves get hungry and need extra snacks, they need to know which Elf to ask: they’d like to know how many Calories are being carried by the Elf carrying the most Calories. In the example above, this is 24000 (carried by the fourth Elf).
Find the Elf carrying the most Calories. How many total Calories is that Elf carrying?
Alright then elves, everyone sum up the amount you’re carrying.
(def elf-totals
(mapv #(reduce + %) elf-inventory))Now, who has the most calories here, how many?
(reduce max elf-totals)By the time you calculate the answer to the Elves’ question, they’ve already realized that the Elf carrying the most Calories of food might eventually run out of snacks.
To avoid this unacceptable situation, the Elves would instead like to know the total Calories carried by the top three Elves carrying the most Calories. That way, even if one of those Elves runs out of snacks, they still have two backups.
In the example above, the top three Elves are the fourth Elf (with 24000 Calories), then the third Elf (with 11000 Calories), then the fifth Elf (with 10000 Calories). The sum of the Calories carried by these three elves is 45000.
Find the top three Elves carrying the most Calories. How many Calories are those Elves carrying in total?
Alright then elves, line up in order of how much snacks you brought, then the three at the front can sum up their amounts.
(def sorted-elves
(reverse (sort elf-totals)))(reduce + (take 3 sorted-elves))The Elves begin to set up camp on the beach. To decide whose tent gets to be closest to the snack storage, a giant Rock Paper Scissors tournament is already in progress.
Rock Paper Scissors is a game between two players. Each game contains many rounds; in each round, the players each simultaneously choose one of Rock, Paper, or Scissors using a hand shape. Then, a winner for that round is selected: Rock defeats Scissors, Scissors defeats Paper, and Paper defeats Rock. If both players choose the same shape, the round instead ends in a draw.
Appreciative of your help yesterday, one Elf gives you an encrypted strategy guide (your puzzle input) that they say will be sure to help you win. “The first column is what your opponent is going to play: A for Rock, B for Paper, and C for Scissors. The second column–” Suddenly, the Elf is called away to help with someone’s tent.
(def day2-data (slurp "resources/day2_input.txt"))The second column, you reason, must be what you should play in response: X for Rock, Y for Paper, and Z for Scissors. Winning every time would be suspicious, so the responses must have been carefully chosen.
(def code->item
{"A" :rock
"B" :paper
"C" :scissors
"X" :rock
"Y" :paper
"Z" :scissors})
(def rounds
(->> (clojure.string/split-lines day2-data)
(mapv #(clojure.string/split % #"[ ]+"))
(mapv #(mapv code->item %))))The winner of the whole tournament is the player with the highest score. Your total score is the sum of your scores for each round. The score for a single round is the score for the shape you selected (1 for Rock, 2 for Paper, and 3 for Scissors) plus the score for the outcome of the round (0 if you lost, 3 if the round was a draw, and 6 if you won).
(defn score-round [[response outcome]]
(let [item-scores {:rock 1, :paper 2, :scissors 3}
outcome-scores {:win 6, :draw 3, :loss 0}]
(+ (response item-scores)
(outcome outcome-scores))))
(defn beats [a b]
(if (= a b)
:draw
(if (or (and (= a :rock) (= b :scissors))
(and (= a :scissors) (= b :paper))
(and (= a :paper) (= b :rock)))
:win
:loss)))
(defn play-round [challenge response]
[response (beats response challenge)])Since you can’t be sure if the Elf is trying to help you or trick you, you should calculate the score you would get if you were to follow the strategy guide.
For example, suppose you were given the following strategy guide:
A Y B X C Z
This strategy guide predicts and recommends the following:
- In the first round, your opponent will choose Rock (A), and you should choose Paper (Y). This ends in a win for you with a score of 8 (2 because you chose Paper + 6 because you won).
- In the second round, your opponent will choose Paper (B), and you should choose Rock (X). This ends in a loss for you with a score of 1 (1 + 0).
- The third round is a draw with both players choosing Scissors, giving you a score of 3 + 3 = 6.
In this example, if you were to follow the strategy guide, you would get a total score of 15 (8 + 1 + 6).
(for [round [(play-round :rock :paper)
(play-round :paper :rock)
(play-round :scissors :scissors)]]
(format "%s = %d" round (score-round round)))What would your total score be if everything goes exactly according to your strategy guide?
(->> rounds
(map #(apply play-round %))
(map score-round)
(reduce +))The Elf finishes helping with the tent and sneaks back over to you. “Anyway, the second column says how the round needs to end: X means you need to lose, Y means you need to end the round in a draw, and Z means you need to win. Good luck!”
(def code->outcome
{"X" :loss
"Y" :draw
"Z" :win})
(def round-strategies
(->> (clojure.string/split-lines day2-data)
(mapv #(clojure.string/split % #"[ ]+"))
(mapv (fn [x] [(code->item (nth x 0)) (code->outcome (nth x 1))]))))The total score is still calculated in the same way, but now you need to figure out what shape to choose so the round ends as indicated. The example above now goes like this:
- In the first round, your opponent will choose Rock (A), and you need the round to end in a draw (Y), so you also choose Rock. This gives you a score of 1 + 3 = 4.
- In the second round, your opponent will choose Paper (B), and you choose Rock so you lose (X) with a score of 1 + 0 = 1.
- In the third round, you will defeat your opponent’s Scissors with Rock for a score of 1 + 6 = 7.
(defn choose-response [challenge outcome]
(cond (= outcome :draw) challenge
(= outcome :win) (case challenge
:rock :paper
:paper :scissors
:scissors :rock)
(= outcome :loss) (case challenge
:rock :scissors
:scissors :paper
:paper :rock)))Now that you’re correctly decrypting the ultra top secret strategy guide, you would get a total score of 12.
Following the Elf’s instructions for the second column, what would your total score be if everything goes exactly according to your strategy guide?
(def calculated-rounds
(mapv (fn [x]
[(nth x 0) (apply choose-response x)])
round-strategies))(->> calculated-rounds
(map #(apply play-round %))
(map score-round)
(reduce +))
One Elf has the important job of loading all of the rucksacks with supplies for the jungle journey. Unfortunately, that Elf didn’t quite follow the packing instructions, and so a few items now need to be rearranged.
Each rucksack has two large compartments. All items of a given type are meant to go into exactly one of the two compartments. The Elf that did the packing failed to follow this rule for exactly one item type per rucksack.
The Elves have made a list of all of the items currently in each rucksack
(your puzzle input), but they need your help finding the errors. Every item
type is identified by a single lowercase or uppercase letter (that is, a and
A refer to different types of items).
The list of items for each rucksack is given as characters all on a single line. A given rucksack always has the same number of items in each of its two compartments, so the first half of the characters represent items in the first compartment, while the second half of the characters represent items in the second compartment.
(def day3-data (slurp "resources/day3_input.txt"))For example, suppose you have the following list of contents from six rucksacks:
vJrwpWtwJgWrhcsFMMfFFhFp jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL PmmdzqPrVvPwwTWBwg wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn ttgJtRGJQctTZtZT CrZsJsPPZsGzwwsLwLmpwMDw
- The first rucksack contains the items
vJrwpWtwJgWrhcsFMMfFFhFp, which means its first compartment contains the itemsvJrwpWtwJgWr, while the second compartment contains the itemshcsFMMfFFhFp. The only item type that appears in both compartments is lowercase p. - The second rucksack’s compartments contain
jqHRNqRjqzjGDLGLandrsFMfFZSrLrFZsSL. The only item type that appears in both compartments is uppercase L. - The third rucksack’s compartments contain
PmmdzqPrVandvPwwTWBwg; the only common item type is uppercase P. - The fourth rucksack’s compartments only share item type v.
- The fifth rucksack’s compartments only share item type t.
- The sixth rucksack’s compartments only share item type s.
(def rucksacks (clojure.string/split-lines day3-data))
(def rucksack-compartments
(map (fn [s] (partition (/ (count s) 2) s)) rucksacks))To help prioritize item rearrangement, every item type can be converted to a priority:
- Lowercase item types a through z have priorities 1 through 26.
- Uppercase item types A through Z have priorities 27 through 52.
In the above example, the priority of the item type that appears in both compartments of each rucksack is 16 (p), 38 (L), 42 (P), 22 (v), 20 (t), and 19 (s); the sum of these is 157.
(defn priority [item]
(let [n (int item)]
(cond (and (>= n (int \a)) (<= n (int \z))) (- n (dec (int \a)))
(and (>= n (int \A)) (<= n (int \Z))) (+ 26 (- n (dec (int \A))))
:else 0)))Find the item type that appears in both compartments of each rucksack. What is the sum of the priorities of those item types?
(defn find-duplicate-items [rucksacks]
(->> rucksacks
(map (fn [n]
(clojure.set/intersection (set (nth n 0))
(set (nth n 1)))))))
(def rucksack-duplicates (find-duplicate-items rucksack-compartments))(->> rucksack-duplicates
(map #(map priority %))
(map #(reduce + %))
(reduce +))As you finish identifying the misplaced items, the Elves come to you with another issue.
The problem is that someone forgot to put this year’s updated authenticity sticker on the badges. All of the badges need to be pulled out of the rucksacks so the new authenticity stickers can be attached.
For safety, the Elves are divided into groups of three. Every Elf carries a
badge that identifies their group. For efficiency, within each group of three
Elves, the badge is the only item type carried by all three Elves. That is,
if a group’s badge is item type B, then all three Elves will have item type
B somewhere in their rucksack, and at most two of the Elves will be
carrying any other item type.
Additionally, nobody wrote down which item type corresponds to each group’s badges. The only way to tell which item type is the right one is by finding the one item type that is common between all three Elves in each group.
Every set of three lines in your list corresponds to a single group, but each group can have a different badge item type. So, in the above example, the first group’s rucksacks are the first three lines:
vJrwpWtwJgWrhcsFMMfFFhFp jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL PmmdzqPrVvPwwTWBwg
And the second group’s rucksacks are the next three lines:
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn ttgJtRGJQctTZtZT CrZsJsPPZsGzwwsLwLmpwMDw
In the first group, the only item type that appears in all three rucksacks is
lowercase r; this must be their badges. In the second group, their badge item
type must be Z.
(def grouped-rucksacks
(partition 3 rucksacks))Priorities for these items must still be found to organize the sticker attachment efforts: here, they are 18 (r) for the first group and 52 (Z) for the second group. The sum of these is 70.
Find the item type that corresponds to the badges of each three-Elf group. What is the sum of the priorities of those item types?
(def badge-id-per-group
(->> grouped-rucksacks
(map #(map set %))
(map #(apply clojure.set/intersection %))))(->> badge-id-per-group
(map #(map priority %))
(map #(reduce + %))
(reduce +))Space needs to be cleared before the last supplies can be unloaded from the ships, and so several Elves have been assigned the job of cleaning up sections of the camp. Every section has a unique ID number, and each Elf is assigned a range of section IDs.
However, as some of the Elves compare their section assignments with each other, they’ve noticed that many of the assignments overlap. To try to quickly find overlaps and reduce duplicated effort, the Elves pair up and make a big list of the section assignments for each pair (your puzzle input).
(def day4-data (slurp "resources/day4_input.txt"))
(defn parse-assignment [s]
(let [[l1 l2 r1 r2]
(mapv #(Integer/parseInt %) (clojure.string/split s #"[,-]"))]
[[l1 l2] [r1 r2]]))
(def assignments
(->> (clojure.string/split-lines day4-data)
(map parse-assignment)))For example, consider the following list of section assignment pairs:
2-4,6-8 2-3,4-5 5-7,7-9 2-8,3-7 6-6,4-6 2-6,4-8
For the first few pairs, this list means:
- Within the first pair of Elves, the first Elf was assigned sections
2-4(sections2,3, and4), while the second Elf was assigned sections6-8(sections6,7,8). - The Elves in the second pair were each assigned two sections.
- The Elves in the third pair were each assigned three sections: one got
sections
5,6, and7, while the other also got7, plus8and9.
This example list uses single-digit section IDs to make it easier to draw; your actual list might contain larger numbers. Visually, these pairs of section assignments look like this:
.234..... 2-4 .....678. 6-8 .23...... 2-3 ...45.... 4-5 ....567.. 5-7 ......789 7-9 .2345678. 2-8 ..34567.. 3-7 .....6... 6-6 ...456... 4-6 .23456... 2-6 ...45678. 4-8
Some of the pairs have noticed that one of their assignments fully contains
the other. For example, 2-8 fully contains 3-7, and 6-6 is fully contained by
4-6. In pairs where one assignment fully contains the other, one Elf in the
pair would be exclusively cleaning sections their partner will already be
cleaning, so these seem like the most in need of reconsideration. In this
example, there are 2 such pairs.
(defn subset? [[l1 l2] [r1 r2]]
(and (>= r1 l1) (<= r2 l2)))
(defn either-subset? [left-range right-range]
(or (subset? left-range right-range)
(subset? right-range left-range)))In how many assignment pairs does one range fully contain the other?
(->> (filter (fn [[left right]] (either-subset? left right)) assignments)
count)It seems like there is still quite a bit of duplicate work planned. Instead, the Elves would like to know the number of pairs that overlap at all.
In the above example, the first two pairs (2-4,6-8 and 2-3,4-5) don’t
overlap, while the remaining four pairs (5-7,7-9, 2-8,3-7, 6-6,4-6, and
2-6,4-8) do overlap:
5-7,7-9overlaps in a single section, 7.2-8,3-7overlaps all of the sections 3 through 7.6-6,4-6overlaps in a single section, 6.2-6,4-8overlaps in sections 4, 5, and 6.
(defn overlaps? [[l1 l2] [r1 r2]]
(or (<= l1 r1 l2) (<= l1 r2 l2)
(<= r1 l1 r2) (<= r1 l2 r2)))So, in this example, the number of overlapping assignment pairs is 4.
In how many assignment pairs do the ranges overlap?
(->> (filter (fn [[left right]] (overlaps? left right)) assignments)
count)The expedition can depart as soon as the final supplies have been unloaded from the ships. Supplies are stored in stacks of marked crates, but because the needed supplies are buried under many other crates, the crates need to be rearranged.
The ship has a giant cargo crane capable of moving crates between stacks. To ensure none of the crates get crushed or fall over, the crane operator will rearrange them in a series of carefully-planned steps. After the crates are rearranged, the desired crates will be at the top of each stack.
The Elves don’t want to interrupt the crane operator during this delicate procedure, but they forgot to ask her which crate will end up where, and they want to be ready to unload them as soon as possible so they can embark.
(def day5-data (slurp "resources/day5_input.txt"))They do, however, have a drawing of the starting stacks of crates and the rearrangement procedure (your puzzle input). For example:
[D] [N] [C] [Z] [M] [P] 1 2 3 move 1 from 2 to 1 move 3 from 1 to 3 move 2 from 2 to 1 move 1 from 1 to 2
In this example, there are three stacks of crates. Stack 1 contains two
crates: crate Z is on the bottom, and crate N is on top. Stack 2 contains
three crates; from bottom to top, they are crates M, C, and D. Finally, stack
3 contains a single crate, P.
(defn parse-stack-row [line]
;; Split line of format '[A] [B] [C]...' by 4 to get columns.
(let [parts (partition 4 4 [\space] line)]
(into []
(map (fn [n]
;; Filter the letter from each part or reduce to
;; a single ' ' if blank.
(if (every? #(= \space %) n)
\space
(first (filter (set "ABCDEFGHIJKLMNOPQRSTUVWXYZ") n))))
parts))))
(defn parse-instruction [line]
;; Convert the instruction lines 'move N from S to D' to
;; an int tuple3 of [N S D].
(into []
(take 3 (map #(Integer/parseInt %)
(re-seq #"\d+" line)))))
(defn transpose-stacks [stacks]
;; Convert the vertical stack string representation to an array
;; of stacks (linked list so conj/take operate on front.
(for [x (range (count (first stacks)))]
(remove #(= \space %) (map #(nth % x) stacks))))
(def day5-parsed-data
(let [lines (clojure.string/split-lines day5-data)]
{:crates (into []
(transpose-stacks
(map parse-stack-row
(filter #(clojure.string/includes? % "[")
lines))))
:instructions (into []
(map parse-instruction
(filter #(clojure.string/includes? % "move")
lines)))}))In the parsed data struct then, :crates is a vector of the stacks from 0..n,
and :instructions is a list of tuples of the form [count from to].
Then, the rearrangement procedure is given. In each step of the procedure, a quantity of crates is moved from one stack to a different stack. In the first step of the above rearrangement procedure, one crate is moved from stack 2 to stack 1, resulting in this configuration:
[D] [N] [C] [Z] [M] [P] 1 2 3
In the second step, three crates are moved from stack 1 to stack 3. Crates are
moved one at a time, so the first crate to be moved (D) ends up below the
second and third crates:
[Z]
[N]
[C] [D]
[M] [P]
1 2 3
Then, both crates are moved from stack 2 to stack 1. Again, because crates are
moved one at a time, crate C ends up below crate M:
[Z]
[N]
[M] [D]
[C] [P]
1 2 3
Finally, one crate is moved from stack 1 to stack 2:
[Z]
[N]
[D]
[C] [M] [P]
1 2 3
The Elves just need to know which crate will end up on top of each stack; in
this example, the top crates are C in stack 1, M in stack 2, and Z in stack 3,
so you should combine these together and give the Elves the message CMZ.
The generic operation here is that we will transform the stack of crates by performing the sequence of instructions successively on each new iteration. If we parameterize the step function, we can separately define what a single instruction must do, given the rules of the CrateMover-9000:
(defn run-all [step-fn crates instructions]
(reduce step-fn crates instructions))
(defn run-step-cm9000 [crates [n from to]]
;; Note: from,to are 1-indexed in the data.
(let [from (dec from)
to (dec to)
taken (take n (nth crates from))]
(-> crates
(update-in [from] #(drop n %))
(update-in [to] #(concat (reverse taken) %)))))After the rearrangement procedure completes, what crate ends up on top of each stack?
(run-all run-step-cm9000
(:crates day5-parsed-data)
(:instructions day5-parsed-data))(->> (run-all run-step-cm9000
(:crates day5-parsed-data)
(:instructions day5-parsed-data))
(map first)
(apply str))As you watch the crane operator expertly rearrange the crates, you notice the process isn’t following your prediction.
Some mud was covering the writing on the side of the crane, and you quickly wipe it away. The crane isn’t a CrateMover 9000 - it’s a CrateMover 9001.
The CrateMover 9001 is notable for many new and exciting features: air conditioning, leather seats, an extra cup holder, and the ability to pick up and move multiple crates at once.
Again considering the example above, the crates begin in the same configuration:
[D] [N] [C] [Z] [M] [P] 1 2 3
Moving a single crate from stack 2 to stack 1 behaves the same as before:
[D] [N] [C] [Z] [M] [P] 1 2 3
However, the action of moving three crates from stack 1 to stack 3 means that those three moved crates stay in the same order, resulting in this new configuration:
[D]
[N]
[C] [Z]
[M] [P]
1 2 3
Next, as both crates are moved from stack 2 to stack 1, they retain their order as well:
[D]
[N]
[C] [Z]
[M] [P]
1 2 3
Finally, a single crate is still moved from stack 1 to stack 2, but now it’s
crate C that gets moved:
[D]
[N]
[Z]
[M] [C] [P]
1 2 3
In this example, the CrateMover 9001 has put the crates in a totally
different order: MCD.
Before the rearrangement process finishes, update your simulation so that the Elves know where they should stand to be ready to unload the final supplies. After the rearrangement procedure completes, what crate ends up on top of each stack?
(defn run-step-cm9001 [crates [n from to]]
(let [from (dec from)
to (dec to)
taken (take n (nth crates from))]
(-> crates
(update-in [from] #(drop n %))
(update-in [to] #(concat taken %)))))(run-all run-step-cm9001
(:crates day5-parsed-data)
(:instructions day5-parsed-data))(->> (run-all run-step-cm9001
(:crates day5-parsed-data)
(:instructions day5-parsed-data))
(map first)
(apply str))The preparations are finally complete; you and the Elves leave camp on foot and begin to make your way toward the star fruit grove.
As you move through the dense undergrowth, one of the Elves gives you a handheld device. He says that it has many fancy features, but the most important one to set up right now is the communication system.
However, because he’s heard you have significant experience dealing with signal-based systems, he convinced the other Elves that it would be okay to give you their one malfunctioning device - surely you’ll have no problem fixing it.
As if inspired by comedic timing, the device emits a few colorful sparks.
To be able to communicate with the Elves, the device needs to lock on to their signal. The signal is a series of seemingly-random characters that the device receives one at a time.
To fix the communication system, you need to add a subroutine to the device that detects a start-of-packet marker in the datastream. In the protocol being used by the Elves, the start of a packet is indicated by a sequence of four characters that are all different.
The device will send your subroutine a datastream buffer (your puzzle input); your subroutine needs to identify the first position where the four most recently received characters were all different. Specifically, it needs to report the number of characters from the beginning of the buffer to the end of the first such four-character marker.
(def day6-data (slurp "resources/day6_input.txt"))For example, suppose you receive the following datastream buffer:
mjqjpqmgbljsphdztnvjfqwrcgsmlb
After the first three characters (mjq) have been received, there haven’t
been enough characters received yet to find the marker. The first time a
marker could occur is after the fourth character is received, making the most
recent four characters mjqj. Because j is repeated, this isn’t a marker.
The first time a marker appears is after the seventh character
arrives. Once it does, the last four characters received are jpqm, which
are all different. In this case, your subroutine should report the value 7,
because the first start-of-packet marker is complete after 7 characters have
been processed.
Here are a few more examples:
bvwbjplbgvbhsrlpgdmjqwftvncz: first marker after character5nppdvjthqldpwncqszvftbrmjlhg: first marker after character6nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg: first marker after character10zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw: first marker after character11
How many characters need to be processed before the first start-of-packet marker is detected?
(defn find-marker [buffer stride]
(loop [index stride
token (take stride buffer)
buffer (drop stride buffer)]
(if (= (count token) (count (set token)))
index
(recur (inc index)
(concat (rest token) [(first buffer)])
(rest buffer)))))(find-marker day6-data 4)Your device’s communication system is correctly detecting packets, but still isn’t working. It looks like it also needs to look for messages.
A start-of-message marker is just like a start-of-packet marker, except it consists of 14 distinct characters rather than 4.
Here are the first positions of start-of-message markers for all of the above examples:
mjqjpqmgbljsphdztnvjfqwrcgsmlb: first marker after character19bvwbjplbgvbhsrlpgdmjqwftvncz: first marker after character23nppdvjthqldpwncqszvftbrmjlhg: first marker after character23nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg: first marker after character29zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw: first marker after character26
How many characters need to be processed before the first start-of-message marker is detected?
(find-marker day6-data 14)List any support references, interesting reading.
Additional boilerplate code. Probably namespace declarations will live down here and not interfere with the readability of the narrative problems.
For a definition of constant data, we don’t need to echo the results back to the buffer, it’s fine that they are sent to the Clojure REPL.
(def ^:const numbers [3, 7, 12, 8, 23])Similarly, when defining a named function we can be satisfied that it exists in Clojure. All the result block would echo is the package and symbol name.
(defn add-two-numbers [a b]
(+ a b))When we want to query something or call a function, the default :results
type will be the value of the expression. Alternatively we could specify
:results output if we want to instead capture anything sent to
*standard-output*.
(map (partial add-two-numbers 5) numbers)(printf "Sum of numbers: %d"
(reduce add-two-numbers numbers))And that’s pretty much as simple as I’ll try to keep things.