AdventOfCode2021/03/main.go

103 lines
2.0 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"strconv"
"time"
)
func main() {
start := time.Now()
partOne()
duration := time.Since(start)
partTwo()
duration2 := time.Since(start)
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
}
func makeScanner(test bool) *bufio.Scanner {
var f *os.File
if test {
f, _ = os.Open("inputs/testinput")
} else {
f, _ = os.Open("inputs/input")
}
reader := bufio.NewReader(f)
return bufio.NewScanner(reader)
}
func partOne() {
scanner := makeScanner(false)
r := map[int]int64{} // index => count of 1s
var lines int64
for scanner.Scan() {
line := scanner.Text()
lines++
n, _ := strconv.ParseInt(line, 2, 64)
for i := 0; i < len(line); i++ {
// add the number (1 or 0) in the i'th place to r[i]
r[i] += (n & (1 << i)) >> i
}
}
var epsilon, gamma int64
for i, b := range r {
// if more than half the bits were ones, gamma gets the 1, otherwise epsilon gets the 1
// alternatively, this could have been an XOR operation, I suppose, once one or the other had been computed
if b > lines/2 {
gamma += 1 << i
} else {
epsilon += 1 << i
}
}
fmt.Println(epsilon * gamma)
}
func partTwo() {
scanner := makeScanner(false)
inputs := []int64{}
var oxgen, co2scrub int64
var bitlen int
for scanner.Scan() {
line := scanner.Text()
if bitlen == 0 {
bitlen = len(line)
}
n, _ := strconv.ParseInt(line, 2, 64)
inputs = append(inputs, n)
}
// on initial loop, oxgen>>i == n>>i etc always come out to 0 == 0
for i := bitlen; i > 0; i-- {
var oxOnes, oxZeroes, coOnes, coZeroes int64
for _, n := range inputs {
if oxgen>>i == n>>i {
if oxgen>>(i-1)^n>>(i-1) == 1 {
oxOnes++
} else {
oxZeroes++
}
}
if co2scrub>>i == n>>i {
if co2scrub>>(i-1)^n>>(i-1) == 1 {
coOnes++
} else {
coZeroes++
}
}
}
if oxOnes >= oxZeroes {
oxgen += (1 << (i - 1))
}
if (coZeroes == 0 && coOnes != 0) || (coOnes < coZeroes && coOnes != 0) {
co2scrub += (1 << (i - 1))
}
}
fmt.Println(oxgen * co2scrub)
}