2022 Day 6
Part 1
Problem
Read in a stream of characters and identify the first point at which 4 consecutive characters are unique.
General solution
This is trivial - we simply read it one line of the file, get the first 4 characters into a queue, and then check whether they are unique. If not, move the start point along by one and check the next four characters.
Solution: Go
Although we could read in a file character by character, this would potentially cause a lot of read requests. Given the small size of the input, we can just read in the entire file (one line) and then process it (even if we read the file one character at a time, the operating system may pull in more than one character into a buffer anyway). If the input was large or the system was severely memory-constrained, we could read the file one character at a time.
Once we have the input, we can move through it in chunks of 4 characters. Each character is added to a map of characters we have ‘seen’. If the count of seen characters is 4, then all the characters must be unique and therefore we can print the end index of the chunk (plus one as end indexes are exclusive).
package main
import (
"fmt"
"os"
"strings"
)
func main() {
const chunkLength = 4
// ASSUMPTION: There is only one line of input and no errors
byteInput, _ := os.ReadFile(os.Stdin.Name())
input := string(byteInput)
for start, end := 0, chunkLength-1; end < len(input); start, end = start+1, end+1 {
// Add one to end because second array slice index is exclusive
chunk := input[start : end+1]
characters := strings.Split(chunk, "")
seen := make(map[string]bool)
for c := range characters {
seen[characters[c]] = true
}
if len(seen) == chunkLength {
// All characters are unique
fmt.Println(end + 1)
os.Exit(0)
}
}
}
Part 2
Problem
As part 1, except find the first point at which 14 consecutive characters are unique.
General solution
Identical to part 1, except we examine 14 character chunks.
Solution: Go
Identical to part 1, except we change the chunk size (handily expressed as a constant - what foresight) to 14. The logic is the same as the loop calculates everything from the chunk size.
package main
import (
"fmt"
"os"
"strings"
)
func main() {
const chunkLength = 14
// ASSUMPTION: There is only one line of input and no errors
byteInput, _ := os.ReadFile(os.Stdin.Name())
input := string(byteInput)
for start, end := 0, chunkLength-1; end < len(input); start, end = start+1, end+1 {
// Add one to end because second array slice index is exclusive
chunk := input[start : end+1]
characters := strings.Split(chunk, "")
seen := make(map[string]bool)
for c := range characters {
seen[characters[c]] = true
}
if len(seen) == chunkLength {
// All characters are unique
fmt.Println(end + 1)
os.Exit(0)
}
}
}
Post-solution thoughts
Parts 1 & 2 could be part of a single file if the ‘search for unique chunk’ loop was moved into a function which took the input and chunk size as a parameter and returned the end point.