github.com/cycloss/advent-of-code@v0.0.0-20221210145555-15039b95faa6/2021/day3/day3.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"math"
     7  	"os"
     8  	"strconv"
     9  )
    10  
    11  const binLen = 40
    12  
    13  func main() {
    14  	file, err := os.Open("day3/bigboyDay3.txt")
    15  	if err != nil {
    16  		fmt.Println(err)
    17  		return
    18  	}
    19  	defer file.Close()
    20  	var nums = convertFileToInts(file)
    21  	fmt.Printf("Part 1 Solution: %d\n", solvePart1(nums))
    22  	fmt.Printf("Part 2 Solution: %d\n", solvePart2(nums))
    23  }
    24  
    25  func convertFileToInts(file *os.File) []int {
    26  	var buff = bufio.NewScanner(file)
    27  	var nums = []int{}
    28  	for buff.Scan() {
    29  		var line = buff.Text()
    30  		var num, _ = strconv.ParseInt(line, 2, 64)
    31  		nums = append(nums, int(num))
    32  	}
    33  	return nums
    34  }
    35  
    36  func solvePart1(nums []int) int {
    37  	var maskBit = 1
    38  	var gamma = 0
    39  	for i := 0; i < binLen; i++ {
    40  		gamma |= extractMostCommonBit(nums, maskBit)
    41  		maskBit <<= 1
    42  	}
    43  	var epsilon = ^gamma & int(math.Pow(2, binLen)-1)
    44  
    45  	return gamma * epsilon
    46  }
    47  
    48  func extractMostCommonBit(nums []int, maskBit int) int {
    49  	var count = 0
    50  	for _, v := range nums {
    51  		var bit = v & maskBit
    52  		if bit > 0 {
    53  			count++
    54  		} else {
    55  			count--
    56  		}
    57  	}
    58  	if count > 0 {
    59  		return maskBit
    60  	} else if count < 0 {
    61  		return 0
    62  	} else {
    63  		return -1
    64  	}
    65  }
    66  
    67  func solvePart2(nums []int) int {
    68  	var oxygenRating = reduceNumbers(nums, 1<<(binLen-1), oxygenFilter)
    69  	var scrubberRating = reduceNumbers(nums, 1<<(binLen-1), scrubberFilter)
    70  	return oxygenRating * scrubberRating
    71  }
    72  
    73  /// returns true if the filter is passed
    74  type filterFunc func(int, int, int) bool
    75  
    76  func reduceNumbers(nums []int, mask int, filter filterFunc) int {
    77  	if len(nums) == 1 {
    78  		return nums[0]
    79  	}
    80  	var commonBit = extractMostCommonBit(nums, mask)
    81  	var nums2 = []int{}
    82  	for _, v := range nums {
    83  		if filter(v, commonBit, mask) {
    84  			nums2 = append(nums2, v)
    85  		}
    86  	}
    87  	return reduceNumbers(nums2, mask>>1, filter)
    88  }
    89  
    90  func oxygenFilter(num int, commonBit int, mask int) bool {
    91  	if commonBit > 0 {
    92  		return (mask & num) != 0
    93  	} else if commonBit == 0 {
    94  		return (mask & num) == 0
    95  	} else {
    96  		return (mask & num) != 0
    97  	}
    98  }
    99  
   100  func scrubberFilter(num int, commonBit int, mask int) bool {
   101  	if commonBit > 0 {
   102  		return (mask & num) == 0
   103  	} else if commonBit == 0 {
   104  		return (mask & num) != 0
   105  	} else {
   106  		return (mask & num) == 0
   107  	}
   108  }