Compare commits
No commits in common. "c87eb85e465b86e1b5902e31df4e32300a487be1" and "8e7fa3c5a8dc3ae3827aef0dc88d9e2203d52a4a" have entirely different histories.
c87eb85e46
...
8e7fa3c5a8
|
@ -1,30 +0,0 @@
|
||||||
name: Go Bump
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main" ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
bump:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
fetch-tags: true
|
|
||||||
|
|
||||||
- name: Deploy to external repository
|
|
||||||
uses: https://git.sour.is/actions/github-action-push-to-another-repository@main
|
|
||||||
env:
|
|
||||||
API_TOKEN_GITHUB: ${{ secrets.GH_TOKEN }}
|
|
||||||
with:
|
|
||||||
# GitHub Action output files
|
|
||||||
source-directory: .
|
|
||||||
destination-github-username: sour-is
|
|
||||||
destination-repository-name: go-pkg
|
|
||||||
user-email: jon@xuu.cc
|
|
||||||
# It defaults to `main`
|
|
||||||
target-branch: "main"
|
|
||||||
|
|
||||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
name: Go Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "main" ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
|
|
||||||
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!"
|
|
||||||
- run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
|
|
||||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
|
||||||
|
|
||||||
- name: List files in the repository
|
|
||||||
run: |
|
|
||||||
ls ${{ gitea.workspace }}
|
|
||||||
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v3
|
|
||||||
with:
|
|
||||||
go-version: 1.21.3
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: go test --race -cover ./...
|
|
||||||
|
|
||||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
|
|
@ -1,4 +0,0 @@
|
||||||
1abc2
|
|
||||||
pqr3stu8vwx
|
|
||||||
a1b2c3d4e5f
|
|
||||||
treb7uchet
|
|
|
@ -1,7 +0,0 @@
|
||||||
two1nine
|
|
||||||
eightwothree
|
|
||||||
abcone2threexyz
|
|
||||||
xtwone3four
|
|
||||||
4nineeightseven2
|
|
||||||
zoneight234
|
|
||||||
7pqrstsixteen
|
|
158
day01/main.go
158
day01/main.go
|
@ -2,41 +2,25 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
aoc "go.sour.is/advent-of-code-2023"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed input.txt
|
||||||
|
var input []byte
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result, err := aoc.Runner(run)
|
buf := bytes.NewReader(input)
|
||||||
if err != nil {
|
scan := bufio.NewScanner(buf)
|
||||||
fmt.Println("ERR", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
type result struct {
|
|
||||||
sum int
|
|
||||||
sum2 int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r result) String() string {
|
|
||||||
return fmt.Sprintln("result pt1:", r.sum, "\nresult pt2:", r.sum2)
|
|
||||||
}
|
|
||||||
|
|
||||||
var numbers = []string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
|
|
||||||
|
|
||||||
func run(scan *bufio.Scanner) (*result, error) {
|
|
||||||
result := &result{}
|
|
||||||
|
|
||||||
|
sum := 0
|
||||||
for scan.Scan() {
|
for scan.Scan() {
|
||||||
var first, last int
|
var first, last int
|
||||||
var first2, last2 int
|
|
||||||
|
orig := scan.Text()
|
||||||
|
_ = orig
|
||||||
|
|
||||||
text := scan.Text()
|
text := scan.Text()
|
||||||
|
|
||||||
|
@ -46,66 +30,110 @@ func run(scan *bufio.Scanner) (*result, error) {
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case slice[0] >= '0' && slice[0] <= '9':
|
case slice[0] >= '0' && slice[0] <= '9':
|
||||||
if first == 0 {
|
|
||||||
first = int(slice[0] - '0')
|
first = int(slice[0] - '0')
|
||||||
}
|
case strings.HasPrefix(string(slice), "one"):
|
||||||
if first2 == 0 {
|
first = 1
|
||||||
first2 = int(slice[0] - '0')
|
case strings.HasPrefix(string(slice), "two"):
|
||||||
}
|
first = 2
|
||||||
default:
|
case strings.HasPrefix(string(slice), "three"):
|
||||||
if first2 != 0 {
|
first = 3
|
||||||
continue
|
case strings.HasPrefix(string(slice), "four"):
|
||||||
}
|
first = 4
|
||||||
|
case strings.HasPrefix(string(slice), "five"):
|
||||||
|
first = 5
|
||||||
|
case strings.HasPrefix(string(slice), "six"):
|
||||||
|
first = 6
|
||||||
|
case strings.HasPrefix(string(slice), "seven"):
|
||||||
|
first = 7
|
||||||
|
case strings.HasPrefix(string(slice), "eight"):
|
||||||
|
first = 8
|
||||||
|
case strings.HasPrefix(string(slice), "nine"):
|
||||||
|
first = 9
|
||||||
|
|
||||||
for i, s := range numbers {
|
|
||||||
if strings.HasPrefix(string(slice), s) {
|
|
||||||
first2 = i
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
if first != 0 {
|
||||||
}
|
|
||||||
if first != 0 && first2 != 0 {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
text = string(aoc.Reverse([]rune(text)))
|
text = string(reverse([]rune(text)))
|
||||||
|
|
||||||
for i := range text {
|
for i := range text {
|
||||||
copy(slice, []rune(text[i:]))
|
copy(slice, []rune(text[i:]))
|
||||||
slice = aoc.Reverse(slice)
|
slice = reverse(slice)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case slice[4] >= '0' && slice[4] <= '9':
|
case slice[4] >= '0' && slice[4] <= '9':
|
||||||
if last == 0 {
|
|
||||||
last = int(slice[4] - '0')
|
last = int(slice[4] - '0')
|
||||||
|
case strings.HasSuffix(string(slice), "one"):
|
||||||
|
last = 1
|
||||||
|
case strings.HasSuffix(string(slice), "two"):
|
||||||
|
last = 2
|
||||||
|
case strings.HasSuffix(string(slice), "three"):
|
||||||
|
last = 3
|
||||||
|
case strings.HasSuffix(string(slice), "four"):
|
||||||
|
last = 4
|
||||||
|
case strings.HasSuffix(string(slice), "five"):
|
||||||
|
last = 5
|
||||||
|
case strings.HasSuffix(string(slice), "six"):
|
||||||
|
last = 6
|
||||||
|
case strings.HasSuffix(string(slice), "seven"):
|
||||||
|
last = 7
|
||||||
|
case strings.HasSuffix(string(slice), "eight"):
|
||||||
|
last = 8
|
||||||
|
case strings.HasSuffix(string(slice), "nine"):
|
||||||
|
last = 9
|
||||||
|
|
||||||
}
|
}
|
||||||
if last2 == 0 {
|
if last != 0 {
|
||||||
last2 = int(slice[4] - '0')
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if last2 != 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for i, s := range numbers {
|
|
||||||
if strings.HasSuffix(string(slice), s) {
|
|
||||||
last2 = i
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
sum += first*10 + last
|
||||||
if last != 0 && last2 != 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.sum += first*10 + last
|
|
||||||
result.sum2 += first2*10 + last2
|
|
||||||
}
|
}
|
||||||
if err := scan.Err(); err != nil {
|
if err := scan.Err(); err != nil {
|
||||||
return nil, err
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
fmt.Println(sum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reverse[T any](arr []T) []T{
|
||||||
|
for i := 0; i < len(arr)/2; i++ {
|
||||||
|
arr[i], arr[len(arr)-i-1] = arr[len(arr)-i-1], arr[i]
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// type sorter[T rune | int] []T
|
||||||
|
|
||||||
|
// func (s sorter[T]) Less(i, j int) bool { return s[i] < s[j] }
|
||||||
|
// func (s sorter[T]) Len() int { return len(s) }
|
||||||
|
// func (s sorter[T]) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
|
||||||
|
/*
|
||||||
|
0
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8
|
||||||
|
9
|
||||||
|
one
|
||||||
|
two
|
||||||
|
three
|
||||||
|
four
|
||||||
|
five
|
||||||
|
six
|
||||||
|
seven
|
||||||
|
eight
|
||||||
|
nine
|
||||||
|
ten
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
_ "embed"
|
|
||||||
|
|
||||||
"github.com/matryer/is"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed example1.txt
|
|
||||||
var example1 []byte
|
|
||||||
|
|
||||||
//go:embed example2.txt
|
|
||||||
var example2 []byte
|
|
||||||
|
|
||||||
//go:embed input.txt
|
|
||||||
var input []byte
|
|
||||||
|
|
||||||
func TestExample1(t *testing.T) {
|
|
||||||
is := is.New(t)
|
|
||||||
scan := bufio.NewScanner(bytes.NewReader(example1))
|
|
||||||
|
|
||||||
result, err := run(scan)
|
|
||||||
is.NoErr(err)
|
|
||||||
|
|
||||||
t.Log(result)
|
|
||||||
is.Equal(result.sum, 142)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func TestExample2(t *testing.T) {
|
|
||||||
is := is.New(t)
|
|
||||||
scan := bufio.NewScanner(bytes.NewReader(example2))
|
|
||||||
|
|
||||||
result, err := run(scan)
|
|
||||||
is.NoErr(err)
|
|
||||||
|
|
||||||
t.Log(result)
|
|
||||||
is.Equal(result.sum2, 281)
|
|
||||||
}
|
|
||||||
func TestInput(t *testing.T) {
|
|
||||||
is := is.New(t)
|
|
||||||
scan := bufio.NewScanner(bytes.NewReader(input))
|
|
||||||
|
|
||||||
result, err := run(scan)
|
|
||||||
is.NoErr(err)
|
|
||||||
|
|
||||||
t.Log(result)
|
|
||||||
is.Equal(result.sum, 54573)
|
|
||||||
is.Equal(result.sum2, 54591)
|
|
||||||
}
|
|
|
@ -2,39 +2,24 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
aoc "go.sour.is/advent-of-code-2023"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
//go:embed input.txt
|
||||||
result, err := aoc.Runner(run)
|
var input []byte
|
||||||
if err != nil {
|
|
||||||
aoc.Log("ERR", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
aoc.Log(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
type result struct {
|
|
||||||
sum int
|
|
||||||
powerSum int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r result) String() string {
|
|
||||||
return fmt.Sprintln("result pt1:", r.sum, "\nresult pt2:", r.powerSum)
|
|
||||||
}
|
|
||||||
|
|
||||||
type gameResult struct {
|
type gameResult struct {
|
||||||
red, green, blue int
|
red, green, blue int
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(scan *bufio.Scanner) (*result, error) {
|
func main() {
|
||||||
|
buf := bytes.NewReader(input)
|
||||||
|
scan := bufio.NewScanner(buf)
|
||||||
|
|
||||||
// only 12 red cubes, 13 green cubes, and 14 blue cubes
|
// only 12 red cubes, 13 green cubes, and 14 blue cubes
|
||||||
maxCounts := gameResult{
|
maxCounts := gameResult{
|
||||||
red: 12,
|
red: 12,
|
||||||
|
@ -77,8 +62,8 @@ func run(scan *bufio.Scanner) (*result, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aoc.Log(games)
|
fmt.Println(games)
|
||||||
aoc.Log(len(games))
|
fmt.Println(len(games))
|
||||||
|
|
||||||
sum := 0
|
sum := 0
|
||||||
powerSum := 0
|
powerSum := 0
|
||||||
|
@ -96,24 +81,24 @@ func run(scan *bufio.Scanner) (*result, error) {
|
||||||
mins.blue = max(mins.blue, round.blue)
|
mins.blue = max(mins.blue, round.blue)
|
||||||
|
|
||||||
if maxCounts.red < round.red {
|
if maxCounts.red < round.red {
|
||||||
aoc.Log("game", i, round, "too many red", round.red)
|
fmt.Println("game", i, round, "too many red", round.red)
|
||||||
ok = false
|
ok = false
|
||||||
} else if maxCounts.blue < round.blue {
|
} else if maxCounts.blue < round.blue {
|
||||||
aoc.Log("game", i, round, "too many blue", round.blue)
|
fmt.Println("game", i, round, "too many blue", round.blue)
|
||||||
ok = false
|
ok = false
|
||||||
} else if maxCounts.green < round.green {
|
} else if maxCounts.green < round.green {
|
||||||
aoc.Log("game", i, round, "too many green", round.green)
|
fmt.Println("game", i, round, "too many green", round.green)
|
||||||
ok = false
|
ok = false
|
||||||
}
|
}
|
||||||
aoc.Log("game", i, round, ok)
|
fmt.Println("game", i, round, ok)
|
||||||
}
|
}
|
||||||
if ok {
|
if ok {
|
||||||
sum += i
|
sum += i
|
||||||
aoc.Log("game", i, "passes", sum)
|
fmt.Println("game", i, "passes", sum)
|
||||||
}
|
}
|
||||||
power := mins.red*mins.blue*mins.green
|
power := mins.red*mins.blue*mins.green
|
||||||
aoc.Log("game", i, "mins", mins, power)
|
fmt.Println("game", i, "mins", mins, power)
|
||||||
powerSum += power
|
powerSum += power
|
||||||
}
|
}
|
||||||
return &result{sum, powerSum}, nil
|
fmt.Println("sum", sum, "power", powerSum)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
_ "embed"
|
|
||||||
|
|
||||||
"github.com/matryer/is"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed example.txt
|
|
||||||
var example []byte
|
|
||||||
|
|
||||||
//go:embed input.txt
|
|
||||||
var input []byte
|
|
||||||
|
|
||||||
func TestExample(t *testing.T) {
|
|
||||||
is := is.New(t)
|
|
||||||
scan := bufio.NewScanner(bytes.NewReader(example))
|
|
||||||
|
|
||||||
result, err := run(scan)
|
|
||||||
is.NoErr(err)
|
|
||||||
|
|
||||||
t.Log(result)
|
|
||||||
is.Equal(result.sum, 8)
|
|
||||||
is.Equal(result.powerSum, 2286)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSolution(t *testing.T) {
|
|
||||||
is := is.New(t)
|
|
||||||
scan := bufio.NewScanner(bytes.NewReader(input))
|
|
||||||
|
|
||||||
result, err := run(scan)
|
|
||||||
is.NoErr(err)
|
|
||||||
|
|
||||||
t.Log(result)
|
|
||||||
is.Equal(result.sum, 2317)
|
|
||||||
is.Equal(result.powerSum, 74804)
|
|
||||||
}
|
|
163
day08/main.go
163
day08/main.go
|
@ -5,12 +5,21 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
aoc "go.sour.is/advent-of-code-2023"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result, err := aoc.Runner(run)
|
if len(os.Args) != 2 {
|
||||||
|
fmt.Fprintln(os.Stderr, "Usage: day08 FILE")
|
||||||
|
}
|
||||||
|
|
||||||
|
input, err := os.Open(os.Args[1])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
scan := bufio.NewScanner(input)
|
||||||
|
|
||||||
|
result, err := run(scan)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("ERR", err)
|
fmt.Println("ERR", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -20,14 +29,10 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type result struct {
|
type result struct {
|
||||||
stepsPT1 uint64
|
stepsPT1 int
|
||||||
stepsPT2 uint64
|
stepsPT2 uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r result) String() string {
|
|
||||||
return fmt.Sprintf("solution 1: %v\nsolution 2: %v\n", r.stepsPT1, r.stepsPT2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func run(scan *bufio.Scanner) (*result, error) {
|
func run(scan *bufio.Scanner) (*result, error) {
|
||||||
var path []rune
|
var path []rune
|
||||||
m := make(nodeMap)
|
m := make(nodeMap)
|
||||||
|
@ -59,8 +64,8 @@ func run(scan *bufio.Scanner) (*result, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
steps1 := m.SolvePT1(path)
|
steps1 := SolutionPT1(m, path)
|
||||||
steps2 := m.SolvePT2(path)
|
steps2 := SolutionPT2(m, path)
|
||||||
|
|
||||||
return &result{steps1, steps2}, nil
|
return &result{steps1, steps2}, nil
|
||||||
}
|
}
|
||||||
|
@ -91,25 +96,26 @@ func (m nodeMap) mapNodes() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m nodeMap) solver(start string, isEnd func(string) bool, path []rune) uint64 {
|
func SolutionPT1(m nodeMap, path []rune) int {
|
||||||
position, ok := m[start]
|
fmt.Println("---- PART 1 BEGIN ----")
|
||||||
|
position, ok := m["AAA"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
var i int
|
var i int
|
||||||
var steps uint64
|
var steps int
|
||||||
|
|
||||||
for steps < ^uint64(0) {
|
for steps < 100000 {
|
||||||
steps++
|
steps++
|
||||||
if path[i] == 'R' {
|
if path[i] == 'R' {
|
||||||
// fmt.Println("step", steps, position.value, "R->", position.rvalue)
|
fmt.Println("step", steps, position.value, "R->", position.rvalue)
|
||||||
position = position.right
|
position = position.right
|
||||||
} else {
|
} else {
|
||||||
// fmt.Println("step", steps, position.value, "L->", position.lvalue)
|
fmt.Println("step", steps, position.value, "L->", position.lvalue)
|
||||||
position = position.left
|
position = position.left
|
||||||
}
|
}
|
||||||
|
|
||||||
if isEnd(position.value) {
|
if position.value == "ZZZ" {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,33 +124,126 @@ func (m nodeMap) solver(start string, isEnd func(string) bool, path []rune) uint
|
||||||
i = 0
|
i = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fmt.Println("---- PART 1 END ----")
|
||||||
return steps
|
return steps
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m nodeMap) SolvePT1(path []rune) uint64 {
|
func SolutionPT2(m nodeMap, path []rune) uint64 {
|
||||||
fmt.Println("---- PART 1 BEGIN ----")
|
|
||||||
defer fmt.Println("---- PART 1 END ----")
|
|
||||||
|
|
||||||
return m.solver("AAA", func(s string) bool { return s == "ZZZ" }, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m nodeMap) SolvePT2(path []rune) uint64 {
|
|
||||||
fmt.Println("---- PART 2 BEGIN ----")
|
fmt.Println("---- PART 2 BEGIN ----")
|
||||||
defer fmt.Println("---- PART 2 END ----")
|
|
||||||
|
|
||||||
var starts []*node
|
type loop struct {
|
||||||
|
start, position, end *node
|
||||||
|
steps uint64
|
||||||
|
}
|
||||||
|
loops := make(map[*node]loop)
|
||||||
|
|
||||||
|
endpoints := make(map[*node]struct{})
|
||||||
for k, n := range m {
|
for k, n := range m {
|
||||||
if strings.HasSuffix(k, "A") {
|
if strings.HasSuffix(k, "A") {
|
||||||
fmt.Println("start", k)
|
fmt.Println("start", k)
|
||||||
starts = append(starts, n)
|
loops[n] = loop{start: n, position: n}
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(k, "Z") {
|
||||||
|
fmt.Println("stop", k)
|
||||||
|
endpoints[n] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loops := make([]uint64, len(starts))
|
var i int
|
||||||
for i, n := range starts {
|
var steps uint64
|
||||||
loops[i] = m.solver(n.value, func(s string) bool { return strings.HasSuffix(s, "Z") }, path)
|
var stops int
|
||||||
|
maxUint := ^uint64(0)
|
||||||
|
loopsFound := 0
|
||||||
|
|
||||||
|
for steps < maxUint {
|
||||||
|
steps++
|
||||||
|
if path[i] == 'R' {
|
||||||
|
for k, loop := range loops {
|
||||||
|
// fmt.Println("step", steps, position.value, "R->", position.rvalue)
|
||||||
|
loop.position = loop.position.right
|
||||||
|
loops[k] = loop
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for k, loop := range loops {
|
||||||
|
// fmt.Println("step", steps, position.value, "L->", position.lvalue)
|
||||||
|
loop.position = loop.position.left
|
||||||
|
loops[k] = loop
|
||||||
}
|
}
|
||||||
return aoc.LCM(loops...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done := true
|
||||||
|
s := 0
|
||||||
|
for k, loop := range loops {
|
||||||
|
if _, ok := endpoints[loop.position]; !ok {
|
||||||
|
// fmt.Println("no stop", i, position.value)
|
||||||
|
done = false
|
||||||
|
// break
|
||||||
|
} else {
|
||||||
|
// fmt.Println("stop", i, position.value)
|
||||||
|
if loop.end == nil {
|
||||||
|
loop.end = loop.position
|
||||||
|
loop.steps = steps
|
||||||
|
fmt.Println("loop found", loop.position.value, "steps", steps)
|
||||||
|
loops[k] = loop
|
||||||
|
loopsFound++
|
||||||
|
}
|
||||||
|
s++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if loopsFound == len(loops) {
|
||||||
|
var values []uint64
|
||||||
|
for _, loop := range loops {
|
||||||
|
values = append(values, loop.steps)
|
||||||
|
}
|
||||||
|
return LCM(values...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s > stops {
|
||||||
|
stops = s
|
||||||
|
fmt.Println("stops", stops, "steps", steps)
|
||||||
|
}
|
||||||
|
|
||||||
|
if done {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
if i > len(path)-1 {
|
||||||
|
i = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("---- PART 2 END ----")
|
||||||
|
return steps
|
||||||
|
}
|
||||||
|
|
||||||
|
// greatest common divisor (GCD) via Euclidean algorithm
|
||||||
|
func GCD(a, b uint64) uint64 {
|
||||||
|
for b != 0 {
|
||||||
|
t := b
|
||||||
|
b = a % b
|
||||||
|
a = t
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
// find Least Common Multiple (LCM) via GCD
|
||||||
|
func LCM(integers ...uint64) uint64 {
|
||||||
|
if len(integers) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if len(integers) == 1 {
|
||||||
|
return integers[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
a, b := integers[0], integers[1]
|
||||||
|
result := a * b / GCD(a, b)
|
||||||
|
|
||||||
|
for _, c := range integers[2:] {
|
||||||
|
result = LCM(result, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ func TestExample1(t *testing.T) {
|
||||||
is.NoErr(err)
|
is.NoErr(err)
|
||||||
|
|
||||||
t.Log(result.stepsPT1)
|
t.Log(result.stepsPT1)
|
||||||
is.Equal(result.stepsPT1, uint64(2))
|
is.Equal(result.stepsPT1, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExample2(t *testing.T) {
|
func TestExample2(t *testing.T) {
|
||||||
|
@ -41,7 +41,7 @@ func TestExample2(t *testing.T) {
|
||||||
is.NoErr(err)
|
is.NoErr(err)
|
||||||
|
|
||||||
t.Log(result.stepsPT1)
|
t.Log(result.stepsPT1)
|
||||||
is.Equal(result.stepsPT1, uint64(6))
|
is.Equal(result.stepsPT1, 6)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExample3(t *testing.T) {
|
func TestExample3(t *testing.T) {
|
||||||
|
@ -63,18 +63,10 @@ func TestInput(t *testing.T) {
|
||||||
is.NoErr(err)
|
is.NoErr(err)
|
||||||
|
|
||||||
t.Log("part1 solution", result.stepsPT1)
|
t.Log("part1 solution", result.stepsPT1)
|
||||||
is.Equal(result.stepsPT1, uint64(14429))
|
is.Equal(result.stepsPT1, 14429)
|
||||||
|
|
||||||
t.Log("part2 solution", result.stepsPT2)
|
t.Log("part2 solution", result.stepsPT2)
|
||||||
is.Equal(result.stepsPT2, uint64(10921547990923))
|
is.Equal(result.stepsPT2, uint64(10921547990923))
|
||||||
}
|
}
|
||||||
|
|
||||||
// first: 14429
|
// first: 14429
|
||||||
// second: 10921547990923
|
// second: 10921547990923
|
||||||
|
|
||||||
// Brüt
|
|
||||||
// stops 1 steps 13201
|
|
||||||
// stops 2 steps 620447
|
|
||||||
// stops 3 steps 36606373
|
|
||||||
// stops 4 steps 2232988753
|
|
||||||
// stops 5 steps 149610246451
|
|
||||||
|
|
76
tools.go
76
tools.go
|
@ -1,76 +0,0 @@
|
||||||
package aoc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Runner[R any, F func(*bufio.Scanner) (R, error)](run F) (R, error) {
|
|
||||||
if len(os.Args) != 2 {
|
|
||||||
Log("Usage:", os.Args[0], "FILE")
|
|
||||||
os.Exit(22)
|
|
||||||
}
|
|
||||||
|
|
||||||
input, err := os.Open(os.Args[1])
|
|
||||||
if err != nil {
|
|
||||||
Log(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
scan := bufio.NewScanner(input)
|
|
||||||
return run(scan)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Log(v ...any) { fmt.Fprintln(os.Stderr, v...) }
|
|
||||||
func Logf(format string, v ...any) {
|
|
||||||
if !strings.HasSuffix(format, "\n") {
|
|
||||||
format += "\n"
|
|
||||||
}
|
|
||||||
fmt.Fprintf(os.Stderr, format, v...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Reverse[T any](arr []T) []T {
|
|
||||||
for i := 0; i < len(arr)/2; i++ {
|
|
||||||
arr[i], arr[len(arr)-i-1] = arr[len(arr)-i-1], arr[i]
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
type integer interface {
|
|
||||||
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64
|
|
||||||
}
|
|
||||||
// type float interface {
|
|
||||||
// complex64 | complex128 | float32 | float64
|
|
||||||
// }
|
|
||||||
// type number interface{ integer | float }
|
|
||||||
|
|
||||||
// greatest common divisor (GCD) via Euclidean algorithm
|
|
||||||
func GCD[T integer](a, b T) T {
|
|
||||||
for b != 0 {
|
|
||||||
t := b
|
|
||||||
b = a % b
|
|
||||||
a = t
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
// find Least Common Multiple (LCM) via GCD
|
|
||||||
func LCM[T integer](integers ...T) T {
|
|
||||||
if len(integers) == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if len(integers) == 1 {
|
|
||||||
return integers[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
a, b := integers[0], integers[1]
|
|
||||||
result := a * b / GCD(a, b)
|
|
||||||
|
|
||||||
for _, c := range integers[2:] {
|
|
||||||
result = LCM(result, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user