Advent of Code 2021 Day 3: Binary Diagnostic
By Andreas Røssland
https://adventofcode.com/2021/day/3 https://github.com/roessland/advent-of-code
Now it’s getting a bit more exciting.
Decided to keep it to strings instead of bit twiddling, but that’s an obvious improvement that can be done.
- Recursion is fun.
- Don’t like the “flip” argument to
find
but it’s the best I could come up with. - I would have gone for actual integers and bitwise operations if the number of bits in the input was a multiple of 8. (It’s 12). In hindsight the code would probably have worked just fine even with a bunch of leading zero bits!
package main
import (
"bufio"
"fmt" "log" "os" "strconv")
func part1(bins []string) {
N := len(bins)
K := len(bins[0])
oneCounts := make([]int, K)
for _, bin := range bins {
for i, bit := range bin {
if bit == '1' {
oneCounts[i]++
}
}
}
gammaRateStr := make([]byte, K)
epsilonStr := make([]byte, K)
for k := range gammaRateStr {
if oneCounts[k] > N/2 {
gammaRateStr[k] = '1'
epsilonStr[k] = '0'
} else {
gammaRateStr[k] = '0'
epsilonStr[k] = '1'
}
}
gammaRate, err := strconv.ParseUint(string(gammaRateStr), 2, 64)
if err != nil {
panic(fmt.Sprint(gammaRate))
}
epsilon, err := strconv.ParseUint(string(epsilonStr), 2, 64)
if err != nil {
panic("nah2")
}
fmt.Println(gammaRate*epsilon)
}
func find(bins []string, k int, flip bool) int {
if len(bins) == 1 {
rating, err := strconv.ParseUint(bins[0], 2, 64)
if err != nil {
panic("whoops")
}
return int(rating)
}
var oneCount int
for _, bin := range bins {
if bin[k] == '1' {
oneCount++
}
}
var mostCommon byte
criteria := oneCount >= len(bins) - oneCount
if flip {
criteria = !criteria
}
if criteria {
mostCommon = '1'
} else {
mostCommon = '0'
}
var filteredBins []string
for _, bin := range bins {
if bin[k] == mostCommon {
filteredBins = append(filteredBins, bin)
}
}
return find(filteredBins, k+1, flip)
}
func part2(bins []string) {
fmt.Println(find(bins, 0, false) * find(bins, 0, true))
}
func main() {
f, err := os.Open("input.txt")
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(f)
var bins []string
for scanner.Scan() {
line := scanner.Text()
bins = append(bins, line)
}
part1(bins)
part2(bins)
}