Skip to content

Commit

Permalink
Advent of Code 2021 - Day 03 - Part 2 - OK
Browse files Browse the repository at this point in the history
  • Loading branch information
fdelbrayelle committed Dec 11, 2021
1 parent 3852a4b commit e061ff6
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 23 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode
11 changes: 0 additions & 11 deletions 2021/Day01/day01_test.go

This file was deleted.

41 changes: 40 additions & 1 deletion 2021/Day03/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,43 @@ Use the binary numbers in your diagnostic report to calculate the gamma rate and

Your puzzle answer was `3429254`.

**The first half of this puzzle is complete! It provides one gold star: ⭐**
**The first half of this puzzle is complete! It provides one gold star: ⭐**

## --- Part Two ---

Next, you should verify the life support rating, which can be determined by multiplying the **oxygen generator rating** by the **CO2 scrubber rating**.

Both the oxygen generator rating and the CO2 scrubber rating are values that can be found in your diagnostic report - finding them is the tricky part. Both values are located using a similar process that involves filtering out values until only one remains. Before searching for either rating value, start with the full list of binary numbers from your diagnostic report and **consider just the first bit** of those numbers. Then:

- Keep only numbers selected by the **bit criteria** for the type of rating value for which you are searching. Discard numbers which do not match the bit criteria.
- If you only have one number left, stop; this is the rating value for which you are searching.
- Otherwise, repeat the process, considering the next bit to the right.

The **bit criteria** depends on which type of rating value you want to find:

- To find **oxygen generator rating**, determine the most common value (`0` or `1`) in the current bit position, and keep only numbers with that bit in that position. If `0` and `1` are equally common, keep values with a `1` in the position being considered.
- To find **CO2 scrubber rating**, determine the **least common** value (`0` or `1`) in the current bit position, and keep only numbers with that bit in that position. If `0` and `1` are equally common, keep values with a `0` in the position being considered.

For example, to determine the **oxygen generator rating** value using the same example diagnostic report from above:

- Start with all 12 numbers and consider only the first bit of each number. There are more `1` bits (7) than `0` bits (5), so keep only the 7 numbers with a `1` in the first position: `11110`, `10110`, `10111`, `10101`, `11100`, `10000`, and `11001`.
- Then, consider the second bit of the 7 remaining numbers: there are more `0` bits (4) than `1` bits (3), so keep only the 4 numbers with a 0 in the second position: `10110`, `10111`, `10101`, and `10000`.
- In the third position, three of the four numbers have a `1`, so keep those three: `10110`, `10111`, and `10101`.
- In the fourth position, two of the three numbers have a `1`, so keep those two: `10110` and `10111`.
- In the fifth position, there are an equal number of `0` bits and `1` bits (one each). So, to find the **oxygen generator rating**, keep the number with a `1` in that position: `10111`.
- As there is only one number left, stop; the **oxygen generator rating** is `10111`, or **`23`** in decimal.

Then, to determine the **CO2 scrubber rating** value from the same example above:

- Start again with all 12 numbers and consider only the first bit of each number. There are fewer `0` bits (5) than `1` bits (7), so keep only the 5 numbers with a `0` in the first position: `00100`, `01111`, `00111`, `00010`, and `01010`.
- Then, consider the second bit of the 5 remaining numbers: there are fewer `1` bits (2) than `0` bits (3), so keep only the 2 numbers with a `1` in the second position: `01111` and `01010`.
- In the third position, there are an equal number of `0` bits and `1` bits (one each). So, to find the **CO2 scrubber rating**, keep the number with a `0` in that position: `01010`.
- As there is only one number left, stop; the **CO2 scrubber rating** is `01010`, or `10` in decimal.

Finally, to find the life support rating, multiply the oxygen generator rating (`23`) by the CO2 scrubber rating (`10`) to get 230.

Use the binary numbers in your diagnostic report to calculate the oxygen generator rating and CO2 scrubber rating, then multiply them together. What is the life support rating of the submarine? (Be sure to represent your answer in decimal, not binary.)

Your puzzle answer was `5410338`.

**Both parts of this puzzle are complete! They provide two gold stars: ⭐⭐**
90 changes: 79 additions & 11 deletions 2021/Day03/day03.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,71 @@ func main() {
fmt.Println("ioutil.ReadFile Err")
}
lines := strings.Split(string(content), "\n")
part1(lines)
part2(lines)
}

func part1(lines []string) {
bit0Counts, bit1Counts := getBitCounts(lines)
var gammaRate []string
for i := 0; i < len(bit0Counts); i++ {
if bit0Counts[i] >= bit1Counts[i] {
gammaRate = append(gammaRate, "0")
} else {
gammaRate = append(gammaRate, "1")
}
}
epsilonRate := revertGammaRate(gammaRate)
gammaRateInt, _ := strconv.ParseInt(strings.Join(gammaRate, ""), 2, 64)
epsilonRateInt, _ := strconv.ParseInt(strings.Join(epsilonRate, ""), 2, 64)
fmt.Println("Part 1 result is:", gammaRateInt*epsilonRateInt)
}

