90 lines
2.6 KiB
Markdown
90 lines
2.6 KiB
Markdown
---
|
|
title: "Advent of Code: Day Six"
|
|
date: 2022-12-06T00:00:00
|
|
slug: advent-of-code-day-six
|
|
tags: [advent-of-code-2022]
|
|
---
|
|
**Spoilers for Advent of Code below**
|
|
|
|
* [Day five](/post/advent-of-code-day-five)
|
|
* [All Advent of Code posts](/blog/category/advent-of-code)
|
|
* [Source](https://github.com/lewisdaleuk/advent-of-code-2022)
|
|
|
|
Day six was a nice, welcome break from the struggle I had yesterday.
|
|
|
|
## Part one
|
|
|
|
Given a set of characters relaying a message, find the index of packet start signal, which comes after the first four unique characters.
|
|
|
|
So if my input is:
|
|
|
|
```txt
|
|
mjqjpqmgbljsphdztnvjfqwrcgsmlb
|
|
```
|
|
|
|
then my output should be `5`, because that is the index of the first set of unique characters - `qjpq`.
|
|
|
|
My first attempt was also my last attempt, as I used a `HashSet` of characters from a moving 5-char block. If the length was 5, that meant I'd found the index of my packet marker.
|
|
|
|
```rust
|
|
pub fn find_marker_index(input: &str) -> Option<usize> {
|
|
let mut set: HashSet<char> = HashSet::new();
|
|
|
|
for idx in 0..input.len() {
|
|
set = HashSet::from_iter(input[idx..=idx+4].chars());
|
|
if set.len() == 5 {
|
|
return Some(idx+4);
|
|
}
|
|
}
|
|
None
|
|
}
|
|
```
|
|
|
|
## Part two
|
|
|
|
Much the same, except now we need to also find a message start signal, which comes after `14` unique characters. I updated my `find_marker_index` function to take an offset, and updated the logic to use it. I also reversed my range, because I realised that I would quite easily hit string overflow issues - it was simply luck that I hadn't yet:
|
|
|
|
```rust
|
|
pub fn find_marker_index(input: &str, marker_offset: usize) -> Option<usize> {
|
|
let mut set: HashSet<char>;
|
|
|
|
for idx in marker_offset..input.len() {
|
|
set = HashSet::from_iter(input[idx-marker_offset..idx].chars());
|
|
if set.len() == marker_offset {
|
|
return Some(idx);
|
|
}
|
|
}
|
|
None
|
|
}
|
|
```
|
|
|
|
As a final pass, I moved my function to a `trait` implemented on `str`, because I'm trying to learn how to properly work with them:
|
|
|
|
```rust
|
|
pub trait FindUnique {
|
|
fn find_unique(&self, offset: usize) -> Option<usize>;
|
|
}
|
|
|
|
impl FindUnique for str {
|
|
fn find_unique(&self, offset: usize) -> Option<usize> {
|
|
for idx in offset..self.len() {
|
|
let len = HashSet::<char>::from_iter(self[idx - offset..idx].chars()).len();
|
|
if len == offset {
|
|
return Some(idx);
|
|
}
|
|
}
|
|
None
|
|
}
|
|
}
|
|
```
|
|
|
|
Which means I can now just call my function straight from reading the file:
|
|
|
|
```rust
|
|
if let Some(idx) = read_file(...).unwrap().find_unique(14) {
|
|
// Output
|
|
}
|
|
```
|
|
|
|
And that worked! Day six checked off, with a nice tidy solution that I'm very happy with.
|