Intro

Today is day 6 I’m already a fifth of the way done with advent!

Yesterday’s puzzle was a noticeable step up in difficultiy so I’m hoping day 6 might be a little simpler.

I’m traveling today so I don’t have as much time to hack before work!

The Puzzle

Today the elves have given me a communicator but sadly it doesn’t quite work.

I can detect a broadcast signal, a long string, but I need to find a packet marking the beginning of a message: that packet is any 4 distinct characters in a row inside of the signal string.

If the signal is:

aaaabcdaaaaa

Then abcd would be the packet I’m looking for! The answer to the puzzle is to find the index after the end of the packet in the string. So for the above example it would be 7.

Input

This puzzle’s input is a loooong string representing the signal:

hrbbjllllspssblslvv....
It is a really long string!

Well getting the input toady is super trival. Once again I’m going to use slurp to get the contents of a text file.

(ns day6.core
  (:gen-class))

(def input (slurp "./advent-of-code/day6/input.txt"))

Right now onto the puzzle itself!

Part 1

Okay this actually doesn’t sounds too difficult. I can use partition to break the input down into smaller chunks, partition takes a size to group into and also an optional step which tells it how far to progress along the string for each partition. If I pass a step of one it’ll give me each group of 4 chars in the string.

(partition 4 1 "abcdefghijkl")
((\a \b \c \d) (\b \c \d \e) (\c \d \e \f) (\d \e \f \g) (\e \f \g \h) (\f \g \h \i) (\g \h \i \j) (\h \i \j \k) (\i \j \k \l))

Okay now I need to go through each of those until I find a sequence of 4 consecutive chars and return the index. I’m going to do this recursively so I can keep track of an index that I can increment every recursive call.

I’m going to write a function that looks at the first potential-packet, 4 chars, then uses distict to remove any duplicates. If after removing any duplicates there are still 4 chars then I’ve found the target packet! :-)

If I haven’t found the packet yet I’ll recur passing in the remaining potential packets and I’ll inc (increment by 1) and index to keep track of how far through I am. Finally I’m going to add a base case check for if we run out of packets because otherwise I risk stack overflows if I pass bad input. Better safe than sorry!

(defn find-packet-index
  ([potential-packets]
   (find-packet-index potential-packets 0))
  ([potential-packets index]
   (if (= 4
	(->> potential-packets
	     first
	     distinct
	     count))
     [index (first potential-packets)]
     (if (empty? potential-packets)
       "Failed"
       (recur
      (rest potential-packets)
      (inc index))))))
(find-packet-index (partition 4 1 "aaaabcdaaaaa"))
[3 (\a \b \c \d)]

Cool, I’ve decided to return a tuple just so I can also see what the packet was as well as the index for the start of the packet. The puzzle actually wanted the index for char after the packet so I need to grab the index from the tuple, then add an offset of 4 to get the end of the packet.

(defn part-1 [signal]
  (let [packet-size 4]
    (->> signal
	 (partition packet-size 1)
	 find-packet-index
	 first
	 (+ packet-size))))
(part-1 input)
1155

Sweet! Let me try that on the website!

That’s the right answer!

Nice! Let’s see what part 2 holds in store!

Part 2

Part 2’s extension to the puzzle is to now find a sequence of 14 unique and consecutive chars in the signal. Thankfully that should be a trivial change. Yesterday I was lazy and just did copy past instead of a small refactor. Today I’ll be a good responsible developer! :-)

I’m going to parameterise find-packet-index function so the length of consecutive chars can be passed in. Everything else will remain the same. Then I’ll update part-1 and write a part-2 function to pass in a packet size a parameter to find-packet-index:

(defn find-packet-index-param
  ([packet-size potential-packets] ;; extra param
   (find-packet-index-param packet-size potential-packets 0))
  ([packet-size potential-packets index] ;; extra param
   (if (= packet-size
	  (->> potential-packets
	       first
	       distinct
	       count))
     [index (first potential-packets)]
     (if (empty? potential-packets)
       "Failed"
       (recur
	packet-size
	(rest potential-packets)
	(inc index))))))

(defn part-2 [signal]
  (let [packet-size 14]
    (->> signal
	 (partition packet-size 1)
	 (find-packet-index-param packet-size)
	 first
	 (+ packet-size))))
(part-1 input)
(part-2 input)
1155
2789

Well looks like I didn’t break part 1 at least! Let’s try submitting 2789 for part 2…

You have completed Day 6!

Nice! Day 6 done and I’ve got more than enough time to get to the office! Today felt easier than yesterday. Probably because the input was much simpler to parse. I’m not complaining! :-)

If you’re interested, I’ve put the code for this puzzle and the other AoC challenges I’ve done on github.

Thanks for reading! :-)