Merge branch 'main' into day07-enhance
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Go Test / build (pull_request) Successful in 37s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Go Test / build (pull_request) Successful in 37s
				
			This commit is contained in:
		
						commit
						3e0ed68db3
					
				
							
								
								
									
										30
									
								
								.gitea/workflows/github-mirror.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								.gitea/workflows/github-mirror.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
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.API_TOKEN_GITHUB }}
 | 
			
		||||
      with:
 | 
			
		||||
        # GitHub Action output files
 | 
			
		||||
        source-directory: .
 | 
			
		||||
        destination-github-username: jonlundy
 | 
			
		||||
        destination-repository-name: advent-of-code
 | 
			
		||||
        user-email: jon@xuu.cc
 | 
			
		||||
        # It defaults to `main`
 | 
			
		||||
        target-branch: "main"
 | 
			
		||||
 | 
			
		||||
    - run: echo "🍏 This job's status is ${{ job.status }}."
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								.gitea/workflows/test.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								.gitea/workflows/test.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
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 }}."
 | 
			
		||||
							
								
								
									
										4
									
								
								day01/example1.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								day01/example1.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
1abc2
 | 
			
		||||
pqr3stu8vwx
 | 
			
		||||
a1b2c3d4e5f
 | 
			
		||||
treb7uchet
 | 
			
		||||
							
								
								
									
										7
									
								
								day01/example2.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								day01/example2.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
two1nine
 | 
			
		||||
eightwothree
 | 
			
		||||
abcone2threexyz
 | 
			
		||||
xtwone3four
 | 
			
		||||
4nineeightseven2
 | 
			
		||||
zoneight234
 | 
			
		||||
7pqrstsixteen
 | 
			
		||||
							
								
								
									
										151
									
								
								day01/main.go
									
									
									
									
									
								
							
							
						
						
									
										151
									
								
								day01/main.go
									
									
									
									
									
								
							@ -2,25 +2,32 @@ package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//go:embed input.txt
 | 
			
		||||
