Compare commits

...

4 Commits

Author SHA1 Message Date
78f122c850 remove redundant type. 2023-12-04 18:51:16 +00:00
f3985498ce use strings.FieldFunc
remove regex and parsing functions

upd compare test
2023-12-04 18:45:30 +00:00
8aa073b5ad day-4 2023-12-04 17:23:02 +00:00
714558f3c1 add test files to .gitignore 2023-12-04 17:20:48 +00:00
9 changed files with 193 additions and 0 deletions

1
.gitignore vendored
View File

@ -21,4 +21,5 @@
go.work
# input files
test*.txt
input.txt

5
day-4/go.mod Normal file
View File

@ -0,0 +1,5 @@
module github.com/onyx-and-iris/aoc2023/day-4
go 1.20
require github.com/go-playground/assert v1.2.1

2
day-4/go.sum Normal file
View File

@ -0,0 +1,2 @@
github.com/go-playground/assert v1.2.1 h1:ad06XqC+TOv0nJWnbULSlh3ehp5uLuQEojZY5Tq8RgI=
github.com/go-playground/assert v1.2.1/go.mod h1:Lgy+k19nOB/wQG/fVSQ7rra5qYugmytMQqvQ2dgjWn8=

35
day-4/one.go Normal file
View File

@ -0,0 +1,35 @@
package main
import (
"strings"
"unicode"
)
// one computes points based on matching numbers
func one(lines []string) (int, error) {
f := func(c rune) bool {
return !unicode.IsDigit(c)
}
sum := 0
cards = make([]Card, len(lines))
for x, line := range lines {
winning, mynums := func() (string, string) {
y := strings.Split(line, ":")
z := strings.Split(y[1], "|")
return z[0], z[1]
}()
m, err := compare(strings.FieldsFunc(winning, f), strings.FieldsFunc(mynums, f))
if err != nil {
return 0, err
}
cards[x].matches = m
if cards[x].matches > 0 {
sum += (pow(2, cards[x].matches-1))
}
}
return sum, nil
}

45
day-4/one_test.go Normal file
View File

@ -0,0 +1,45 @@
package main
import (
"strings"
"testing"
"unicode"
"github.com/go-playground/assert"
)
func TestCompare(t *testing.T) {
//t.Skip("skipping test")
input := []string{
"Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53",
"Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19",
}
winning1, mynums1 := func() (string, string) {
y := strings.Split(input[0], ":")
z := strings.Split(y[1], "|")
return z[0], z[1]
}()
winning2, mynums2 := func() (string, string) {
y := strings.Split(input[1], ":")
z := strings.Split(y[1], "|")
return z[0], z[1]
}()
f := func(c rune) bool {
return !unicode.IsDigit(c)
}
res1, _ := compare(strings.FieldsFunc(winning1, f), strings.FieldsFunc(mynums1, f))
res2, _ := compare(strings.FieldsFunc(winning2, f), strings.FieldsFunc(mynums2, f))
t.Run("Should return 4 matches", func(t *testing.T) {
assert.Equal(t, 4, res1)
})
t.Run("Should return 2 matches", func(t *testing.T) {
assert.Equal(t, 2, res2)
})
}

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

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

22
day-4/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)
}

27
day-4/two.go Normal file
View File

@ -0,0 +1,27 @@
package main
// Cards represents a single card.
// it tracks its matching numbers and occurrences
type Card struct {
matches int
occurrences int
}
var cards = []Card{}
// two returns the total number of occurrences for all cards
func two(lines []string) (int, error) {
var sum = 0
for i := range cards {
cards[i].occurrences++
for j := i + 1; j <= i+cards[i].matches; j++ {
cards[j].occurrences += cards[i].occurrences
}
sum += cards[i].occurrences
}
return sum, nil
}

51
day-4/util.go Normal file
View File

@ -0,0 +1,51 @@
package main
import (
"bufio"
"log"
"math"
"os"
)
// 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
}
// compare returns the number of matching elements
func compare(a []string, b []string) (int, error) {
n := 0
for _, elem := range a {
if contains(b, elem) {
n += 1
}
}
return n, nil
}
// contains returns true if a slice of elements contains a given element
func contains[T comparable](elems []T, v T) bool {
for _, s := range elems {
if v == s {
return true
}
}
return false
}
// pow returns the value of x to the n
func pow(x, n int) int {
return int(math.Pow(float64(x), float64(n)))
}