commit 07d24c2e8a5d1b4830bab7bc2b6e2889dc27da80 Author: onyx-and-iris Date: Sat Dec 2 15:07:04 2023 +0000 day-1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5bd2407 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work + +# input files +input.txt \ No newline at end of file diff --git a/day-1/go.mod b/day-1/go.mod new file mode 100644 index 0000000..9eb1bf5 --- /dev/null +++ b/day-1/go.mod @@ -0,0 +1,11 @@ +module github.com/onyx-and-iris/aoc2023/day-1 + +go 1.20 + +require github.com/stretchr/testify v1.8.4 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/day-1/go.sum b/day-1/go.sum new file mode 100644 index 0000000..fa4b6e6 --- /dev/null +++ b/day-1/go.sum @@ -0,0 +1,10 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/day-1/one.go b/day-1/one.go new file mode 100644 index 0000000..a32cc1d --- /dev/null +++ b/day-1/one.go @@ -0,0 +1,27 @@ +package main + +import ( + "fmt" + "regexp" + "strconv" +) + +// one takes a string array and for each line: +// Combine the first digit and the last digit (in that order) to form a single two-digit number. +// Returns the sum of all calibrated values. +func one(lines []string) (int, error) { + re := regexp.MustCompile(`\d`) + + sum := 0 + for _, line := range lines { + m := re.FindAllString(line, -1) + if len(m) > 0 { + num, err := strconv.Atoi(fmt.Sprintf("%s%s", m[0], m[len(m)-1])) + if err != nil { + return 0, err + } + sum += num + } + } + return sum, nil +} diff --git a/day-1/one_test.go b/day-1/one_test.go new file mode 100644 index 0000000..b33a0e7 --- /dev/null +++ b/day-1/one_test.go @@ -0,0 +1,22 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestOne(t *testing.T) { + //t.Skip("skipping test") + input := []string{ + "1abc2", + "pqr3stu8vwx", + "a1b2c3d4e5f", + "treb7uchet", + } + retval, _ := one(input) + + t.Run("Return the sum of all calibrated numbers, solution one", func(t *testing.T) { + assert.Equal(t, 142, retval) + }) +} diff --git a/day-1/run.sh b/day-1/run.sh new file mode 100755 index 0000000..3f6776a --- /dev/null +++ b/day-1/run.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +INPUT="input.txt" + +cat $INPUT | go run . \ No newline at end of file diff --git a/day-1/solution.go b/day-1/solution.go new file mode 100644 index 0000000..3ea39e6 --- /dev/null +++ b/day-1/solution.go @@ -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) +} diff --git a/day-1/two.go b/day-1/two.go new file mode 100644 index 0000000..048e4ba --- /dev/null +++ b/day-1/two.go @@ -0,0 +1,68 @@ +package main + +import ( + "fmt" + "regexp" + "strconv" +) + +var replaceMap = map[string]string{ + "one": "1", + "two": "2", + "three": "3", + "four": "4", + "five": "5", + "six": "6", + "seven": "7", + "eight": "8", + "nine": "9", +} + +var r = regexp.MustCompile(`\d|one|two|three|four|five|six|seven|eight|nine`) +var rr = regexp.MustCompile(`\d|eno|owt|eerht|ruof|evif|xis|neves|thgie|enin`) + +// forward parses a single line from start to last +// Match all substrings matching `\d|one|two|three|four|five|six|seven|eight|nine` +// Returns the first match +func forward(s string) string { + m_all := r.FindAllString(s, -1) + match := m_all[0] + match, ok := replaceMap[match] + if !ok { + match = m_all[0] + } + + return match +} + +// backward parses a single line in reverse order +// Match all substrings matching `\d|eno|owt|eerht|ruof|evif|xis|neves|thgie|enin` +// Returns the first match +func backward(s string) string { + m_all := rr.FindAllString(s, -1) + match := m_all[0] + match, ok := replaceMap[reverse(match)] + if !ok { + match = m_all[0] + } + + return match +} + +// two takes a string array and for each line: +// Search by regex all substrings matching numeric (and word representations of numeric) values. +// It then combines the first digit and the last digit (in that order) to form a single two-digit number. +// Returns the sum of all calibrated values. +func two(lines []string) (int, error) { + sum := 0 + for _, line := range lines { + m1 := forward(line) + m2 := backward(reverse(line)) + n, err := strconv.Atoi(fmt.Sprintf("%s%s", m1, m2)) + if err != nil { + return 0, err + } + sum += n + } + return sum, nil +} diff --git a/day-1/two_test.go b/day-1/two_test.go new file mode 100644 index 0000000..11acae3 --- /dev/null +++ b/day-1/two_test.go @@ -0,0 +1,25 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestTwo(t *testing.T) { + //t.Skip("skipping test") + input := []string{ + "two1nine", + "eightwothree", + "abcone2threexyz", + "xtwone3four", + "4nineeightseven2", + "zoneight234", + "7pqrstsixteen", + } + retval, _ := two(input) + + t.Run("Return the sum of all calibrated numbers, solution two", func(t *testing.T) { + assert.Equal(t, 281, retval) + }) +} diff --git a/day-1/util.go b/day-1/util.go new file mode 100644 index 0000000..d052dc3 --- /dev/null +++ b/day-1/util.go @@ -0,0 +1,32 @@ +package main + +import ( + "bufio" + "log" + "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 +} + +// reverse accepts a string and returns its reverse +func reverse(s string) (result string) { + for _, v := range s { + result = string(v) + result + } + return +} diff --git a/day-1/util_test.go b/day-1/util_test.go new file mode 100644 index 0000000..2929004 --- /dev/null +++ b/day-1/util_test.go @@ -0,0 +1,16 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestReverse(t *testing.T) { + //t.Skip("skipping test") + input := "eightwone3" + expected := "3enowthgie" + t.Run("Should reverse the string", func(t *testing.T) { + assert.Equal(t, expected, reverse(input)) + }) +}