var input []byte
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	buf := bytes.NewReader(input)
 | 
			
		||||
	scan := bufio.NewScanner(buf)
 | 
			
		||||
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() {
 | 
			
		||||
		var first, last int
 | 
			
		||||
 | 
			
		||||
		orig := scan.Text()
 | 
			
		||||
		_ = orig
 | 
			
		||||
		var first2, last2 int
 | 
			
		||||
 | 
			
		||||
		text := scan.Text()
 | 
			
		||||
 | 
			
		||||
@ -30,110 +37,66 @@ func main() {
 | 
			
		||||
 | 
			
		||||
			switch {
 | 
			
		||||
			case slice[0] >= '0' && slice[0] <= '9':
 | 
			
		||||
				first = int(slice[0] - '0')
 | 
			
		||||
			case strings.HasPrefix(string(slice), "one"):
 | 
			
		||||
				first = 1
 | 
			
		||||
			case strings.HasPrefix(string(slice), "two"):
 | 
			
		||||
				first = 2
 | 
			
		||||
			case strings.HasPrefix(string(slice), "three"):
 | 
			
		||||
				first = 3
 | 
			
		||||
			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
 | 
			
		||||
				if first == 0 {
 | 
			
		||||
					first = int(slice[0] - '0')
 | 
			
		||||
				}
 | 
			
		||||
				if first2 == 0 {
 | 
			
		||||
					first2 = int(slice[0] - '0')
 | 
			
		||||
				}
 | 
			
		||||
			default:
 | 
			
		||||
				if first2 != 0 {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				for i, s := range numbers {
 | 
			
		||||
					if strings.HasPrefix(string(slice), s) {
 | 
			
		||||
						first2 = i
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if first != 0 {
 | 
			
		||||
			if first != 0 && first2 != 0 {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		text = string(reverse([]rune(text)))
 | 
			
		||||
		text = string(aoc.Reverse([]rune(text)))
 | 
			
		||||
 | 
			
		||||
		for i := range text {
 | 
			
		||||
			copy(slice, []rune(text[i:]))
 | 
			
		||||
			slice = reverse(slice)
 | 
			
		||||
			slice = aoc.Reverse(slice)
 | 
			
		||||
 | 
			
		||||
			switch {
 | 
			
		||||
			case slice[4] >= '0' && slice[4] <= '9':
 | 
			
		||||
				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 last == 0 {
 | 
			
		||||
					last = int(slice[4] - '0')
 | 
			
		||||
				}
 | 
			
		||||
				if last2 == 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
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
			if last != 0 {
 | 
			
		||||
			if last != 0 && last2 != 0 {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sum += first*10 + last
 | 
			
		||||
		result.sum += first*10 + last
 | 
			
		||||
		result.sum2 += first2*10 + last2
 | 
			
		||||
	}
 | 
			
		||||
	if err := scan.Err(); err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Println(sum)
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										54
									
								
								day01/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								day01/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
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,24 +2,39 @@ package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//go:embed input.txt
 | 
			
		||||
var input []byte
 | 
			
		||||
func main() {
 | 
			
		||||
	result, err := aoc.Runner(run)
 | 
			
		||||
	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 {
 | 
			
		||||
	red, green, blue int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	buf := bytes.NewReader(input)
 | 
			
		||||
	scan := bufio.NewScanner(buf)
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	// only 12 red cubes, 13 green cubes, and 14 blue cubes
 | 
			
		||||
	maxCounts := gameResult{
 | 
			
		||||
		red:   12,
 | 
			
		||||
@ -36,12 +51,10 @@ func main() {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		games = append(games, []gameResult{})
 | 
			
		||||
		rounds := aoc.SliceMap(func(text string) gameResult {
 | 
			
		||||
			round := gameResult{}
 | 
			
		||||
 | 
			
		||||
		for _, round := range strings.Split(text, ";") {
 | 
			
		||||
			game := gameResult{}
 | 
			
		||||
 | 
			
		||||
			for _, result := range strings.Split(round, ",") {
 | 
			
		||||
			for _, result := range strings.Split(text, ",") {
 | 
			
		||||
				ns, color, _ := strings.Cut(strings.TrimSpace(result), " ")
 | 
			
		||||
				n, err := strconv.Atoi(ns)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
@ -50,20 +63,21 @@ func main() {
 | 
			
		||||
 | 
			
		||||
				switch color {
 | 
			
		||||
				case "red":
 | 
			
		||||
					game.red = n
 | 
			
		||||
					round.red = n
 | 
			
		||||
				case "green":
 | 
			
		||||
					game.green = n
 | 
			
		||||
					round.green = n
 | 
			
		||||
				case "blue":
 | 
			
		||||
					game.blue = n
 | 
			
		||||
					round.blue = n
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
			games[len(games)-1] = append(games[len(games)-1], game)
 | 
			
		||||
		}
 | 
			
		||||
			return round
 | 
			
		||||
		}, strings.Split(text, ";")...)
 | 
			
		||||
 | 
			
		||||
		games = append(games, rounds)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Println(games)
 | 
			
		||||
	fmt.Println(len(games))
 | 
			
		||||
	aoc.Log(games)
 | 
			
		||||
	aoc.Log(len(games))
 | 
			
		||||
 | 
			
		||||
	sum := 0
 | 
			
		||||
	powerSum := 0
 | 
			
		||||
@ -81,24 +95,24 @@ func main() {
 | 
			
		||||
			mins.blue = max(mins.blue, round.blue)
 | 
			
		||||
 | 
			
		||||
			if maxCounts.red < round.red {
 | 
			
		||||
				fmt.Println("game", i, round, "too many red", round.red)
 | 
			
		||||
				aoc.Log("game", i, round, "too many red", round.red)
 | 
			
		||||
				ok = false
 | 
			
		||||
			} else if maxCounts.blue < round.blue {
 | 
			
		||||
				fmt.Println("game", i, round, "too many blue", round.blue)
 | 
			
		||||
				aoc.Log("game", i, round, "too many blue", round.blue)
 | 
			
		||||
				ok = false
 | 
			
		||||
			} else if maxCounts.green < round.green {
 | 
			
		||||
				fmt.Println("game", i, round, "too many green", round.green)
 | 
			
		||||
				aoc.Log("game", i, round, "too many green", round.green)
 | 
			
		||||
				ok = false
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Println("game", i, round, ok)
 | 
			
		||||
			aoc.Log("game", i, round, ok)
 | 
			
		||||
		}
 | 
			
		||||
		if ok {
 | 
			
		||||
			sum += i
 | 
			
		||||
			fmt.Println("game", i, "passes", sum)
 | 
			
		||||
			aoc.Log("game", i, "passes", sum)
 | 
			
		||||
		}
 | 
			
		||||
		power := mins.red*mins.blue*mins.green
 | 
			
		||||
		fmt.Println("game", i, "mins", mins, power)
 | 
			
		||||
		power := mins.red * mins.blue * mins.green
 | 
			
		||||
		aoc.Log("game", i, "mins", mins, power)
 | 
			
		||||
		powerSum += power
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Println("sum", sum, "power", powerSum)
 | 
			
		||||
	return &result{sum, powerSum}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										41
									
								
								day02/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								day02/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
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)
 | 
			
		||||
}
 | 
			
		||||
@ -2,14 +2,14 @@ package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//go:embed input.txt
 | 
			
		||||
var input []byte
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type partNumber struct {
 | 
			
		||||
	number    int
 | 
			
		||||
@ -56,10 +56,12 @@ func (tab symbolTab) scanSymbol(p partNumber) bool {
 | 
			
		||||
// 553079
 | 
			
		||||
// 84363105
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	buf := bytes.NewReader(input)
 | 
			
		||||
	scan := bufio.NewScanner(buf)
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	parts := []partNumber{}
 | 
			
		||||
	symbols := make(symbolTab)
 | 
			
		||||
	symbolList := []*symbol{}
 | 
			
		||||
@ -95,28 +97,32 @@ func main() {
 | 
			
		||||
		if v, err := strconv.Atoi(string(slice)); err == nil {
 | 
			
		||||
			parts = append(parts, partNumber{number: v, row: row, col: col - len(slice), end: col - 1})
 | 
			
		||||
			slice = slice[:0]
 | 
			
		||||
			_ = slice
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sum := 0
 | 
			
		||||
	for i, p := range parts {
 | 
			
		||||
		ok := symbols.scanSymbol(p)
 | 
			
		||||
		parts[i].hasSymbol = ok
 | 
			
		||||
		if ok {
 | 
			
		||||
			sum += p.number
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	sum := aoc.SumIFunc(
 | 
			
		||||
		func(i int, p partNumber) int {
 | 
			
		||||
			ok := symbols.scanSymbol(p)
 | 
			
		||||
			parts[i].hasSymbol = ok
 | 
			
		||||
			if ok {
 | 
			
		||||
				return p.number
 | 
			
		||||
			}
 | 
			
		||||
			return 0
 | 
			
		||||
		}, parts...)
 | 
			
		||||
 | 
			
		||||
	sumGears := 0
 | 
			
		||||
	for _, s := range symbolList {
 | 
			
		||||
		if s.symbol == '*' && len(s.adjacentParts) == 2 {
 | 
			
		||||
			sumGears += s.adjacentParts[0].number * s.adjacentParts[1].number
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	sumGears := aoc.SumFunc(
 | 
			
		||||
		func(s *symbol) int {
 | 
			
		||||
			if s.symbol == '*' && len(s.adjacentParts) == 2 {
 | 
			
		||||
				return s.adjacentParts[0].number * s.adjacentParts[1].number
 | 
			
		||||
			}
 | 
			
		||||
			return 0
 | 
			
		||||
		}, symbolList...)
 | 
			
		||||
 | 
			
		||||
	// fmt.Println(parts)
 | 
			
		||||
	// fmt.Println(symbols)
 | 
			
		||||
	// fmt.Println(symbolList)
 | 
			
		||||
	fmt.Println("part1:", sum)
 | 
			
		||||
	fmt.Println("part2:", sumGears)
 | 
			
		||||
	return &result{sum, sumGears}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										43
									
								
								day03/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								day03/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"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.valuePT1, int(4361))
 | 
			
		||||
 | 
			
		||||
	is.Equal(result.valuePT2, 467835)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.valuePT1)
 | 
			
		||||
	is.Equal(result.valuePT1, int(553079))
 | 
			
		||||
 | 
			
		||||
	t.Log(result.valuePT2)
 | 
			
		||||
	is.Equal(result.valuePT2, 84363105)
 | 
			
		||||
}
 | 
			
		||||
@ -2,13 +2,12 @@ package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log/slog"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//go:embed input.txt
 | 
			
		||||
@ -21,22 +20,14 @@ type card struct {
 | 
			
		||||
	copies  int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	var level slog.Level
 | 
			
		||||
	if err := level.UnmarshalText([]byte(os.Getenv("DEBUG_LEVEL"))); err == nil && level != 0 {
 | 
			
		||||
		slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: level})))
 | 
			
		||||
	}
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
	buf := bytes.NewReader(input)
 | 
			
		||||
	scan := bufio.NewScanner(buf)
 | 
			
		||||
 | 
			
		||||
	points, cards := run(scan)
 | 
			
		||||
 | 
			
		||||
	fmt.Println("points:", points)
 | 
			
		||||
	fmt.Println("cards:", cards)
 | 
			
		||||
type result struct {
 | 
			
		||||
	points int
 | 
			
		||||
	cards  int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (int, int) {
 | 
			
		||||
func run(scan *bufio.Scanner) (result, error) {
 | 
			
		||||
	cards := []*card{}
 | 
			
		||||
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
@ -46,7 +37,7 @@ func run(scan *bufio.Scanner) (int, int) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		num, _ := strconv.Atoi(strings.TrimSpace(strings.SplitN(pfx, " ", 2)[1]))
 | 
			
		||||
		num := aoc.Atoi(strings.TrimSpace(strings.SplitN(pfx, " ", 2)[1]))
 | 
			
		||||
		cards = append(cards, &card{card: num})
 | 
			
		||||
		buf := make([]rune, 0, 4)
 | 
			
		||||
		winner := true
 | 
			
		||||
@ -71,7 +62,7 @@ func run(scan *bufio.Scanner) (int, int) {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(buf) > 0 {
 | 
			
		||||
			num, _ = strconv.Atoi(string(buf))
 | 
			
		||||
			num = aoc.Atoi(string(buf))
 | 
			
		||||
			buf = buf[:0]
 | 
			
		||||
			_ = buf // ignore
 | 
			
		||||
			cards[len(cards)-1].scratch = append(cards[len(cards)-1].scratch, num)
 | 
			
		||||
@ -105,5 +96,5 @@ func run(scan *bufio.Scanner) (int, int) {
 | 
			
		||||
		slog.Debug("points", "card", card.card, "match", m, "score", sumPoints)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sumPoints, sumCards
 | 
			
		||||
	return result{sumPoints, sumCards}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -17,16 +17,18 @@ func TestExample(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(example))
 | 
			
		||||
 | 
			
		||||
	points, cards := run(scan)
 | 
			
		||||
	is.Equal(points, 13)
 | 
			
		||||
	is.Equal(cards, 30)
 | 
			
		||||
	r, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
	is.Equal(r.points, 13)
 | 
			
		||||
	is.Equal(r.cards, 30)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestSolution(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(input))
 | 
			
		||||
 | 
			
		||||
	points, cards := run(scan)
 | 
			
		||||
	is.Equal(points, 23235)
 | 
			
		||||
	is.Equal(cards, 5920640)
 | 
			
		||||
	r, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
	is.Equal(r.points, 23235)
 | 
			
		||||
	is.Equal(r.cards, 5920640)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -7,27 +7,18 @@ import (
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	if len(os.Args) != 2 {
 | 
			
		||||
		fmt.Fprintln(os.Stderr, "Usage: day05 FILE")
 | 
			
		||||
	}
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
	input, err := os.Open(os.Args[1])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Fprintln(os.Stderr, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scan := bufio.NewScanner(input)
 | 
			
		||||
 | 
			
		||||
	minLocation, minRangeLocation := run(scan)
 | 
			
		||||
 | 
			
		||||
	fmt.Println("min location:", minLocation)
 | 
			
		||||
	fmt.Println("min range location:", minRangeLocation)
 | 
			
		||||
type result struct {
 | 
			
		||||
	minLocation int
 | 
			
		||||
	minRange    int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (int, int) {
 | 
			
		||||
func run(scan *bufio.Scanner) (result, error) {
 | 
			
		||||
	log("begin...")
 | 
			
		||||
 | 
			
		||||
	var seeds []int
 | 
			
		||||
@ -55,15 +46,14 @@ func run(scan *bufio.Scanner) (int, int) {
 | 
			
		||||
		lookup["humidity-to-location"],
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	return findMinLocation(seeds, find), FindMinRangeLocationMulti(seedRanges, find)
 | 
			
		||||
	return result{findMinLocation(seeds, find), FindMinRangeLocationMulti(seedRanges, find)}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readSeeds(text string) ([]int, [][2]int) {
 | 
			
		||||
	var seeds [] int 
 | 
			
		||||
	var seeds []int
 | 
			
		||||
	var seedRanges [][2]int
 | 
			
		||||
	sp := strings.Fields(strings.TrimPrefix(text, "seeds: "))
 | 
			
		||||
	for i, s := range sp {
 | 
			
		||||
		n, _ := strconv.Atoi(s)
 | 
			
		||||
 | 
			
		||||
	for i, n := range aoc.SliceMap(aoc.Atoi, strings.Fields(strings.TrimPrefix(text, "seeds: "))...) {
 | 
			
		||||
		seeds = append(seeds, n)
 | 
			
		||||
 | 
			
		||||
		if i%2 == 0 {
 | 
			
		||||
@ -121,7 +111,7 @@ func FindMinRangeLocation(ranges [][2]int, find *Finder) int {
 | 
			
		||||
 | 
			
		||||
	for _, s := range ranges {
 | 
			
		||||
		for i := 0; i < s[1]; i++ {
 | 
			
		||||
			seedLocations = append(seedLocations, find.Find(s[0] + i))
 | 
			
		||||
			seedLocations = append(seedLocations, find.Find(s[0]+i))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return min(seedLocations...)
 | 
			
		||||
@ -164,7 +154,7 @@ func FindMinRangeLocationMulti(ranges [][2]int, find *Finder) int {
 | 
			
		||||
	seedLocations := make([]int, 0, results)
 | 
			
		||||
	expectResults := make([]struct{}, len(ranges))
 | 
			
		||||
	for range expectResults {
 | 
			
		||||
		r := <- resultsCh
 | 
			
		||||
		r := <-resultsCh
 | 
			
		||||
		seedLocations = append(seedLocations, r...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -20,19 +20,20 @@ func TestExample(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(example))
 | 
			
		||||
 | 
			
		||||
	minLocation, minRangeLocation := run(scan)
 | 
			
		||||
	is.Equal(minLocation, 35)
 | 
			
		||||
	is.Equal(minRangeLocation, 46)
 | 
			
		||||
	r, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
	is.Equal(r.minLocation, 35)
 | 
			
		||||
	is.Equal(r.minRange, 46)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SkipTestSolution(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(input))
 | 
			
		||||
 | 
			
		||||
	minLocation, minRangeLocation := run(scan)
 | 
			
		||||
	is.Equal(minLocation, 199602917)
 | 
			
		||||
	is.Equal(minRangeLocation, 0)
 | 
			
		||||
 | 
			
		||||
	r, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
	is.Equal(r.minLocation, 199602917)
 | 
			
		||||
	is.Equal(r.minRange, 2254686)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestLookup(t *testing.T) {
 | 
			
		||||
@ -44,9 +45,9 @@ func TestLookup(t *testing.T) {
 | 
			
		||||
	is.Equal(find.Find(79), 81)
 | 
			
		||||
 | 
			
		||||
	find = &Lookup{ranges: Ranges{
 | 
			
		||||
		{77,45,23},
 | 
			
		||||
		{45,81,19},
 | 
			
		||||
		{64,68,13},
 | 
			
		||||
		{77, 45, 23},
 | 
			
		||||
		{45, 81, 19},
 | 
			
		||||
		{64, 68, 13},
 | 
			
		||||
	}}
 | 
			
		||||
	is.Equal(find.Find(77), 45)
 | 
			
		||||
 | 
			
		||||
@ -62,38 +63,38 @@ func TestFinder(t *testing.T) {
 | 
			
		||||
		}},
 | 
			
		||||
		// soil-to-fertilizer
 | 
			
		||||
		&Lookup{ranges: Ranges{
 | 
			
		||||
			{15, 0,37},
 | 
			
		||||
			{52,37,2},
 | 
			
		||||
			{0,39,15},
 | 
			
		||||
			{15, 0, 37},
 | 
			
		||||
			{52, 37, 2},
 | 
			
		||||
			{0, 39, 15},
 | 
			
		||||
		}},
 | 
			
		||||
		// fertilizer-to-water
 | 
			
		||||
		&Lookup{ranges: Ranges{
 | 
			
		||||
			{53,49,8},
 | 
			
		||||
			{11,0,42},
 | 
			
		||||
			{0,42,7},
 | 
			
		||||
			{7,57,4},
 | 
			
		||||
			{53, 49, 8},
 | 
			
		||||
			{11, 0, 42},
 | 
			
		||||
			{0, 42, 7},
 | 
			
		||||
			{7, 57, 4},
 | 
			
		||||
		}},
 | 
			
		||||
		// water-to-light
 | 
			
		||||
		&Lookup{ranges: Ranges{
 | 
			
		||||
			{18,88,7},
 | 
			
		||||
			{25,18,70},
 | 
			
		||||
			{18, 88, 7},
 | 
			
		||||
			{25, 18, 70},
 | 
			
		||||
		}},
 | 
			
		||||
		// light-to-temperature
 | 
			
		||||
		&Lookup{ranges: Ranges{
 | 
			
		||||
			{77,45,23},
 | 
			
		||||
			{45,81,19},
 | 
			
		||||
			{64,68,13},
 | 
			
		||||
			{77, 45, 23},
 | 
			
		||||
			{45, 81, 19},
 | 
			
		||||
			{64, 68, 13},
 | 
			
		||||
		}},
 | 
			
		||||
		// temperature-to-humidity
 | 
			
		||||
		&Lookup{ranges: Ranges{
 | 
			
		||||
			{69,0,1},
 | 
			
		||||
			{0,1,69},
 | 
			
		||||
			{69, 0, 1},
 | 
			
		||||
			{0, 1, 69},
 | 
			
		||||
		}},
 | 
			
		||||
		// humidity-to-location
 | 
			
		||||
		&Lookup{ranges: Ranges{
 | 
			
		||||
			{56,60,37},
 | 
			
		||||
			{93,56,4},
 | 
			
		||||
			{56, 60, 37},
 | 
			
		||||
			{93, 56, 4},
 | 
			
		||||
		}},
 | 
			
		||||
	)
 | 
			
		||||
	is.Equal(find.Find(82), 46)
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								day08/example1.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								day08/example1.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
RL
 | 
			
		||||
 | 
			
		||||
AAA = (BBB, CCC)
 | 
			
		||||
BBB = (DDD, EEE)
 | 
			
		||||
CCC = (ZZZ, GGG)
 | 
			
		||||
DDD = (DDD, DDD)
 | 
			
		||||
EEE = (EEE, EEE)
 | 
			
		||||
GGG = (GGG, GGG)
 | 
			
		||||
ZZZ = (ZZZ, ZZZ)
 | 
			
		||||
							
								
								
									
										5
									
								
								day08/example2.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								day08/example2.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
LLR
 | 
			
		||||
 | 
			
		||||
AAA = (BBB, BBB)
 | 
			
		||||
BBB = (AAA, ZZZ)
 | 
			
		||||
ZZZ = (ZZZ, ZZZ)
 | 
			
		||||
							
								
								
									
										10
									
								
								day08/example3.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								day08/example3.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
LR
 | 
			
		||||
 | 
			
		||||
11A = (11B, XXX)
 | 
			
		||||
11B = (XXX, 11Z)
 | 
			
		||||
11Z = (11B, XXX)
 | 
			
		||||
22A = (22B, XXX)
 | 
			
		||||
22B = (22C, 22C)
 | 
			
		||||
22C = (22Z, 22Z)
 | 
			
		||||
22Z = (22B, 22B)
 | 
			
		||||
XXX = (XXX, XXX)
 | 
			
		||||
							
								
								
									
										708
									
								
								day08/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										708
									
								
								day08/input.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,708 @@
 | 
			
		||||
LLLLRLRLRRLRRRLRRLRLRRLRLLRRRLRRLRRRLRLLLRLRRLRLLRRRLRRLRLRRLLRRRLRRRLRLRRLRRRLRRLRRLLRRRLLLLRRLRRLRRLRRRLLLRLRLRLRRLRRRLRLRRRLRLRRRLRRLRRLLRRLLRLRRRLRLRRRLLLRLRRRLRLRRRLRRLRLRRLRRRLRRRLRRLLLRRRLRRLRRLRRLRRRLLLRRLRLRRRLLLLRRRLRRLRRRLLRLRLRRLLRRRLLRLRLRLRRLRRLRRRLRRLLRLRRLRRLLLLRRLRLRRLLRRLLRRLRRLRRRLLLRRRR
 | 
			
		||||
 | 
			
		||||
BRR = (LVC, FSJ)
 | 
			
		||||
BHX = (GMG, QTN)
 | 
			
		||||
TJD = (HQF, PBJ)
 | 
			
		||||
JGN = (JXR, DGK)
 | 
			
		||||
NMC = (VPC, CRF)
 | 
			
		||||
DVJ = (KMM, DFJ)
 | 
			
		||||
LML = (MTG, KNX)
 | 
			
		||||
JKL = (LRX, FRD)
 | 
			
		||||
FJR = (MHX, SBX)
 | 
			
		||||
LMC = (QNB, QCK)
 | 
			
		||||
LJF = (KCJ, HCT)
 | 
			
		||||
KTL = (XTG, NGM)
 | 
			
		||||
GJB = (KTQ, KTQ)
 | 
			
		||||
BXR = (TDR, KMK)
 | 
			
		||||
GKB = (VXT, NQR)
 | 
			
		||||
PJL = (FPL, TFX)
 | 
			
		||||
LNZ = (CJC, DQL)
 | 
			
		||||
KCG = (KDL, LMF)
 | 
			
		||||
PGG = (NDL, XXC)
 | 
			
		||||
PMS = (XQM, DFG)
 | 
			
		||||
CJF = (MCG, RTJ)
 | 
			
		||||
JTH = (PGS, SGZ)
 | 
			
		||||
QBS = (JSC, KMT)
 | 
			
		||||
DQL = (KRR, PBL)
 | 
			
		||||
HSF = (SNP, KJR)
 | 
			
		||||
XVQ = (VQR, HSX)
 | 
			
		||||
QKF = (PBT, XLC)
 | 
			
		||||
DNA = (DQL, CJC)
 | 
			
		||||
LNF = (RVC, TJD)
 | 
			
		||||
MKT = (LDX, CGC)
 | 
			
		||||
BXP = (RGX, TTR)
 | 
			
		||||
SBX = (PGT, JGN)
 | 
			
		||||
JQK = (HDQ, BHQ)
 | 
			
		||||
MHL = (TLX, JDN)
 | 
			
		||||
BBD = (QNJ, BRM)
 | 
			
		||||
MTT = (BVK, DXB)
 | 
			
		||||
FVR = (VLN, PRV)
 | 
			
		||||
RVC = (HQF, PBJ)
 | 
			
		||||
LDX = (LRS, KBV)
 | 
			
		||||
BKF = (PXH, TNB)
 | 
			
		||||
BRM = (XTV, NGH)
 | 
			
		||||
DDL = (JNG, SFF)
 | 
			
		||||
BBT = (BQJ, BCN)
 | 
			
		||||
GPK = (CVK, DDL)
 | 
			
		||||
TLX = (BDN, XNT)
 | 
			
		||||
JHL = (BRX, QBT)
 | 
			
		||||
NTL = (HSR, DJD)
 | 
			
		||||
XBH = (PJX, JQK)
 | 
			
		||||
PPF = (LCT, BJL)
 | 
			
		||||
SFF = (FVR, NFG)
 | 
			
		||||
HNA = (CTC, BSG)
 | 
			
		||||
CNG = (DXM, QFN)
 | 
			
		||||
GML = (NRD, TVN)
 | 
			
		||||
RHH = (NBT, LJH)
 | 
			
		||||
LDM = (DDN, TRN)
 | 
			
		||||
XSK = (PLB, NVJ)
 | 
			
		||||
NCQ = (MDN, XGT)
 | 
			
		||||
FCQ = (HCT, KCJ)
 | 
			
		||||
DRC = (JKL, JNM)
 | 
			
		||||
SHR = (KLX, VLH)
 | 
			
		||||
FTP = (DRN, DKV)
 | 
			
		||||
QBF = (GVS, NXK)
 | 
			
		||||
GXK = (XDK, LVF)
 | 
			
		||||
KMK = (VXV, XCS)
 | 
			
		||||
PKK = (QNJ, BRM)
 | 
			
		||||
NJH = (TKL, PQK)
 | 
			
		||||
BRX = (MNM, HVC)
 | 
			
		||||
VTD = (BJK, LML)
 | 
			
		||||
QVX = (DVJ, DSF)
 | 
			
		||||
GRM = (JCV, SQB)
 | 
			
		||||
RDQ = (HCG, XMB)
 | 
			
		||||
RGX = (FCN, TPD)
 | 
			
		||||
HBH = (FPR, DHX)
 | 
			
		||||
PHM = (JSP, RCR)
 | 
			
		||||
NBT = (FRG, CMJ)
 | 
			
		||||
XRH = (HCB, FBM)
 | 
			
		||||
GMR = (FDJ, NJD)
 | 
			
		||||
MVG = (RDJ, QSD)
 | 
			
		||||
BDL = (JSB, TFN)
 | 
			
		||||
VXT = (MBM, JND)
 | 
			
		||||
TXC = (QDG, LTV)
 | 
			
		||||
SRL = (RRX, NDS)
 | 
			
		||||
SGN = (MPL, CBB)
 | 
			
		||||
HVH = (SLJ, CBC)
 | 
			
		||||
VPC = (CCG, QSJ)
 | 
			
		||||
KCJ = (CKC, TTD)
 | 
			
		||||
RLT = (LLT, VVL)
 | 
			
		||||
RXV = (KXQ, VBR)
 | 
			
		||||
FQS = (STP, BHX)
 | 
			
		||||
SGC = (RLJ, QGB)
 | 
			
		||||
XLX = (HRG, DGV)
 | 
			
		||||
XKV = (QQB, TNQ)
 | 
			
		||||
SLJ = (GTB, MPF)
 | 
			
		||||
PKV = (CQN, THS)
 | 
			
		||||
RPP = (QFT, TNK)
 | 
			
		||||
DKL = (MFC, MFC)
 | 
			
		||||
BCG = (FXM, GPR)
 | 
			
		||||
RFV = (DRC, MPD)
 | 
			
		||||
VVC = (FGN, CVL)
 | 
			
		||||
HQB = (QNT, VVC)
 | 
			
		||||
RRP = (VVC, QNT)
 | 
			
		||||
TRS = (RCM, GHN)
 | 
			
		||||
QBT = (HVC, MNM)
 | 
			
		||||
XKS = (SCC, VXX)
 | 
			
		||||
TPS = (FMH, KFN)
 | 
			
		||||
MTS = (VXT, NQR)
 | 
			
		||||
FXM = (LDM, FQT)
 | 
			
		||||
LNB = (XJV, SJN)
 | 
			
		||||
HVF = (QXC, RBH)
 | 
			
		||||
LSG = (QHM, TSM)
 | 
			
		||||
JMP = (HBH, NQK)
 | 
			
		||||
NGM = (KDP, HHP)
 | 
			
		||||
HCG = (SLR, TSC)
 | 
			
		||||
HGX = (DFG, XQM)
 | 
			
		||||
DLG = (BVN, GMM)
 | 
			
		||||
DJD = (VGP, VML)
 | 
			
		||||
HBT = (XKL, JBQ)
 | 
			
		||||
NVJ = (GKX, PKS)
 | 
			
		||||
CPS = (PKJ, RSV)
 | 
			
		||||
SKN = (NBT, LJH)
 | 
			
		||||
CCK = (TTJ, SLV)
 | 
			
		||||
DXM = (CBN, BXR)
 | 
			
		||||
RJD = (XJH, SKH)
 | 
			
		||||
RDJ = (CNF, TTG)
 | 
			
		||||
PKJ = (BCM, XKC)
 | 
			
		||||
FQL = (SRV, DFC)
 | 
			
		||||
KDS = (MFB, CLQ)
 | 
			
		||||
QKR = (VGD, CXK)
 | 
			
		||||
XXC = (NFD, SPS)
 | 
			
		||||
PSQ = (NJH, BLR)
 | 
			
		||||
BLR = (PQK, TKL)
 | 
			
		||||
LMX = (DGV, HRG)
 | 
			
		||||
GCK = (CSR, CSR)
 | 
			
		||||
GKJ = (JHL, PNN)
 | 
			
		||||
GVS = (TLN, LJX)
 | 
			
		||||
FPR = (JCH, GKD)
 | 
			
		||||
VQV = (DGB, GGN)
 | 
			
		||||
CPF = (VMH, JQQ)
 | 
			
		||||
GKD = (SGF, PHM)
 | 
			
		||||
JNM = (LRX, FRD)
 | 
			
		||||
CXV = (LNF, HGF)
 | 
			
		||||
TNK = (RRD, HKC)
 | 
			
		||||
DXX = (LMC, ZZZ)
 | 
			
		||||
DGG = (PPF, TRR)
 | 
			
		||||
MLH = (TVL, PBR)
 | 
			
		||||
LBC = (LJL, FTR)
 | 
			
		||||
FVQ = (TBC, LKB)
 | 
			
		||||
LTF = (CBC, SLJ)
 | 
			
		||||
TVH = (XMS, GJS)
 | 
			
		||||
SFB = (TTJ, SLV)
 | 
			
		||||
LVF = (MBT, SJB)
 | 
			
		||||
XPP = (QDM, PJL)
 | 
			
		||||
BVK = (RPV, JMP)
 | 
			
		||||
VGD = (MRX, FJR)
 | 
			
		||||
FRD = (XBH, CDN)
 | 
			
		||||
LKM = (CMF, XNS)
 | 
			
		||||
TCJ = (MMS, PGG)
 | 
			
		||||
DHQ = (MTT, BKS)
 | 
			
		||||
HDQ = (GPH, XKH)
 | 
			
		||||
KTJ = (QQT, MKR)
 | 
			
		||||
NMQ = (VFK, VSD)
 | 
			
		||||
RSK = (QDM, PJL)
 | 
			
		||||
XQC = (KFP, HVB)
 | 
			
		||||
LQN = (NGM, XTG)
 | 
			
		||||
TKG = (XDQ, XDQ)
 | 
			
		||||
KBB = (VQR, HSX)
 | 
			
		||||
TQQ = (QDG, LTV)
 | 
			
		||||
SQN = (TDQ, XKV)
 | 
			
		||||
TSM = (TSH, MRP)
 | 
			
		||||
KPH = (THS, CQN)
 | 
			
		||||
HCB = (DVL, RTV)
 | 
			
		||||
MLR = (GHT, NSN)
 | 
			
		||||
BFM = (GCK, SLX)
 | 
			
		||||
GXQ = (QKM, JJL)
 | 
			
		||||
GNF = (HRQ, XTK)
 | 
			
		||||
TRR = (BJL, LCT)
 | 
			
		||||
AAA = (QNB, QCK)
 | 
			
		||||
SDL = (KJX, LSN)
 | 
			
		||||
DKV = (KBB, XVQ)
 | 
			
		||||
RMR = (MQR, CPR)
 | 
			
		||||
MQC = (CBV, SRP)
 | 
			
		||||
PRV = (KDS, FBX)
 | 
			
		||||
GTB = (CCK, SFB)
 | 
			
		||||
SNP = (PXX, SHR)
 | 
			
		||||
NTR = (VHT, KXK)
 | 
			
		||||
MKJ = (DDL, CVK)
 | 
			
		||||
LSQ = (HSF, RMN)
 | 
			
		||||
TTJ = (CBH, QKF)
 | 
			
		||||
DNH = (MVG, JCJ)
 | 
			
		||||
KMM = (KPH, PKV)
 | 
			
		||||
NTT = (RQK, PFK)
 | 
			
		||||
QMF = (BFM, PJB)
 | 
			
		||||
RJB = (RBH, QXC)
 | 
			
		||||
LRS = (MJT, BVM)
 | 
			
		||||
CJG = (RMR, BMN)
 | 
			
		||||
DVQ = (GXM, DDH)
 | 
			
		||||
MFC = (LMC, LMC)
 | 
			
		||||
XTG = (HHP, KDP)
 | 
			
		||||
HKB = (RDQ, TVT)
 | 
			
		||||
PKS = (JQM, DGG)
 | 
			
		||||
BJK = (KNX, MTG)
 | 
			
		||||
TVT = (XMB, HCG)
 | 
			
		||||
JNR = (JHG, JLN)
 | 
			
		||||
VFK = (XKS, QBH)
 | 
			
		||||
NPC = (PKK, BBD)
 | 
			
		||||
PXX = (KLX, VLH)
 | 
			
		||||
XLC = (NST, BXP)
 | 
			
		||||
CBB = (LMX, XLX)
 | 
			
		||||
KLX = (MSH, LCF)
 | 
			
		||||
CLQ = (JNF, JNC)
 | 
			
		||||
TSS = (MKR, QQT)
 | 
			
		||||
SSS = (RMQ, RCS)
 | 
			
		||||
QSD = (TTG, CNF)
 | 
			
		||||
NHG = (DVQ, VNB)
 | 
			
		||||
CTC = (VCN, RJD)
 | 
			
		||||
THS = (QRH, GPT)
 | 
			
		||||
KDR = (RTK, GKJ)
 | 
			
		||||
NTD = (CGG, SPN)
 | 
			
		||||
GHP = (NCQ, FCD)
 | 
			
		||||
KXQ = (RLS, VRM)
 | 
			
		||||
GNV = (BQJ, BCN)
 | 
			
		||||
DXQ = (QHC, FXN)
 | 
			
		||||
RQB = (FVQ, TNF)
 | 
			
		||||
CNF = (TXC, TQQ)
 | 
			
		||||
BGB = (QQS, LRV)
 | 
			
		||||
ZZZ = (QCK, QNB)
 | 
			
		||||
NFM = (MGV, VTD)
 | 
			
		||||
MFD = (DBF, KSN)
 | 
			
		||||
NST = (RGX, TTR)
 | 
			
		||||
XJV = (LGL, LGL)
 | 
			
		||||
TRQ = (TVH, KJL)
 | 
			
		||||
PPV = (CJP, VHH)
 | 
			
		||||
DNV = (DBM, VGJ)
 | 
			
		||||
JBQ = (MHL, RFN)
 | 
			
		||||
HRG = (JFD, VQP)
 | 
			
		||||
RMB = (JKJ, JGJ)
 | 
			
		||||
RGQ = (RSK, XPP)
 | 
			
		||||
KHF = (TJG, KPX)
 | 
			
		||||
HPZ = (BSG, CTC)
 | 
			
		||||
LFJ = (TSN, NMB)
 | 
			
		||||
MBT = (XRC, PJR)
 | 
			
		||||
QFN = (CBN, BXR)
 | 
			
		||||
QSJ = (BRS, BKF)
 | 
			
		||||
XJH = (RSF, VNP)
 | 
			
		||||
GST = (LVF, XDK)
 | 
			
		||||
DDN = (NMS, RLT)
 | 
			
		||||
CXK = (FJR, MRX)
 | 
			
		||||
PHH = (FPB, TCJ)
 | 
			
		||||
XHV = (KTJ, TSS)
 | 
			
		||||
VHT = (NPC, DMG)
 | 
			
		||||
RNL = (NHG, DVN)
 | 
			
		||||
TKL = (KPN, FKX)
 | 
			
		||||
DGB = (GPJ, QMF)
 | 
			
		||||
PNN = (QBT, BRX)
 | 
			
		||||
TBC = (NTR, FKG)
 | 
			
		||||
PGS = (QDT, JQL)
 | 
			
		||||
SLX = (CSR, LNB)
 | 
			
		||||
BVV = (LVC, FSJ)
 | 
			
		||||
JQL = (MLH, GSC)
 | 
			
		||||
PXH = (CJF, CKM)
 | 
			
		||||
LHM = (DSF, DVJ)
 | 
			
		||||
NND = (NTD, DTB)
 | 
			
		||||
MFB = (JNF, JNC)
 | 
			
		||||
TTR = (FCN, TPD)
 | 
			
		||||
HRQ = (JTD, JTD)
 | 
			
		||||
SLR = (TXT, JSN)
 | 
			
		||||
VQP = (XPK, XGB)
 | 
			
		||||
QHM = (MRP, TSH)
 | 
			
		||||
RTJ = (PXB, TLP)
 | 
			
		||||
QQT = (RRL, QHQ)
 | 
			
		||||
CSR = (XJV, XJV)
 | 
			
		||||
CJP = (CJG, HQQ)
 | 
			
		||||
RMC = (MPD, DRC)
 | 
			
		||||
XMS = (LXX, GPN)
 | 
			
		||||
HSR = (VGP, VML)
 | 
			
		||||
MNM = (VSS, QXR)
 | 
			
		||||
SJN = (LGL, LNZ)
 | 
			
		||||
KBV = (MJT, BVM)
 | 
			
		||||
KFN = (NRC, VSG)
 | 
			
		||||
JNC = (RHR, LFJ)
 | 
			
		||||
MPF = (SFB, CCK)
 | 
			
		||||
QVK = (GNK, BCG)
 | 
			
		||||
NJD = (KCG, LDB)
 | 
			
		||||
DBM = (MJG, MFD)
 | 
			
		||||
NKF = (GGN, DGB)
 | 
			
		||||
BCN = (JNR, MHK)
 | 
			
		||||
GNK = (FXM, GPR)
 | 
			
		||||
KMT = (HFC, CPS)
 | 
			
		||||
FDJ = (KCG, LDB)
 | 
			
		||||
LVD = (PHH, QDR)
 | 
			
		||||
FCN = (VDP, MQC)
 | 
			
		||||
QQB = (GJB, GJB)
 | 
			
		||||
PLF = (JNL, HBT)
 | 
			
		||||
QDM = (FPL, TFX)
 | 
			
		||||
GXM = (CLD, NNL)
 | 
			
		||||
MRV = (BCG, GNK)
 | 
			
		||||
LKB = (NTR, FKG)
 | 
			
		||||
TTG = (TQQ, TXC)
 | 
			
		||||
GFD = (VSD, VFK)
 | 
			
		||||
RCS = (KQQ, DNH)
 | 
			
		||||
QXR = (FCQ, LJF)
 | 
			
		||||
HMQ = (RJQ, FQL)
 | 
			
		||||
VCN = (SKH, XJH)
 | 
			
		||||
QQG = (HSR, DJD)
 | 
			
		||||
HGF = (RVC, TJD)
 | 
			
		||||
XMB = (TSC, SLR)
 | 
			
		||||
PJB = (GCK, SLX)
 | 
			
		||||
HFC = (RSV, PKJ)
 | 
			
		||||
JJL = (GXK, GST)
 | 
			
		||||
QTN = (JLV, SGX)
 | 
			
		||||
KDP = (GNV, BBT)
 | 
			
		||||
VRF = (TFN, JSB)
 | 
			
		||||
GPN = (CPF, SRQ)
 | 
			
		||||
TSC = (TXT, JSN)
 | 
			
		||||
CRF = (QSJ, CCG)
 | 
			
		||||
TNF = (TBC, LKB)
 | 
			
		||||
VLH = (LCF, MSH)
 | 
			
		||||
BCV = (JSC, KMT)
 | 
			
		||||
NNL = (KVX, FQS)
 | 
			
		||||
RVT = (HCB, FBM)
 | 
			
		||||
QHC = (QKV, NCJ)
 | 
			
		||||
VDP = (CBV, SRP)
 | 
			
		||||
CBV = (VQV, NKF)
 | 
			
		||||
CMF = (XHV, TPR)
 | 
			
		||||
TRN = (RLT, NMS)
 | 
			
		||||
JSB = (XTH, TRS)
 | 
			
		||||
CFC = (TVT, RDQ)
 | 
			
		||||
KDL = (TKG, TKG)
 | 
			
		||||
TTD = (BBC, GHP)
 | 
			
		||||
KJR = (PXX, SHR)
 | 
			
		||||
MTV = (GVS, NXK)
 | 
			
		||||
BVN = (KDR, PVP)
 | 
			
		||||
DXB = (RPV, JMP)
 | 
			
		||||
FSJ = (QPQ, GML)
 | 
			
		||||
PBJ = (LQN, KTL)
 | 
			
		||||
PXB = (BDL, VRF)
 | 
			
		||||
NDS = (BGB, NGX)
 | 
			
		||||
CBN = (KMK, TDR)
 | 
			
		||||
NFG = (VLN, PRV)
 | 
			
		||||
JTD = (PGS, PGS)
 | 
			
		||||
MKR = (QHQ, RRL)
 | 
			
		||||
JSN = (RFV, RMC)
 | 
			
		||||
CVK = (SFF, JNG)
 | 
			
		||||
FGN = (BVQ, XQC)
 | 
			
		||||
HHF = (RPS, QQF)
 | 
			
		||||
PLB = (PKS, GKX)
 | 
			
		||||
BJB = (QMC, GPG)
 | 
			
		||||
STP = (QTN, GMG)
 | 
			
		||||
DGK = (RKK, BVT)
 | 
			
		||||
JJM = (VGD, CXK)
 | 
			
		||||
LTS = (QPN, BCL)
 | 
			
		||||
LVC = (QPQ, GML)
 | 
			
		||||
QNB = (GJN, RVB)
 | 
			
		||||
RBH = (HMQ, HPS)
 | 
			
		||||
NQK = (DHX, FPR)
 | 
			
		||||
MRP = (BDT, SGN)
 | 
			
		||||
JQM = (TRR, PPF)
 | 
			
		||||
TSH = (BDT, SGN)
 | 
			
		||||
JLN = (JCC, FCB)
 | 
			
		||||
BRP = (LDX, CGC)
 | 
			
		||||
SJC = (HRQ, HRQ)
 | 
			
		||||
LJL = (BVB, PPV)
 | 
			
		||||
SPN = (SDL, VHM)
 | 
			
		||||
SDM = (DDF, LTS)
 | 
			
		||||
LJH = (FRG, CMJ)
 | 
			
		||||
CMG = (MKD, JGT)
 | 
			
		||||
GPR = (LDM, FQT)
 | 
			
		||||
QPQ = (NRD, TVN)
 | 
			
		||||
JCJ = (RDJ, QSD)
 | 
			
		||||
HSX = (CMG, SHF)
 | 
			
		||||
VML = (RMB, MHC)
 | 
			
		||||
DHX = (JCH, GKD)
 | 
			
		||||
MTG = (FPX, SPD)
 | 
			
		||||
BDT = (MPL, CBB)
 | 
			
		||||
CJC = (PBL, KRR)
 | 
			
		||||
JLS = (LJL, FTR)
 | 
			
		||||
HQF = (LQN, KTL)
 | 
			
		||||
HQQ = (RMR, BMN)
 | 
			
		||||
QMC = (RBP, PXD)
 | 
			
		||||
RPV = (HBH, NQK)
 | 
			
		||||
JHG = (JCC, FCB)
 | 
			
		||||
TPD = (VDP, MQC)
 | 
			
		||||
BHQ = (XKH, GPH)
 | 
			
		||||
XKC = (HDD, GXR)
 | 
			
		||||
RPS = (KJP, KJP)
 | 
			
		||||
QNT = (CVL, FGN)
 | 
			
		||||
JSC = (HFC, CPS)
 | 
			
		||||
KXG = (DTB, NTD)
 | 
			
		||||
CKM = (RTJ, MCG)
 | 
			
		||||
FTD = (KPX, TJG)
 | 
			
		||||
VSD = (XKS, QBH)
 | 
			
		||||
MCG = (TLP, PXB)
 | 
			
		||||
XKH = (HLP, CXV)
 | 
			
		||||
TNB = (CJF, CKM)
 | 
			
		||||
XTH = (RCM, GHN)
 | 
			
		||||
DFN = (GMR, DSS)
 | 
			
		||||
LMF = (TKG, XST)
 | 
			
		||||
FMH = (NRC, VSG)
 | 
			
		||||
XCS = (JTS, GRM)
 | 
			
		||||
GVF = (NDS, RRX)
 | 
			
		||||
CXM = (HGX, PMS)
 | 
			
		||||
VRM = (XJT, DXQ)
 | 
			
		||||
JLV = (QVX, LHM)
 | 
			
		||||
JCH = (PHM, SGF)
 | 
			
		||||
NMS = (VVL, LLT)
 | 
			
		||||
BHS = (XJR, LKM)
 | 
			
		||||
CKC = (BBC, GHP)
 | 
			
		||||
CBH = (XLC, PBT)
 | 
			
		||||
PRL = (QFT, TNK)
 | 
			
		||||
SDF = (VTD, MGV)
 | 
			
		||||
RVB = (MLR, XHT)
 | 
			
		||||
GPT = (PLF, MJX)
 | 
			
		||||
KRR = (RVT, XRH)
 | 
			
		||||
GXR = (BVV, BRR)
 | 
			
		||||
NSN = (RGQ, JMQ)
 | 
			
		||||
KJX = (TCR, MSL)
 | 
			
		||||
PHL = (TSM, QHM)
 | 
			
		||||
MQR = (MTS, GKB)
 | 
			
		||||
XDK = (SJB, MBT)
 | 
			
		||||
NRC = (DGN, BJB)
 | 
			
		||||
JQQ = (LBC, JLS)
 | 
			
		||||
JTS = (JCV, SQB)
 | 
			
		||||
RLJ = (JJM, QKR)
 | 
			
		||||
DTB = (CGG, SPN)
 | 
			
		||||
BRS = (PXH, TNB)
 | 
			
		||||
SRV = (SPC, DNV)
 | 
			
		||||
MNP = (JJL, QKM)
 | 
			
		||||
KTQ = (XSK, XSK)
 | 
			
		||||
FPX = (SJC, GNF)
 | 
			
		||||
VBR = (VRM, RLS)
 | 
			
		||||
KSN = (HQB, RRP)
 | 
			
		||||
RJQ = (SRV, DFC)
 | 
			
		||||
BKS = (BVK, DXB)
 | 
			
		||||
BVB = (VHH, CJP)
 | 
			
		||||
XTK = (JTD, JTH)
 | 
			
		||||
PBT = (BXP, NST)
 | 
			
		||||
PVP = (RTK, GKJ)
 | 
			
		||||
QPN = (BCV, QBS)
 | 
			
		||||
QQF = (KJP, HPZ)
 | 
			
		||||
QRH = (PLF, MJX)
 | 
			
		||||
GHS = (BKN, TPS)
 | 
			
		||||
RCM = (MNP, GXQ)
 | 
			
		||||
DCT = (DDF, LTS)
 | 
			
		||||
JLC = (HGX, PMS)
 | 
			
		||||
VNC = (XSK, CXZ)
 | 
			
		||||
BQJ = (MHK, JNR)
 | 
			
		||||
SHF = (JGT, MKD)
 | 
			
		||||
FXN = (QKV, NCJ)
 | 
			
		||||
FPB = (PGG, MMS)
 | 
			
		||||
JGJ = (KXG, NND)
 | 
			
		||||
VBM = (PSQ, QKN)
 | 
			
		||||
GKX = (DGG, JQM)
 | 
			
		||||
DSF = (KMM, DFJ)
 | 
			
		||||
CMJ = (GPK, MKJ)
 | 
			
		||||
NCJ = (SDM, DCT)
 | 
			
		||||
MKD = (GQG, DHQ)
 | 
			
		||||
CFZ = (RQB, SHH)
 | 
			
		||||
RQK = (DKL, DKL)
 | 
			
		||||
XGT = (HPQ, VRQ)
 | 
			
		||||
SRP = (NKF, VQV)
 | 
			
		||||
BSG = (VCN, RJD)
 | 
			
		||||
XRC = (NFM, SDF)
 | 
			
		||||
DVL = (SRL, GVF)
 | 
			
		||||
HVB = (HXS, MLD)
 | 
			
		||||
MPD = (JNM, JKL)
 | 
			
		||||
JSP = (PHL, LSG)
 | 
			
		||||
BCR = (XJR, LKM)
 | 
			
		||||
PQK = (KPN, FKX)
 | 
			
		||||
FCD = (XGT, MDN)
 | 
			
		||||
MDL = (JLC, CXM)
 | 
			
		||||
FBX = (CLQ, MFB)
 | 
			
		||||
VNP = (RGM, GHS)
 | 
			
		||||
HMK = (RMN, HSF)
 | 
			
		||||
SJB = (PJR, XRC)
 | 
			
		||||
JFD = (XPK, XGB)
 | 
			
		||||
HHP = (GNV, BBT)
 | 
			
		||||
TVN = (VBM, KJN)
 | 
			
		||||
DMG = (PKK, BBD)
 | 
			
		||||
RGM = (BKN, TPS)
 | 
			
		||||
TRF = (KXQ, VBR)
 | 
			
		||||
XHT = (NSN, GHT)
 | 
			
		||||
DFJ = (KPH, PKV)
 | 
			
		||||
KJP = (CTC, BSG)
 | 
			
		||||
LLT = (NTS, LVD)
 | 
			
		||||
RMN = (SNP, KJR)
 | 
			
		||||
GSC = (TVL, PBR)
 | 
			
		||||
RSV = (XKC, BCM)
 | 
			
		||||
TLP = (VRF, BDL)
 | 
			
		||||
GGN = (GPJ, QMF)
 | 
			
		||||
XJR = (CMF, XNS)
 | 
			
		||||
GQG = (BKS, MTT)
 | 
			
		||||
JPN = (MRV, QVK)
 | 
			
		||||
RSF = (RGM, GHS)
 | 
			
		||||
QQS = (DLG, JPV)
 | 
			
		||||
DGV = (VQP, JFD)
 | 
			
		||||
JDN = (XNT, BDN)
 | 
			
		||||
LMA = (QDT, JQL)
 | 
			
		||||
QDG = (QGC, DTX)
 | 
			
		||||
HDD = (BVV, BRR)
 | 
			
		||||
RRD = (CNG, XLJ)
 | 
			
		||||
QBH = (VXX, SCC)
 | 
			
		||||
GPH = (HLP, CXV)
 | 
			
		||||
CVN = (MRV, QVK)
 | 
			
		||||
RLS = (XJT, DXQ)
 | 
			
		||||
QKN = (NJH, BLR)
 | 
			
		||||
NRD = (VBM, KJN)
 | 
			
		||||
NMB = (HVF, RJB)
 | 
			
		||||
XNT = (RXV, TRF)
 | 
			
		||||
XNS = (XHV, TPR)
 | 
			
		||||
SGX = (LHM, QVX)
 | 
			
		||||
NTS = (PHH, QDR)
 | 
			
		||||
SPS = (LTF, HVH)
 | 
			
		||||
KPX = (BCR, BHS)
 | 
			
		||||
GNM = (RPS, RPS)
 | 
			
		||||
CXZ = (NVJ, PLB)
 | 
			
		||||
VVL = (LVD, NTS)
 | 
			
		||||
VTC = (NHG, DVN)
 | 
			
		||||
PXD = (BHH, SSS)
 | 
			
		||||
TVL = (MKT, BRP)
 | 
			
		||||
TPR = (KTJ, TSS)
 | 
			
		||||
MJX = (JNL, HBT)
 | 
			
		||||
BKN = (FMH, KFN)
 | 
			
		||||
MBM = (BVC, FTP)
 | 
			
		||||
RTV = (GVF, SRL)
 | 
			
		||||
GPG = (PXD, RBP)
 | 
			
		||||
KXK = (DMG, NPC)
 | 
			
		||||
JPV = (GMM, BVN)
 | 
			
		||||
LXP = (VPC, CRF)
 | 
			
		||||
RMQ = (DNH, KQQ)
 | 
			
		||||
DRN = (KBB, XVQ)
 | 
			
		||||
MMS = (XXC, NDL)
 | 
			
		||||
GMG = (SGX, JLV)
 | 
			
		||||
MJT = (KHF, FTD)
 | 
			
		||||
XJT = (QHC, FXN)
 | 
			
		||||
JMQ = (XPP, RSK)
 | 
			
		||||
QCS = (TVH, KJL)
 | 
			
		||||
BVC = (DRN, DKV)
 | 
			
		||||
SPC = (DBM, VGJ)
 | 
			
		||||
SHH = (TNF, FVQ)
 | 
			
		||||
VGA = (PLB, NVJ)
 | 
			
		||||
RKK = (JPN, CVN)
 | 
			
		||||
SCC = (TRQ, QCS)
 | 
			
		||||
CDN = (JQK, PJX)
 | 
			
		||||
VSS = (LJF, FCQ)
 | 
			
		||||
JNF = (LFJ, RHR)
 | 
			
		||||
VGP = (MHC, RMB)
 | 
			
		||||
VGJ = (MJG, MFD)
 | 
			
		||||
QGC = (RHH, SKN)
 | 
			
		||||
RKJ = (KTQ, VNC)
 | 
			
		||||
DTX = (SKN, RHH)
 | 
			
		||||
HPQ = (VDR, SGC)
 | 
			
		||||
CCG = (BRS, BKF)
 | 
			
		||||
VLN = (FBX, KDS)
 | 
			
		||||
BHH = (RMQ, RCS)
 | 
			
		||||
BBC = (FCD, NCQ)
 | 
			
		||||
JCV = (GNM, GNM)
 | 
			
		||||
TNQ = (GJB, RKJ)
 | 
			
		||||
QNJ = (NGH, XTV)
 | 
			
		||||
GHT = (RGQ, JMQ)
 | 
			
		||||
LJX = (CFC, HKB)
 | 
			
		||||
TLN = (HKB, CFC)
 | 
			
		||||
PFK = (DKL, LFL)
 | 
			
		||||
PJR = (SDF, NFM)
 | 
			
		||||
JNG = (NFG, FVR)
 | 
			
		||||
PJX = (BHQ, HDQ)
 | 
			
		||||
VHH = (CJG, HQQ)
 | 
			
		||||
RTK = (PNN, JHL)
 | 
			
		||||
XGB = (MLN, SQN)
 | 
			
		||||
JCC = (NQX, NTT)
 | 
			
		||||
BVT = (CVN, JPN)
 | 
			
		||||
HPS = (RJQ, FQL)
 | 
			
		||||
TCR = (DFN, RHS)
 | 
			
		||||
LLA = (SHH, RQB)
 | 
			
		||||
NGX = (QQS, LRV)
 | 
			
		||||
SLV = (CBH, QKF)
 | 
			
		||||
BMN = (CPR, MQR)
 | 
			
		||||
XKL = (RFN, MHL)
 | 
			
		||||
CGG = (VHM, SDL)
 | 
			
		||||
KJN = (PSQ, QKN)
 | 
			
		||||
LDB = (KDL, LMF)
 | 
			
		||||
SPD = (SJC, GNF)
 | 
			
		||||
VDR = (RLJ, QGB)
 | 
			
		||||
DDF = (QPN, BCL)
 | 
			
		||||
KQQ = (MVG, JCJ)
 | 
			
		||||
DSS = (FDJ, NJD)
 | 
			
		||||
NFD = (HVH, LTF)
 | 
			
		||||
GPJ = (BFM, PJB)
 | 
			
		||||
LGL = (DQL, CJC)
 | 
			
		||||
TDQ = (QQB, TNQ)
 | 
			
		||||
RCR = (PHL, LSG)
 | 
			
		||||
SKH = (VNP, RSF)
 | 
			
		||||
DGN = (QMC, GPG)
 | 
			
		||||
NGH = (RNL, VTC)
 | 
			
		||||
TSN = (HVF, RJB)
 | 
			
		||||
MGV = (LML, BJK)
 | 
			
		||||
QHQ = (LXP, NMC)
 | 
			
		||||
KJL = (GJS, XMS)
 | 
			
		||||
RBP = (BHH, SSS)
 | 
			
		||||
QDR = (FPB, TCJ)
 | 
			
		||||
RHR = (NMB, TSN)
 | 
			
		||||
NXK = (LJX, TLN)
 | 
			
		||||
FCB = (NQX, NTT)
 | 
			
		||||
TFN = (TRS, XTH)
 | 
			
		||||
MJG = (KSN, DBF)
 | 
			
		||||
BVQ = (KFP, HVB)
 | 
			
		||||
GMM = (PVP, KDR)
 | 
			
		||||
MDN = (VRQ, HPQ)
 | 
			
		||||
LTV = (DTX, QGC)
 | 
			
		||||
LRV = (DLG, JPV)
 | 
			
		||||
MHC = (JKJ, JGJ)
 | 
			
		||||
DFC = (DNV, SPC)
 | 
			
		||||
LXV = (SHH, RQB)
 | 
			
		||||
PBL = (RVT, XRH)
 | 
			
		||||
BDN = (RXV, TRF)
 | 
			
		||||
JKJ = (KXG, NND)
 | 
			
		||||
MSH = (MTV, QBF)
 | 
			
		||||
NDL = (SPS, NFD)
 | 
			
		||||
FKG = (VHT, KXK)
 | 
			
		||||
PBR = (MKT, BRP)
 | 
			
		||||
VSG = (BJB, DGN)
 | 
			
		||||
RRX = (BGB, NGX)
 | 
			
		||||
NQR = (JND, MBM)
 | 
			
		||||
MRX = (MHX, SBX)
 | 
			
		||||
DVN = (DVQ, VNB)
 | 
			
		||||
HKC = (CNG, XLJ)
 | 
			
		||||
PGT = (JXR, DGK)
 | 
			
		||||
DBF = (HQB, RRP)
 | 
			
		||||
FRG = (GPK, MKJ)
 | 
			
		||||
DFG = (NMQ, GFD)
 | 
			
		||||
QDT = (MLH, GSC)
 | 
			
		||||
KVX = (STP, BHX)
 | 
			
		||||
LCT = (MDL, KCL)
 | 
			
		||||
LSN = (TCR, MSL)
 | 
			
		||||
TXT = (RMC, RFV)
 | 
			
		||||
MXM = (LXV, CFZ)
 | 
			
		||||
TJG = (BHS, BCR)
 | 
			
		||||
BCM = (GXR, HDD)
 | 
			
		||||
FKX = (NTL, QQG)
 | 
			
		||||
SRQ = (JQQ, VMH)
 | 
			
		||||
BCL = (BCV, QBS)
 | 
			
		||||
LRX = (CDN, XBH)
 | 
			
		||||
RHS = (DSS, GMR)
 | 
			
		||||
CLD = (FQS, KVX)
 | 
			
		||||
XLJ = (DXM, QFN)
 | 
			
		||||
KCL = (CXM, JLC)
 | 
			
		||||
HXS = (PRL, RPP)
 | 
			
		||||
JND = (BVC, FTP)
 | 
			
		||||
VQR = (SHF, CMG)
 | 
			
		||||
VNB = (DDH, GXM)
 | 
			
		||||
QGB = (JJM, QKR)
 | 
			
		||||
CVL = (BVQ, XQC)
 | 
			
		||||
RFN = (JDN, TLX)
 | 
			
		||||
FBM = (DVL, RTV)
 | 
			
		||||
TFX = (LSQ, HMK)
 | 
			
		||||
XQM = (NMQ, GFD)
 | 
			
		||||
BJL = (KCL, MDL)
 | 
			
		||||
FTR = (PPV, BVB)
 | 
			
		||||
KNX = (FPX, SPD)
 | 
			
		||||
MHK = (JHG, JLN)
 | 
			
		||||
TDR = (XCS, VXV)
 | 
			
		||||
HVC = (VSS, QXR)
 | 
			
		||||
QXC = (HPS, HMQ)
 | 
			
		||||
RRL = (NMC, LXP)
 | 
			
		||||
MLD = (PRL, RPP)
 | 
			
		||||
LCF = (MTV, QBF)
 | 
			
		||||
VXV = (JTS, GRM)
 | 
			
		||||
XTV = (RNL, VTC)
 | 
			
		||||
LFL = (MFC, DXX)
 | 
			
		||||
CBC = (GTB, MPF)
 | 
			
		||||
CQN = (GPT, QRH)
 | 
			
		||||
DDH = (NNL, CLD)
 | 
			
		||||
GHN = (GXQ, MNP)
 | 
			
		||||
JGT = (DHQ, GQG)
 | 
			
		||||
HCT = (CKC, TTD)
 | 
			
		||||
QCK = (GJN, RVB)
 | 
			
		||||
SGF = (JSP, RCR)
 | 
			
		||||
MPL = (XLX, LMX)
 | 
			
		||||
XDQ = (LXV, LXV)
 | 
			
		||||
MLN = (TDQ, XKV)
 | 
			
		||||
SGZ = (JQL, QDT)
 | 
			
		||||
VRQ = (SGC, VDR)
 | 
			
		||||
FPL = (LSQ, HMK)
 | 
			
		||||
SQB = (GNM, HHF)
 | 
			
		||||
MHX = (PGT, JGN)
 | 
			
		||||
QFT = (HKC, RRD)
 | 
			
		||||
LXX = (CPF, SRQ)
 | 
			
		||||
CPR = (GKB, MTS)
 | 
			
		||||
HLP = (LNF, HGF)
 | 
			
		||||
GJS = (GPN, LXX)
 | 
			
		||||
QKV = (DCT, SDM)
 | 
			
		||||
XST = (XDQ, MXM)
 | 
			
		||||
VXX = (QCS, TRQ)
 | 
			
		||||
KFP = (HXS, MLD)
 | 
			
		||||
MSL = (RHS, DFN)
 | 
			
		||||
NQX = (RQK, PFK)
 | 
			
		||||
CGC = (LRS, KBV)
 | 
			
		||||
FQT = (TRN, DDN)
 | 
			
		||||
VMH = (LBC, JLS)
 | 
			
		||||
VHM = (LSN, KJX)
 | 
			
		||||
JXR = (BVT, RKK)
 | 
			
		||||
KPN = (QQG, NTL)
 | 
			
		||||
QKM = (GST, GXK)
 | 
			
		||||
JNL = (XKL, JBQ)
 | 
			
		||||
BVM = (KHF, FTD)
 | 
			
		||||
XPK = (SQN, MLN)
 | 
			
		||||
GJN = (MLR, XHT)
 | 
			
		||||
							
								
								
									
										149
									
								
								day08/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								day08/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,149 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	result, err := aoc.Runner(run)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println("ERR", err)
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Println("result", result)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	stepsPT1 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) {
 | 
			
		||||
	var path []rune
 | 
			
		||||
	m := make(nodeMap)
 | 
			
		||||
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		text := scan.Text()
 | 
			
		||||
		if len(text) == 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(path) == 0 {
 | 
			
		||||
			fmt.Println("path", text)
 | 
			
		||||
			path = []rune(strings.TrimSpace(text))
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		n := &node{}
 | 
			
		||||
		i, err := fmt.Sscanf(text, "%s = (%s %s", &n.value, &n.lvalue, &n.rvalue)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		n.lvalue = strings.TrimRight(n.lvalue, ",)")
 | 
			
		||||
		n.rvalue = strings.TrimRight(n.rvalue, ",)")
 | 
			
		||||
		m[n.value] = n
 | 
			
		||||
 | 
			
		||||
		fmt.Println("value", i, n.value, n.lvalue, n.rvalue)
 | 
			
		||||
	}
 | 
			
		||||
	if err := m.mapNodes(); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	steps1 := m.SolvePT1(path)
 | 
			
		||||
	steps2 := m.SolvePT2(path)
 | 
			
		||||
 | 
			
		||||
	return &result{steps1, steps2}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type node struct {
 | 
			
		||||
	value          string
 | 
			
		||||
	lvalue, rvalue string
 | 
			
		||||
	left, right    *node
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type nodeMap map[string]*node
 | 
			
		||||
 | 
			
		||||
func (m nodeMap) mapNodes() error {
 | 
			
		||||
	for k, v := range m {
 | 
			
		||||
		if ptr, ok := m[v.lvalue]; ok {
 | 
			
		||||
			v.left = ptr
 | 
			
		||||
		} else {
 | 
			
		||||
			return fmt.Errorf("%s L-> %s not found", k, v.lvalue)
 | 
			
		||||
		}
 | 
			
		||||
		if ptr, ok := m[v.rvalue]; ok {
 | 
			
		||||
			v.right = ptr
 | 
			
		||||
		} else {
 | 
			
		||||
			return fmt.Errorf("%s R-> %s not found", k, v.rvalue)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m[k] = v
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m nodeMap) solver(start string, isEnd func(string) bool, path []rune) uint64 {
 | 
			
		||||
	position, ok := m[start]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	var i int
 | 
			
		||||
	var steps uint64
 | 
			
		||||
 | 
			
		||||
	for steps < ^uint64(0) {
 | 
			
		||||
		steps++
 | 
			
		||||
		if path[i] == 'R' {
 | 
			
		||||
			// fmt.Println("step", steps, position.value, "R->", position.rvalue)
 | 
			
		||||
			position = position.right
 | 
			
		||||
		} else {
 | 
			
		||||
			// fmt.Println("step", steps, position.value, "L->", position.lvalue)
 | 
			
		||||
			position = position.left
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if isEnd(position.value) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		i++
 | 
			
		||||
		if i > len(path)-1 {
 | 
			
		||||
			i = 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return steps
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m nodeMap) SolvePT1(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 ----")
 | 
			
		||||
	defer fmt.Println("---- PART 2 END ----")
 | 
			
		||||
 | 
			
		||||
	var starts []*node
 | 
			
		||||
 | 
			
		||||
	for k, n := range m {
 | 
			
		||||
		if strings.HasSuffix(k, "A") {
 | 
			
		||||
			fmt.Println("start", k)
 | 
			
		||||
			starts = append(starts, n)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	loops := make([]uint64, len(starts))
 | 
			
		||||
	for i, n := range starts {
 | 
			
		||||
		loops[i] = m.solver(n.value, func(s string) bool { return strings.HasSuffix(s, "Z") }, path)
 | 
			
		||||
	}
 | 
			
		||||
	return aoc.LCM(loops...)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										80
									
								
								day08/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								day08/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,80 @@
 | 
			
		||||
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 example3.txt
 | 
			
		||||
var example3 []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.stepsPT1)
 | 
			
		||||
	is.Equal(result.stepsPT1, uint64(2))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.stepsPT1)
 | 
			
		||||
	is.Equal(result.stepsPT1, uint64(6))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestExample3(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(example3))
 | 
			
		||||
 | 
			
		||||
	result, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
 | 
			
		||||
	t.Log(result.stepsPT2)
 | 
			
		||||
	is.Equal(result.stepsPT2, uint64(6))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestInput(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(input))
 | 
			
		||||
 | 
			
		||||
	result, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
 | 
			
		||||
	t.Log("part1 solution", result.stepsPT1)
 | 
			
		||||
	is.Equal(result.stepsPT1, uint64(14429))
 | 
			
		||||
 | 
			
		||||
	t.Log("part2 solution", result.stepsPT2)
 | 
			
		||||
	is.Equal(result.stepsPT2, uint64(10921547990923))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// first: 14429
 | 
			
		||||
// second: 10921547990923
 | 
			
		||||
 | 
			
		||||
// Brüt
 | 
			
		||||
// stops 1 steps 13201
 | 
			
		||||
// stops 2 steps 620447
 | 
			
		||||
// stops 3 steps 36606373
 | 
			
		||||
// stops 4 steps 2232988753
 | 
			
		||||
// stops 5 steps 149610246451
 | 
			
		||||
							
								
								
									
										3
									
								
								day09/example.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								day09/example.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
0 3 6 9 12 15
 | 
			
		||||
1 3 6 10 15 21
 | 
			
		||||
10 13 16 21 30 45
 | 
			
		||||
							
								
								
									
										200
									
								
								day09/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								day09/input.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,200 @@
 | 
			
		||||
28 38 58 115 255 558 1167 2343 4564 8699 16328 30378 56447 105549 199601 381868 735876 1418100 2712150 5115341 9472583
 | 
			
		||||
24 34 56 103 191 343 593 990 1602 2520 3862 5777 8449 12101 16999 23456 31836 42558 56100 73003 93875
 | 
			
		||||
12 30 66 118 187 291 486 901 1807 3760 7885 16402 33536 67001 130303 246169 451478 804146 1392500 2347766 3860393
 | 
			
		||||
11 7 -1 -10 4 101 392 1052 2337 4631 8595 15584 28661 54781 109041 222274 453659 910327 1775963 3349730 6094694
 | 
			
		||||
13 26 56 110 200 360 677 1347 2785 5847 12267 25493 52275 105732 211455 420013 833076 1658291 3323777 6713131 13636877
 | 
			
		||||
24 36 50 68 92 124 166 220 288 372 474 596 740 908 1102 1324 1576 1860 2178 2532 2924
 | 
			
		||||
4 10 18 35 81 207 523 1232 2664 5299 9766 16819 27345 42607 65306 103013 177906 352348 792280 1916515 4732055
 | 
			
		||||
2 4 15 46 115 246 479 915 1841 4022 9326 21995 51143 115539 252570 534754 1099830 2205374 4328183 8346246 15873877
 | 
			
		||||
6 16 41 104 240 508 1016 1959 3670 6684 11815 20246 33632 54216 84958 129677 193206 281560 402117 563812 777344
 | 
			
		||||
10 24 59 127 240 410 649 969 1382 1900 2535 3299 4204 5262 6485 7885 9474 11264 13267 15495 17960
 | 
			
		||||
1 3 19 65 161 334 621 1072 1753 2749 4167 6139 8825 12416 17137 23250 31057 40903 53179 68325 86833
 | 
			
		||||
1 3 14 46 118 256 493 869 1431 2233 3336 4808 6724 9166 12223 15991 20573 26079 32626 40338 49346
 | 
			
		||||
5 20 54 111 200 339 551 863 1338 2203 4189 9270 22068 52271 118490 254073 515553 994838 1837662 3275301 5689494
 | 
			
		||||
11 19 37 74 152 315 630 1176 2019 3189 4728 6991 11599 23863 58350 151043 385257 945993 2232085 5082986 11226568
 | 
			
		||||
-6 -5 -1 6 16 29 45 64 86 111 139 170 204 241 281 324 370 419 471 526 584
 | 
			
		||||
19 44 79 123 175 234 299 369 443 520 599 679 759 838 915 989 1059 1124 1183 1235 1279
 | 
			
		||||
20 26 41 76 144 261 459 824 1572 3189 6707 14297 30581 65483 140200 299218 633600 1324592 2722729 5487182 10824554
 | 
			
		||||
2 13 49 134 316 686 1400 2714 5060 9211 16601 29879 53781 96407 171038 298877 513930 873445 1482345 2550372 4520094
 | 
			
		||||
7 22 55 116 218 381 645 1090 1862 3209 5540 9533 16335 27918 47680 81409 138761 235440 396309 659706 1083288
 | 
			
		||||
23 34 43 54 73 105 151 202 234 223 220 555 2284 8074 23894 62315 149406 340397 757350 1681105 3771572
 | 
			
		||||
-2 9 31 72 157 346 769 1701 3724 8065 17266 36441 75513 153008 302220 580858 1085650 1973817 3493849 6028622 10154597
 | 
			
		||||
17 35 83 175 326 554 878 1305 1800 2233 2292 1349 -1702 -8485 -20570 -37084 -47977 -18173 145725 659887 1980386
 | 
			
		||||
6 19 49 119 273 598 1257 2530 4856 8858 15310 24963 38082 53479 66865 68818 44405 -18660 -94790 -14282 809438
 | 
			
		||||
17 21 22 20 15 7 -4 -18 -35 -55 -78 -104 -133 -165 -200 -238 -279 -323 -370 -420 -473
 | 
			
		||||
8 23 59 139 312 672 1383 2710 5056 9005 15371 25253 40096 61758 92583 135480 194008 272467 375995 510671 683624
 | 
			
		||||
9 16 34 63 103 154 216 289 373 468 574 691 819 958 1108 1269 1441 1624 1818 2023 2239
 | 
			
		||||
8 19 59 140 275 481 794 1315 2308 4381 8817 18206 37692 77458 157694 318613 640892 1287715 2591041 5226414 10560561
 | 
			
		||||
8 21 37 57 82 107 117 88 -4 -163 -339 -377 54 1555 5117 12270 25264 47285 82709 137397 219034
 | 
			
		||||
22 34 44 52 58 62 64 64 62 58 52 44 34 22 8 -8 -26 -46 -68 -92 -118
 | 
			
		||||
28 57 114 220 416 779 1446 2651 4785 8494 14832 25483 43057 71450 116238 185052 287858 437047 647230 934638 1316054
 | 
			
		||||
16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96
 | 
			
		||||
28 39 48 62 97 180 347 630 1022 1413 1518 905 -557 -1064 7553 50137 189888 570667 1494764 3559032 7883557
 | 
			
		||||
5 0 3 30 106 262 542 1035 1947 3728 7269 14184 27192 50614 91000 157901 264801 430224 679031 1043922 1567158
 | 
			
		||||
4 21 55 119 239 461 864 1591 2913 5356 9967 18894 36631 72557 145803 294037 588486 1158435 2229571 4181885 7634411
 | 
			
		||||
8 11 15 33 81 182 384 805 1728 3777 8206 17321 35023 67400 123199 213865 352632 551879 817609 1139457 1474069
 | 
			
		||||
6 15 30 69 162 358 754 1560 3223 6658 13679 27799 55705 109973 214073 411584 783020 1476065 2758724 5110417 9373988
 | 
			
		||||
18 26 37 54 84 138 231 382 614 954 1433 2086 2952 4074 5499 7278 9466 12122 15309 19094 23548
 | 
			
		||||
3 -2 -7 -12 -17 -22 -27 -32 -37 -42 -47 -52 -57 -62 -67 -72 -77 -82 -87 -92 -97
 | 
			
		||||
16 32 61 121 242 466 847 1451 2356 3652 5441 7837 10966 14966 19987 26191 33752 42856 53701 66497 81466
 | 
			
		||||
13 35 79 160 302 554 1015 1865 3399 6061 10475 17470 28096 43628 65555 95551 135425 187047 252247 332684 429682
 | 
			
		||||
13 6 -9 -20 11 156 538 1364 2981 5967 11279 20495 36207 62647 106658 179157 297277 487420 789503 1262734 1993315
 | 
			
		||||
14 11 18 51 141 348 790 1714 3660 7803 16602 34939 71995 144184 279550 524126 950858 1671811 2854498 4743307 7687145
 | 
			
		||||
2 7 22 56 123 242 437 737 1176 1793 2632 3742 5177 6996 9263 12047 15422 19467 24266 29908 36487
 | 
			
		||||
19 34 68 128 220 349 519 733 993 1300 1654 2054 2498 2983 3505 4059 4639 5238 5848 6460 7064
 | 
			
		||||
21 48 85 132 195 292 468 836 1684 3739 8772 20876 48964 111327 243473 510946 1029407 1994954 3728471 6738732 11810049
 | 
			
		||||
11 27 55 108 210 394 696 1143 1733 2405 2997 3190 2436 -132 -5810 -16455 -34641 -63841 -108637 -174960 -270362
 | 
			
		||||
12 12 12 25 90 292 791 1869 4012 8064 15537 29266 54829 103647 199701 393835 793523 1623291 3344337 6885726 14081159
 | 
			
		||||
5 13 31 72 164 358 736 1410 2499 4070 6039 8076 9700 11088 15835 38309 120943 371965 1044017 2693426 6497234
 | 
			
		||||
-1 -4 4 46 162 411 867 1607 2698 4206 6273 9338 14615 24985 46510 90835 178809 345728 648682 1176574 2063472
 | 
			
		||||
8 16 23 40 92 216 455 847 1408 2108 2839 3374 3316 2036 -1401 -8323 -20552 -40520 -71401 -117260 -183220
 | 
			
		||||
27 54 93 143 215 340 581 1059 2009 3892 7603 14833 28665 54510 101519 184641 327535 566586 956321 1576571 2541779
 | 
			
		||||
18 25 37 63 114 201 333 515 746 1017 1309 1591 1818 1929 1845 1467 674 -679 -2763 -5777 -9950
 | 
			
		||||
11 23 58 131 266 508 956 1834 3618 7240 14408 28142 53779 101035 188408 352630 668776 1292502 2547568 5104551 10339633
 | 
			
		||||
20 30 55 112 230 464 919 1792 3444 6514 12092 22012 39486 70717 129039 244932 488666 1018738 2181538 4711697 10130222
 | 
			
		||||
8 15 22 29 36 43 50 57 64 71 78 85 92 99 106 113 120 127 134 141 148
 | 
			
		||||
8 17 18 5 -32 -110 -256 -510 -928 -1585 -2578 -4029 -6088 -8936 -12788 -17896 -24552 -33091 -43894 -57391 -74064
 | 
			
		||||
0 6 28 73 155 304 573 1043 1826 3066 4938 7645 11413 16484 23107 31527 41972 54638 69672 87153 107071
 | 
			
		||||
8 14 26 39 49 61 112 320 974 2687 6657 15139 32341 66134 131237 254984 487637 921079 1723959 3210704 5981290
 | 
			
		||||
-3 6 32 88 209 468 1005 2092 4276 8669 17497 35106 69812 137381 267702 517614 995199 1904592 3626038 6854228 12829699
 | 
			
		||||
16 14 18 32 52 64 53 40 180 979 3722 11247 29252 68383 147421 297965 571096 1046604 1845466 3146378 5207268
 | 
			
		||||
0 19 60 146 330 708 1432 2721 4864 8205 13096 19800 28322 38142 47820 54439 52848 34663 -13020 -109250 -281238
 | 
			
		||||
19 37 70 119 185 269 372 495 639 805 994 1207 1445 1709 2000 2319 2667 3045 3454 3895 4369
 | 
			
		||||
8 18 30 51 92 174 350 764 1787 4310 10347 24225 54843 119816 252855 516572 1024178 1975442 3715028 6825207 12270294
 | 
			
		||||
9 31 64 108 163 229 306 394 493 603 724 856 999 1153 1318 1494 1681 1879 2088 2308 2539
 | 
			
		||||
27 36 46 65 110 223 504 1178 2725 6116 13214 27417 54640 104755 193632 345950 598975 1007532 1650430 2638633 4125506
 | 
			
		||||
-3 -9 -19 -25 -9 63 252 660 1449 2882 5441 10155 19412 38768 80661 171586 365345 766697 1572457 3141343 6110353
 | 
			
		||||
9 13 16 19 30 81 256 730 1819 4041 8188 15409 27304 46029 74412 116080 175597 258613 372024 524143 724882
 | 
			
		||||
8 17 26 35 44 53 62 71 80 89 98 107 116 125 134 143 152 161 170 179 188
 | 
			
		||||
13 29 69 150 300 564 1014 1770 3055 5340 9688 18482 36824 75023 152753 305660 595433 1124631 2057879 3651414 6293380
 | 
			
		||||
19 39 64 101 169 299 534 929 1551 2479 3804 5629 8069 11251 15314 20409 26699 34359 43576 54549 67489
 | 
			
		||||
26 48 79 119 168 226 293 369 454 548 651 763 884 1014 1153 1301 1458 1624 1799 1983 2176
 | 
			
		||||
16 28 45 62 80 120 240 563 1330 3003 6482 13603 28310 59352 126262 272164 590489 1279633 2753130 5858989 12311553
 | 
			
		||||
16 27 38 49 60 71 82 93 104 115 126 137 148 159 170 181 192 203 214 225 236
 | 
			
		||||
16 26 52 107 212 412 806 1601 3204 6384 12578 24502 47411 91748 178785 352718 706597 1437520 2962583 6158201 12843931
 | 
			
		||||
15 23 44 100 234 527 1138 2396 4995 10379 21457 43857 88008 172421 328611 608145 1092295 1904695 3227218 5318970 8537806
 | 
			
		||||
19 35 67 125 219 359 555 817 1155 1579 2099 2725 3467 4335 5339 6489 7795 9267 10915 12749 14779
 | 
			
		||||
14 9 -2 -25 -60 -96 -107 -38 250 1146 3714 10678 28555 72047 172745 395881 871826 1854119 3824278 7677249 15042442
 | 
			
		||||
0 14 48 119 263 559 1175 2446 5004 10002 19512 37235 69743 128583 233715 418934 740144 1287614 2203656 3707527 6129775
 | 
			
		||||
-6 -13 -11 9 54 127 233 409 798 1797 4331 10342 23629 51210 105348 206191 384454 682459 1149765 1826027 2697892
 | 
			
		||||
14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -1 -2 -3 -4 -5 -6
 | 
			
		||||
9 15 23 41 93 228 528 1127 2265 4422 8622 17094 34685 71869 151157 320706 682873 1452897 3076233 6455943 13379245
 | 
			
		||||
26 38 54 85 154 309 648 1354 2736 5284 9786 17637 31605 57512 107535 206117 399770 772302 1467138 2718337 4891512
 | 
			
		||||
7 2 -4 -11 -19 -28 -38 -49 -61 -74 -88 -103 -119 -136 -154 -173 -193 -214 -236 -259 -283
 | 
			
		||||
17 40 72 120 202 355 665 1340 2867 6327 14000 30508 64985 135242 275772 552897 1092529 2128842 4085140 7700052 14210216
 | 
			
		||||
-3 -4 -7 -12 -19 -28 -39 -52 -67 -84 -103 -124 -147 -172 -199 -228 -259 -292 -327 -364 -403
 | 
			
		||||
9 21 38 62 99 161 268 450 749 1221 1938 2990 4487 6561 9368 13090 17937 24149 31998 41790 53867
 | 
			
		||||
2 9 39 99 204 393 760 1519 3132 6545 13600 27720 54996 105835 197349 356668 625334 1064865 1763453 2843561 4469892
 | 
			
		||||
20 33 49 75 125 228 457 1004 2337 5480 12453 26893 54846 105671 192927 335020 555266 880875 1340177 1957191 2742379
 | 
			
		||||
18 21 16 6 5 57 270 860 2190 4774 9202 15936 24945 35235 44593 50493 54394 73951 171296 510662 1464845
 | 
			
		||||
10 11 18 38 71 100 71 -142 -790 -2316 -5409 -10945 -19511 -29701 -33227 -2480 138638 579164 1757487 4641596 11293649
 | 
			
		||||
25 33 43 67 138 323 742 1611 3346 6797 13731 27756 55976 111792 219447 421300 789851 1449309 2618271 4700169 8479106
 | 
			
		||||
27 42 62 88 120 169 286 615 1492 3635 8492 18826 39628 79522 153115 285551 522357 951296 1749478 3279940 6279276
 | 
			
		||||
-1 11 47 125 280 574 1106 2022 3525 5885 9449 14651 22022 32200 45940 64124 87771 118047 156275 203945 262724
 | 
			
		||||
13 21 51 115 225 393 631 951 1365 1885 2523 3291 4201 5265 6495 7903 9501 11301 13315 15555 18033
 | 
			
		||||
20 35 53 83 140 245 425 713 1148 1775 2645 3815 5348 7313 9785 12845 16580 21083 26453 32795 40220
 | 
			
		||||
10 26 63 132 248 429 694 1074 1663 2751 5098 10427 22235 47044 96239 188667 354200 638496 1109225 1864062 3040786
 | 
			
		||||
6 -1 -9 -15 -17 -13 13 141 635 2188 6391 16606 39556 88146 186315 377108 735668 1389501 2549183 4553679 7935653
 | 
			
		||||
9 15 43 117 265 514 885 1388 2017 2745 3519 4255 4833 5092 4825 3774 1625 -1997 -7533 -15495 -26471
 | 
			
		||||
7 22 41 65 106 207 489 1245 3117 7431 16845 36609 76972 157632 315649 618971 1188707 2234572 4109585 7392185 13006510
 | 
			
		||||
10 9 5 -1 3 51 224 700 1840 4321 9327 18809 35825 64971 112914 189038 306214 481705 738217 1105107 1619759
 | 
			
		||||
12 16 30 69 148 282 486 775 1164 1668 2302 3081 4020 5134 6438 7947 9676 11640 13854 16333 19092
 | 
			
		||||
1 0 10 42 98 172 270 462 979 2368 5718 12970 27324 53756 99658 175614 296325 481696 758098 1159818 1730710
 | 
			
		||||
8 19 38 73 142 283 562 1079 1973 3430 5708 9217 14739 23954 40566 72513 136014 262573 510546 983505 1858428
 | 
			
		||||
9 24 57 114 205 359 643 1184 2197 4026 7209 12582 21441 35785 58667 94684 150641 236428 366153 559578 843909
 | 
			
		||||
8 14 22 32 44 58 74 92 112 134 158 184 212 242 274 308 344 382 422 464 508
 | 
			
		||||
24 34 44 54 64 74 84 94 104 114 124 134 144 154 164 174 184 194 204 214 224
 | 
			
		||||
16 30 63 126 233 405 686 1187 2184 4316 8979 19130 40965 87415 185254 389023 807192 1649322 3307839 6494862 12463897
 | 
			
		||||
-7 -7 1 32 121 335 787 1666 3321 6479 12739 25563 52073 106047 212569 414805 783321 1428197 2513885 4276266 7040633
 | 
			
		||||
-2 1 4 7 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58
 | 
			
		||||
13 27 38 41 36 48 177 688 2156 5707 13455 29337 60698 121182 235783 449463 842011 1554867 2842648 5177133 9461476
 | 
			
		||||
15 42 93 182 326 549 884 1374 2086 3178 5119 9300 19562 45721 111199 268798 632393 1439844 3177921 6832092 14389654
 | 
			
		||||
7 28 73 151 265 408 559 679 707 556 109 -785 -2315 -4712 -8253 -13265 -20129 -29284 -41231 -56537 -75839
 | 
			
		||||
8 5 13 42 97 177 284 446 766 1532 3473 8340 20149 47680 109278 241921 518597 1082840 2220086 4508651 9140126
 | 
			
		||||
17 27 40 71 149 317 632 1165 2001 3239 4992 7387 10565 14681 19904 26417 34417 44115 55736 69519 85717
 | 
			
		||||
24 37 47 65 117 257 594 1347 2963 6367 13474 28217 58615 120994 248715 510261 1046343 2144574 4386122 8926186 18016274
 | 
			
		||||
11 16 36 80 158 277 445 706 1254 2711 6703 16929 40991 93338 199774 404089 777493 1431666 2536382 4342822 7213860
 | 
			
		||||
0 -2 8 48 141 321 657 1303 2580 5096 9915 18799 34571 61685 107144 181982 303624 499562 812938 1310810 2096097
 | 
			
		||||
4 15 39 91 211 473 995 1967 3741 7078 13740 27774 58093 123376 261026 543285 1106377 2204300 4310572 8314176 15899538
 | 
			
		||||
-7 6 36 87 163 272 446 788 1568 3411 7651 16966 36460 75419 150039 287505 531891 952452 1654990 2797097 4608209
 | 
			
		||||
13 29 56 95 152 244 405 692 1191 2023 3350 5381 8378 12662 18619 26706 37457 51489 69508 92315 120812
 | 
			
		||||
15 27 59 125 237 417 722 1283 2361 4428 8300 15415 28528 53504 103742 210470 445527 969865 2133765 4678765 10135083
 | 
			
		||||
20 31 57 122 274 596 1223 2377 4439 8101 14695 26909 50338 96812 191434 387177 794467 1639641 3377468 6902112 13932807
 | 
			
		||||
10 37 91 200 416 820 1528 2716 4696 8091 14175 25464 46666 86122 157896 284700 501870 862641 1445003 2360456 3765020
 | 
			
		||||
6 24 54 95 153 251 440 812 1516 2778 4926 8421 13895 22197 34448 52106 77042 111628 158838 222363 306741
 | 
			
		||||
9 24 49 84 125 162 193 281 693 2172 6405 16762 39393 84782 169869 320863 576881 994560 1653801 2664816 4176661
 | 
			
		||||
3 10 23 57 149 386 945 2142 4499 8866 16685 30566 55492 101260 187366 352765 675303 1309938 2562335 5026719 9836291
 | 
			
		||||
15 29 55 109 226 481 1024 2134 4299 8344 15672 28779 52397 95981 178896 340733 660899 1294259 2533505 4914517 9388784
 | 
			
		||||
14 33 78 166 331 644 1248 2423 4711 9165 17861 34963 68917 136884 273538 548338 1099300 2198986 4383250 8701159 17195603
 | 
			
		||||
7 5 5 7 11 17 25 35 47 61 77 95 115 137 161 187 215 245 277 311 347
 | 
			
		||||
0 2 9 21 38 60 87 119 156 198 245 297 354 416 483 555 632 714 801 893 990
 | 
			
		||||
8 11 29 79 200 478 1087 2365 4957 10076 19965 38689 73433 136495 248086 439830 758518 1269449 2059289 3241351 4974534
 | 
			
		||||
9 26 71 154 282 459 686 961 1279 1632 2009 2396 2776 3129 3432 3659 3781 3766 3579 3182 2534
 | 
			
		||||
-8 -9 -1 23 70 147 261 419 628 895 1227 1631 2114 2683 3345 4107 4976 5959 7063 8295 9662
 | 
			
		||||
14 38 88 183 349 621 1047 1694 2656 4064 6098 9001 13095 18799 26649 37320 51650 70666 95612 127979 169537
 | 
			
		||||
1 4 7 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58 61
 | 
			
		||||
10 17 33 71 156 319 593 1016 1655 2681 4550 8393 16823 35591 76964 166498 356232 749489 1545759 3118955 6149158
 | 
			
		||||
-2 5 20 55 147 378 896 1945 3924 7507 13868 25067 44665 78648 136752 234293 394618 652305 1057252 1679807 2617103
 | 
			
		||||
-2 -3 -3 12 76 250 640 1443 3044 6202 12405 24581 48599 96524 193673 393656 809674 1677915 3482413 7194006 14714566
 | 
			
		||||
-5 -2 2 11 40 131 388 1045 2594 6015 13162 27362 54272 103007 187497 327953 552225 896728 1406510 2133961 3135644
 | 
			
		||||
-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21
 | 
			
		||||
6 23 51 90 140 201 273 356 450 555 671 798 936 1085 1245 1416 1598 1791 1995 2210 2436
 | 
			
		||||
22 44 78 135 237 421 758 1410 2772 5783 12540 27421 59046 123639 250801 493519 945638 1772306 3262446 5917591 10599023
 | 
			
		||||
24 37 60 106 197 375 727 1435 2867 5730 11311 21837 40990 74618 131688 225532 375442 608675 962934 1489396 2256363
 | 
			
		||||
12 20 49 112 222 392 635 964 1392 1932 2597 3400 4354 5472 6767 8252 9940 11844 13977 16352 18982
 | 
			
		||||
2 7 24 61 126 227 372 569 826 1151 1552 2037 2614 3291 4076 4977 6002 7159 8456 9901 11502
 | 
			
		||||
12 11 22 60 158 379 821 1618 2953 5122 8728 15159 27666 53731 110255 234858 510014 1112985 2415218 5172306 10872818
 | 
			
		||||
17 24 49 120 294 677 1456 2952 5715 10719 19792 36560 68444 130715 254454 501802 994701 1968430 3870295 7539464 14530122
 | 
			
		||||
25 40 65 122 253 535 1117 2293 4630 9184 17861 34010 63355 115342 204806 353380 588983 939636 1414390 1959381 2372399
 | 
			
		||||
25 52 90 138 195 260 332 410 493 580 670 762 855 948 1040 1130 1217 1300 1378 1450 1515
 | 
			
		||||
0 2 24 87 221 468 885 1547 2550 4014 6086 8943 12795 17888 24507 32979 43676 57018 73476 93575 117897
 | 
			
		||||
19 32 61 117 214 369 603 947 1457 2242 3509 5629 9228 15307 25395 41739 67535 107204 166717 253973 379234
 | 
			
		||||
23 32 38 44 60 103 197 373 669 1130 1808 2762 4058 5769 7975 10763 14227 18468 23594 29720 36968
 | 
			
		||||
4 11 19 35 76 180 439 1069 2539 5797 12662 26510 53500 104832 201057 380617 717363 1357502 2598934 5062820 10063437
 | 
			
		||||
10 19 23 14 -24 -121 -314 -610 -897 -761 888 6598 22021 59353 144459 331532 733040 1580211 3343069 6963206 14293206
 | 
			
		||||
3 17 48 105 201 354 600 1028 1847 3495 6800 13203 25053 45984 81384 138966 229451 367373 572016 868493 1288977
 | 
			
		||||
-4 -3 10 49 132 289 583 1147 2252 4449 8873 17855 36050 72341 142802 274973 513588 927669 1618516 2727541 4442064
 | 
			
		||||
19 39 74 133 236 422 765 1415 2696 5313 10758 22099 45557 93732 192181 392487 797276 1606233 3197558 6267150 12058959
 | 
			
		||||
-7 -10 -13 -16 -19 -22 -25 -28 -31 -34 -37 -40 -43 -46 -49 -52 -55 -58 -61 -64 -67
 | 
			
		||||
21 44 74 122 221 432 849 1603 2865 4848 7808 12044 17897 25748 36015 49149 65629 85956 110646 140222 175205
 | 
			
		||||
18 26 39 66 116 198 321 494 726 1026 1403 1866 2424 3086 3861 4758 5786 6954 8271 9746 11388
 | 
			
		||||
21 40 78 164 356 766 1605 3259 6420 12322 23187 43106 79841 148586 279840 535679 1042583 2055644 4079972 8092520 15934162
 | 
			
		||||
20 37 62 95 136 185 242 307 380 461 550 647 752 865 986 1115 1252 1397 1550 1711 1880
 | 
			
		||||
0 2 15 48 121 283 642 1407 2942 5832 10961 19602 33519 55081 87388 134409 201132 293726 419715 588164 809877
 | 
			
		||||
8 13 15 13 15 42 131 338 755 1592 3455 8105 20256 51423 127543 303162 686530 1482119 3060047 6065853 11589253
 | 
			
		||||
12 30 59 93 125 157 214 361 722 1498 2987 5640 10262 18599 34737 67942 137708 281702 566759 1101727 2048287
 | 
			
		||||
-3 10 49 127 264 492 863 1464 2440 4028 6633 11078 19417 37246 79490 183510 436575 1030078 2361565 5219525 11107638
 | 
			
		||||
16 33 54 90 174 378 846 1849 3867 7702 14625 26559 46299 77769 126315 199032 305122 456279 667096 955488 1343124
 | 
			
		||||
19 43 88 176 343 647 1194 2198 4111 7897 15598 31482 64323 131829 269087 544536 1090317 2160903 4249054 8320480 16296305
 | 
			
		||||
22 41 67 112 212 447 969 2039 4084 7808 14445 26357 48398 90840 175255 345646 688410 1366499 2675535 5132758 9613680
 | 
			
		||||
12 25 47 89 162 277 445 677 984 1377 1867 2465 3182 4029 5017 6157 7460 8937 10599 12457 14522
 | 
			
		||||
5 0 -7 -1 49 197 534 1225 2596 5304 10634 21018 41034 79540 154415 302881 602927 1215420 2462671 4968277 9895903
 | 
			
		||||
-9 -14 -15 1 65 237 627 1430 2974 5775 10594 18507 31038 50464 80459 127293 201992 324897 538038 942790 1811370
 | 
			
		||||
2 4 0 -10 -11 41 233 709 1684 3458 6430 11112 18143 28303 42527 61919 87766 121552 164972 219946 288633
 | 
			
		||||
7 26 67 150 317 656 1342 2714 5434 10819 21508 42739 84695 166680 324376 622208 1174037 2177180 3967333 7105608 12513901
 | 
			
		||||
12 22 38 64 119 247 532 1123 2276 4424 8309 15295 28210 53572 107038 225653 493336 1090494 2385292 5093646 10548309
 | 
			
		||||
14 12 10 19 59 159 357 700 1244 2054 3204 4777 6865 9569 12999 17274 22522 28880 36494 45519 56119
 | 
			
		||||
2 14 43 115 280 632 1341 2710 5286 10076 18959 35465 66244 123814 231609 433008 806986 1494370 2740499 4962479 8852304
 | 
			
		||||
16 36 82 165 307 556 1007 1841 3405 6374 12066 23034 44170 84820 163047 314653 612780 1210538 2432293 4964944 10250289
 | 
			
		||||
10 8 10 20 58 188 557 1451 3382 7223 14402 27147 48738 83665 137509 216252 324578 462546 619794 766166 837338
 | 
			
		||||
9 22 46 85 154 288 571 1200 2601 5616 11777 23672 45407 83249 146871 252546 431725 752582 1369644 2629419 5280540
 | 
			
		||||
16 20 35 87 210 449 878 1653 3133 6129 12402 25663 53593 111897 232285 477770 971150 1946550 3840269 7447123 14183748
 | 
			
		||||
22 44 94 197 405 821 1643 3250 6376 12465 24392 47913 94545 187207 371116 734593 1448530 2841203 5540681 10747619 20760527
 | 
			
		||||
4 15 42 101 226 487 1024 2115 4318 8768 17778 36006 72647 145461 288069 563007 1084756 2059673 3853830 7105719 12909204
 | 
			
		||||
15 23 48 115 271 611 1319 2724 5371 10107 18182 31365 52075 83527 129893 196478 289911 418351 591708 821879 1122999
 | 
			
		||||
7 6 17 48 107 202 341 532 783 1102 1497 1976 2547 3218 3997 4892 5911 7062 8353 9792 11387
 | 
			
		||||
-4 3 25 70 153 309 619 1270 2682 5750 12268 25628 51937 101824 193553 358902 655155 1190487 2177891 4048307 7684230
 | 
			
		||||
-2 4 19 40 65 112 264 766 2210 5847 14057 30979 63235 120551 215877 364424 581237 878545 1269600 1800115 2661524
 | 
			
		||||
18 30 45 58 64 58 35 -10 -82 -186 -327 -510 -740 -1022 -1361 -1762 -2230 -2770 -3387 -4086 -4872
 | 
			
		||||
8 20 59 143 292 523 844 1247 1700 2138 2453 2483 2000 697 -1826 -6077 -12688 -22432 -36241 -55225 -80692
 | 
			
		||||
11 12 8 -7 -28 -26 65 361 1041 2360 4662 8393 14114 22514 34423 50825 72871 101892 139412 187161 247088
 | 
			
		||||
6 6 19 54 113 189 264 307 272 96 -303 -1028 -2205 -3985 -6546 -10095 -14870 -21142 -29217 -39438 -52187
 | 
			
		||||
26 40 63 112 222 455 906 1708 3036 5116 8278 13187 21602 38439 76677 167925 383519 874229 1941697 4162964 8603981
 | 
			
		||||
12 19 31 58 110 209 412 843 1741 3551 7128 14215 28539 58216 120779 253209 531098 1103839 2256973 4519124 8840092
 | 
			
		||||
14 28 47 71 102 153 266 539 1162 2462 4957 9419 16946 29043 47712 75551 115862 172768 251339 357727 499310
 | 
			
		||||
19 22 38 89 208 457 958 1941 3833 7447 14380 27796 53861 104226 200137 378978 704206 1279303 2264473 3888958 6437241
 | 
			
		||||
20 38 83 177 353 665 1204 2120 3650 6152 10145 16355 25767 39683 59786 88210 127616 181274 253151 348005 471485
 | 
			
		||||
18 33 52 75 103 147 258 596 1573 4137 10313 24197 53757 114135 233848 466630 914030 1767831 3387708 6439669 12137157
 | 
			
		||||
16 32 61 98 136 164 171 173 281 836 2678 7743 20501 51456 125378 299753 704238 1621680 3648963 8007452 17127734
 | 
			
		||||
0 9 25 62 141 293 566 1037 1844 3286 6097 12096 25583 56164 124287 271914 582905 1221701 2506400 5046590 10003946
 | 
			
		||||
-4 12 56 141 280 486 772 1151 1636 2240 2976 3857 4896 6106 7500 9091 10892 12916 15176 17685 20456
 | 
			
		||||
							
								
								
									
										134
									
								
								day09/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								day09/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,134 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"cmp"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
			
		||||
 | 
			
		||||
var log = aoc.Log
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	var histories [][]int
 | 
			
		||||
	var values []int
 | 
			
		||||
	var rvalues []int
 | 
			
		||||
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		text := scan.Text()
 | 
			
		||||
		if len(text) == 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		histories = append(histories, aoc.ReadStringToInts(strings.Fields(text)))
 | 
			
		||||
 | 
			
		||||
		log(last(histories...))
 | 
			
		||||
 | 
			
		||||
		values = append(values, predictNext(last(histories...)))
 | 
			
		||||
		rvalues = append(rvalues, predictPrev(last(histories...)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log("values", values)
 | 
			
		||||
	log("rvalues", rvalues)
 | 
			
		||||
 | 
			
		||||
	return &result{valuePT1: sum(values...), valuePT2: sum(rvalues...)}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func predictNext(in []int) int {
 | 
			
		||||
	log(" ---- PREDICT NEXT ----")
 | 
			
		||||
	defer log(" ----------------------")
 | 
			
		||||
 | 
			
		||||
	history := makeHistory(in)
 | 
			
		||||
 | 
			
		||||
	aoc.Reverse(history)
 | 
			
		||||
 | 
			
		||||
	return predict(history, func(a, b int) int { return a + b })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func predictPrev(in []int) int {
 | 
			
		||||
	log(" ---- PREDICT PREV ----")
 | 
			
		||||
	defer log(" ----------------------")
 | 
			
		||||
 | 
			
		||||
	history := makeHistory(in)
 | 
			
		||||
 | 
			
		||||
	for i := range history {
 | 
			
		||||
		aoc.Reverse(history[i])
 | 
			
		||||
	}
 | 
			
		||||
	aoc.Reverse(history)
 | 
			
		||||
 | 
			
		||||
	return predict(history, func(a, b int) int { return b - a })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func predict(history [][]int, diff func(a, b int) int) int {
 | 
			
		||||
	log(" ---- PREDICT ----")
 | 
			
		||||
	defer log(" -----------------")
 | 
			
		||||
 | 
			
		||||
	for i := range history[1:] {
 | 
			
		||||
		lastHistory, curHistory := last(history[i]...), last(history[i+1]...)
 | 
			
		||||
 | 
			
		||||
		history[i+1] = append(history[i+1], diff(lastHistory, curHistory))
 | 
			
		||||
		log(lastHistory, curHistory, last(history[i+1]))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log("last", last(history...))
 | 
			
		||||
	return last(last(history...)...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeHistory(in []int) [][]int {
 | 
			
		||||
	var history [][]int
 | 
			
		||||
	history = append(history, in)
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		var diffs []int
 | 
			
		||||
 | 
			
		||||
		current := history[len(history)-1]
 | 
			
		||||
		for i := range current[1:] {
 | 
			
		||||
			diffs = append(diffs, current[i+1]-current[i])
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		history = append(history, diffs)
 | 
			
		||||
		log(diffs)
 | 
			
		||||
 | 
			
		||||
		if max(diffs[0], diffs[1:]...) == 0 && min(diffs[0], diffs[1:]...) == 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return history
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func max[T cmp.Ordered](a T, v ...T) T {
 | 
			
		||||
	for _, b := range v {
 | 
			
		||||
		if b > a {
 | 
			
		||||
			a = b
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return a
 | 
			
		||||
}
 | 
			
		||||
func min[T cmp.Ordered](a T, v ...T) T {
 | 
			
		||||
	for _, b := range v {
 | 
			
		||||
		if b < a {
 | 
			
		||||
			a = b
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return a
 | 
			
		||||
}
 | 
			
		||||
func sum[T cmp.Ordered](v ...T) T {
 | 
			
		||||
	var s T
 | 
			
		||||
	for _, a := range v {
 | 
			
		||||
		s += a
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
func last[T any](v ...T) T {
 | 
			
		||||
	return v[len(v)-1]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								day09/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								day09/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"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.valuePT1, int(114))
 | 
			
		||||
 | 
			
		||||
	is.Equal(result.valuePT2, 2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.valuePT1)
 | 
			
		||||
	is.Equal(result.valuePT1, int(1806615041))
 | 
			
		||||
 | 
			
		||||
	t.Log(result.valuePT2)
 | 
			
		||||
	is.True(result.valuePT2 < 1806615046) // first attempt
 | 
			
		||||
	is.Equal(result.valuePT2, 1211)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								day10/example1.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								day10/example1.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
.....
 | 
			
		||||
.S-7.
 | 
			
		||||
.|.|.
 | 
			
		||||
.L-J.
 | 
			
		||||
.....
 | 
			
		||||
							
								
								
									
										5
									
								
								day10/example2.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								day10/example2.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
..F7.
 | 
			
		||||
.FJ|.
 | 
			
		||||
SJ.L7
 | 
			
		||||
|F--J
 | 
			
		||||
LJ...
 | 
			
		||||
							
								
								
									
										9
									
								
								day10/example3.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								day10/example3.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
...........
 | 
			
		||||
.S-------7.
 | 
			
		||||
.|F-----7|.
 | 
			
		||||
.||.....||.
 | 
			
		||||
.||.....||.
 | 
			
		||||
.|L-7.F-J|.
 | 
			
		||||
.|..|.|..|.
 | 
			
		||||
.L--J.L--J.
 | 
			
		||||
...........
 | 
			
		||||
							
								
								
									
										10
									
								
								day10/example4.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								day10/example4.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
.F----7F7F7F7F-7....
 | 
			
		||||
.|F--7||||||||FJ....
 | 
			
		||||
.||.FJ||||||||L7....
 | 
			
		||||
FJL7L7LJLJ||LJ.L-7..
 | 
			
		||||
L--J.L7...LJS7F-7L7.
 | 
			
		||||
....F-J..F7FJ|L7L7L7
 | 
			
		||||
....L7.F7||L7|.L7L7|
 | 
			
		||||
.....|FJLJ|FJ|F7|.LJ
 | 
			
		||||
....FJL-7.||.||||...
 | 
			
		||||
....L---J.LJ.LJLJ...
 | 
			
		||||
							
								
								
									
										10
									
								
								day10/example5.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								day10/example5.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
FF7FSF7F7F7F7F7F---7
 | 
			
		||||
L|LJ||||||||||||F--J
 | 
			
		||||
FL-7LJLJ||||||LJL-77
 | 
			
		||||
F--JF--7||LJLJ7F7FJ-
 | 
			
		||||
L---JF-JLJ.||-FJLJJ7
 | 
			
		||||
|F|F-JF---7F7-L7L|7|
 | 
			
		||||
|FFJF7L7F-JF7|JL---7
 | 
			
		||||
7-L-JL7||F7|L7F-7F7|
 | 
			
		||||
L.L7LFJ|||||FJL7||LJ
 | 
			
		||||
L7JLJL-JLJLJL--JLJ.L
 | 
			
		||||
							
								
								
									
										140
									
								
								day10/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								day10/input.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,140 @@
 | 
			
		||||
F---7-FJ.7--FJ7.-.7-|7F.|7FJ77F7J-|--.FLF|.F-7-F7.F.J77|--|7--|7|-J-F--7-F7.F7-F7F7F-|-|-F777L7|-.FLF|-77F7-FJF|JF--F.77J-L7-FF--7.FFF7FF7.7
 | 
			
		||||
|J.F|7F|F7J.J-L-|-|.L7F7JF7-7-LJ|LJ.F7.L|.F|F7FJ7.F7.|F|L7.L7L|-F-|7|L|JFF.F||F777L|-77L-|JF7FJJJLF7LL7|.L77|L7LLLJ.|..LLL7|L7-.-JFFLL-7L-FF
 | 
			
		||||
F7L7JLLJL-7FL7|F7-J7.-J.7L7J|.|-JF|FLFF7L-JLL|-F7-F|77|.|L7FJ7JJFJL7JJJFF.FJ||||JFF|LL7F-JF|.LJ7F.|F7F|J7LLL-7||||LFFFF77|-L7LL7F7-JL7|FF7L|
 | 
			
		||||
JFL7FJ7.--JJ7L||.LF|7JJFLFLF7.|.LFF7-FJ|-J-77|-F.|J|LLFF-|-7JL7-J7L|JLF7-7F7|LJL-7|L7F7J-FJ|F|7|77|J-F..FJL.|F77-7F|-FJ|J7J.--7.7J.7-|-||LF|
 | 
			
		||||
.|LLFJLF--J.FL|-J.F77F-77.L|L7F77F7.F|FJ7.FJ7JF7F7|F-J..7JL|..FF---|J-F|JF|||F--7|-FL7.J-J.|LFFJ-7.L7J|.7-|LJJF7L77LL||.FL--JJ|-L-F|7F-JJ|.|
 | 
			
		||||
FL77J|LJFJFF7JJ|J7LJ.|.LF.LL7|||7||-FJL---7.LFJL7J7|FLF7J|F77-J|JJFJ-F-7FFJLJL-7LJ7LLLJ7JLL-7||J|||L-7|---L.FFLLFF---|F--J.|.|L.||FJ7.LLL|-J
 | 
			
		||||
|L-J-JJ-F-F-J7F--7.F7F7F7FF-JLJ|FJ|JL7F-7FJ7-L7FJF-7F7||7FFF7JL7.-JLF|FJFJF7F7FJFFL-|.L-7J|FJFJ-JJ7.L|7.|7J-|J.||||LFLJ-F|F7-7|FF-L7|7-.|L7|
 | 
			
		||||
7|LF|JLL|.F.F-FJF-7|||LJL7L-7F-JL7L7FJL7LJF77F|||L7||||L-7F||.7F7FLFFJL-JFJLJLJ-F|J.F-FL7.LJ||.|L.F7|.F7.7|FJ||-J|J-J7.7-7---|-LJF|7F|-77-L-
 | 
			
		||||
|J.7|LF7JF|F7|L.L7|||L7F-J-F||F7FJFJ|F-JF7||F7||-F|||||F-JFJ|7J|L|F-L-7F7L-7F777.|JF77J-F7FFF777LFFF-F-7-7--LJL|-L|.FF-F.JL|.LFJ-77-F|7F77FJ
 | 
			
		||||
JJ--JLJL-J|J.FLF-J|||L||F77FJ||||FJFJ|F7|||LJLJ|JFJ||||L77L7|F--7F7-F7LJ|F7|||F7F7.L|.F-JL7FJL7F---7JL7L7F7.L|F--7L-L7.J-.-7JJ|L-7L.|JFJLJF|
 | 
			
		||||
|JFLJF|-77F-7.FL-7LJL-J|||FJFJ|||L7|FJ|LJ|L---7L7|FJ|LJFJ7FJLJF-J||.||F-J|LJ|LJLJ|7-J7L-7FJL7FJ|F--J--L7|||7FFF-FJ|JLL|FLFLJ.-L7FLL-|L|.7.FF
 | 
			
		||||
L-77LJJ|FJ|7J.--LL----7|||L7|FJ||FJ||FJF-JF7|FJFJ|L7L7FJF7|F7FJ-FJL-J||F7L-7L7F--J.7|F-7||F7||FJL7L|-F-JLJL-7-|FJLJ77.|7.L7JF|L|7.|---|F--.F
 | 
			
		||||
7JFF7||FJJJJL7J7.F-7F-JLJL-JLJFJ||7|LJFJF7|L7L7L7L7|-|L7|LJ|LJJ.L---7|LJL7FJ|||F-77LLL7||LJLJLJF-J-|LL---7F-J|||..JJF-.F7.F-7|L|7F77JFJ-L|FJ
 | 
			
		||||
|-|LLJF-7LJ|LL|--L7|L7F--7F--7L-JL7L7FJFJ||FJF|FJFJ|FJFJL-7L-7F-7LF7|L7F7|L7FJ||FJF7FFJLJF-----JF-7F7F-7FJL--777-7L-|JF|77LLLL7JFJ|F-JJ.L|7|
 | 
			
		||||
77LJ7F--7J7L7L|.F-J|FJ|F-J|F-JF-7FJFJL7|FJ|L7FJL-JFJ|FJF7|L7FJL7|F|||FJ|LJFJL7||L7|L7L--7L7F-7F7|FJ||L7||F---JL|-L7J.-77J-F.||JF|.L--J.--L7|
 | 
			
		||||
L77--L-7J-|7LFF7L-7|L-JL-7||F7|FJL7|F-J|L-JFJL-7F7|FJL7||F-J|F-J|FJLJL7|F7L7-||L7LJFJJF7|FJL7LJLJL7||FJ||L--7F-7-|7.F.|7JL-L7J-7JFFL--JFFL.L
 | 
			
		||||
..FFJL7L7-LLF7|L--JL-7F--J|LJ||L7FJ|L7F|F--JF7-LJ|||F-J||L-7LJF-JL--7FJLJ|FJFJL7|F-JF7||||F7|F----J||L7LJF--JL7|F--7LFLJ--||||FLLF7-J.FF-.F|
 | 
			
		||||
F-J|7L|-77|-J7|F7F--7|L---JF-JL7|L-JFJFJL-7FJL7F7|||L7|||F7|F-JF7.F7||F7FJL7L7FJ||.FJ||LJ||LJL-7-F7||JL7FJF7F7||L-7|-FJ-7LL77-F7-F|J.F7||F-7
 | 
			
		||||
LL7L77L-7-7-LLLJLJF-JL-----JF--JL--7L-JF7FJL7FJ||||L7L7|LJLJ|F7|L7||||||L-7L7||FJL-JFJL-7||F---JFJLJ|F-J|FJLJLJ|F7|L7JF7.7JL7|LF-7.F-FF77JJ.
 | 
			
		||||
FF--.7.LJLL7|.|FF-JF--------JF7F7F7|F--J||F-JL-JLJ|FJFJL7F--J|LJFJ|||||L7|L7LJ||F---JF--JLJL--7JL7F-JL7FJ|F----J|||FJFJ|7JF-J-7|JL||LLLJL7-F
 | 
			
		||||
7|..L-FFJJFL7FFLL-7|F---77F7FJLJLJ||L7F7LJL--7F---JL7|F7||F--JF-JFJ||||FJF7L7FJ||F--7L---7F---JF-JL7F7|L-JL7F--7|||L-JFJF7L7F7JJ.FJF-7L7J|7|
 | 
			
		||||
F7.L7LJJ.FJL|F7L|7LJL7F7L-J|L----7|L7LJL7F7FFJL7F-7||||LJLJF--JF7L7||LJL7|L-JL7|LJF7|F7F-JL-7F7L7F-J|||F---J|F7||LJF--J||L7JLJ.LFLJ|LJ--7JL|
 | 
			
		||||
J7-FJ.|7.|J-F7L7LF7F-J||F-7|F7FF-JL7|F--J||FJF-J|FJFJ||F7F7L--7||FJLJF-7|L---7||F-JLJ||L--7FJ|L7|L7FJLJL7F-7LJ|LJF-JF7F7L7L7||--|..|F7|LJ|F|
 | 
			
		||||
|F7LF77J.LF-LJJ.FJLJF7|||FJLJL7L--7LJL7F7|||FJF7||FJFJLJ||L---J||L--7|FLJJF--J||L-7F7||FF-JL7|FJL7|L-7F-J|FJF7L-7L7FJLJL7|FJ7|F7|F.|--7-LL|7
 | 
			
		||||
|L||F---F.F7LJ-FL---J||||L--7FJF7L|F--J|||||L7||||L7L-7FJL-7F-7||F7FJL7F-7L--7LJF-J|||L7L7F-J|L7FJL-7|L-7|L7||F7|FJ|F---J||F---77-|J|7L-F.L7
 | 
			
		||||
-7F77JJF-|7JJ.F-F--77||LJF--JL-JL-J|F7J||||L7|||||FJF7|L7F-JL7|||||L7FJ|FJF-7L7FJF-J||FJFJL7FJFJL7F-J|F-J|FJ|||||L7|L7F7FJ||F--JJ7|.L7|F|.LJ
 | 
			
		||||
.L.|L|.F-L|7|FFLL-7L7LJF7L--------7LJL-JLJ|FJ||LJ|L7|LJFJ|F7FJLJ||L-J|.||FJFJFJL-JF-J||FJF-JL7|F-JL7FJ|F7||FJLJLJFJ|FJ||L7LJ|F-7JF777.LFFJL|
 | 
			
		||||
J..L.LL|J-J-|7J.LLL7L-7|L---------JF--7F7FJL7|L-7L-JL77L7LJLJF--JL7F-JFJ|L7|FJF---JF7|LJFJF7FJ|L-7FJL7||||||F----JFJL7|L-JF-J|FJ-LF77.|L||.F
 | 
			
		||||
.F-.L7.|7.F7.F-7.FLL7FJL----------7L-7LJLJF7|L7FJF-7FJF7|F--7L--7FJL77L7L7|LJFJ|F7FJ|L-7|FJ|L7L--J||FJLJ||LJ|F7F7FJF-JL7F-JF7||F77.JJ-L-|-LJ
 | 
			
		||||
FF|-.FFF-JJLLJL|FF--JL7F77F7F7F--7|F-JF7F7|||FJL-JFJL-JLJL-7L---JL7FJF7L7|L-7L7FJ||FJF-J||FJ7L---7L7|F--JL-7LJLJLJFJF-7||F-JLJLJ|-J7|-|F7-L7
 | 
			
		||||
|L-JLLJL-J7F||.J|L---7LJL-JLJLJF7LJL7-|||||LJL7-F7|F7F---7FJF7F-7FJL7||FJ|F7|FJL7||L7L-7|||F7F7F7|FJ||F7F7FJF----7L-JFJ|||F---7FJFL7.FFJJ|F7
 | 
			
		||||
..|.|F7L77LL77J|F-7F7L--------7|L--7L-JLJ|L--7|FJ||||L7F7LJ|||L7LJF-J||L7LJ||L--J||FJF-JLJ||LJLJ||L7|LJ|||L7L-7F7L--7L-JLJL7F7LJ-7F|-7.|7FLJ
 | 
			
		||||
F.L|-|J.F7.|L|-LL7LJL----7F-7FJ|F-7L7F---JF7FJLJFJLJ|FJ|L--7||FJF-JF7||JL-7LJF7F-J|L7L--7FJL7F--J|FJ|F-J||FJF-J|L--7L7F7F--J|L7L|F-J|F|JLJ|J
 | 
			
		||||
|F-L.|.-JL7|JF-L|L------7|L7LJFJL7|FJ|F--7||L--7|F7FJL7|F--J||L7|F-J|||F7-L-7|LJF7|FJF7FJ|F7||F7FJL-J|F7|||FJLFJF--J-|||L---JFJ.-JF|JLJ|J.JJ
 | 
			
		||||
7-LJFJ7|J.F-.J77FF------JL-JF-J..||L7||F-J||FF7||||L7FJ||F7L||F||L-7|||||F7F||F7|||||||L7|||||||L7F--J||||||F7|FJF77FJ||F-7F7|F7-|FL-F.7-7J|
 | 
			
		||||
F7-|7.FF-FJ-|JF7FL--7F7F7F--JF7-FJL-J|||F7||FJ|||||FJ|FJLJ|FJ|FJL7FJ||||||L7|LJLJ|||FJ|FJ||||||L7||F-7|LJLJLJLJL-JL7L7||L7||LJ|L--7J7|FL-|-F
 | 
			
		||||
LJ--F7L---JFLJL-JJ-LLJLJLJF--JL7L7F77||LJLJ||JLJ||LJL|L-7.||FJL-7|||LJ||LJFJL7F--J|LJFJL7LJ||||FJ|||L||F----------7L7||L7|||F-JF--JJ-F7LLJ-J
 | 
			
		||||
|.LF-JF-F|.|J7.L77|.F--7F7L---7L-J|L7|L7F--JL-7F||LF-JF7L7LJL7F-JLJF--J|F-JF-JL7F7L77L--JJFJ|||L7|LJFJ|L---------7L7||L7|||LJF7L7|7|F|L..L7J
 | 
			
		||||
|7F-J7.FFLLJ|F..F7F-JF7LJL---7L---JFJL-JL--7F-JFJL7L7FJL7L-7FJL---7|F-7||F7L7F7LJ|FJF7LF--JFJ||FJL77|FJF---------J|LJL-JLJL7FJL7L--7J-J-7...
 | 
			
		||||
.-J|||-|7L|7FJF7||L-7|L-7F--7|FF7F7L--7F7F-JL7FJF7|FJL-7L7FJL7F7F-J||FJ|||L7LJ|F-J|FJL7L7F7L7LJL-7|FJ|FJF--7F7F--7F-----7FFJ|JFJF--J-7.FF--F
 | 
			
		||||
J7|FLJF-L7|LF7|LJL7|LJF7LJF-JL-JLJL---J||L7F7|L7|||L7F7|FJL7-LJ|L77LJ|FJ||FJF-J|F7LJF7L7|||FJ|F--J|L7|L-JF7LJLJF7LJF7F-7|FJFJ|L7|JLJF7-FJ7||
 | 
			
		||||
||L7.FL|LL-L.LL7F7L7LFJ|F7L------------JL7||||-LJ|L7||||L-7L--7L7L7JFJL7LJL7L7FJ|L7FJL-J||||F7L---JJ||F--JL----SL--JLJJLJ|FJF--J|7FL-.F77.F|
 | 
			
		||||
J.||F--7.J7J|-LLJL7L7L7||L---------------JLJ|L--7L7|LJ|L-7L7F-JJL7L7L7FJF--JFJL7L7|L-7F7LJLJ|L-----7LJL7F----------7F7F7|LJ7L---J777.L7LJ--|
 | 
			
		||||
L-|-|..L7-|LF.LJ-LL7L7||L--------7F--7F7F77FJF-7L7||F-JF7L7|L-7.FJFJFJ|-L-7FJF-JFJ|F7LJL7F7FJF-7F-7L7F7LJF7F-7F----J|||L7.LJJFLL-7|F7JJ.||.|
 | 
			
		||||
L7F-JF-F|7.F77J|-F7L7LJL7-F---7F7LJF7LJLJL7L7|-L7|||L-7|L-J|F-JFJFJFJFJF--J|LL-7|J|||F--J|||FJFJL7L7LJL--JLJFJL-----JLJFJF|..|LL7JJ-LJ-F7FJ-
 | 
			
		||||
.F.|FFFF--7||F7LFJL7L7F7|FJF-7LJL7F|L-----JFJL7J||LJF-JL-7FJL7.|FJFL-JLL7F7L-7.|L7|||L---J||L7L7FJ7L7F7F-7F7L----------JJF7-.|L-.||LJ.FLJJ|.
 | 
			
		||||
FJF|--JL-7||||L7L-7L7LJ||L-JFL7F7L-JFF7F7F7L-7L7|L7.L-7F7||F7L7|L-7|F---J||F-JFJFJ||L7F---JL-JFJL7F7LJLJJLJL-----7LF7F7F7|||.F-J7LJ7.7|J.L|-
 | 
			
		||||
|7JL|..L||LJLJFJF7L7L7|||7F7F-J|L7F--JLJLJL-7L-J|FJF--J||||||FJ|F7|FJF7F7|||FFJFJFJ|FJL---7F--JF-J||F7-F7F------7|FJLJLJLJL-77LLF7L7-L77L.|7
 | 
			
		||||
-J7.F----|F7F7L-JL7L7L-JL-JLJF7L7LJF-------7L--7|L7L7F7|||||LJL|||||FJ||||LJFJFJ7L7|L--7F-J|F7FJF-JLJL-JLJF7F--7LJL7F-------J..|JF.77LJ-J-||
 | 
			
		||||
L-FFF77|-LJLJL---7|JL-7F7F7F7||FJF7L------7|F7FJ|FJ-LJ||||||7F-J||||L7LJ|L7FJFJ|F7LJLF-JL7-||LJ7L----7F---JLJF7|JF7|||F-----7.F7FF7FJ-|...||
 | 
			
		||||
|7|FJL-7-F-7F7F7FJL7F-J|||||LJLJFJL-------JLJ|L7LJLF7FJ|||||FJF7|LJ|FJF-JFJL7L-7|L--7L7F7L7LJF------7|L7F----J|L-JLJL-JF-7F-J-|L-J|JL-J7.F-7
 | 
			
		||||
---L7F-J7|FJ||||L-7|L--JLJ||F7F7L7F---------7L-J|F-JLJFJ||||L7|||F-J|FJF7|F-JF7|L--7L-J||FJF7|F----7|L-JL--7F7L--7F7F7FJ.|L-7-|F--J7J|LF-J-F
 | 
			
		||||
L7LFJ|F7-|L-JLJL--JL7F7|F7LJ|||L7LJF----7F-7L---7L7F7FJ|||||L||||L-7|L-J||L-7|||F--JF7FJ||FJ|||F---JL------J||LF7LJLJLJF7L7FJFJL-7LF-7LL7FF7
 | 
			
		||||
FL-L7|||F|F7F-7F7F-7LJL-J|7FJ||FJF7L---7|L7|F7F-J.|||L-7|||L7|||L7FJL-7FJ|F-J|||L7F7|LJFJLJFJLJL7F7F--7F----JL-JL----7L|L7LJFJF--J7|FJ.LLLLJ
 | 
			
		||||
LLF-JLJL-J|LJFJ|||FL-7F-7L7L7LJL-JL----JL7|LJLJF-7LJL7FJ|||FJ||L-J|F--J|FJL7FJ|L7||||F-JF7FJLFF7LJLJF7||F------------JFJFJF7L7|JFLFF|J.L|7L|
 | 
			
		||||
F-L---7F7FJF7L7|||F--JL7L7L-JF-7F7F--7F7FJL---7|FJF7FJ||LJ|L7LJJF7|L--7||7F|L7L7||||||F7|||F7FJL-7JFJLJ|L-----7F7LF7F7L7L7|L7|L77FF7|LF.F--|
 | 
			
		||||
L77LJLLJ||FJL-J||||F---J||F-7|FLJLJF-J||L7F--7LJL-J|L7|F-7|FJF--JLJF7FJ|L7FJFJFJ|LJ|||||||LJ||F-7L-JF-7|LF7F7FJ|L-JLJL7|FJ|FJ|FJFLF7F7|L.FL|
 | 
			
		||||
F-LJFLLFJ|L-7F7|||LJF----JL7||F----JF7|L7|L-7|F---7L7|LJFJ|L7|F7F--J||-L7|L7L7|FJF-J|||LJ|F-JLJ||F-7L7||FJLJLJJ|F--7F-J|L-JL-J|F7F|LJL7FFLJJ
 | 
			
		||||
||LFJ-LL7L7FJ|||LJFFJF7F7F7||||F-7F7|||FJL-7||L--7L-JL--J.L-J|||L--7|L-7|L7|FJLJJ|F7|||F-JL7F---J|FJFJLJL------JL7FJL--JF----7LJL-JF7FJJJJJ|
 | 
			
		||||
F7|JFF|.L-JL7|LJ7F7L-J||LJ||LJLJFLJLJLJ|FF7LJL---JF-----77L-FJ|L7F7||F7|L7|||JFF-J|||LJ|F--JL----JL7L7LF7F7F-7F7FJL-----J.F-7L-7F7FJLJJJ..|J
 | 
			
		||||
|L--|FFF---7||F--JL---J|F-J|F-7F7F-----JFJL7F--7F7|F---7L7|||FJFLJ||||LJ|LJLJ77L-7|LJF7LJF--7LF7F77L-JFJLJLJ.LJLJF7F-7F--7|FJF7LJLJJ|J-7-7..
 | 
			
		||||
J|LF-7.L--7LJ||F7F7F-7FJL--JL7|||L---7F7|F-J|F7LJLJ|F7LL7L7-||.J|LLJLJ7.-JJLFF---J|F-JL--JF7L-J|||F--7L----7F7F--JLJFJ|F-J|L-JL-7JJJ|JF7JFJ7
 | 
			
		||||
|F-JF-JL|FJF-J||LJLJFJL7.F7F-JLJL-7F7LJLJ|F7||L---7LJL7JL-J7LJ7.FF|-J--7LF-7-L-7F7|L--7F7FJL7F7LJ|L7FJJF---J|LJF7F7FJF|L--JF---7L77FF7JJFFJJ
 | 
			
		||||
LL7.LJ|FFJFJF-J|F---JF7|FJ|L-7F7F7LJL---7LJ||L---7L--7L---7-..F-F|.LJ7LL.7J||LLLJ|L--7||LJF7LJ|F7L-JL--JF---JF7||||L--JF--7L-7|L7L-7||J.J.77
 | 
			
		||||
J..F|.|LL7|JL-7|L----JLJ|FJF-J|||L-----7L7FJ|F---JF-7|F---J-F|..L|L.|L..F|-||F7F-JF7FJLJF-JL-7LJL--7F---JF---JLJLJL7F7FJF7L-7L-7|F7LJ|JL.7L-
 | 
			
		||||
.FF-J.|FJ||J.F||F-----7L||FJF-JLJF--7F7L7|L-JL----JFJ|L-77JL7J--J|FFF7|.L|-|-F-|F-J||F-7L---7|JF7F7LJF7F7L-----7F7-||LJ7|L-7|F-JLJ|F-J|.FL-J
 | 
			
		||||
FF|-7.-JFLJ.FLLJL----7L-JLJFJ|F-7L-7LJL-J|F-7F-7F7FJ-L-7L-7J|...F7F7|FL7-JJL7J|LJJ|LJL7L-7F7||FJLJL--JLJL-----7LJL7|L---JF-J|L--7||L7J7--JJ|
 | 
			
		||||
L-7--JLLJL|.J.F77F7F-JF7F--JF-JFJF7L----7|L7LJFJ|LJF7F7L--J-L.|.FJ|L77..7J.FF.FLJ.J7.|L-7LJLJ|L7F7F--7F------7|F--J|F-7F7L-7L---J-L-JJ|-7.F7
 | 
			
		||||
FL77L||.F--J-FJL-JLJF7|||F--JF7L-JL-----J|FJF7L-JF-J||L-7J.LL7L-JL..L-J7..JFLF-|FJ.|.F7FJF7F7L7LJ||F-J|F--7F-JLJF7LLJFJ||F7L7F7||7||.L--7.-7
 | 
			
		||||
JJL7-77.JJLJ.L7F---7|LJLJL---JL---------7|L-JL7-FJF-J|F-J.|.|L-|FL--77|7F7F7||.|7F-F-J|L-JLJL7|F7LJL-7||F7LJF7F7||F-7|FJ||L7LJL-7-7-7-L7J-L|
 | 
			
		||||
|.-7L||-J--JFFLJF--J|F--------------7F--JL7F-7L7|FJF7||F-7F-77FJ7J|7JF7JJFL-7J-7F77|F7L------JLJL7JF7LJLJL--JLJLJLJFJLJ-LJFJF7F-J.|||..L-..F
 | 
			
		||||
77|J.LF-J|.|LFF7L--7|L---7F7F-7F7F-7LJF7F7LJFL7LJL7|||LJFJ|FJF7|L777JFJ|FL7F|7..L|-LJL-7F------7FJFJL7F-7F-7F------JF7F--7L-J|L7J77F7-|.||FJ
 | 
			
		||||
LFL-77|.F7-FF7||JF7LJ7F77LJLJLLJLJ|L--JLJL7F-7L---J|||F-JFJL-J|J.JLJJ|||F|JLJF-JLJ7L7|FLJ7F----JL-JF-JL7LJJLJ|F7F---JLJF-JJF7L-J-7-7F7FL7.FL
 | 
			
		||||
FF|7|FL|--F-JLJ|FJL---J|F7F7.F------------J|FJ.F--7||||F7L7F--J7F7F7F-L-77FFJJJJFLL7|JFF-7L-7F7F7F7L-77L-7F7F7|LJF-----JF7FJL7F-77J|-F|7|FJJ
 | 
			
		||||
||L|--.JJ|L---7LJF7F--7LJLJL7L---------7FF7|L7FJF-J||||||.|L--77.|LL7-J-7--|||-F|||-.L|L7|F7LJLJ|||F7L-77LJLJLJF7|7F7-F7|||F-J|FJF7LF-|F7J7.
 | 
			
		||||
-LJ||.LL7F|JLLL--JLJ7FJF-7F7L7F--------JFJLJFJL7|JFJLJLJL-JF--JJ7L-7J-|-FJ..|7.-|F|77|F-J|||F7F-J||||F7L7F--7F7||L-JL-JLJLJL--JL-JL7|LJ-J.L7
 | 
			
		||||
|F-|-J.FF7L7F||F7F---JFJFLJ|FJL7F--7F7F7|F--JF7|L-JF--7F7F-JJJL-JF|--.7L|.7FL--.L|FF-7L-7LJLJ|L--JLJLJL7|L-7|||||F--------7F----7F-J-FLJ-7-|
 | 
			
		||||
F7||-F-F-JJF7-FJLJF--7L7F--JL7JLJF7LJLJ|||-F7|LJF-7L-7|||L-7.7JFLFJ-7FJ7|7L7--LF7F7L7L-7L---7|F7F--7F--JL--JLJLJLJF---7LF7LJF7F7||F77JF-7-F7
 | 
			
		||||
7JF|.L--7J7F7-L--7|F-JFJL--7FJF7F||F---J|L7|LJF-JFL--JLJL--JF7.|J|.|F7F7JFJL|.F||||-|F-J|F--JLJ||F7|L--7F---7F7F7FL-7FJFJL--JLJ|LJ||F7FL7JJ|
 | 
			
		||||
..F--77JJFFFJJ|.LLJL--JF---JL-JL-JLJF7F-JFJ|F7L--------7F7F7|L7JFLFLJL7L-F--LF-J|||FJL-7FJF7F-7|LJ||F7JLJF--J|LJL7F-JL-JF7F7F-7L--JLJL7FJJF-
 | 
			
		||||
L7|L|LJ.77F77LF7F---7F7L--7F7F-7F---J||F7|J||L-------7FJ|LJLJFJFF-L7JF7FL|.LLL-7LJ|L--7|L-JLJL||F7||||F--JF7FJF7FJ|F---7|||LJF|F-7F--7|-J.LJ
 | 
			
		||||
.F|7|L-F--|L7FJ|L--7||L--7LJLJ7LJF---J||LJFJL-------7LJFJF7F-J.L77LJ.-77-LJ..|7L7FJF--JL-7F7JFJLJLJ|||L---JLJFJLJ-||F-7|||L--7LJ-LJJLLJJF7-F
 | 
			
		||||
FF.JJ7|LJ-L7|L7|F7FJ||F-7L-------JF7|FJL--JF-7F--7F7L7FJFJLJJF7JJL|J77.F7JFFF-7FJL7L----7LJL7L----7||L-------J|F7FJLJFJLJL7F7|.F7F7|.||.---J
 | 
			
		||||
FJ-|7F-7F|L|L-J|||L7|LJFJF7F7F7F-7|L-JF7F-7|FJL-7LJL-JL7L7F--JL-7.77F7-|J|FJ|FJL7FJF---7L--7L-7F7FJLJF-7F7F-7F7|||F--JF--7LJ|L-JLJL7-777-|-7
 | 
			
		||||
|J-77|J|F7JL7F7LJL-JL7.L-JLJLJLJJLJF--JLJ|LJL7F7L7F7-F-JFJL7F---JF7FJL--7F7FJ|F7|L7L--7|F7FJF7LJLJF-7|FJ|||FJ||||||.F7L7FJF7L7F7F7FJ.J..F||F
 | 
			
		||||
|LFJFJ7LF--FJ||F7F-7FJF7F7F-7F-----JF7F7F-7F7||L7LJL7L7FJF7|L-7F7|LJF7F-J||L7LJLJFJF7J|LJLJFJ|F7F7|.LJL-JLJL-JLJLJL-JL7|L-JL7LJ||LJLF.FF7LL|
 | 
			
		||||
|-7F|JF.LL.L7|LJLJFJL-JLJ|L7|L------JLJ|L7LJ|LJLL---JFJL7|||F-J|||F-JLJF7||LL--7FJFJL7|F7F7L7||||LJF7F7F7F7F7F-7F7F7F7LJF7F7L7FJL7F--7-.|7|F
 | 
			
		||||
J||FF7..-7FLLJF---JF----7L-JL----------JFJF7L------7FL7FJ||||F7|LJL-7F7||||F7F-JL7L7FJLJLJ|FJLJLJ.FJLJLJLJLJ||F|||||||F7|LJ|FJL-7LJF-JFF7JF-
 | 
			
		||||
J-|L--|7LL7J|-L----JF--7L------------7F-JFJL7F-7F--JF7|L7|LJ||||F---J|||LJ|||L7F7L7|L-7F7|LJF-----JF-7F----7|L7LJ||LJ|||L-7||F-7|F7|7.LJJ7||
 | 
			
		||||
||JLJ7|F.|J.F-F-----JF7L-------------J|F-JF7LJJ||F-7|||FJ|F-J|||L7F-7||L7FJ||-||L7||F-J||F7JL-7F7F7|FJ|LF--JL7L-7|L-7LJ|F-J|LJFJ|||L-7.FJJ7L
 | 
			
		||||
FF7-7|F7FF77.FL--7F7FJL7F------7F--7F7|L--JL--7||L7|||||F|L7FJ||FJ|FJ|L-J|FJL7||FJ||L-7|LJL--7LJLJLJL7L7L-7F7L--JL--JF7LJF7L7FJL|||F-J-F|FFJ
 | 
			
		||||
F-J-7-7||-L7-F--7LJ|L-7||F-----J|F7LJLJF--7F--J||FJ||||L7|FJL7LJL7|L-JF--JL7FJLJL7LJF-JL---7FJLF-7F--JFJF-J|L--------JL--JL7|L-7LJLJJJJLL-7|
 | 
			
		||||
77F.|LFJJL-|JL-7|F7L--J||L------J||F7F7L-7LJF77||L7||LJFJ||F7|F--J|F--JF-7||L--77L-7L7F-7F7||F-JFJL--7L7L--JF--------------JL--J-|JJ|-FJJ.FJ
 | 
			
		||||
|L-.LF-J7JF7-F-JLJ|F--7LJF--7F7|FJLJ|||F7L7-|L7LJFJLJF7|FJ||LJL---JL--7L7|FJF--JF--JFJL7LJ||||F-J|F-7L-JF---JF7F----7|F7LF--7.F7F|J.|7L77-L7
 | 
			
		||||
J-J7.LJL--F--JF--7|L7FJF7L-7|||FJF-7LJLJL7L7|FJF7|F--J||L7||F---------JFJ|L7|LF7L--7|F7L-7LJ||L--7L7L-7|L----JLJF---JFJL-JF-JFJL7--F7|LJL77|
 | 
			
		||||
L-J777-F|LL---JF-J|FJL7||F-JLJLJFJ.L----7L-J|L7|LJL--7LJJ||||F--7F7.F7FL7|FJL7||F7FJLJ|F-JF7|L-7FJFJF7L----7F---JF7JFJF-7FJF7L7FJLFJ|7JLFFFL
 | 
			
		||||
FFJFFJ7-F.|FF--JF7|L7FJ||L---7F7|F7F----JJF7L7|L7F---JF-7||||L7FJ|L7||F7|||F-J|LJ|L-7FJL--J||F7||JL-JL----7|L----JL7|FJ|LJ7||FJL-7L7|--77FJ.
 | 
			
		||||
FJ-LL.L7F--7|F--J||FJ|.|L----J|LJ|LJ|F7-F7||FJ|FJL-7F7L7LJLJL7|L7L7LJ||||||L-7|F7|F7||F7F--J||||L7F-7F7F7FJL7F--7F7LJL77F-7|||F--J-||J-JF7L.
 | 
			
		||||
|F-F7FFLL7|F||F--J|L7L7L-----7L7FJF--JL7|||LJFJL7F-J|L7L7F-7FJL7|FJF-J|LJLJF-JLJ||||||||L7F7||||FJL7LJLJLJF-JL7.|||F-7L7L7LJLJ|F7F7||J|FL7J7
 | 
			
		||||
F7J.L7|-JLLLLJL7F7L-JFJF7F7F-JFJL-JF---J|||F7L--J|F7|FJ|LJFJ|7FJ||FJF-JF---JF-7FJ||||LJ|FLJ|||LJL7FJF7F--7L--7L7LJLJ.L7L7|F---J||||||F-7.7J|
 | 
			
		||||
LJ-F-FJJ--J-L|LLJL7F7L-J||||F7|F---JF7F7||LJL-7F7||||L7-F7L7L7L7|||J|F-J-F7FJFJL7|||L7FJF7FJ||F--JL-JLJF7L--7L7L-----7L7LJL-7F7|||||||FJ7L7.
 | 
			
		||||
LFFF7JF-7J|-FJ-F--J||F-7LJ|LJLJL----JLJLJ|F7F7||LJ|LJFJFJ|.L7L7||||FJL7F7|||FJF-J||L7|L7||L7LJ|.F-7-F--JL---JFJF-7F--J|L7F--J|||LJLJLJL-7L||
 | 
			
		||||
.|J.77|F7F-.|--L-7FJLJJL-7|F7F7F--------7||LJ|||F7L7FJ-|FJF7L7LJ|||L-7LJ|||||FL-7||FJ|FJ||-L-7L7L7L7L----7.F7L-J7LJLF7-FJL---JLJF7F-7F7FJ.L-
 | 
			
		||||
F.|7|-F|F--|.L|F-J|F7F-7FJLJLJLJF---7F-7LJL-7||LJ|FJ|F7||FJL7L-7|||F-JF-J|||L7F7|||L7|L7||F7FJFJFJFJLF--7L-JL-------JL7L-7F---7FJLJ.LJLJ|FF|
 | 
			
		||||
|7L-J.LJ7J||-FFJF-J||L7|L-7F7F7FJF--J|FJF7F7|||F-J|FJ||||L7FJF7||||L7FJF7||L7||||||FJL7|||||L7|LL7|F7L7FJF-------7F7F7L7-||F-7LJF-7F77LL|7-F
 | 
			
		||||
FFL7|FFJLF|.|L|FJF-JL-JL--J||||||L--7||FJ|||||||F-J|FJ||L7|L7|LJLJL7|L7|||L7|||||||L7FJ||||L7||F7||||FJ|FJF----7.LJ||L-JFJLJFJ|FJFJ||7LL|J.7
 | 
			
		||||
F|L|-|7J-J|FL7LJ7L--------7|LJLJF7F7|||L7||||||||F-J|-||FJL7|L-7F--J|FJ|LJFJ||||||L7||FJ|||FJ|LJ|||||L7|L-JF--7L--7|L7F7|F-7L--JFJL|L7F-LJ-F
 | 
			
		||||
F--..L7...F7L|J.FF---7F7F-J|F---JLJLJ||FJ||LJ|||||F7L7LJL7FJ|F7|L7F7|L7L7LL-J||||L7|LJ|FJ||L7L-7LJ|||FJ|F-7L-7L---JL7LJ|||FJF7F7L7||FJ-7|7.|
 | 
			
		||||
7J|F7JL77-FJJ|.-JL--7LJLJF7|L------7FJ|L7|L7FJ|LJ||L7L-7F|L7||||FJ|||FJFJF--7LJ|L7|L-7|L7||FJF7L7L|||L7|L7L-7L-----7|F7|||L7|LJL7L-J|J-L.F-F
 | 
			
		||||
7-J-7-FF-7LJ.F-F7JF-JF7F7|LJ-F-7F7FJL7L7||FJL7L77LJFJF7L7L7|LJ|||FJLJL7L-JF7L7FJFJL7FJ|FJ||L7||FJFJ|L7||FJF-JF7F---JLJLJ|L7|L--7L7F7L-7-FJFF
 | 
			
		||||
L|.|LFFJ|F|JF|LLF-JF7|||LJLF7L7LJLJF7L7LJLJF7|FJF--JFJ|FJFJL-7||||F---JF-7||FJL7L-7||FJL7||FJ|||-L7L7LJ||7|F-J||LF7F7F7J|FJL7F-JF||L--J7F7..
 | 
			
		||||
FL|F-J.FF-||-77JL-7|LJLJ7F-J|FJF7F7|L7L---7|||L7L7F7L7||FJF-7|||LJL7F7FJFJ|||F7|F-JLJ|F7|||L-JLJF-JFJF-JL7LJF-JL-JLJ||L7LJF7|L--7|L-77-7|.F7
 | 
			
		||||
7J.FLF--JLL|F7-F-7LJF7-F7L-7LJFJLJLJFJF7F7LJ|L7L7LJ|FJ||L7L7LJ||7F-J||L7|FJ|LJ||L---7||LJ|L-7F--JF7L7L-7FJF-JF--7F-7LJFJF7||L---JL7FJ7|||-||
 | 
			
		||||
|FLL7J||L|FJ7|.L7L--JL-JL-7|F7L7F--7L7||||F7L7|FJF-JL7LJ7L7L7FJL7|F7||FJ|L7|F7|L7F7FJLJF-JF-JL7F7||FJ7FJL7|F-JF-J|7|F-J7|LJL---7JLLJ..FLL--L
 | 
			
		||||
JJ|.|F|FFL|FLL-LL--------7|LJL7LJF-J-LJ||||L7||L7L7F7L-7F7|FJL7FJLJ|||||L7||||L7||LJF7LL--JF7-||LJ|L-7L7FJ|L-7|F7L7||F--JF-7F7FJJ|J-F7--J777
 | 
			
		||||
FLJ.LLJJ7L|7.LF7F7F------JL---JF7L-7|F-J|LJF|||FJFJ||F7||LJL7FJ|F--J||L-7LJLJ|FJ|L--JL7F---J|FJL-7|F7|-LJFJF7||||FJ|LJF7FJ||||L7FL-F|L|F7L-L
 | 
			
		||||
LJL|.FL.|LL.FF|LJLJF7F7F7F---7FJL-7|FJF7L--7|||L7|FJ||LJ|F7FJL7|L--7||F7L7F--JL7L7F-7FJL7F-7LJF--J|||L--7L7|LJ|||L7|F7||L-7LJL-J-||FJFJL-JLL
 | 
			
		||||
|J-|JJ|-F7|LFFJF7F7|||||||F7F|L--7|||FJ|F--J||L7||L7|L7FJ|||.FJ|F--J||||FJL--7FJFJL7LJ.FJL7|F7L--7||L7F-JL|L-7||L7||||||F7L----7|L|.F||F7||J
 | 
			
		||||
|.|F7JL7|FFJFJFJLJLJ||LJLJ|L-JF7FJLJ||F|L--7||FJ|L7||FJ|FJ|L7|FJL--7|LJ||F7F7||JL-7L-7FJF-J||L7F-J||F|L--7|F7|||FJ|||LJ|||F---7|J.-7.F7.F7|.
 | 
			
		||||
F7-LL.LJLJL7L-JF7F--J|F---JF7FJ||F7-LJFJF-7||||FJFLJ||-|L7L7|LJF---JL-7|||LJLJL7F7|F7||FJ.FJL7|L7FJ|FJF--JLJ||||L7||L-7LJ|L--7LJJ7LL7L7FFJ-J
 | 
			
		||||
.|JJL7.7|FFLF--JLJF7FJL-7F-J||L||||F--JFJJ||||||F---JL7L7L7||F7|F-7F7FJ||L-7F7FJ||LJLJ||F-JF-JL7||FJL7L----7||||FJ||F-JF-JF-7L-7.|7.|-|FJ.L.
 | 
			
		||||
|..FFLLJF7JJ|F-7F-J|L7F-J|F-JL7LJ|LJF7FJF-J|LJ||L7F7F7L7L-JLJ|LJ|FJ||L7|L7LLJ|L-JL7F-7|||F7|F--J|LJF7L7F7F-J||LJL7||L-7|F7L7|F-J7LF.|.|7|J|L
 | 
			
		||||
|J77L-JL|L|7LJLLJFFJFJL--JL7F7L7FJF7||L7|F7L-7LJ-||||L7L---7JL7FJL7|L7||FJF--JF--7LJFJLJLJ||L--7L-7|L-J||L-7|L-7FJ|L7FJLJ|FJ|L-77JJF7JL7|-7|
 | 
			
		||||
7.FL7J|...J7.J-LL-L7|JLFF--J||FJL7|||L-J||L7FJ7F-J||L7L-7F-JF-JL7.||FJ|||FJF-7L-7|F7L-7-F-J|F--JF-J|F7FJ|F-J|F-JL7L7||F|||L7L-7|--FFJLF|7LL|
 | 
			
		||||
L-L7L-JJ7.LFJ|.LJFLLJJJFJF7FJ|L7FLJ|L7F-JL7|L-7L7FJL-JFFJL7FJF-7L7|||FJ||L7|-L7FJLJL-7L7|F7|L--7L-7|||L7LJF7LJJ|L|FJLJ-L-L7L7.LJJF.||F|F77FJ
 | 
			
		||||
7|||L|-||..||-.77LF-F--JFJ|L7L7|F--JFJL--7|L7FJFJL-7F--JF-JL7|7L-JLJ||LLJFJ|F-JL----7|FJLJ||F--JF7|||L7L--J|FJJ-LLJJJ|.L--L7|J.LJF-7FJJLL7||
 | 
			
		||||
.-JLFJF7L7.F|7|-7|LFJF-7|FJFJ-LJL7F7L7.F7LJFLJFJF7FJL7F7L--7LJ77LF--JL-7FJFJL-7F7F7FJ|L-7FJ||F7FJ|||L7L7F--JJ|.FLJ-JF--.LJFLJ|.LF-L|JLL|FJJ-
 | 
			
		||||
FJ7F7JL|JL-LJ-L7FF-L7|FJ|L7|J-|F-J|L7L-JL7L|7.|FJ||F-J|L7F7L-7JFFJF-7F7||FJJF-J||||L7|F-J|FJLJ|L7||L7|FJL7|J7L77.|LF|JF-7F|JL7JFL7||F|F.L-|.
 | 
			
		||||
F-|JJ7.JJ-|F77-LLJJ-LJL-JLLJJJFJF7|FJF---J-||7LJ-LJ|F7L7LJ|F7|F-JFJFJ|||||F-JF7|||L7||L7-||-F-JFJLJ-|||F-J-77|L--L-L|.|-F|.LLJL|.7FF7L7J--F7
 | 
			
		||||
LF-.|FL-F-F|7.LFJ-|.|7|L|7J77|L7|LJL7L---7-7|FJJJ.FLJ|FJ.LLJ||L7FJLL7|||||L-7|LJLJ.||L-J-LJ-L--J7|J-||LJJL7|LF7||.LLL7J-F|-J.7-F--FJL7|F7JLF
 | 
			
		||||
F-.F||..LFJLL7FJ.F|-7-77FL.JFFLLJ-F7|F---J.||7J|.F7.LLJ-7-L7LJ-|L7-LLJLJ|||F|L----7LJ7F7JLL.LJ.LFJ|.LJJL--.|-F7-77.F7J|FL|JF7JF|LJLJFJL-F.FF
 | 
			
		||||
F-F||-7-FLF7JFLJ7F|-JJ.LJJJ|-JJ|JF|LJ|F7LJ-JL77-F7JFJLL7FJ.F7.LL-J7LJJJL||F-JF7F-7L---J|LFJ-.J7JJ7L||..LL-JJ7J|F||FFF.LF.|.|L-LF-JFFLJ-FJ-J|
 | 
			
		||||
L7J||.L-JLLJ--7.FL-7||.F|-L7.|.|-FJF7LJ|..7-LFJ.|L7L-||L|7-|-L.|.|L|.FF7LJL7FJLJJ|F----J.|7L|--7.|.LJ-7..|JF7|L-L-7F--L|FJ7|FLL|FJ7|-7.|-|JL
 | 
			
		||||
FL7F||.||7L-F--|JF-.-F-JLF7J||L..L7||F-J7J.-.|.FL|J-FLF.|J7JFL-|-7.--F|L---JL7LF-JL--7|JF-7L7.L-FJ7|LJ7F77JJ.|JL|.-LL.|L-L-|-7.||.L7-F-7.|JL
 | 
			
		||||
L|7-FLJ--F77|-LJ.|--JJJL.|JLJFJF7-LJLJ-F|7L.FJ-77J..F-|-|J|F7.|LLL-7|LL--7F7FJ.L-7F--J7F7F7-JJ.LJ--FJL|FF-7LF|7.L7FFJ-J|.L.|.LFL7.LJFJFF-|..
 | 
			
		||||
.|..|.|7L.L|J.LL-L-7F7-LFJ|.FF.F7.J.|L--|7.|--7|F7FJJ.|L|-L7|--JF|.|-7F|LLJ|L77LFLJ-J.J-.JJ.|||FJF|J..|-LJF-L|7L|-7L|7L7J-JJ.L-J-||-|-LJ|LLF
 | 
			
		||||
LJ-F---J.F7|77JFL-||-F7||-J-LJ-FJLJF-7|F|F-JFFJ|.F--7-LJ|LFL|-7||JFF-|LF.JL|FJ7FFJL7J-|7L77F|FFJJ|7..LL-J.777F7F|JF-77J|LFFF77FL|LL-|-.LJJJ|
 | 
			
		||||
.|JF|-L|.J7LJJ77|F7|7F--|-|JL7-L7LFFJ-77-J|F-JFJ7JF|J|7|F-|7|-L|||F7.|L7-F|LJJ7-|7.|FLLF7LL-FFJ|.-L--7.LF||F-J.L|F7.L7F7.F7LLJ7J|F|-|J|L|L77
 | 
			
		||||
F-7|L77L..F-J7F---7J7||.|-F.LL7.|F7.JL|F7LF|-FF-LF7|-7-|.L--|...FL|L-JFF-J-.|.7F||JF||.FL7L.7||L7JJ-7FF-7|F|-|-LF--J7L7LL7JL||LF|F--LJ|-FJ|7
 | 
			
		||||
L|L--JJJ-LLJ-FF.JJLLJ7-L7-JLJJ|-.F7..-|LJ.FJ.|J..L7J.L-.--JL|.-FJ-L-LL.|.JJ-FJ.F|JLLJF-7J7JJJ|7JLJ..FL--JJ-77L7.|JLL-JL-L.LL-|7-L|J.LLL-L-|.
 | 
			
		||||
							
								
								
									
										331
									
								
								day10/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								day10/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,331 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// var log = aoc.Log
 | 
			
		||||
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	m := &Path{s: -1}
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		text := scan.Text()
 | 
			
		||||
		_ = text
 | 
			
		||||
 | 
			
		||||
		m.readLine(text)
 | 
			
		||||
	}
 | 
			
		||||
	dist := m.buildPath()
 | 
			
		||||
	// log(m)
 | 
			
		||||
 | 
			
		||||
	r := &Region{List: m.List, w: m.w, l: len(m.m)}
 | 
			
		||||
	count := r.Count()
 | 
			
		||||
 | 
			
		||||
	return &result{valuePT1: dist, valuePT2: count}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type node struct {
 | 
			
		||||
	value  rune
 | 
			
		||||
	pos    int
 | 
			
		||||
	whence int8
 | 
			
		||||
	left   *node
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (n *node) add(a *node) *node {
 | 
			
		||||
	if a == nil {
 | 
			
		||||
		return n
 | 
			
		||||
	}
 | 
			
		||||
	n.left = a
 | 
			
		||||
	return a
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (n *node) String() string {
 | 
			
		||||
	if n == nil {
 | 
			
		||||
		return "EOL"
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("node %s from %s", string(n.value), enum(n.whence))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type List struct {
 | 
			
		||||
	head *node
 | 
			
		||||
	n    *node
 | 
			
		||||
	p    map[int]*node
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewList(a *node) *List {
 | 
			
		||||
	lis := &List{
 | 
			
		||||
		head: a,
 | 
			
		||||
		n:    a,
 | 
			
		||||
		p:    make(map[int]*node),
 | 
			
		||||
	}
 | 
			
		||||
	lis.add(a)
 | 
			
		||||
 | 
			
		||||
	return lis
 | 
			
		||||
}
 | 
			
		||||
func (l *List) add(a *node) {
 | 
			
		||||
	l.n = l.n.add(a)
 | 
			
		||||
	l.p[a.pos] = a
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Path struct {
 | 
			
		||||
	m []rune
 | 
			
		||||
	w int
 | 
			
		||||
	s int
 | 
			
		||||
 | 
			
		||||
	*List
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Path) String() string {
 | 
			
		||||
	var buf strings.Builder
 | 
			
		||||
	n := m.head
 | 
			
		||||
 | 
			
		||||
	buf.WriteString(fmt.Sprintf("head %d", len(m.p)))
 | 
			
		||||
	for n != nil {
 | 
			
		||||
		buf.WriteString("\n ")
 | 
			
		||||
		buf.WriteString(n.String())
 | 
			
		||||
		n = n.left
 | 
			
		||||
	}
 | 
			
		||||
	return buf.String()
 | 
			
		||||
}
 | 
			
		||||
func (m *Path) readLine(text string) {
 | 
			
		||||
	if m.w == 0 {
 | 
			
		||||
		m.w = len(text)
 | 
			
		||||
	}
 | 
			
		||||
	if m.s == -1 {
 | 
			
		||||
		if i := strings.IndexRune(text, 'S'); i != -1 {
 | 
			
		||||
			m.s = i + len(m.m)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m.m = append(m.m, []rune(text)...)
 | 
			
		||||
}
 | 
			
		||||
func (m *Path) buildPath() int {
 | 
			
		||||
	m.start()
 | 
			
		||||
	for m.next() {
 | 
			
		||||
	}
 | 
			
		||||
	return (len(m.p) + 1) / 2
 | 
			
		||||
}
 | 
			
		||||
func (m *Path) start() {
 | 
			
		||||
	m.List = NewList(&node{value: 'S', pos: m.s})
 | 
			
		||||
 | 
			
		||||
	switch {
 | 
			
		||||
	case m.peek(UP) != nil:
 | 
			
		||||
		m.add(m.peek(UP))
 | 
			
		||||
	case m.peek(DN) != nil:
 | 
			
		||||
		m.add(m.peek(DN))
 | 
			
		||||
	case m.peek(LF) != nil:
 | 
			
		||||
		m.add(m.peek(LF))
 | 
			
		||||
	case m.peek(RT) != nil:
 | 
			
		||||
		m.add(m.peek(RT))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (m *Path) next() bool {
 | 
			
		||||
	var n *node
 | 
			
		||||
	switch m.n.value {
 | 
			
		||||
	case '7':
 | 
			
		||||
		if m.n.whence == LF {
 | 
			
		||||
			n = m.peek(DN)
 | 
			
		||||
		} else {
 | 
			
		||||
			n = m.peek(LF)
 | 
			
		||||
		}
 | 
			
		||||
	case '|':
 | 
			
		||||
		if m.n.whence == UP {
 | 
			
		||||
			n = m.peek(DN)
 | 
			
		||||
		} else {
 | 
			
		||||
			n = m.peek(UP)
 | 
			
		||||
		}
 | 
			
		||||
	case 'F':
 | 
			
		||||
		if m.n.whence == RT {
 | 
			
		||||
			n = m.peek(DN)
 | 
			
		||||
		} else {
 | 
			
		||||
			n = m.peek(RT)
 | 
			
		||||
		}
 | 
			
		||||
	case '-':
 | 
			
		||||
		if m.n.whence == LF {
 | 
			
		||||
			n = m.peek(RT)
 | 
			
		||||
		} else {
 | 
			
		||||
			n = m.peek(LF)
 | 
			
		||||
		}
 | 
			
		||||
	case 'J':
 | 
			
		||||
		if m.n.whence == LF {
 | 
			
		||||
			n = m.peek(UP)
 | 
			
		||||
		} else {
 | 
			
		||||
			n = m.peek(LF)
 | 
			
		||||
		}
 | 
			
		||||
	case 'L':
 | 
			
		||||
		if m.n.whence == RT {
 | 
			
		||||
			n = m.peek(UP)
 | 
			
		||||
		} else {
 | 
			
		||||
			n = m.peek(RT)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if n == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if n.value == 'S' {
 | 
			
		||||
		last := n.whence
 | 
			
		||||
		next := m.head.left.whence
 | 
			
		||||
 | 
			
		||||
		switch last<<4 | next {
 | 
			
		||||
		case UP<<4 | UP, DN<<4 | DN:
 | 
			
		||||
			m.head.value = '|' // UP UP, DN DN
 | 
			
		||||
		case LF<<4 | LF, RT<<4 | RT:
 | 
			
		||||
			m.head.value = '-' // LF LF, RT RT
 | 
			
		||||
 | 
			
		||||
		case UP<<4 | RT, LF<<4 | DN:
 | 
			
		||||
			m.head.value = 'J' // UP RT, LT DN
 | 
			
		||||
		case UP<<4 | LF, RT<<4 | DN:
 | 
			
		||||
			m.head.value = 'L' // UP RT, RT DN
 | 
			
		||||
 | 
			
		||||
		case DN<<4 | RT, LF<<4 | UP:
 | 
			
		||||
			m.head.value = '7' // DN LF, LF UP
 | 
			
		||||
		case RT<<4 | UP, DN<<4 | LF:
 | 
			
		||||
			m.head.value = 'F' // DN LF, RT UP
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m.add(n)
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	ST int8 = iota
 | 
			
		||||
	UP
 | 
			
		||||
	DN
 | 
			
		||||
	LF
 | 
			
		||||
	RT
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func enum(e int8) string {
 | 
			
		||||
	switch e {
 | 
			
		||||
	case ST:
 | 
			
		||||
		return "ST"
 | 
			
		||||
	case UP:
 | 
			
		||||
		return "UP"
 | 
			
		||||
	case DN:
 | 
			
		||||
		return "DN"
 | 
			
		||||
	case LF:
 | 
			
		||||
		return "LF"
 | 
			
		||||
	case RT:
 | 
			
		||||
		return "RT"
 | 
			
		||||
	default:
 | 
			
		||||
		return "XX"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Path) peek(d int8) *node {
 | 
			
		||||
	switch d {
 | 
			
		||||
	case UP:
 | 
			
		||||
		x, y := toXY(m.n.pos, m.w)
 | 
			
		||||
		if y == 0 {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p := fromXY(x, y-1, m.w)
 | 
			
		||||
		r := m.m[p]
 | 
			
		||||
		if any(r, '7', '|', 'F', 'S') {
 | 
			
		||||
			return &node{value: r, whence: DN, pos: p}
 | 
			
		||||
		}
 | 
			
		||||
	case DN:
 | 
			
		||||
		x, y := toXY(m.n.pos, m.w)
 | 
			
		||||
		if y == m.w {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p := fromXY(x, y+1, m.w)
 | 
			
		||||
		r := m.m[p]
 | 
			
		||||
		if any(r, 'J', '|', 'L', 'S') {
 | 
			
		||||
			return &node{value: r, whence: UP, pos: p}
 | 
			
		||||
		}
 | 
			
		||||
	case LF:
 | 
			
		||||
		x, y := toXY(m.n.pos, m.w)
 | 
			
		||||
		if x == 0 {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p := fromXY(x-1, y, m.w)
 | 
			
		||||
		r := m.m[p]
 | 
			
		||||
		if any(r, 'F', '-', 'L', 'S') {
 | 
			
		||||
			return &node{value: r, whence: RT, pos: p}
 | 
			
		||||
		}
 | 
			
		||||
	case RT:
 | 
			
		||||
		x, y := toXY(m.n.pos, m.w)
 | 
			
		||||
		if x == m.w {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		p := fromXY(x+1, y, m.w)
 | 
			
		||||
		r := m.m[p]
 | 
			
		||||
		if any(r, '7', '-', 'J', 'S') {
 | 
			
		||||
			return &node{value: r, whence: LF, pos: p}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fromXY(x, y, w int) int { return y*w + x }
 | 
			
		||||
func toXY(i, w int) (int, int) {
 | 
			
		||||
	return i % w, i / w
 | 
			
		||||
}
 | 
			
		||||
func any[T comparable](n T, stack ...T) bool {
 | 
			
		||||
	var found bool
 | 
			
		||||
	for _, s := range stack {
 | 
			
		||||
		if n == s {
 | 
			
		||||
			found = true
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return found
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Region struct {
 | 
			
		||||
	*List
 | 
			
		||||
	inLoop bool
 | 
			
		||||
	count  int
 | 
			
		||||
	w      int
 | 
			
		||||
	l      int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Region) Count() int {
 | 
			
		||||
	for i := 0; i < r.l; i++ {
 | 
			
		||||
		if i%r.w == 0 {
 | 
			
		||||
			r.inLoop = false
 | 
			
		||||
			// fmt.Println(": ", i)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		a, ok := r.p[i]
 | 
			
		||||
		if ok && any(a.value, '|', '7', 'F', 'X') {
 | 
			
		||||
			r.inLoop = !r.inLoop
 | 
			
		||||
			// fmt.Print(string(a.value))
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !ok && r.inLoop {
 | 
			
		||||
			// fmt.Print("I")
 | 
			
		||||
			r.count++
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ok {
 | 
			
		||||
			// fmt.Print(string(a.value))
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		// fmt.Print(".")
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return r.count
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										110
									
								
								day10/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								day10/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,110 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/matryer/is"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//go:embed example1.txt
 | 
			
		||||
var example1 []byte
 | 
			
		||||
 | 
			
		||||
//go:embed example2.txt
 | 
			
		||||
var example2 []byte
 | 
			
		||||
 | 
			
		||||
//go:embed example3.txt
 | 
			
		||||
var example3 []byte
 | 
			
		||||
 | 
			
		||||
//go:embed example4.txt
 | 
			
		||||
var example4 []byte
 | 
			
		||||
 | 
			
		||||
//go:embed example5.txt
 | 
			
		||||
var example5 []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.valuePT1)
 | 
			
		||||
	is.Equal(result.valuePT1, 4)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.valuePT1)
 | 
			
		||||
	is.Equal(result.valuePT1, 8)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestExample3(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(example3))
 | 
			
		||||
 | 
			
		||||
	result, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
 | 
			
		||||
	// t.Log(result.valuePT1)
 | 
			
		||||
	is.Equal(result.valuePT1, 23)
 | 
			
		||||
 | 
			
		||||
	// t.Log(result.valuePT2)
 | 
			
		||||
	is.Equal(result.valuePT2, 4)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestExample4(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(example4))
 | 
			
		||||
 | 
			
		||||
	result, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
 | 
			
		||||
	// t.Log(result.valuePT1)
 | 
			
		||||
	is.Equal(result.valuePT1, 70)
 | 
			
		||||
 | 
			
		||||
	// t.Log(result.valuePT2)
 | 
			
		||||
	is.Equal(result.valuePT2, 8)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestExample5(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(example5))
 | 
			
		||||
 | 
			
		||||
	result, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
 | 
			
		||||
	// t.Log(result.valuePT1)
 | 
			
		||||
	is.Equal(result.valuePT1, 80)
 | 
			
		||||
 | 
			
		||||
	// t.Log(result.valuePT2)
 | 
			
		||||
	is.Equal(result.valuePT2, 10)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.valuePT1)
 | 
			
		||||
	is.True(result.valuePT1 != 51)
 | 
			
		||||
	is.Equal(result.valuePT1, 6649)
 | 
			
		||||
 | 
			
		||||
	t.Log(result.valuePT2)
 | 
			
		||||
	is.True(result.valuePT2 != 0)
 | 
			
		||||
	is.Equal(result.valuePT2, 601)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// first: 51 false
 | 
			
		||||
							
								
								
									
										10
									
								
								day11/example.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								day11/example.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
...#......
 | 
			
		||||
.......#..
 | 
			
		||||
#.........
 | 
			
		||||
..........
 | 
			
		||||
......#...
 | 
			
		||||
.#........
 | 
			
		||||
.........#
 | 
			
		||||
..........
 | 
			
		||||
.......#..
 | 
			
		||||
#...#.....
 | 
			
		||||
							
								
								
									
										140
									
								
								day11/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								day11/input.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,140 @@
 | 
			
		||||
..............................#.........................#.......................#..............................#.........................#..
 | 
			
		||||
....#.....#...................................#.............................................................................................
 | 
			
		||||
.....................................#..................................#...................................................................
 | 
			
		||||
...................................................#....................................................................#...................
 | 
			
		||||
...............................................................#..................#...............................#.........................
 | 
			
		||||
...............#.......................................#...................................#.....#.......#.........................#........
 | 
			
		||||
............................................................................................................................................
 | 
			
		||||
............................................................................#...............................................................
 | 
			
		||||
.......#.......................#....................#.......................................................................................
 | 
			
		||||
........................#..................#....................................................................#...........................
 | 
			
		||||
..#.......................................................#.........#....................#....................................#.............
 | 
			
		||||
..............#...........................................................#..........................................................#......
 | 
			
		||||
......................................#...........................................#..........................#..............................
 | 
			
		||||
.....................................................#.........#..........................................................................#.
 | 
			
		||||
#.......#....................................#.................................................#............................................
 | 
			
		||||
..............................#.......................................#..............#....................#..........#......................
 | 
			
		||||
....#...................................#...................................................................................................
 | 
			
		||||
....................................................................................................#.......................................
 | 
			
		||||
.....................#...........#...............................................#..................................................#.......
 | 
			
		||||
...............................................#.........#..................................................#..................#............
 | 
			
		||||
..........................................................................#...............#........................#........................
 | 
			
		||||
.................#.......................................................................................................#..................
 | 
			
		||||
......................................................................................#..................#..............................#...
 | 
			
		||||
.............#...................................................................................#..........................................
 | 
			
		||||
#...........................#..........#....................................................................................................
 | 
			
		||||
.........#........................................................................#...............................#.........................
 | 
			
		||||
.....................#.........................#.....................................................#....................#......#..........
 | 
			
		||||
.....................................................................#......................................................................
 | 
			
		||||
................................#.....................................................................................................#.....
 | 
			
		||||
...............#..........................................#.................#................#..............................................
 | 
			
		||||
....................................#...........................#...........................................#...............................
 | 
			
		||||
.......#...................#................#.......................................#..............................#......................#.
 | 
			
		||||
......................#.................................................#................................................#..................
 | 
			
		||||
....................................................#......................................#............#...................................
 | 
			
		||||
.............#........................#..........................................................#.............#............................
 | 
			
		||||
...................#..............................................................#.........................................................
 | 
			
		||||
.........................................................#..................#..........#....................................................
 | 
			
		||||
........................#.....................#..............................................#.........................................#....
 | 
			
		||||
.................................................................#.........................................#...................#............
 | 
			
		||||
...................................................#........#.....................................#......................#..................
 | 
			
		||||
.........#....................#.......#................................................................#............#.......................
 | 
			
		||||
#.............................................................................#.....................................................#.......
 | 
			
		||||
..................#.......#.................................................................................................................
 | 
			
		||||
.............#........................................................#........................#................#..........#..............#.
 | 
			
		||||
.....................................................#......................................................................................
 | 
			
		||||
.......#...............#.................#......................#................#..........................................................
 | 
			
		||||
...................................#.....................................................#............................#.....................
 | 
			
		||||
............................................................................................................................................
 | 
			
		||||
...............................#........................................#.........................#.........................................
 | 
			
		||||
.....#.........#...............................#...................#.....................................................................#..
 | 
			
		||||
............................................................................................................................................
 | 
			
		||||
..........#......................................................................#..........................................................
 | 
			
		||||
.........................................#.............................................#......#...................#...................#.....
 | 
			
		||||
........................#.....#........................................................................#....................................
 | 
			
		||||
...................................................#.....#...................#..............................................................
 | 
			
		||||
....................................................................#...............#....................................#........#.........
 | 
			
		||||
...........................#..............................................................#.................................................
 | 
			
		||||
...#........................................#.........#.......................................................#..............#..............
 | 
			
		||||
..........#....................................................#................#...........................................................
 | 
			
		||||
..................................#..................................................................................#...............#......
 | 
			
		||||
.................#..........................................................................................................................
 | 
			
		||||
............................................................................................................................................
 | 
			
		||||
............................#.............#................................#.........................#.....................#................
 | 
			
		||||
.........#.........................................#............#.........................#............................................#....
 | 
			
		||||
....#................................................................#.........................#..............#.............................
 | 
			
		||||
...................#......................................#.................................................................................
 | 
			
		||||
..............................#......#..............................................#..............#................#.......................
 | 
			
		||||
.............................................................................#..............................................................
 | 
			
		||||
.......#.........................................................................................................................#..........
 | 
			
		||||
..............#............#....................#...................#............#.......#.................................#................
 | 
			
		||||
................................#......................#................................................#.................................#.
 | 
			
		||||
............................................................................................................................................
 | 
			
		||||
.#......................#......................................#...............................................#............................
 | 
			
		||||
........................................................................#............................#......................................
 | 
			
		||||
..................................................#..........................#..........................................#.......#...........
 | 
			
		||||
.........................................#..........................................#....................#..............................#...
 | 
			
		||||
......#...............#.................................#...................................................................................
 | 
			
		||||
....................................#.......................................................................................................
 | 
			
		||||
...............................................................#................#........#.........................#..........#.............
 | 
			
		||||
..#........#.....#..........#...................#...................................................#.......................................
 | 
			
		||||
.......................................#...........................#...........................................#............................
 | 
			
		||||
.............................................................................#..............................................................
 | 
			
		||||
.......................#..................................#............#...............#.......#.....................................#......
 | 
			
		||||
............................................................................................................................................
 | 
			
		||||
............#.....#................................#...........#...................................................#............#...........
 | 
			
		||||
...........................................#..............................................#.................................................
 | 
			
		||||
..................................#..............................................#.....................#....................................
 | 
			
		||||
..................................................................#.........................................................................
 | 
			
		||||
...#..........................#............................................#................................................................
 | 
			
		||||
.......................................................#..........................................#........#........#.......................
 | 
			
		||||
.......................................#.................................................................................#......#...........
 | 
			
		||||
.................................................#..........#.........#.......................#.............................................
 | 
			
		||||
............................................................................................................................................
 | 
			
		||||
....#...........#........................................................................................#.......#...........#..............
 | 
			
		||||
......................#...........#.......#....................#..............#.....#.......................................................
 | 
			
		||||
.........#...............................................................................#..................................................
 | 
			
		||||
..................................................#.........................................................................................
 | 
			
		||||
...................#......................................#...........................................#...........................#......#..
 | 
			
		||||
.............#..........#.....................#....................#........................................................................
 | 
			
		||||
...............................................................................#.....#.....#.................#......#.......................
 | 
			
		||||
...#.........................#...................................................................#........................#.................
 | 
			
		||||
............................................................................................................................................
 | 
			
		||||
.......#.........#..........................................#...............................................................................
 | 
			
		||||
.................................#..............................................................................................#...........
 | 
			
		||||
........................................................................#..............#.......#..................#........................#
 | 
			
		||||
.#...................................#......#......#........................................................................................
 | 
			
		||||
............................................................................................................................................
 | 
			
		||||
.............#................#............................................................#..............#.................................
 | 
			
		||||
......#.....................................................#.......................#................#...............................#......
 | 
			
		||||
...................#..............................................#.......................................................#.................
 | 
			
		||||
....................................#.....................................#.................................................................
 | 
			
		||||
........................................................................................................#.......#...........................
 | 
			
		||||
....#.....................................#...............#...................#...............#.........................................#...
 | 
			
		||||
.....................................................................................#......................................................
 | 
			
		||||
....................................................#...........#......................................................#............#.......
 | 
			
		||||
........................#...................................................................................#...............................
 | 
			
		||||
............................................................................#.....#.........#......................#........................
 | 
			
		||||
...#.....#.....#.......................#....................................................................................................
 | 
			
		||||
............................................................................................................................................
 | 
			
		||||
......................................................................#.....................................................................
 | 
			
		||||
......................................................................................#............#..........................#.............
 | 
			
		||||
.....#.............#.........................................................#................#.............................................
 | 
			
		||||
..............................#..........#............#.....#...........................................................#.............#.....
 | 
			
		||||
........................................................................#................#..................................................
 | 
			
		||||
..................................................................................#.........................................................
 | 
			
		||||
......................#.............#....................#........................................................#.........................
 | 
			
		||||
.................#................................#.............#.............#.............................................................
 | 
			
		||||
............................................................................................................................................
 | 
			
		||||
...#..........................#.............#....................................................#.......#...............#.........#........
 | 
			
		||||
........#...........#.................#..................................................................................................#..
 | 
			
		||||
..............#.................................#.....#..........................................................#..........................
 | 
			
		||||
...........................................................#......#.........................................................................
 | 
			
		||||
............................#..................................................#.....................................#......................
 | 
			
		||||
...................................................#.......................................#................................................
 | 
			
		||||
.#................#................#...............................................#...........................................#.....#......
 | 
			
		||||
.............#....................................................................................................#.........................
 | 
			
		||||
.........................#...........................................#.....#......................#..........#..............................
 | 
			
		||||
........................................#...................#...........................................#...................................
 | 
			
		||||
...#......#............................................................................#....................................................
 | 
			
		||||
...............................................#.......................................................................#....................
 | 
			
		||||
							
								
								
									
										197
									
								
								day11/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								day11/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,197 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// var log = aoc.Log
 | 
			
		||||
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	m := NewMap()
 | 
			
		||||
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		text := scan.Text()
 | 
			
		||||
		m.readLine(text)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &result{
 | 
			
		||||
		valuePT1: m.expand(1).sumPaths(),
 | 
			
		||||
		valuePT2: m.expand(999_999).sumPaths(),
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Map struct {
 | 
			
		||||
	rows int
 | 
			
		||||
	cols int
 | 
			
		||||
 | 
			
		||||
	emptyRows map[int]bool
 | 
			
		||||
	emptyCols map[int]bool
 | 
			
		||||
 | 
			
		||||
	*aoc.List[rune]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewMap() *Map {
 | 
			
		||||
	return &Map{
 | 
			
		||||
		emptyRows: make(map[int]bool),
 | 
			
		||||
		emptyCols: make(map[int]bool),
 | 
			
		||||
		List:      aoc.NewList[rune](nil),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (m *Map) String() string {
 | 
			
		||||
	buf := &strings.Builder{}
 | 
			
		||||
	fmt.Fprintf(buf, "Map size %d x %d\n", m.rows, m.cols)
 | 
			
		||||
	fmt.Fprintln(buf, "empty rows:", all(m.emptyRows))
 | 
			
		||||
	fmt.Fprintln(buf, "empty cols:", all(m.emptyCols))
 | 
			
		||||
 | 
			
		||||
	n := m.Head()
 | 
			
		||||
	for n != nil {
 | 
			
		||||
		fmt.Fprintln(buf, toXY(n.Position(), m.cols), n.String())
 | 
			
		||||
		n = n.Next()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for row := 0; row < m.rows; row++ {
 | 
			
		||||
		for col := 0; col < m.cols; col++ {
 | 
			
		||||
			if n := m.getRC(row, col); n != nil {
 | 
			
		||||
				buf.WriteRune('#')
 | 
			
		||||
			} else {
 | 
			
		||||
				buf.WriteRune('.')
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		buf.WriteRune('\n')
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return buf.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Map) readLine(text string) {
 | 
			
		||||
	if m.cols == 0 {
 | 
			
		||||
		m.cols = len(text)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	emptyRow, ok := m.emptyRows[m.rows]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		emptyRow = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	row := []rune(text)
 | 
			
		||||
	for col, r := range row {
 | 
			
		||||
		emptyCol, ok := m.emptyCols[col]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			emptyCol = true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if r == '#' {
 | 
			
		||||
			m.Add(r, fromXY(col, m.rows, m.cols))
 | 
			
		||||
			emptyCol = false
 | 
			
		||||
			emptyRow = false
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m.emptyRows[m.rows] = emptyRow
 | 
			
		||||
		m.emptyCols[col] = emptyCol
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m.rows++
 | 
			
		||||
}
 | 
			
		||||
func (m *Map) getRC(row, col int) *aoc.Node[rune] {
 | 
			
		||||
	return m.List.Get(fromXY(col, row, m.cols))
 | 
			
		||||
}
 | 
			
		||||
func (m *Map) expand(rate int) *Map {
 | 
			
		||||
	newM := NewMap()
 | 
			
		||||
 | 
			
		||||
	newM.rows = m.rows + rate*len(all(m.emptyRows))
 | 
			
		||||
	newM.cols = m.cols + rate*len(all(m.emptyCols))
 | 
			
		||||
 | 
			
		||||
	offsetC := 0
 | 
			
		||||
	for col := 0; col < m.cols; col++ {
 | 
			
		||||
		if empty, ok := m.emptyCols[col]; ok && empty {
 | 
			
		||||
			for r := 0; r <= rate; r++ {
 | 
			
		||||
				newM.emptyCols[offsetC+col+r] = true
 | 
			
		||||
			}
 | 
			
		||||
			offsetC += rate
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	offsetR := 0
 | 
			
		||||
	for row := 0; row < m.rows; row++ {
 | 
			
		||||
		if empty, ok := m.emptyRows[row]; ok && empty {
 | 
			
		||||
			for r := 0; r <= rate; r++ {
 | 
			
		||||
				newM.emptyRows[offsetR+row+r] = true
 | 
			
		||||
			}
 | 
			
		||||
			offsetR += rate
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		offsetC := 0
 | 
			
		||||
		for col := 0; col < m.cols; col++ {
 | 
			
		||||
			if empty, ok := m.emptyCols[col]; ok && empty {
 | 
			
		||||
				offsetC += rate
 | 
			
		||||
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if n := m.getRC(row, col); n != nil {
 | 
			
		||||
				newM.Add('#', fromXY(offsetC+col, offsetR+row, newM.cols))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newM
 | 
			
		||||
}
 | 
			
		||||
func (m *Map) sumPaths() int {
 | 
			
		||||
	var positions []int
 | 
			
		||||
 | 
			
		||||
	n := m.Head()
 | 
			
		||||
	for n != nil {
 | 
			
		||||
		positions = append(positions, n.Position())
 | 
			
		||||
		n = n.Next()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var paths []int
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < len(positions); i++ {
 | 
			
		||||
		p := positions[i]
 | 
			
		||||
		pXY := toXY(p, m.cols)
 | 
			
		||||
 | 
			
		||||
		for j := i; j < len(positions); j++ {
 | 
			
		||||
			c := positions[j]
 | 
			
		||||
			if c == p {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			cXY := toXY(c, m.cols)
 | 
			
		||||
 | 
			
		||||
			path := aoc.ABS(cXY[0]-pXY[0]) + aoc.ABS(cXY[1]-pXY[1])
 | 
			
		||||
			paths = append(paths, path)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return aoc.Sum(paths...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func all(m map[int]bool) []int {
 | 
			
		||||
	lis := make([]int, 0, len(m))
 | 
			
		||||
	for k, v := range m {
 | 
			
		||||
		if v {
 | 
			
		||||
			lis = append(lis, k)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	sort.Ints(lis)
 | 
			
		||||
	return lis
 | 
			
		||||
}
 | 
			
		||||
func fromXY(x, y, w int) int { return y*w + x }
 | 
			
		||||
func toXY(i, w int) [2]int   { return [2]int{i % w, i / w} }
 | 
			
		||||
							
								
								
									
										41
									
								
								day11/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								day11/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
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.valuePT1, 374)
 | 
			
		||||
	is.Equal(result.valuePT2, 82000210)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.valuePT1, 9627977)
 | 
			
		||||
	is.Equal(result.valuePT2, 644248339497)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								day12/example.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								day12/example.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
???.### 1,1,3
 | 
			
		||||
.??..??...?##. 1,1,3
 | 
			
		||||
?#?#?#?#?#?#?#? 1,3,1,6
 | 
			
		||||
????.#...#... 4,1,1
 | 
			
		||||
????.######..#####. 1,6,5
 | 
			
		||||
?###???????? 3,2,1
 | 
			
		||||
							
								
								
									
										1000
									
								
								day12/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1000
									
								
								day12/input.txt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										187
									
								
								day12/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								day12/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,187 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"slices"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// var log = aoc.Log
 | 
			
		||||
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	var matches []int
 | 
			
		||||
	var matches2 []int
 | 
			
		||||
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		text := scan.Text()
 | 
			
		||||
		status, text, ok := strings.Cut(text, " ")
 | 
			
		||||
		if !ok {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// part 1 - brute force
 | 
			
		||||
		grouping := aoc.SliceMap(aoc.Atoi, strings.Split(text, ",")...)
 | 
			
		||||
		pattern := []rune(status)
 | 
			
		||||
		// sp := spring{pattern: pattern, grouping: grouping, missingNo: countQuestion(pattern)}
 | 
			
		||||
		// matches = append(matches, sp.findMatches())
 | 
			
		||||
		matches = append(matches, countPossible(pattern, grouping))
 | 
			
		||||
 | 
			
		||||
		// part 2 - NFA
 | 
			
		||||
		b, a := status, text
 | 
			
		||||
		bn, an := "", ""
 | 
			
		||||
		for i := 0; i < 5; i++ {
 | 
			
		||||
			bn, an = bn+b+"?", an+a+","
 | 
			
		||||
		}
 | 
			
		||||
		b, a = strings.TrimSuffix(bn, "?"), strings.TrimSuffix(an, ",")
 | 
			
		||||
		matches2 = append(matches2, countPossible([]rune(b), aoc.SliceMap(aoc.Atoi, strings.Split(a, ",")...)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &result{valuePT1: aoc.Sum(matches...), valuePT2: aoc.Sum(matches2...)}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type spring struct {
 | 
			
		||||
	pattern   []rune
 | 
			
		||||
	grouping  []int
 | 
			
		||||
	missingNo int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *spring) findMatches() int {
 | 
			
		||||
	matches := 0
 | 
			
		||||
	for _, pattern := range s.genPatterns() {
 | 
			
		||||
		pattern := []rune(pattern)
 | 
			
		||||
		target := make([]rune, len(s.pattern))
 | 
			
		||||
		i := 0
 | 
			
		||||
		for j, r := range s.pattern {
 | 
			
		||||
			if r == '?' {
 | 
			
		||||
				target[j] = pattern[i]
 | 
			
		||||
				i++
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			target[j] = r
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if slices.Equal(countGroupings(target), s.grouping) {
 | 
			
		||||
			matches++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return matches
 | 
			
		||||
}
 | 
			
		||||
func (s *spring) genPatterns() []string {
 | 
			
		||||
	buf := &strings.Builder{}
 | 
			
		||||
	combinations := aoc.Power2(s.missingNo)
 | 
			
		||||
	lis := make([]string, 0, combinations)
 | 
			
		||||
	for i := 0; i < combinations; i++ {
 | 
			
		||||
		for b := 0; b < s.missingNo; b++ {
 | 
			
		||||
			if i>>b&0b1 == 1 {
 | 
			
		||||
				buf.WriteRune('#')
 | 
			
		||||
			} else {
 | 
			
		||||
				buf.WriteRune('.')
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		lis = append(lis, buf.String())
 | 
			
		||||
		buf.Reset()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return lis
 | 
			
		||||
}
 | 
			
		||||
func countPossible(s []rune, c []int) int {
 | 
			
		||||
	pos := 0
 | 
			
		||||
 | 
			
		||||
	cstates := map[state]int{{}: 1} // current state
 | 
			
		||||
	nstates := map[state]int{}      // next state
 | 
			
		||||
 | 
			
		||||
	for len(cstates) > 0 {
 | 
			
		||||
		for st, num := range cstates {
 | 
			
		||||
			si, ci, cc, expdot := st.springIndex, st.groupIndex, st.continuous, st.expectDot
 | 
			
		||||
 | 
			
		||||
			// have we reached the end?
 | 
			
		||||
			if si == len(s) {
 | 
			
		||||
				if ci == len(c) {
 | 
			
		||||
					pos += num
 | 
			
		||||
				}
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			switch {
 | 
			
		||||
			case (s[si] == '#' || s[si] == '?') && ci < len(c) && !expdot:
 | 
			
		||||
				// we are still looking for broken springs
 | 
			
		||||
				if s[si] == '?' && cc == 0 {
 | 
			
		||||
					// we are not in a run of broken springs, so ? can be working
 | 
			
		||||
					nstates[state{si + 1, ci, cc, expdot}] += num
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				cc++
 | 
			
		||||
 | 
			
		||||
				if cc == c[ci] {
 | 
			
		||||
					// we've found the full next contiguous section of broken springs
 | 
			
		||||
					ci++
 | 
			
		||||
					cc = 0
 | 
			
		||||
					expdot = true // we only want a working spring next
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				nstates[state{si + 1, ci, cc, expdot}] += num
 | 
			
		||||
 | 
			
		||||
			case (s[si] == '.' || s[si] == '?') && cc == 0:
 | 
			
		||||
				// we are not in a contiguous run of broken springs
 | 
			
		||||
				expdot = false
 | 
			
		||||
				nstates[state{si + 1, ci, cc, expdot}] += num
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// swap and clear previous states
 | 
			
		||||
		cstates, nstates = nstates, cstates
 | 
			
		||||
		clear(nstates)
 | 
			
		||||
	}
 | 
			
		||||
	return pos
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type state struct {
 | 
			
		||||
	springIndex int
 | 
			
		||||
	groupIndex  int
 | 
			
		||||
	continuous  int
 | 
			
		||||
	expectDot   bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func countQuestion(pattern []rune) int {
 | 
			
		||||
	count := 0
 | 
			
		||||
	for _, r := range pattern {
 | 
			
		||||
		if r == '?' {
 | 
			
		||||
			count++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return count
 | 
			
		||||
}
 | 
			
		||||
func countGroupings(pattern []rune) []int {
 | 
			
		||||
	var groupings []int
 | 
			
		||||
	inGroup := false
 | 
			
		||||
	for _, r := range pattern {
 | 
			
		||||
 | 
			
		||||
		if r == '#' {
 | 
			
		||||
			if !inGroup {
 | 
			
		||||
				groupings = append(groupings, 0)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			inGroup = true
 | 
			
		||||
			groupings[len(groupings)-1]++
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
		if inGroup && r != '#' {
 | 
			
		||||
			inGroup = false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return groupings
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								day12/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								day12/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	_ "embed"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
 | 
			
		||||
	"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.valuePT1, 21)
 | 
			
		||||
	is.Equal(result.valuePT2, 525152)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.valuePT1, 8193)
 | 
			
		||||
	is.Equal(result.valuePT2, 45322533163795)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPower2(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
	is.Equal(aoc.Power2(1), 2)
 | 
			
		||||
	is.Equal(aoc.Power2(2), 4)
 | 
			
		||||
	is.Equal(aoc.Power2(3), 8)
 | 
			
		||||
	is.Equal(aoc.Power2(4), 16)
 | 
			
		||||
	is.Equal(aoc.Power2(5), 32)
 | 
			
		||||
	is.Equal(aoc.Power2(6), 64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCountGroupings(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	is.Equal([]int{1, 3, 1}, countGroupings([]rune(".#.###.#")))
 | 
			
		||||
	is.Equal([]int{1, 3, 1}, countGroupings([]rune(".#.###...#.")))
 | 
			
		||||
	is.Equal([]int{1, 3, 1}, countGroupings([]rune("#.###...#.")))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCombination(t *testing.T) {
 | 
			
		||||
	s := spring{
 | 
			
		||||
		pattern:   []rune("???"),
 | 
			
		||||
		grouping:  []int{1},
 | 
			
		||||
		missingNo: 3,
 | 
			
		||||
	}
 | 
			
		||||
	s.findMatches()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								day13/example.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								day13/example.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
#.##..##.
 | 
			
		||||
..#.##.#.
 | 
			
		||||
##......#
 | 
			
		||||
##......#
 | 
			
		||||
..#.##.#.
 | 
			
		||||
..##..##.
 | 
			
		||||
#.#.##.#.
 | 
			
		||||
 | 
			
		||||
#...##..#
 | 
			
		||||
#....#..#
 | 
			
		||||
..##..###
 | 
			
		||||
#####.##.
 | 
			
		||||
#####.##.
 | 
			
		||||
..##..###
 | 
			
		||||
#....#..#
 | 
			
		||||
							
								
								
									
										7
									
								
								day13/example00.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								day13/example00.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
#.##..##.
 | 
			
		||||
..#.##.#.
 | 
			
		||||
##......#
 | 
			
		||||
##......#
 | 
			
		||||
..#.##.#.
 | 
			
		||||
..##..##.
 | 
			
		||||
#.#.##.#.
 | 
			
		||||
							
								
								
									
										1301
									
								
								day13/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1301
									
								
								day13/input.txt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										11
									
								
								day13/input07.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								day13/input07.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
##.#.##.#
 | 
			
		||||
...#..#..
 | 
			
		||||
.##...#..
 | 
			
		||||
.##...#..
 | 
			
		||||
.#.#..#..
 | 
			
		||||
##.#.##.#
 | 
			
		||||
.#...####
 | 
			
		||||
..#.#..##
 | 
			
		||||
...#...##
 | 
			
		||||
.#....#.#
 | 
			
		||||
.#....#.#
 | 
			
		||||
							
								
								
									
										179
									
								
								day13/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								day13/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,179 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var log = aoc.Log
 | 
			
		||||
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	maps := []Map{}
 | 
			
		||||
	m := Map{}
 | 
			
		||||
	r := &result{}
 | 
			
		||||
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		text := scan.Text()
 | 
			
		||||
 | 
			
		||||
		if text == "" {
 | 
			
		||||
			maps = append(maps, m)
 | 
			
		||||
			m = Map{}
 | 
			
		||||
		} else {
 | 
			
		||||
			m = append(m, []rune(text))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	maps = append(maps, m)
 | 
			
		||||
 | 
			
		||||
	for _, m := range maps {
 | 
			
		||||
		sum, sum2 := findSmudge(m)
 | 
			
		||||
 | 
			
		||||
		if sum == -1 || sum2 == -1 {
 | 
			
		||||
			mr := Map(aoc.Transpose(m))
 | 
			
		||||
			Hsum, Hsum2 := findSmudge(mr)
 | 
			
		||||
 | 
			
		||||
			if sum2 == -1 {
 | 
			
		||||
				sum2 = Hsum2 * 100
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if sum == -1 {
 | 
			
		||||
				sum = Hsum * 100
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		r.valuePT1 += sum
 | 
			
		||||
		r.valuePT2 += sum2
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Map [][]rune
 | 
			
		||||
 | 
			
		||||
func (m Map) String() string {
 | 
			
		||||
	var buf strings.Builder
 | 
			
		||||
	for i, row := range m {
 | 
			
		||||
		if i == 0 {
 | 
			
		||||
			fmt.Fprint(&buf, "   ")
 | 
			
		||||
			for j := range row {
 | 
			
		||||
				fmt.Fprintf(&buf, "%d", j)
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Fprint(&buf, "\n")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		fmt.Fprintf(&buf, "%d ", i)
 | 
			
		||||
		buf.WriteRune(' ')
 | 
			
		||||
		buf.WriteString(string(row))
 | 
			
		||||
		buf.WriteRune('\n')
 | 
			
		||||
	}
 | 
			
		||||
	buf.WriteRune('\n')
 | 
			
		||||
	return buf.String()
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// func findReflection(m Map) (int, bool) {
 | 
			
		||||
// 	candidates := make(map[int]bool)
 | 
			
		||||
// 	var candidateList []int
 | 
			
		||||
 | 
			
		||||
// 	for _, row := range m {
 | 
			
		||||
// 		for col := 1; col < len(row); col++ {
 | 
			
		||||
// 			if v, ok := candidates[col]; !ok || v {
 | 
			
		||||
// 				candidates[col], _ = reflects(row[:col], row[col:])
 | 
			
		||||
// 			}
 | 
			
		||||
// 		}
 | 
			
		||||
// 		candidateList = all(candidates)
 | 
			
		||||
// 		if len(candidateList) == 0 {
 | 
			
		||||
// 			return 0, false
 | 
			
		||||
// 		}
 | 
			
		||||
// 	}
 | 
			
		||||
 | 
			
		||||
// 	if len(candidateList) == 1 {
 | 
			
		||||
// 		return candidateList[0], true
 | 
			
		||||
// 	}
 | 
			
		||||
 | 
			
		||||
// 	return 0, false
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
type level struct {
 | 
			
		||||
	blips  int
 | 
			
		||||
	nequal int
 | 
			
		||||
	fail   bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func findSmudge(m Map) (int, int) {
 | 
			
		||||
	candidates := make(map[int]level)
 | 
			
		||||
 | 
			
		||||
	for _, row := range m {
 | 
			
		||||
		for col := 1; col < len(row); col++ {
 | 
			
		||||
			candidate := candidates[col]
 | 
			
		||||
			if candidate.fail {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			eq, bl := reflects(row[:col], row[col:])
 | 
			
		||||
			if !eq {
 | 
			
		||||
				candidate.nequal++
 | 
			
		||||
			}
 | 
			
		||||
			candidate.blips += bl
 | 
			
		||||
 | 
			
		||||
			if candidate.nequal > 1 || candidate.blips > 1 {
 | 
			
		||||
				candidate.fail = true
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			candidates[col] = candidate
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	a, b := -1, -1
 | 
			
		||||
	for i, cand := range candidates {
 | 
			
		||||
		if !cand.fail && cand.blips == 1 {
 | 
			
		||||
			b = i
 | 
			
		||||
		}
 | 
			
		||||
		if !cand.fail && cand.blips == 0 {
 | 
			
		||||
			a = i
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return a, b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func reflects(a, b []rune) (bool, int) {
 | 
			
		||||
	c := min(len(a), len(b))
 | 
			
		||||
 | 
			
		||||
	a = append([]rune{}, a...)
 | 
			
		||||
	b = append([]rune{}, b...)
 | 
			
		||||
	aoc.Reverse(a)
 | 
			
		||||
	a = a[:c]
 | 
			
		||||
	b = b[:c]
 | 
			
		||||
 | 
			
		||||
	blips := 0
 | 
			
		||||
	for i := range a {
 | 
			
		||||
		if a[i] != b[i] {
 | 
			
		||||
			blips++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return blips == 0, blips
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func all[T comparable](m map[T]bool) []T {
 | 
			
		||||
	lis := make([]T, 0, len(m))
 | 
			
		||||
	for k, v := range m {
 | 
			
		||||
		if v {
 | 
			
		||||
			lis = append(lis, k)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return lis
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								day13/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								day13/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
			
		||||
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.valuePT1, 405)
 | 
			
		||||
	is.Equal(result.valuePT2, 400)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.True(result.valuePT1 > 1704) // attempt 1
 | 
			
		||||
	is.Equal(result.valuePT1, 30705)
 | 
			
		||||
	is.Equal(result.valuePT2, 44615)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								day14/example.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								day14/example.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
O....#....
 | 
			
		||||
O.OO#....#
 | 
			
		||||
.....##...
 | 
			
		||||
OO.#O....O
 | 
			
		||||
.O.....O#.
 | 
			
		||||
O.#..O.#.#
 | 
			
		||||
..O..#O..O
 | 
			
		||||
.......O..
 | 
			
		||||
#....###..
 | 
			
		||||
#OO..#....
 | 
			
		||||
							
								
								
									
										100
									
								
								day14/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								day14/input.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,100 @@
 | 
			
		||||
...#.O.#.#.O.O....#...O....#..#........OO.O#...O..O#O#.......O.O....O.....#...OO#.O....OOO..OO#..#..
 | 
			
		||||
.##.....#.OOO.OO#...O.......O#..O.##OO.O.......O##....O....#O..O..#.#....#OO..#...O.O#.#...#....#O.O
 | 
			
		||||
O...##.O.O.O.O..#.#.....#O....#..#O..O...O..OO..O...##.......OO#..OOO..#O..#.O#.O......#..#O..O..O.O
 | 
			
		||||
..OO....OOO....O.O..OOO.....O........#...O.O.O.O..O#.O...O..#.#O........O.....#O...##....#...#.#....
 | 
			
		||||
##.O.O#..O..##O.....O.#.....O.O#O.O..#...#...OO.##OOO...OO#...O...O........O.#.O.........#O.#...#.#.
 | 
			
		||||
.#.O.O.....#..O###..O#.#..O....O.O....#...##.O..O.OOO..O.O..O#.O..O....#.#.O..#..##O...O....#O#.....
 | 
			
		||||
.......O...##..O..O##..##...O....###.O.#.#.O......O...O.O......#O.....#..O..O#..##O.O#O##O....O#....
 | 
			
		||||
.#O..#....##.##..O#..#..#..O........OO....#..##.O.#.O.O..OO.O.O#..#O##O......OO...O...OO...#....OO..
 | 
			
		||||
#.....O#......O#.....#..O...#O..OO..OO.#O...O...O.........O...#O...O.....#.....#...#.....O##.O.....O
 | 
			
		||||
OO.O..O...O......#.O......#O....#..#.#...O.O....O.#.O#...O........O......#.#O#.O...O.........#O....O
 | 
			
		||||
O.O..O..#......O.O.OO...OO..##.....OO.....#.O...O.#.#...OO..OO.O.........#O..#.O...O#.#..O..OO.##O..
 | 
			
		||||
..#.......O....#...#....##..O.O......O....O#.O..O..#.#.O#O.O.#...#.##.....O...O.O...O.#...O...O.#...
 | 
			
		||||
.O...#..O.....O.O.....OO.O.O.......O..O..........#...O..O..O......O....#OOO...O#O...#.O#........O...
 | 
			
		||||
.OO#....#.....O...#.###..#..O..O.....#O..#..OO...OOO#.O#..O#O........#..#.O..OOO#O#..O..OO........#.
 | 
			
		||||
..O.....#..#..O.............#..O.O..O#.......#.O.........O.#..OO.O..#..##..O.O#O....OO.O.O.O.....O#.
 | 
			
		||||
........#O..O#OO...#.##O.O....O...O..........##.#O..O......O..O.#...#O.O.OO...#.#OOO.#...O#....#.O.#
 | 
			
		||||
.....O.O...#OO#.OO#......#..O.O..#.OO.......#...#.O.O#.O.#O.O#..#O##..OO...#......#.O....#.....O.#O.
 | 
			
		||||
.O#OOOO...#.#..........O#.#.#.#.O....O..O...O...OOO.O.O.O..OO..O..O#.#...#....#...#O#.OO.O..#.O#....
 | 
			
		||||
OO#OO..#.O.#....#..#.#..#O#.O#O#.#..O.O....#..O...OO..O..#........#.O...O#.#.....#....O.....#.O.....
 | 
			
		||||
.O.....#...OO...#..O..#..O..O##..OO...O....#.O.#............###.O.#..O..O.........O..#.O..O.#OO.#...
 | 
			
		||||
.##O.#.O.#....O..O..#..O.#.O..##O..O......OO...#...O..OO#....O..O#O.##.OO#...O#...#.......O.O#.#OO..
 | 
			
		||||
.OO#O#...O..##.O......O..O.O....O...OOO.O..#...O#.#.O.OOO..#...#.##..OO..................OOOOO...###
 | 
			
		||||
.#..##...####.O#...O........O...#O..O..O....O##O..O..OO..#.....#...O.....OO......OOO.#..O.##OO##...#
 | 
			
		||||
....O#........O##.O...O#..#.O#O...O...O.O........#..#.#.O......O..#.....#.O..#.#..#..#O....O##...#..
 | 
			
		||||
.O..OO.O##..O...O.OO....O.OOO..#O#.O##......O.O#....O#O.O......#.O..#O..#O.........#..OO....#.OO..O.
 | 
			
		||||
.#OO..#OO.###........#...#..#.O..#O.O#O...O.#.....O...#......O.......#.O.#.##.O..#O.O###OOOO...#..O.
 | 
			
		||||
##...OOO.#..........O#...O#.....OO...O#..OO.OO.#.OOO..OO....O..OOO...##O...O.........##O...#.#O.....
 | 
			
		||||
.#....O.....#OO.O.OO..O......#.OO..#O...O..##O.#O....#O.OO..#O.OO...O..O.#..##...O......#O##OO.#.O..
 | 
			
		||||
.#..O....O....#......#.O.##...OO.O.O...O.OO.O....#...#..O....O#O..#...#.#..#...OO......OOO...O..#...
 | 
			
		||||
#.#OO.#....O.#.OO....#........O.O.##...O.#.................OOOO....O..#......O..#.#...O....#.O#OO.#O
 | 
			
		||||
....O.O.......##..O.........OO#O..O.O#.#.#.O....#..OO.O..O#O....O..O.O......O.O.#..O.......O.O..O.O#
 | 
			
		||||
...........#OO...O....#.O.#..#O.O#.....O..O.....O#.....OO.#O...#O.#O.#.....OO.O.O....OO......O#O.O..
 | 
			
		||||
OOOO.OO..O....O.O...O..#.........O#.##OOO#.O..O.O.O......O..#..O..#..#.O..O....O#O.#OO..O.O...O#.##.
 | 
			
		||||
##.O.#O.#OO#..........OO#.OO.#..#.#......#.OO...#.O.O.......O##....O..O..#.#.#O....O..##.#OO.O..O..O
 | 
			
		||||
#O...OO..#.#....##.O#.#...##OO#........O#.O..O#.........O.O.#....O.#.O.......O..OOO......O#O.###.O..
 | 
			
		||||
....O#....#..O...#.#.....O.O#O..#O....O...O.OO#...O..O#.##.O.....O...#..#.O.....O...O#..O.#...#.#O..
 | 
			
		||||
O.OO......#..O...O.O....#...OO..O#.O..OO..#.##.....#....O.O#O#.O....O..#..OOO..O....O.O..#..O.O..O..
 | 
			
		||||
.#..#..##O..O.....O#.#.O.O..O..OO..O.O..OO.##.O...O..O#........O.............#.OO..#......O..#O#OOO.
 | 
			
		||||
.#..##...O.#..OO...O..#..#O#..#..##.O#.#.....#....O.O..O.........#.###...#.O##..O...#.O.OO..........
 | 
			
		||||
........#O.......O...O#.#....#.O#....#..O.....OO........O...#.........##.....O...O#.O...O.O..#OO.O.#
 | 
			
		||||
.#..#.O##..##.O#.#.......OO...OO#...#O#............#.#...#...O...#.O..#O.#.O.........O..OO.O...O.#..
 | 
			
		||||
#.O#OO...OO.O.#...##........#....O.#.O.....##.#.O.O.O.#..O#...O..#......#..O...###O..OO..##..OO.#OOO
 | 
			
		||||
.OO...#O....O##.O...O.#....O...#O.......O.....OO.O...O..#...OO.OO.O#...O##.....O..#.#...#OO......O..
 | 
			
		||||
..O..#...O...##..O...O..OO.O.O.O.....#.....O.....O..#OOO.....OOOO#.#.O..O..#........O.#O#.#O..O.##..
 | 
			
		||||
.....##.....O.....O#...##.OOO....O.O..O.#.#O........OO.....#...##...#.#......#....OO.O.....#O....#.#
 | 
			
		||||
..O.OO#....O..O.#O.#OO#..#.O.##.#..#.OO##....O#...#..O.#..#...#.#....OOOO.#...OOOO..O.........##O.O.
 | 
			
		||||
O.O.#......O#...O..#.......#O.O..OOOO..#....#.#.OO.O..#O......#.#....#...#..O....#O.OO..O.......#.#.
 | 
			
		||||
...O.O....O#......#.O.O....O#.#..#O.#.....#...#...#.O#.........O.OO..O###...O....O.#.O.#.....##..O..
 | 
			
		||||
.#.OO...O#O.....O#....O......OO...OO.OOOOOO##....#..#..#O.#.OO....O#..OO.#O........O#..O.O#.#.......
 | 
			
		||||
#OO#.#.....O#OOO#...O.........#......O#.......O.....O#.#O...O........#....O...O.....#.......##.OOO#.
 | 
			
		||||
..#.O##..#OO..#....#O....#....#..........#O...#...O.#.O.O###O..O..#...#.OO....##..O.O.O.....O..O....
 | 
			
		||||
....OOO#.#......#..O.O......##O.#.O.#.O.OO....#..O.......#.....#O.O...##O###.##.##..#.O.#.O#..#..O#.
 | 
			
		||||
......O#OO......#.#..#.O#OO#O..O#O.O##.......O...O........O......O#.....#..#....#...#.#..O...O##.#O.
 | 
			
		||||
#..OO..O.O.....#O.O.#.#......O......O.#....O.#OO.........#.O.O#..#..#.O..O.#..#...#...O.#..........O
 | 
			
		||||
..O#OOO#.#.....O.....O..##.#..OOO.O..#..O#...##O..OO...#....#..#...#...OO.....##OO#.OO...#.O....#.#.
 | 
			
		||||
#.#O.............#....O#.....O.....O.##O.....#.#.#.....O....O...O...##..O...#........#O..##.#.....##
 | 
			
		||||
.O.....O...#O.#.O#..O#........#.##...O##O..........O##.O......O..#....##....###......O##..##O..#.O#.
 | 
			
		||||
.#...#..#..O.O.............#....O.OO.....OO#O.....OO..OOO#O.O.O.O...#...#.........OO..O#.O...#.##..#
 | 
			
		||||
..O...#O#.......#OO..........OO#..#.....OO#...#OO.O#....OO....O..O..#....#OO......O#O...#......O..O.
 | 
			
		||||
O.......O..O..#O.....O#O.........O##.O#.#.O.O....##....O.#....O....OOO..#O#...#...O.O#.O.....O.O#.O.
 | 
			
		||||
O.#O....O..##....O.........##.OO###....O...O...O..O#O#...#O.O.O....#..O..#..#.O.......###..#....#..O
 | 
			
		||||
.........O..#O...O..OO.....#...O..#O#.....O....#O#....##...#.OOOO.O..O#...O..O.O#.#..O.O..#..#.OO...
 | 
			
		||||
...#.....#..OO.O.#.#.O.....O#...#..O...O..O..#...O..O.O..#...#.###..#..##O.#.#O.......O..##O.O.O#...
 | 
			
		||||
.##O......O....#....O....#O..#.....#.O..O.O.O..#.#O.....O#.O...#.#O.#...#.........O....O....OO..O...
 | 
			
		||||
.OO.O.O.O#O..O##.O...OO.....O..O....O....#..#...O.O...O....O.#.O......#O.#.O#O..O...O.O.#.O..O.#....
 | 
			
		||||
O#..#.#..#..#...#.O...O.###.##.OO.O.#.OOO..O..#O.#.O...OO...O.OOO....#.....#OO.O##.O.#.#O...#.#.....
 | 
			
		||||
.#.....#.........O.#.........#...OO..O.#.O...O##O...#..O.O.OO#....###.OO.....#..........#.#OO...O.O.
 | 
			
		||||
........OO..O.O.#..O.#.......#.#O.OOO...OO.O............O#O#...O...#.O.....#...........O...#..OO.O#O
 | 
			
		||||
..#.#.#...O....#O.......#...#...O###.O.....O.O.OO....#O...OO.O.O........O.O.#O.O....OO.....OO.....#.
 | 
			
		||||
#..OOO#......O.#.O#...#..#..O..O.O.O.#...O#OOO.#...O.#.OO.#O..#....#..#O....O.#.O...O...O#OO...#....
 | 
			
		||||
.....#.....##...O....#..O..O.....O#OO.#O#.....O...O.##.#........O..O........#.#......##......#..#..O
 | 
			
		||||
O..O....O.##..#.#O##.#.....OO....O.##O......#...#..OO.O.....#...#........O..O#O##.O.......#..##O..##
 | 
			
		||||
#.....#O....O...#OOO#..O#.O.....O..OO.#..#.#.O#..O..O#.O###....O......O.#.O..#O.....#.......##O.O..O
 | 
			
		||||
O.O.#..#....O....O.......#.O..O#O#.O..........#O.....#OO.O...#.OO.....#...O....OO....#...O....O.#..O
 | 
			
		||||
..#...OO....OO......O....#..#..........##..##..#.....##...#..#O.....#OO......#........O.....O..O...#
 | 
			
		||||
.OO#...O#.O....#.........OO#...O#..O.#..O.O.O.#O......##.O.......O...O...###.O......O....O...#.OO#..
 | 
			
		||||
..O..O#O.#..O.#O...OOO#O.#.O....O.#......O....#....###....OO......O...#...OO.#....O........O#..#..OO
 | 
			
		||||
#..OO..O......#...##..O#.O........O.O...##.#O...O...#O#.O.O....#.............#.O#.#..O..#..OO#.....#
 | 
			
		||||
#..........O...O##.O#..O..OO..O.....#O.#.O......#......O.O....##.O#OO..O.O..O.O.O..#..O....O..#....O
 | 
			
		||||
.O.O...O.#..O.O....#.#.O.O.##.##..O..#OOOO.###...#O...#...O.....O...#.##.OO..O.#..#.O.#.......O....#
 | 
			
		||||
#....#....OOOOOOO.#...OO....##O.#..#......O..#..........O......##..O..###..#.O....O.......OO......#.
 | 
			
		||||
.O.O..##.O.#O.#...#....O..O.....#..##......O.......O..O#.O##.#........O..#.O.#.O.O..##..###..##.#...
 | 
			
		||||
..OOO..O##..OOOO.O.....OO##..O..O.#....#.....OO......O.OOO#...#O.OO...O.O......O#..O.##....###...#.O
 | 
			
		||||
....O...O.O....#..O#.O.....O.O.#.......O##...O#..OO.O.O##...#.....O#.###....O....#O.........OO..O.O.
 | 
			
		||||
O#.O......##..#.#..............#......#.#.OO#......##O#OO..OOO..##.O##....#..O...#......##O.O##...OO
 | 
			
		||||
...#OO....OO...O#.#..##....OO.#..#O......O#....#.O.....O.#O..OO.#..OO...O#.O#....O.#.OO.O.O#..O.....
 | 
			
		||||
#..O.OO#O...O..O..........#..#.#..#..#O.....#O#..O....#..O...O.#.#O#.#OO.....OOO.#..#.........O...O#
 | 
			
		||||
....O......#..........O...#.....OOOO........#.#OO.O............O...#....O........#....#....#........
 | 
			
		||||
...O.......###...O.O...#O.##O.OOO.........O.###.O.......O....O.O...O.#.....#..#O..#..OO..O.O...O....
 | 
			
		||||
O.O#....##.O.O.....O....#............OO.#O...O..#...##.#.#O#O.#.....O......O....#.OO#.O#....#.....O.
 | 
			
		||||
..O####.O.........O...........OO..OO.#.....O.......#..O#.O....O#...##.......#.#....O..O..O#..##.....
 | 
			
		||||
.#..#......O.##.O.OOO.O.OO....O.......#......#.O...OOOO...O..#..#.O.#......O...O#.#.O.#.O....O....O.
 | 
			
		||||
##....O.O..O..O.#...O##.......O....#...#OOO.O..##.....#....O.......#O..#.#O..O.#.......O..#.O.O#.O##
 | 
			
		||||
...O....O#O.#...#......#..O.O.O.O...O.....O..O.#..#.....O#...OO...#.O.O....#..OOO...#.....OO.OO..O..
 | 
			
		||||
O##.O.##.O#OO...OO...OO..O....OO#O.#O..O.O....OO..........O..#.O.#O#.......O.O..#O#....#..#...#O..#.
 | 
			
		||||
.#.#..........#.......#..OO#....O.#.#.O.....OO.#.O..#.#.O....#..O....#..#..O.#O#O.....#.O.O.#O.O.#O.
 | 
			
		||||
.O.#....##O...#..OOO.#......#...#.O.......OO....#.......#..#.OOO........OO..O..###O##..O.....O##....
 | 
			
		||||
OO##..O#....O.##.......O...#........O.O...#O#.#.OOO....#......#.#O.O.O..O..O...#.#.O.O.OOO.O#O......
 | 
			
		||||
#O...#....OOO.O...#O....O...O..........O..#..O#.O..#O.....#......#.#..#.OO..#....#O#....O...O....##.
 | 
			
		||||
.OOOO......##.#O.#O...#......O..#..O..#.O...O.OO...............#O...O..##..#.#....O...O..O.##..O.O..
 | 
			
		||||
							
								
								
									
										157
									
								
								day14/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								day14/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,157 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
	"golang.org/x/exp/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// var log = aoc.Log
 | 
			
		||||
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	var maplist []Map
 | 
			
		||||
	var m Map
 | 
			
		||||
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		text := scan.Text()
 | 
			
		||||
		if len(text) == 0 {
 | 
			
		||||
			maplist = append(maplist, m)
 | 
			
		||||
			m = Map{}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m = append(m, []rune(text))
 | 
			
		||||
	}
 | 
			
		||||
	maplist = append(maplist, m)
 | 
			
		||||
 | 
			
		||||
	score1 := 0
 | 
			
		||||
	for _, m := range maplist {
 | 
			
		||||
		m = aoc.Transpose(reverse(m))
 | 
			
		||||
		m.Sort()
 | 
			
		||||
		score1 += m.Score()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	score2 := 0
 | 
			
		||||
	type record [5]int
 | 
			
		||||
	var current record
 | 
			
		||||
	memo := make(map[record]int)
 | 
			
		||||
 | 
			
		||||
	for _, m := range maplist {
 | 
			
		||||
		// fmt.Println(m)
 | 
			
		||||
 | 
			
		||||
		m = aoc.Transpose(reverse(m))
 | 
			
		||||
 | 
			
		||||
		for i := 0; i < 1_000_000_000; i++ {
 | 
			
		||||
			m, current = cycle(m)
 | 
			
		||||
 | 
			
		||||
			v, ok := memo[current]
 | 
			
		||||
			if ok && v > 1 {
 | 
			
		||||
				counts := aoc.Reduce(
 | 
			
		||||
					func(i int, v int, counts [3]int) [3]int {
 | 
			
		||||
						counts[v]++
 | 
			
		||||
						return counts
 | 
			
		||||
					}, [3]int{}, maps.Values(memo)...)
 | 
			
		||||
 | 
			
		||||
				// fmt.Println(i, counts)
 | 
			
		||||
				i = 1_000_000_000 - (1_000_000_000-counts[0]-counts[1])%counts[2]
 | 
			
		||||
				clear(memo)
 | 
			
		||||
			}
 | 
			
		||||
			memo[current] += 1
 | 
			
		||||
			// fmt.Println(i, current, v)
 | 
			
		||||
		}
 | 
			
		||||
		score2 += m.Score()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &result{valuePT1: score1, valuePT2: score2}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Map [][]rune
 | 
			
		||||
 | 
			
		||||
func (m Map) String() string {
 | 
			
		||||
	var buf strings.Builder
 | 
			
		||||
	for _, row := range m {
 | 
			
		||||
		buf.WriteString(string(row))
 | 
			
		||||
		buf.WriteRune('\n')
 | 
			
		||||
	}
 | 
			
		||||
	buf.WriteRune('\n')
 | 
			
		||||
 | 
			
		||||
	return buf.String()
 | 
			
		||||
}
 | 
			
		||||
func (m *Map) Sort() {
 | 
			
		||||
	if m == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	for _, row := range *m {
 | 
			
		||||
		base := 0
 | 
			
		||||
		for i, r := range row {
 | 
			
		||||
			if r == '#' {
 | 
			
		||||
				base = i + 1
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if r == 'O' {
 | 
			
		||||
				if base < i {
 | 
			
		||||
					row[base], row[i] = row[i], row[base]
 | 
			
		||||
				}
 | 
			
		||||
				base++
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (m *Map) Score() int {
 | 
			
		||||
	if m == nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sum := 0
 | 
			
		||||
	max := len(*m)
 | 
			
		||||
	for _, row := range *m {
 | 
			
		||||
		for i, r := range row {
 | 
			
		||||
			if r == 'O' {
 | 
			
		||||
				sum += max - i
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return sum
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func reverse(m Map) Map {
 | 
			
		||||
	for _, row := range m {
 | 
			
		||||
		aoc.Reverse(row)
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
func cycle(m Map) (Map, [5]int) {
 | 
			
		||||
	var current [5]int
 | 
			
		||||
 | 
			
		||||
	m.Sort()
 | 
			
		||||
	current[0] = m.Score()
 | 
			
		||||
 | 
			
		||||
	m = aoc.Transpose(reverse(m))
 | 
			
		||||
	m.Sort()
 | 
			
		||||
	current[1] = m.Score()
 | 
			
		||||
 | 
			
		||||
	m = aoc.Transpose(reverse(m))
 | 
			
		||||
	m.Sort()
 | 
			
		||||
	current[2] = m.Score()
 | 
			
		||||
 | 
			
		||||
	m = aoc.Transpose(reverse(m))
 | 
			
		||||
	m.Sort()
 | 
			
		||||
	current[3] = m.Score()
 | 
			
		||||
 | 
			
		||||
	m = aoc.Transpose(reverse(m))
 | 
			
		||||
	current[4] = m.Score()
 | 
			
		||||
 | 
			
		||||
	return m, current
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								day14/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								day14/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
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.valuePT1, 136)
 | 
			
		||||
	is.Equal(result.valuePT2, 64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.True(result.valuePT2 < 87286) // first submission
 | 
			
		||||
 is.True(result.valuePT2 < 87292) // second submission
 | 
			
		||||
 is.True(result.valuePT2 < 87287) // third submission
 | 
			
		||||
 | 
			
		||||
	is.Equal(result.valuePT1, 110407)
 | 
			
		||||
	is.Equal(result.valuePT2, 87273)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								day15/example.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								day15/example.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7
 | 
			
		||||
							
								
								
									
										1
									
								
								day15/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								day15/input.txt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										136
									
								
								day15/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								day15/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,136 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"slices"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var log = aoc.Log
 | 
			
		||||
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	r := &result{}
 | 
			
		||||
 | 
			
		||||
	var ops []string
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		text := scan.Text()
 | 
			
		||||
		ops = strings.Split(text, ",")
 | 
			
		||||
 | 
			
		||||
		r.valuePT1 = aoc.Reduce(func(i int, t string, sum int) int {
 | 
			
		||||
			sum += hash(t)
 | 
			
		||||
			return sum
 | 
			
		||||
		}, 0, ops...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var boxen boxes
 | 
			
		||||
 | 
			
		||||
	boxen = aoc.Reduce(func(i int, op string, b boxes) boxes {
 | 
			
		||||
		return b.Op(op)
 | 
			
		||||
	}, boxen, ops...)
 | 
			
		||||
 | 
			
		||||
	r.valuePT2 = boxen.Sum()
 | 
			
		||||
 | 
			
		||||
	log(boxen)
 | 
			
		||||
 | 
			
		||||
	return r, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hash(s string) int {
 | 
			
		||||
	var sum int
 | 
			
		||||
	for _, a := range s {
 | 
			
		||||
		sum += int(a)
 | 
			
		||||
		sum *= 17
 | 
			
		||||
		sum %= 256
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sum
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type lens struct {
 | 
			
		||||
	label string
 | 
			
		||||
	value int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l lens) String() string {
 | 
			
		||||
	return fmt.Sprintf("[%s %d]", l.label, l.value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type box []lens
 | 
			
		||||
 | 
			
		||||
func (lis box) String() string {
 | 
			
		||||
	var buf strings.Builder
 | 
			
		||||
	if len(lis) > 0 {
 | 
			
		||||
		buf.WriteString(lis[0].String())
 | 
			
		||||
	}
 | 
			
		||||
	for _, l := range lis[1:] {
 | 
			
		||||
		buf.WriteString(l.String())
 | 
			
		||||
	}
 | 
			
		||||
	return buf.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type boxes [256]box
 | 
			
		||||
 | 
			
		||||
func (lis boxes) String() string {
 | 
			
		||||
	var buf strings.Builder
 | 
			
		||||
	buf.WriteString("Boxes:\n")
 | 
			
		||||
	for i, b := range lis {
 | 
			
		||||
		if len(b) > 0 {
 | 
			
		||||
			fmt.Fprintf(&buf, "Box %d: %v\n", i, b)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return buf.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (lis boxes) Op(op string) boxes {
 | 
			
		||||
	if a, _, ok := strings.Cut(op, "-"); ok {
 | 
			
		||||
		i := hash(a)
 | 
			
		||||
 | 
			
		||||
		pos := slices.IndexFunc(lis[i], func(l lens) bool { return l.label == a })
 | 
			
		||||
 | 
			
		||||
		if pos >= 0 {
 | 
			
		||||
			lis[i] = append(lis[i][:pos], lis[i][pos+1:]...)
 | 
			
		||||
		}
 | 
			
		||||
	} else if a, b, ok := strings.Cut(op, "="); ok {
 | 
			
		||||
		i := hash(a)
 | 
			
		||||
		v := aoc.Atoi(b)
 | 
			
		||||
 | 
			
		||||
		pos := slices.IndexFunc(lis[i], func(l lens) bool { return l.label == a })
 | 
			
		||||
 | 
			
		||||
		if pos == -1 {
 | 
			
		||||
			lis[i] = append(lis[i], lens{a, v})
 | 
			
		||||
		} else {
 | 
			
		||||
			lis[i][pos].value = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return lis
 | 
			
		||||
}
 | 
			
		||||
func (lis boxes) Sum() int {
 | 
			
		||||
	// return aoc.Reduce(func(b int, box box, sum int) int {
 | 
			
		||||
	// 	return aoc.Reduce(
 | 
			
		||||
	// 		func(s int, lens lens, sum int) int {
 | 
			
		||||
	// 			return sum + (b+1)*(s+1)*lens.value
 | 
			
		||||
	// 		}, sum, box...)
 | 
			
		||||
	// 	}, 0, lis[:]...)
 | 
			
		||||
 | 
			
		||||
	var sum int
 | 
			
		||||
	for b := range lis {
 | 
			
		||||
		for s := range lis[b] {
 | 
			
		||||
			sum += (b + 1) * (s + 1) * lis[b][s].value
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return sum
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								day15/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								day15/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
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.valuePT1, 1320)
 | 
			
		||||
	is.Equal(result.valuePT2, 145)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.valuePT1, 503154)
 | 
			
		||||
	is.Equal(result.valuePT2, 251353)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								day16/example.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								day16/example.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
.|...\....
 | 
			
		||||
|.-.\.....
 | 
			
		||||
.....|-...
 | 
			
		||||
........|.
 | 
			
		||||
..........
 | 
			
		||||
.........\
 | 
			
		||||
..../.\\..
 | 
			
		||||
.-.-/..|..
 | 
			
		||||
.|....-|.\
 | 
			
		||||
..//.|....
 | 
			
		||||
							
								
								
									
										110
									
								
								day16/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								day16/input.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,110 @@
 | 
			
		||||
\.......................\..........................................-..................-.../................-..
 | 
			
		||||
....../.......\...-......-.|...\..............\.................|............././....-........................
 | 
			
		||||
...............-...-........................................\......\..-.............|......-....\....-........
 | 
			
		||||
..\..|.|...........................-.|........................................./.|....|................|......
 | 
			
		||||
|../................|............................................................\........../..\..............
 | 
			
		||||
........\............../................/..........................\...\....|............./....-.........\\...
 | 
			
		||||
.................-...-...................\../........-|.................../......-...........|................
 | 
			
		||||
........-............/...|-............-.....\.|..............-....-../\../..................\...\././........
 | 
			
		||||
........................-|................................................................-........-..........
 | 
			
		||||
-......./.................|.....\.................\.....//............-........./..../....|...................
 | 
			
		||||
....-.............-........-..........-|.......|...../...\...................\.....................|..........
 | 
			
		||||
...|...\.........|.................|.....|....-....\.......\./........................-.../..../.....-........
 | 
			
		||||
....|....-.-..............\.........|.......................-.......-..............\................/.........
 | 
			
		||||
.....|.\...........-.................-.-........../...\............|...............|...|......./.......|...../
 | 
			
		||||
.....\.........................-.../..-./...\...................../......\...-.......|.\........-|............
 | 
			
		||||
............|.....................................-....../....\.............../-...|...\..\................./.
 | 
			
		||||
......-./|....../............|.........\............-../...-......./.\..\....../......|/...\..................
 | 
			
		||||
................................|.......|..-..../.............................../.-..................-..-/..|.
 | 
			
		||||
...............................-......./......................|./...............-............./....../........
 | 
			
		||||
..................../....................\........\...........................-............/.../..............
 | 
			
		||||
.|||......../.................|.................../..\............................-......./..|...|/.-.........
 | 
			
		||||
......-......./\....../.........|....../.......-...............|.\........-............/.../..................
 | 
			
		||||
.....................-.\/|................//.../.........|.|......\.-..|.........|.........\..................
 | 
			
		||||
.........................\/.......|.|............................|........|.............................././..
 | 
			
		||||
.................................|.................\../..|/.................\.................-...-........-/.
 | 
			
		||||
......................-...-.........../...........................\....\......-..-.......\.-....\....|........
 | 
			
		||||
......-......../..............\/..................\..|........-..............|...-...../......|...............
 | 
			
		||||
|.......|.../....|..............//.....................|..........|/......../................|................
 | 
			
		||||
...|.|..................../|..../.-.......-...........|.....|./....\......-......-................|...........
 | 
			
		||||
......\/./.|\..../|.|..|..........-....|...........|.-.|...................-.\.....|....................\.....
 | 
			
		||||
......../.\......................|.....|...........|.........../.......|....|...|.......-......../......\...-.
 | 
			
		||||
...|...-...||......-..|..-...........|.-.................|.................................-..................
 | 
			
		||||
..............-.\.-........|......\..........................................\./.\........../.....|...........
 | 
			
		||||
../\.........|...............|............|.\/.-/.................-....|...-.................-.....|..../.....
 | 
			
		||||
....................../......../..../-.....\........................\..-.\....|....-.........../-.............
 | 
			
		||||
.................................|................|.........|................../|.....|....\\............/.\..
 | 
			
		||||
...///./.....\.................|/.....................\...................-............|................|.....
 | 
			
		||||
............-...........................--........\................/.............-\................\.....-.../
 | 
			
		||||
...............\.........../|............................|.....................\...-...\.....................-
 | 
			
		||||
...\.............|.............|................\............\|...../...|.........................|...........
 | 
			
		||||
..................|......|..........-.-..............\.........................\..............................
 | 
			
		||||
....-................../.........../...|................/...............|./.|.../....\..../......./......//...
 | 
			
		||||
...../....../..............................|...\../..........-..........-........-..//..../...................
 | 
			
		||||
...............-......|......................|./........./............/..-...........|../.....-........-./....
 | 
			
		||||
..\.........................|...-.......\.................|..............-........\....-.............-....|...
 | 
			
		||||
.......|......|....../........\...........|......-........../......-..................../....................\
 | 
			
		||||
.......................|....-..|........./.|.-...............|..\......\.....-.......\...-/....|/.........\...
 | 
			
		||||
\......\..-.....................\..........................\................................../...........\...
 | 
			
		||||
-....-......../............................................................../.\.......|..............|....-..
 | 
			
		||||
........|......................|.............-....\................................./..\.......|..........-...
 | 
			
		||||
...-...............|........./......\...../.......|...|...............\.../...\.../......|.....-.\......\.....
 | 
			
		||||
............./.....|......................|.....................................\...||.................-....|.
 | 
			
		||||
./.....-................/........|./....-......../......./..............\..................................\..
 | 
			
		||||
.../..../\........-..........................|.-/.|..\................\\-.......|......./...||.......|........
 | 
			
		||||
.....-.........................-...............\...........|.............-.\.../.|......-.|......../...-.....-
 | 
			
		||||
......\....................|...../......................|.../......-..|............|......./.../.........|....
 | 
			
		||||
...|...........-....................................../.|............./....|..../........./.....\../..........
 | 
			
		||||
....../.../................\........................\...\....\......\............../|...............\.-.......
 | 
			
		||||
./....\.../.............|............................-.../............../............/...........\...|........
 | 
			
		||||
............................|.................|/..........//.........../..-...............|...................
 | 
			
		||||
.....\......\.................|.....|...\-./...............\................|....../.....-..\........-....-...
 | 
			
		||||
........................./-........\................./........-/.|....-.......\............-/\......|.\...-...
 | 
			
		||||
..../../..|.|...............\.......................................-.........................................
 | 
			
		||||
...........|...................................................-...-......|..................\............../.
 | 
			
		||||
/....|......................................................................|\.../.......-...........-...|....
 | 
			
		||||
......|.-.\......-........|.....-..|.\..............-......./......-|.........................-...............
 | 
			
		||||
............\......................................|........................|.-...............................
 | 
			
		||||
.........-.........../....\./....../.-...-..//.........../.......\\...........................................
 | 
			
		||||
........\......../............./...-......\.../..|..|............................../......../..\..............
 | 
			
		||||
--.........|.....-...|............../...|.......|..............\|............|.........................|.-....
 | 
			
		||||
-\......./..............-....-....\...|.-........\/.\./............-/...\........|-.........../../...\........
 | 
			
		||||
.\|\..............-......-.\...-....\..........................\........|...........-......./.............../.
 | 
			
		||||
..........................|...\..../.../..........\.............-...//...............\..................-.....
 | 
			
		||||
........./..........................\............|-.....|..-...|......../........-...........................\
 | 
			
		||||
.......\.../.....\....../.......|..|...............-......................|....-...................-.|........
 | 
			
		||||
......|.......\.../..............................-..............................|......-.-...................\
 | 
			
		||||
/.....|.......-............/|.....|-......./..../......-........../..|......../.-..\..../....../...|..........
 | 
			
		||||
............/..--..........-............\.......\................\........................../../....|.........
 | 
			
		||||
..|..-................|.|..|................/.......\............-//.......................\..\...............
 | 
			
		||||
.......................-......-..................|....\................-......\.|....\....|..../../|.-........
 | 
			
		||||
........................-..................-...........................-..-................-................|.
 | 
			
		||||
/.\....|.-.................................\..-.....\./.........../-.|..............\..\.....--|/....\........
 | 
			
		||||
.......-..-../..................\..--|..............|...............|\........|...--................|./.\.....
 | 
			
		||||
..........|................-.......|..................................................|...................|...
 | 
			
		||||
-.-..|....-.|........-./...|.-.........\.....\/........-........\........../................./.../........\...
 | 
			
		||||
..................../...|/......................................../............\.|./../................/\|....
 | 
			
		||||
...//.........................\....../..............\../.......-..\....|......................................
 | 
			
		||||
............................./..|./../.........-/..\..........................................................
 | 
			
		||||
......\.....|..................|..................\.....\.-..\...../............................../...........
 | 
			
		||||
..........\...........-..........-.....-....\/................../.................................\.....|..\..
 | 
			
		||||
..../.\...................................\............\...\....|.................|.....................-.....
 | 
			
		||||
...........-...........................\.......|-../.|....|.....|......................-...../................
 | 
			
		||||
.......|.........\..............|....\...-......../...........-.....-..-...........-..................\...\.|.
 | 
			
		||||
...........|.......................|....-..........\............................\.................../.\.......
 | 
			
		||||
..../.................\.......-..|.................../........................|...............\...........-.|.
 | 
			
		||||
............./..|.-\..../.....-............-....|..\......|......../............-.........|................\..
 | 
			
		||||
...................\...\/......\............|......................\....|...................-./-..............
 | 
			
		||||
..-\...........|.................../.....|....|............................-..|............\.............\....
 | 
			
		||||
.|.....\....\........|..................\...............|..-/.........|.-/...........-............-...........
 | 
			
		||||
.....\...../......-............|........./..|............-........................\....-......................
 | 
			
		||||
......\......../........|..............\...-..-...|.......................................................|...
 | 
			
		||||
...................|.................................\.....\...........................|../.|.-......-........
 | 
			
		||||
..................|..............\.....\............|........../....../...............\.........\.............
 | 
			
		||||
..|...........-..../....\.........--...\................../.............-...-....................-..../....|..
 | 
			
		||||
.|...\...................|......-...........-\..........\.....|.....|..........|.........|....|-../...........
 | 
			
		||||
.............\|...................../\...............\....../.......-....\.....................-..............
 | 
			
		||||
.......//.....................\....\......\......\.........|...................../......../.........\......-..
 | 
			
		||||
.\./.........-...-./-.\.............../......|................................\|....\...../....-..............
 | 
			
		||||
.......|......../......../......./.........../...............|............................../..|......../.....
 | 
			
		||||
............./.........|.....-./.........../....-......./|......-................|............................
 | 
			
		||||
							
								
								
									
										189
									
								
								day16/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								day16/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,189 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// var log = aoc.Log
 | 
			
		||||
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	var m Map
 | 
			
		||||
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		text := scan.Text()
 | 
			
		||||
		m = append(m, []rune(text))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rows := len(m)
 | 
			
		||||
	cols := len(m[0])
 | 
			
		||||
 | 
			
		||||
	options := make([]int, 2*(rows+cols)+2)
 | 
			
		||||
	i := 0
 | 
			
		||||
	for j:=0; j<=rows-1; j++ {
 | 
			
		||||
		options[i+0] = runCycle(m, ray{[2]int{j, -1}, RT})
 | 
			
		||||
		options[i+1] = runCycle(m, ray{[2]int{j, cols}, LF})
 | 
			
		||||
		i+=2
 | 
			
		||||
	}
 | 
			
		||||
	for j:=0; j<=cols-1; j++ {
 | 
			
		||||
		options[i+0] = runCycle(m, ray{[2]int{-1, j}, DN})
 | 
			
		||||
		options[i+1] = runCycle(m, ray{[2]int{rows, j}, UP})
 | 
			
		||||
		i+=2
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// fmt.Println(options)
 | 
			
		||||
	return &result{valuePT1: options[0], valuePT2: aoc.Max(options[0], options[1:]...)}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type stack[T any] []T
 | 
			
		||||
 | 
			
		||||
func (s *stack[T]) Push(v T) {
 | 
			
		||||
	if s == nil {
 | 
			
		||||
		panic("nil stack")
 | 
			
		||||
	}
 | 
			
		||||
	*s = append(*s, v)
 | 
			
		||||
}
 | 
			
		||||
func (s *stack[T]) Pop() T {
 | 
			
		||||
	if s == nil || len(*s) == 0 {
 | 
			
		||||
		panic("empty stack")
 | 
			
		||||
	}
 | 
			
		||||
	defer func() { *s = (*s)[:len(*s)-1] }()
 | 
			
		||||
	return (*s)[len(*s)-1]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ZERO = [2]int{0, -1}
 | 
			
		||||
 | 
			
		||||
	UP = [2]int{-1, 0}
 | 
			
		||||
	DN = [2]int{1, 0}
 | 
			
		||||
	LF = [2]int{0, -1}
 | 
			
		||||
	RT = [2]int{0, 1}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ray struct {
 | 
			
		||||
	pos [2]int
 | 
			
		||||
	dir [2]int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *ray) next() [2]int {
 | 
			
		||||
	r.pos[0] += r.dir[0]
 | 
			
		||||
	r.pos[1] += r.dir[1]
 | 
			
		||||
	return r.pos
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Map [][]rune
 | 
			
		||||
 | 
			
		||||
func (m *Map) Get(p [2]int) rune {
 | 
			
		||||
	if p[0] < 0 || p[0] >= len((*m)) {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	if p[1] < 0 || p[1] >= len((*m)[0]) {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (*m)[p[0]][p[1]]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func runCycle(m Map, r ray) int {
 | 
			
		||||
	current := r
 | 
			
		||||
 | 
			
		||||
	s := stack[ray]{}
 | 
			
		||||
	s.Push(current)
 | 
			
		||||
 | 
			
		||||
	energized := make(map[[2]int]bool)
 | 
			
		||||
	// energized[current.pos] = true
 | 
			
		||||
 | 
			
		||||
	cycle := make(map[[4]int]bool)
 | 
			
		||||
 | 
			
		||||
	for len(s) > 0 {
 | 
			
		||||
		current = s.Pop()
 | 
			
		||||
 | 
			
		||||
		r := m.Get(current.next())
 | 
			
		||||
		// fmt.Println("pos", current.pos, current.dir, string(r), len(s))
 | 
			
		||||
		if r == 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		energized[current.pos] = true
 | 
			
		||||
		v := [4]int{
 | 
			
		||||
			current.pos[0],
 | 
			
		||||
			current.pos[1],
 | 
			
		||||
			current.dir[0],
 | 
			
		||||
			current.dir[1],
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if _, ok := cycle[v]; ok {
 | 
			
		||||
			// fmt.Println("cycle")
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		cycle[v] = true
 | 
			
		||||
 | 
			
		||||
		switch r {
 | 
			
		||||
		case '|':
 | 
			
		||||
			switch current.dir {
 | 
			
		||||
			case UP, DN:
 | 
			
		||||
				// pass
 | 
			
		||||
			case LF, RT:
 | 
			
		||||
				current.dir = UP
 | 
			
		||||
				s.Push(ray{current.pos, DN})
 | 
			
		||||
			}
 | 
			
		||||
		case '-':
 | 
			
		||||
			switch current.dir {
 | 
			
		||||
			case LF, RT:
 | 
			
		||||
				// pass
 | 
			
		||||
			case UP, DN:
 | 
			
		||||
				current.dir = LF
 | 
			
		||||
				s.Push(ray{current.pos, RT})
 | 
			
		||||
			}
 | 
			
		||||
		case '/':
 | 
			
		||||
			switch current.dir {
 | 
			
		||||
			case UP:
 | 
			
		||||
				current.dir = RT
 | 
			
		||||
			case DN:
 | 
			
		||||
				current.dir = LF
 | 
			
		||||
			case LF:
 | 
			
		||||
				current.dir = DN
 | 
			
		||||
			case RT:
 | 
			
		||||
				current.dir = UP
 | 
			
		||||
			}
 | 
			
		||||
		case '\\':
 | 
			
		||||
			switch current.dir {
 | 
			
		||||
			case UP:
 | 
			
		||||
				current.dir = LF
 | 
			
		||||
			case DN:
 | 
			
		||||
				current.dir = RT
 | 
			
		||||
			case LF:
 | 
			
		||||
				current.dir = UP
 | 
			
		||||
			case RT:
 | 
			
		||||
				current.dir = DN
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		s.Push(current)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// for i := range m {
 | 
			
		||||
	// 	for j := range m[i] {
 | 
			
		||||
	// 		if v := energized[[2]int{i,j}]; v {
 | 
			
		||||
	// 			fmt.Print("#")
 | 
			
		||||
	// 		} else {
 | 
			
		||||
	// 			fmt.Print(".")
 | 
			
		||||
	// 		}
 | 
			
		||||
	// 	}
 | 
			
		||||
	// 	fmt.Println("")
 | 
			
		||||
	// }
 | 
			
		||||
 | 
			
		||||
	return len(energized)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								day16/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								day16/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
			
		||||
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.valuePT1, 46)
 | 
			
		||||
	is.Equal(result.valuePT2, 51)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.valuePT1, 8098)
 | 
			
		||||
	is.Equal(result.valuePT2, 8335)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestStack(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
	s := stack[int]{}
 | 
			
		||||
	s.Push(5)
 | 
			
		||||
	is.Equal(s.Pop(), 5)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								day20/example1.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								day20/example1.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
broadcaster -> a, b, c
 | 
			
		||||
%a -> b
 | 
			
		||||
%b -> c
 | 
			
		||||
%c -> inv
 | 
			
		||||
&inv -> a
 | 
			
		||||
							
								
								
									
										5
									
								
								day20/example2.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								day20/example2.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
broadcaster -> a
 | 
			
		||||
%a -> inv, con
 | 
			
		||||
&inv -> b
 | 
			
		||||
%b -> con
 | 
			
		||||
&con -> output
 | 
			
		||||
							
								
								
									
										58
									
								
								day20/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								day20/input.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
			
		||||
%vg -> lf, vd
 | 
			
		||||
%dr -> kg
 | 
			
		||||
%cn -> mv, pt
 | 
			
		||||
%rq -> bk, gr
 | 
			
		||||
%vp -> lp, bk
 | 
			
		||||
%kg -> lv
 | 
			
		||||
%lv -> jc, tp
 | 
			
		||||
%sj -> rm, vd
 | 
			
		||||
%jc -> tp, qr
 | 
			
		||||
%km -> tp, dr
 | 
			
		||||
%jx -> cn
 | 
			
		||||
&vd -> tf, lf, nb, cx, hx, lr
 | 
			
		||||
%lp -> jt, bk
 | 
			
		||||
%vj -> ps
 | 
			
		||||
broadcaster -> km, lr, xh, rf
 | 
			
		||||
%dj -> pt, gc
 | 
			
		||||
%cg -> vd, hx
 | 
			
		||||
&ln -> tg
 | 
			
		||||
%fl -> pt, sk
 | 
			
		||||
%lm -> tr, bk
 | 
			
		||||
%lr -> vd, vg
 | 
			
		||||
&pt -> vq, rf, cm, jx, rg
 | 
			
		||||
%cx -> gp
 | 
			
		||||
%gp -> vd, sj
 | 
			
		||||
&db -> tg
 | 
			
		||||
%st -> vd
 | 
			
		||||
%jt -> bk
 | 
			
		||||
%jh -> lm, bk
 | 
			
		||||
%xf -> bd, tp
 | 
			
		||||
%gc -> cm, pt
 | 
			
		||||
&tp -> dr, km, kg, db, vj, qr
 | 
			
		||||
%ps -> xf, tp
 | 
			
		||||
%rf -> pt, dj
 | 
			
		||||
%lf -> nb
 | 
			
		||||
%bd -> tp, gg
 | 
			
		||||
%dk -> tp, vj
 | 
			
		||||
%mn -> jh, bk
 | 
			
		||||
&tg -> rx
 | 
			
		||||
%ql -> bk, zx
 | 
			
		||||
%tr -> bk, vp
 | 
			
		||||
%sk -> pt
 | 
			
		||||
%nb -> cg
 | 
			
		||||
%sb -> vd, cx
 | 
			
		||||
%qr -> dk
 | 
			
		||||
%xh -> bk, ql
 | 
			
		||||
%rg -> sd
 | 
			
		||||
%hx -> sb
 | 
			
		||||
%sd -> pt, jx
 | 
			
		||||
%gr -> bk, mn
 | 
			
		||||
%gg -> tp
 | 
			
		||||
%zx -> rq
 | 
			
		||||
&bk -> xh, ln, zx
 | 
			
		||||
%rm -> st, vd
 | 
			
		||||
%hq -> fl, pt
 | 
			
		||||
&vq -> tg
 | 
			
		||||
%cm -> rg
 | 
			
		||||
&tf -> tg
 | 
			
		||||
%mv -> pt, hq
 | 
			
		||||
							
								
								
									
										282
									
								
								day20/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								day20/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,282 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
	"golang.org/x/exp/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// var log = aoc.Log
 | 
			
		||||
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	m := &machine{}
 | 
			
		||||
	receivers := make(map[string][]string)
 | 
			
		||||
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		text := scan.Text()
 | 
			
		||||
 | 
			
		||||
		name, text, _ := strings.Cut(text, " -> ")
 | 
			
		||||
		dest := strings.Split(text, ", ")
 | 
			
		||||
 | 
			
		||||
		switch {
 | 
			
		||||
		case name == "broadcaster":
 | 
			
		||||
			m.Add(name, &broadcaster{dest: dest})
 | 
			
		||||
		case strings.HasPrefix(name, "%"):
 | 
			
		||||
			name = strings.TrimPrefix(name, "%")
 | 
			
		||||
			m.Add(name, &flipflop{name: name, dest: dest})
 | 
			
		||||
 | 
			
		||||
		case strings.HasPrefix(name, "&"):
 | 
			
		||||
			name = strings.TrimPrefix(name, "&")
 | 
			
		||||
			m.Add(name, &conjunction{name: name, dest: dest})
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, d := range dest {
 | 
			
		||||
			// rx is present so enable pt 2
 | 
			
		||||
			if d == "rx" {
 | 
			
		||||
				m.Add("rx", &rx{})
 | 
			
		||||
			}
 | 
			
		||||
			receivers[d] = append(receivers[d], name)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m.setup(receivers)
 | 
			
		||||
 | 
			
		||||
	result := &result{}
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < 10_000; i++ { // need enough presses to find the best LCM values for each conjunction
 | 
			
		||||
		if i == 1000 {
 | 
			
		||||
			result.valuePT1 = m.highPulses * m.lowPulses
 | 
			
		||||
		}
 | 
			
		||||
		m.Push(i)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// rx is present.. perform part 2.
 | 
			
		||||
	if rx, ok := receivers["rx"]; ok {
 | 
			
		||||
		tip := m.m[rx[0]].(*conjunction) // panic if missing!
 | 
			
		||||
 | 
			
		||||
		var lvalues []int
 | 
			
		||||
		for k, v := range tip.pushes {
 | 
			
		||||
			for i, h := range makeHistory(v) {
 | 
			
		||||
				if i == 1 && len(h) > 0 && h[0] > 0 {
 | 
			
		||||
					fmt.Println(tip.name, k, "frequency", h[0])
 | 
			
		||||
					lvalues = append(lvalues, h[0])
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		result.valuePT2 = aoc.LCM(lvalues...)
 | 
			
		||||
		fmt.Println(tip.name, "LCM", result.valuePT2, lvalues)
 | 
			
		||||
	}
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type signal bool
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	LOW  signal = false
 | 
			
		||||
	HIGH signal = true
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type message struct {
 | 
			
		||||
	signal
 | 
			
		||||
	from, to string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type machine struct {
 | 
			
		||||
	m map[string]pulser
 | 
			
		||||
 | 
			
		||||
	queue []message
 | 
			
		||||
 | 
			
		||||
	press      int
 | 
			
		||||
	highPulses int
 | 
			
		||||
	lowPulses  int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machine) Add(name string, p pulser) {
 | 
			
		||||
	if m.m == nil {
 | 
			
		||||
		m.m = make(map[string]pulser)
 | 
			
		||||
	}
 | 
			
		||||
	p.SetMachine(m)
 | 
			
		||||
	m.m[name] = p
 | 
			
		||||
}
 | 
			
		||||
func (m *machine) Send(msgs ...message) {
 | 
			
		||||
	m.queue = append(m.queue, msgs...)
 | 
			
		||||
	for _, msg := range msgs {
 | 
			
		||||
		// fmt.Println(msg)
 | 
			
		||||
		if msg.signal {
 | 
			
		||||
			m.highPulses++
 | 
			
		||||
		} else {
 | 
			
		||||
			m.lowPulses++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (m *machine) Push(i int) {
 | 
			
		||||
	m.press = i
 | 
			
		||||
	m.Send(generate(LOW, "button", "broadcaster")...)
 | 
			
		||||
	m.processQueue(i)
 | 
			
		||||
}
 | 
			
		||||
func (m *machine) processQueue(i int) {
 | 
			
		||||
	// look for work and process up to the queue length. repeat.
 | 
			
		||||
	hwm := 0
 | 
			
		||||
	for hwm < len(m.queue) {
 | 
			
		||||
		end := len(m.queue)
 | 
			
		||||
 | 
			
		||||
		for ; hwm < end; hwm++ {
 | 
			
		||||
			msg := m.queue[hwm]
 | 
			
		||||
 | 
			
		||||
			if p, ok := m.m[msg.to]; ok {
 | 
			
		||||
				// fmt.Println(i, "S:", m.m[msg.from], msg.signal, "R:", p)
 | 
			
		||||
				p.Pulse(msg)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		hwm = 0
 | 
			
		||||
		copy(m.queue, m.queue[end:])
 | 
			
		||||
		m.queue = m.queue[:len(m.queue)-end]
 | 
			
		||||
		// fmt.Println("")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (m *machine) setup(receivers map[string][]string) {
 | 
			
		||||
	for name, recv := range receivers {
 | 
			
		||||
		if p, ok := m.m[name]; ok {
 | 
			
		||||
			if p, ok := p.(interface{ Receive(...string) }); ok {
 | 
			
		||||
				p.Receive(recv...)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type pulser interface {
 | 
			
		||||
	Pulse(message)
 | 
			
		||||
	SetMachine(*machine)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsModule implements the machine registration for each module.
 | 
			
		||||
type IsModule struct {
 | 
			
		||||
	*machine
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *IsModule) SetMachine(m *machine) { p.machine = m }
 | 
			
		||||
 | 
			
		||||
type broadcaster struct {
 | 
			
		||||
	dest []string
 | 
			
		||||
	IsModule
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *broadcaster) Pulse(msg message) {
 | 
			
		||||
	b.Send(generate(msg.signal, "broadcaster", b.dest...)...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type flipflop struct {
 | 
			
		||||
	name  string
 | 
			
		||||
	state signal
 | 
			
		||||
	dest  []string
 | 
			
		||||
 | 
			
		||||
	IsModule
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *flipflop) Pulse(msg message) {
 | 
			
		||||
	if !msg.signal {
 | 
			
		||||
		b.state = !b.state
 | 
			
		||||
		b.Send(generate(b.state, b.name, b.dest...)...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type conjunction struct {
 | 
			
		||||
	name  string
 | 
			
		||||
	state map[string]signal
 | 
			
		||||
	dest  []string
 | 
			
		||||
 | 
			
		||||
	pushes map[string][]int
 | 
			
		||||
 | 
			
		||||
	IsModule
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *conjunction) Receive(names ...string) {
 | 
			
		||||
	if b.state == nil {
 | 
			
		||||
		b.state = make(map[string]signal)
 | 
			
		||||
		b.pushes = make(map[string][]int)
 | 
			
		||||
	}
 | 
			
		||||
	for _, name := range names {
 | 
			
		||||
		b.state[name] = false
 | 
			
		||||
		b.pushes[name] = []int{}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (b *conjunction) Pulse(msg message) {
 | 
			
		||||
	b.state[msg.from] = msg.signal
 | 
			
		||||
 | 
			
		||||
	if msg.signal {
 | 
			
		||||
		// collect frequency of pushes to esti,ate rate
 | 
			
		||||
		b.pushes[msg.from] = append(b.pushes[msg.from], b.press)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if all(HIGH, maps.Values(b.state)...) {
 | 
			
		||||
		b.Send(generate(LOW, b.name, b.dest...)...)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	b.Send(generate(HIGH, b.name, b.dest...)...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type rx struct {
 | 
			
		||||
	IsModule
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (rx *rx) Pulse(msg message) {
 | 
			
		||||
	if !msg.signal {
 | 
			
		||||
		panic("pulse received") // will never happen...
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// helper funcs
 | 
			
		||||
func all[T comparable](match T, lis ...T) bool {
 | 
			
		||||
	for _, b := range lis {
 | 
			
		||||
		if b != match {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
func generate(t signal, from string, destinations ...string) []message {
 | 
			
		||||
	msgs := make([]message, len(destinations))
 | 
			
		||||
	for i, to := range destinations {
 | 
			
		||||
		msgs[i] = message{signal: t, from: from, to: to}
 | 
			
		||||
	}
 | 
			
		||||
	return msgs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// makeHistory from day 9
 | 
			
		||||
func makeHistory(in []int) [][]int {
 | 
			
		||||
	var history [][]int
 | 
			
		||||
	history = append(history, in)
 | 
			
		||||
 | 
			
		||||
	// for {
 | 
			
		||||
	var diffs []int
 | 
			
		||||
 | 
			
		||||
	current := history[len(history)-1]
 | 
			
		||||
 | 
			
		||||
	for i := range current[1:] {
 | 
			
		||||
		diffs = append(diffs, current[i+1]-current[i])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	history = append(history, diffs)
 | 
			
		||||
 | 
			
		||||
	// if len(diffs) == 0 || aoc.Max(diffs[0], diffs[1:]...) == 0 && aoc.Min(diffs[0], diffs[1:]...) == 0 {
 | 
			
		||||
	// 	break
 | 
			
		||||
	// }
 | 
			
		||||
	// }
 | 
			
		||||
	return history
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								day20/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								day20/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
			
		||||
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.valuePT1, 32000000)
 | 
			
		||||
	is.Equal(result.valuePT2, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.valuePT1, 11687500)
 | 
			
		||||
	is.Equal(result.valuePT2, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.valuePT1, 819397964)
 | 
			
		||||
	is.Equal(result.valuePT2, 252667369442479)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								go.mod
									
									
									
									
									
								
							@ -1,5 +1,10 @@
 | 
			
		||||
module go.sour.is/advent-of-code
 | 
			
		||||
 | 
			
		||||
go 1.21.3
 | 
			
		||||
go 1.21.4
 | 
			
		||||
 | 
			
		||||
require github.com/matryer/is v1.4.1
 | 
			
		||||
toolchain go1.21.5
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/matryer/is v1.4.1
 | 
			
		||||
	golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@ -1,2 +1,4 @@
 | 
			
		||||
github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
 | 
			
		||||
github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
 | 
			
		||||
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4=
 | 
			
		||||
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										0
									
								
								template/example.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								template/example.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								template/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								template/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										30
									
								
								template/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								template/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// var log = aoc.Log
 | 
			
		||||
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		_ = scan.Text()
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &result{}, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								template/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								template/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
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.valuePT1, 0)
 | 
			
		||||
	is.Equal(result.valuePT2, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.valuePT1, 0)
 | 
			
		||||
	is.Equal(result.valuePT2, 0)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										93
									
								
								tools_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								tools_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,93 @@
 | 
			
		||||
package aoc_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/matryer/is"
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestReverse(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
	is.Equal(aoc.Reverse([]int{1, 2, 3, 4}), []int{4, 3, 2, 1})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestLCM(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
	is.Equal(aoc.LCM([]int{}...), 0)
 | 
			
		||||
	is.Equal(aoc.LCM(5), 5)
 | 
			
		||||
	is.Equal(aoc.LCM(5, 3), 15)
 | 
			
		||||
	is.Equal(aoc.LCM(5, 3, 2), 30)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestReadStringToInts(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
	is.Equal(aoc.ReadStringToInts([]string{"1", "2", "3"}), []int{1, 2, 3})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestRepeat(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
	is.Equal(aoc.Repeat(5, 3), []int{5, 5, 5})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPower2(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
	is.Equal(aoc.Power2(0), 1)
 | 
			
		||||
	is.Equal(aoc.Power2(1), 2)
 | 
			
		||||
	is.Equal(aoc.Power2(2), 4)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestABS(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
	is.Equal(aoc.ABS(1), 1)
 | 
			
		||||
	is.Equal(aoc.ABS(0), 0)
 | 
			
		||||
	is.Equal(aoc.ABS(-1), 1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestTranspose(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
	is.Equal(
 | 
			
		||||
		aoc.Transpose(
 | 
			
		||||
			[][]int{
 | 
			
		||||
				{1, 1},
 | 
			
		||||
				{0, 0},
 | 
			
		||||
				{1, 1},
 | 
			
		||||
			},
 | 
			
		||||
		),
 | 
			
		||||
		[][]int{
 | 
			
		||||
			{1, 0, 1},
 | 
			
		||||
			{1, 0, 1},
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestList(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
	lis := aoc.NewList[int](nil)
 | 
			
		||||
	lis.Add(5, 0)
 | 
			
		||||
 | 
			
		||||
	a, _ := lis.Head().Value()
 | 
			
		||||
 | 
			
		||||
	is.Equal(a, 5)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGraph(t *testing.T) {
 | 
			
		||||
	g := aoc.Graph[int, uint](7)
 | 
			
		||||
	g.AddEdge(0, 1, 2)
 | 
			
		||||
	g.AddEdge(0, 2, 6)
 | 
			
		||||
	g.AddEdge(1, 3, 5)
 | 
			
		||||
	g.AddEdge(2, 3, 8)
 | 
			
		||||
	g.AddEdge(3, 4, 10)
 | 
			
		||||
	g.AddEdge(3, 5, 15)
 | 
			
		||||
	g.AddEdge(4, 6, 2)
 | 
			
		||||
	g.AddEdge(5, 6, 6)
 | 
			
		||||
	// g.Dijkstra(0)
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user