Advent Of Code 2022 - Day 06
Dec 06, 2022
It's December. Time for snow, slippery roads, hot chocolate and cozy fire places. Also time for Advent of Code. An advent calendar with small, daily programming puzzles, growing progressively more difficult.
Every year I participate in a programming language I did not use for Advent of Code before, in order to learn new ways of doing things and to challenge myself. This year, that language is F#.
Day 06: Tuning Trouble
Summary: Given a string, find the first location where four different characters have occurred in succession.
Example input:
ababcdefgabababa
In this example input the first sequence of four different characters is abcd
which ends at position 6
.
Find the full description here.
In order to find the first sequence of four different characters we have to look at every subsequence of four characters and determine if they are unique. My input was 4096 characters, so that's easily quick enough.
1. [a b a b]c d e f g a b a b a b a 2. a[b a b c]d e f g a b a b a b a 3. a b[a b c d]e f g a b a b a b a
After the third step we have found the unique sequence.
In F# we find a built-in function to do just this, List.windowed
, which
returns every subsequence of size n
in order.
There are various ways to check if a subsequence is unique. We can convert the
subsequence to a set and check its length. Or we can check the length of
List.distinct
. I went for the latter.
In order to find the first such sequence we can call List.findIndex
on the
result of List.windowed
.
Finally, because the question asks where the sequence ends, we have to add the length of the subsequence we're looking for to that index.
Combined, here's how that looks:
input |> Seq.windowed 4 |> Seq.findIndex (fun window -> Seq.distinct window |> Seq.length = 4) |> ((+) 4)
Part 2
Summary: Instead of finding the first sequence of four different characters, find the first sequence of fourteen different characters.
Since the input is quite small the same method is still easily fast enough. All we have to do is change some numbers.
input |> Seq.windowed 14 |> Seq.findIndex (fun window -> Seq.distinct window |> Seq.length = 14) |> ((+) 14)
Improvements
With so little code there's also very little to improve. All I changed was abstract into a single method, taking the size of the subsequence as an argument:
let findFirstUniqueSubsequence n seq = seq |> Seq.windowed n |> Seq.findIndex (fun window -> Seq.distinct window |> Seq.length = n) |> ((+) n)
Reflection
A surprisingly simple problem today. There have definitely been day 1 or day 2 problems that were more difficult than this one.
Personally I would have preferred the input to have been longer and more diverse, enabling for part 2 to ask for a much longer subsequence, so that the very straight forward implementation of windowing over the input would not be efficient enough. That would have made for a more interesting implementation and a more interesting post. Onto the next one!
The full code for the day is on GitHub