diff --git a/2021/3/improved.go b/2021/3/improved.go new file mode 100644 index 0000000..f7bd0a7 --- /dev/null +++ b/2021/3/improved.go @@ -0,0 +1,154 @@ +package main + +import ( + aoc "AoC/2021/common" + "bufio" + "log" + "strconv" +) + +func main() { + part1() + part2() +} + +func count(entries []string, width int) [2][]int { + counts := [2][]int{make([]int, width), make([]int, width)} + + for _, entry := range entries { + for i, c := range entry { + if string(c) == "0" { + counts[0][i]++ + } else if string(c) == "1" { + counts[1][i]++ + } else { + log.Fatalf("Unknown character '%s'\n", string(c)) + } + } + } + + return counts +} + +func filter(entries []string, i int, value string) []string { + n := 0 + for _, num := range entries { + if string(num[i]) == value { + entries[n] = num + n++ + } + } + + return entries[:n] +} + +func process(input *bufio.Scanner) ([]string, int) { + var numbers []string + width := 0 + + for i :=0; input.Scan(); i++ { + line := input.Text() + numbers = append(numbers, line) + + if len(line) > width { + width = len(line) + } + } + + return numbers, width +} + +func part1() { + aoc := aoc.New(2021, 3) + + aoc.Test(` +00100 +11110 +10110 +10111 +10101 +01111 +00111 +11100 +10000 +11001 +00010 +01010 + `, 198) + + aoc.Solution(func (input *bufio.Scanner) int { + entries, width := process(input) + counts := count(entries, width) + + gamma := 0 + epsilon := 0 + for i := 0; i < width; i++ { + if counts[0][i] > counts[1][i] { + epsilon += 1 << (width - 1 - i) + } else { + gamma += 1 << (width - 1 - i) + } + } + + return gamma * epsilon + }) +} + +func part2() { + aoc := aoc.New(2021, 3) + + aoc.Test(` +00100 +11110 +10110 +10111 +10101 +01111 +00111 +11100 +10000 +11001 +00010 +01010 + `, 230) + + aoc.Solution(func (input *bufio.Scanner) int { + oxygen, width := process(input) + oxygenCounts := count(oxygen, width) + + co2 := make([]string, len(oxygen)); copy(co2, oxygen) + co2Counts := count(co2, width) + + for i := 0; i < width; i++ { + f1 := "1" + if oxygenCounts[0][i] > oxygenCounts[1][i] { + f1 = "0" + } + if len(oxygen) > 1 { + oxygen = filter(oxygen, i, f1) + oxygenCounts = count(oxygen, width) + } + + f2 := "0" + if co2Counts[0][i] > co2Counts[1][i] { + f2 = "1" + } + if len(co2) > 1 { + co2 = filter(co2, i, f2) + co2Counts = count(co2, width) + } + } + + oxygenNum, err := strconv.ParseInt(oxygen[0], 2, 0) + if err != nil { + panic(err) + } + + co2Num, err := strconv.ParseInt(co2[0], 2, 0) + if err != nil { + panic(err) + } + + return int(oxygenNum) * int(co2Num) + }) +}