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) }