This commit is contained in:
onyx-and-iris 2023-12-02 20:13:42 +00:00
parent 07d24c2e8a
commit bf97f15d04
8 changed files with 266 additions and 0 deletions

3
day-2/go.mod Normal file
View File

@ -0,0 +1,3 @@
module github.com/onyx-and-iris/aoc2023/day-2
go 1.20

65
day-2/one.go Normal file
View File

@ -0,0 +1,65 @@
package main
import (
"regexp"
"strconv"
"strings"
)
var regex = map[string]*regexp.Regexp{
"red": regexp.MustCompile(`(?P<red>\d+) red`),
"green": regexp.MustCompile(`(?P<green>\d+) green`),
"blue": regexp.MustCompile(`(?P<blue>\d+) blue`),
"game": regexp.MustCompile(`Game (?P<game>\d+)`),
}
var limits = map[string]int{
"red": 12,
"green": 13,
"blue": 14,
}
// isValidGame calculates if a game was possible based on the limits of each cube colour
func isValidGame(data string) (bool, error) {
valid := true
for _, colour := range []string{"red", "green", "blue"} {
m := regex[colour].FindAllStringSubmatch(data, -1)
for _, s := range m {
n, err := strconv.Atoi(s[1])
if err != nil {
return false, err
}
if n > limits[colour] {
valid = false
}
}
}
return valid, nil
}
// one returns the sum of ids for all games that were possible
func one(lines []string) (int, error) {
sum := 0
for _, line := range lines {
identifier, data := func() (string, string) {
x := strings.Split(line, ":")
return x[0], x[1]
}()
isValidGame, err := isValidGame(data)
if err != nil {
return 0, err
}
if isValidGame {
id, err := getIdForGame(identifier)
if err != nil {
return 0, err
}
sum += id
}
}
return sum, nil
}

41
day-2/one_test.go Normal file
View File

@ -0,0 +1,41 @@
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsValidGame(t *testing.T) {
//t.Skip("skipping test")
game1 := "3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green"
game2 := "1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue"
game3 := "8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red"
game4 := "1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red"
game5 := "6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"
isValid1, _ := isValidGame(game1)
isValid2, _ := isValidGame(game2)
isValid3, _ := isValidGame(game3)
isValid4, _ := isValidGame(game4)
isValid5, _ := isValidGame(game5)
t.Run("Should be a valid game", func(t *testing.T) {
assert.Equal(t, true, isValid1)
})
t.Run("Should be a valid game", func(t *testing.T) {
assert.Equal(t, true, isValid2)
})
t.Run("Should not be a valid game", func(t *testing.T) {
assert.Equal(t, false, isValid3)
})
t.Run("Should not be a valid game", func(t *testing.T) {
assert.Equal(t, false, isValid4)
})
t.Run("Should be a valid game", func(t *testing.T) {
assert.Equal(t, true, isValid5)
})
}

5
day-2/run.sh Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
INPUT="input.txt"
cat $INPUT | go run .

22
day-2/solution.go Normal file
View File

@ -0,0 +1,22 @@
package main
import (
"fmt"
"log"
)
func main() {
lines := readlines()
ans, err := one(lines)
if err != nil {
log.Fatal(err)
}
fmt.Printf("solution one: %d\n", ans)
ans, err = two(lines)
if err != nil {
log.Fatal(err)
}
fmt.Printf("solution two: %d\n", ans)
}

51
day-2/two.go Normal file
View File

@ -0,0 +1,51 @@
package main
import (
"strconv"
"strings"
)
// powerForGame returns the power of the minimum set of cubes for a game
func powerForGame(data string) (int, error) {
var counter = map[string]int{
"red": 0,
"green": 0,
"blue": 0,
}
for _, colour := range []string{"red", "green", "blue"} {
m := regex[colour].FindAllStringSubmatch(data, -1)
for _, s := range m {
n, err := strconv.Atoi(s[1])
if err != nil {
return 0, err
}
if counter[colour] == 0 {
counter[colour] = n
} else if counter[colour] < n {
counter[colour] = n
}
}
}
return counter["red"] * counter["green"] * counter["blue"], nil
}
// two returns the sum of powers for all games
func two(lines []string) (int, error) {
sum := 0
for _, line := range lines {
_, data := func() (string, string) {
x := strings.Split(line, ":")
return x[0], x[1]
}()
pow, err := powerForGame(data)
if err != nil {
return 0, err
}
sum += pow
}
return sum, nil
}

42
day-2/two_test.go Normal file
View File

@ -0,0 +1,42 @@
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestPowerForGame(t *testing.T) {
//t.Skip("skipping test")
game1 := "3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green"
game2 := "1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue"
game3 := "8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red"
game4 := "1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red"
game5 := "6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"
power1, _ := powerForGame(game1)
power2, _ := powerForGame(game2)
power3, _ := powerForGame(game3)
power4, _ := powerForGame(game4)
power5, _ := powerForGame(game5)
t.Run("Should have power value 48", func(t *testing.T) {
assert.Equal(t, 48, power1)
})
t.Run("Should have power value 12", func(t *testing.T) {
assert.Equal(t, 12, power2)
})
t.Run("Should have power value 1560", func(t *testing.T) {
assert.Equal(t, 1560, power3)
})
t.Run("Should have power value 630", func(t *testing.T) {
assert.Equal(t, 630, power4)
})
t.Run("Should have power value 36", func(t *testing.T) {
assert.Equal(t, 36, power5)
})
}

37
day-2/util.go Normal file
View File

@ -0,0 +1,37 @@
package main
import (
"bufio"
"log"
"os"
"strconv"
)
// readlines reads lines from stdin.
// Then it returns them as an array of strings
func readlines() []string {
lines := []string{}
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
return lines
}
// getIdForGame returns the id for a game
func getIdForGame(identifier string) (int, error) {
m := regex["game"].FindStringSubmatch(identifier)
i := regex["game"].SubexpIndex("game")
id, err := strconv.Atoi(m[i])
if err != nil {
return 0, err
}
return id, nil
}