Add solution for day 3

This commit is contained in:
2021-12-03 14:14:36 +00:00
parent 95b0635e7a
commit 5fc7348bdf
5 changed files with 1224 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ import (
"strings" "strings"
"unsupervised.ca/aoc2021/one" "unsupervised.ca/aoc2021/one"
"unsupervised.ca/aoc2021/three"
"unsupervised.ca/aoc2021/two" "unsupervised.ca/aoc2021/two"
) )
@@ -28,6 +29,8 @@ func main() {
day = one.Init("one/input.txt") day = one.Init("one/input.txt")
case "two": case "two":
day = two.Init("two/input.txt") day = two.Init("two/input.txt")
case "three":
day = three.Init("three/input.txt")
default: default:
fmt.Printf("%q does not have a solution.\n", flagParts[1]) fmt.Printf("%q does not have a solution.\n", flagParts[1])
help() help()

144
three/diagnostic.go Normal file
View File

@@ -0,0 +1,144 @@
package three
import (
"bufio"
"os"
)
type report struct {
gammaRate int
epsilonRate int
oxygenRating int
co2Rating int
values []string
}
func (r *report) read(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
r.values = append(r.values, scanner.Text())
}
return nil
}
func (r *report) computePowerConsumption() {
if len(r.values) == 0 {
return
}
inputLength := len(r.values[0])
// Loop over every bit of the input
for i := 0; i < inputLength; i++ {
ones := 0
zeros := 0
// Loop over every value to determine the most and least common bit values
for _, value := range r.values {
if value[i] == '1' {
ones++
} else {
zeros++
}
}
if ones > zeros {
r.gammaRate = r.gammaRate<<1 + 1
r.epsilonRate = r.epsilonRate<<1 + 0
} else {
r.gammaRate = r.gammaRate<<1 + 0
r.epsilonRate = r.epsilonRate<<1 + 1
}
}
}
func (r *report) computeOxygenRating() {
if len(r.values) == 0 {
return
}
inputLength := len(r.values[0])
filtered := r.values
// Loop over every bit of the input
for i := 0; i < inputLength; i++ {
if len(filtered) == 1 {
break
}
ones := []string{}
zeros := []string{}
// Loop over every value to determine the most and least common bit values
for _, value := range filtered {
if value[i] == '1' {
ones = append(ones, value)
} else {
zeros = append(zeros, value)
}
}
if len(ones) >= len(zeros) {
filtered = ones
} else {
filtered = zeros
}
}
for _, b := range filtered[0] {
if b == '1' {
r.oxygenRating = r.oxygenRating<<1 + 1
} else {
r.oxygenRating = r.oxygenRating<<1 + 0
}
}
}
func (r *report) computeCO2Rating() {
if len(r.values) == 0 {
return
}
inputLength := len(r.values[0])
filtered := r.values
// Loop over every bit of the input
for i := 0; i < inputLength; i++ {
if len(filtered) == 1 {
break
}
ones := []string{}
zeros := []string{}
// Loop over every value to determine the most and least common bit values
for _, value := range filtered {
if value[i] == '1' {
ones = append(ones, value)
} else {
zeros = append(zeros, value)
}
}
if len(ones) < len(zeros) {
filtered = ones
} else {
filtered = zeros
}
}
for _, b := range filtered[0] {
if b == '1' {
r.co2Rating = r.co2Rating<<1 + 1
} else {
r.co2Rating = r.co2Rating<<1 + 0
}
}
}

43
three/diagnostic_test.go Normal file
View File

@@ -0,0 +1,43 @@
package three
import "testing"
var test_input = []string{
"00100",
"11110",
"10110",
"10111",
"10101",
"01111",
"00111",
"11100",
"10000",
"11001",
"00010",
"01010",
}
func Test_read(t *testing.T) {
r := report{}
if err := r.read("input.txt"); err != nil {
t.FailNow()
}
if len(r.values) != 1000 {
t.Logf("Expected 1000 values, found %d", len(r.values))
t.Fail()
}
}
func Test_computeCO2Rating(t *testing.T) {
r := report{
values: test_input,
}
r.computeCO2Rating()
if r.co2Rating != 10 {
t.Logf("Expected a CO2 rating of 10, got %d", r.co2Rating)
t.Fail()
}
}

1000
three/input.txt Normal file

File diff suppressed because it is too large Load Diff

34
three/main.go Normal file
View File

@@ -0,0 +1,34 @@
package three
import "fmt"
type Three struct {
report report
}
func Init(filepath string) *Three {
three := &Three{
report: report{},
}
three.report.read(filepath)
return three
}
func (d *Three) Answer() string {
d.report.computePowerConsumption()
return fmt.Sprintf("The power rates are gamma: %d, epsilon: %d, for %d total", d.report.gammaRate, d.report.epsilonRate, d.report.gammaRate*d.report.epsilonRate)
}
func (d *Three) FollowUp() string {
d.report.computeOxygenRating()
d.report.computeCO2Rating()
return fmt.Sprintf(
"The oxygen rating is %d and CO2 rating is %d, for a life support rating of %d",
d.report.oxygenRating,
d.report.co2Rating,
d.report.oxygenRating * d.report.co2Rating,
)
}