func part2(lines []string) int64 {
ogr, _ := strconv.ParseInt(getOxygenGeneratorRating(lines, 0), 2, 64)
csr, _ := strconv.ParseInt(getCO2ScrubberRating(lines, 0), 2, 64)
result := ogr * csr
fmt.Println("Part 2 result is:", result)
return result
}

func getOxygenGeneratorRating(lines []string, rowIdx int) string {
bit0Counts, bit1Counts := getBitCounts(lines)
if len(lines) == 1 {
return lines[0]
}
var remainingLines = make([]string, 0)
mostCommonBitInRow := mostCommonBit(bit0Counts, bit1Counts, rowIdx)
for _, line := range lines {
if len(line) == 0 {
continue
}
if strings.Split(line, "")[rowIdx] == mostCommonBitInRow {
remainingLines = append(remainingLines, line)
}
}
return getOxygenGeneratorRating(remainingLines, rowIdx+1)
}

func getCO2ScrubberRating(lines []string, rowIdx int) string {
bit0Counts, bit1Counts := getBitCounts(lines)
if len(lines) == 1 {
return lines[0]
}
var remainingLines = make([]string, 0)
leastCommonBitInRow := leastCommonBit(bit0Counts, bit1Counts, rowIdx)
for _, line := range lines {
if len(line) == 0 {
continue
}
if strings.Split(line, "")[rowIdx] == leastCommonBitInRow {
remainingLines = append(remainingLines, line)
}
}
return getCO2ScrubberRating(remainingLines, rowIdx+1)
}

func getBitCounts(lines []string) (map[int]int, map[int]int) {
var bit0Counts = make(map[int]int)
var bit1Counts = make(map[int]int)
for _, line := range lines {
Expand All @@ -28,18 +93,21 @@ func main() {
}
}
}
var gammaRate []string
for i := 0; i < len(bit0Counts); i++ {
if bit0Counts[i] >= bit1Counts[i] {
gammaRate = append(gammaRate, "0")
} else {
gammaRate = append(gammaRate, "1")
}
return bit0Counts, bit1Counts
}

func mostCommonBit(bit0Counts map[int]int, bit1Counts map[int]int, row int) string {
if bit0Counts[row] <= bit1Counts[row] {
return "1"
}
epsilonRate := revertGammaRate(gammaRate)
gammaRateInt, _ := strconv.ParseInt(strings.Join(gammaRate, ""), 2, 64)
epsilonRateInt, _ := strconv.ParseInt(strings.Join(epsilonRate, ""), 2, 64)
fmt.Println("Part 1 result is:", gammaRateInt*epsilonRateInt)
return "0"
}

func leastCommonBit(bit0Counts map[int]int, bit1Counts map[int]int, row int) string {
if bit0Counts[row] <= bit1Counts[row] {
return "0"
}
return "1"
}

func revertGammaRate(gammaRate []string) []string {
Expand Down
84 changes: 84 additions & 0 deletions 2021/Day03/day03_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package main

import "testing"

func TestPart2(t *testing.T) {
// Given
lines := []string{
"00100",
"11110",
"10110",
"10111",
"10101",
"01111",
"00111",
"11100",
"10000",
"11001",
"00010",
"01010"}
var expectedLifeSupportRating int64 = 230

// When
var actualLifeSupportRating int64 = part2(lines)

// Then
if actualLifeSupportRating != expectedLifeSupportRating {
t.Errorf("Life support rating was incorrect, actual: %d, expected: %d",
actualLifeSupportRating, expectedLifeSupportRating)
}
}

func TestGetOxygenGeneratorRating(t *testing.T) {
// Given
lines := []string{
"00100",
"11110",
"10110",
"10111",
"10101",
"01111",
"00111",
"11100",
"10000",
"11001",
"00010",
"01010"}
expectedOxygenGeneratorRating := "10111"

// When
actualOxygenGeneratorRating := getOxygenGeneratorRating(lines, 0)

// Then
if actualOxygenGeneratorRating != expectedOxygenGeneratorRating {
t.Errorf("Oxygen generator rating was incorrect, actual: %s, expected: %s",
actualOxygenGeneratorRating, expectedOxygenGeneratorRating)
}
}

func TestGetCO2ScrubberRating(t *testing.T) {
// Given
lines := []string{
"00100",
"11110",
"10110",
"10111",
"10101",
"01111",
"00111",
"11100",
"10000",
"11001",
"00010",
"01010"}
expectedCO2ScrubberRating := "01010"

// When
actualCO2ScrubberRating := getCO2ScrubberRating(lines, 0)

// Then
if actualCO2ScrubberRating != expectedCO2ScrubberRating {
t.Errorf("CO2 scrubber rating was incorrect, actual: %s, expected: %s",
actualCO2ScrubberRating, expectedCO2ScrubberRating)
}
}

0 comments on commit e061ff6

Please sign in to comment.