mirror of
				https://github.com/onyx-and-iris/aoc2024.git
				synced 2025-11-04 06:51:47 +00:00 
			
		
		
		
	implement using custom sort function on an update struct
rerun benchmarks
This commit is contained in:
		
							parent
							
								
									965e704d39
								
							
						
					
					
						commit
						6b7f79b6f0
					
				@ -2,14 +2,14 @@ goos: linux
 | 
			
		||||
goarch: amd64
 | 
			
		||||
pkg: github.com/onyx-and-iris/aoc2024/day-05
 | 
			
		||||
cpu: Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.02016 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.02019 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.02182 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.01990 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.02056 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.02031 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.02083 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.02167 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.02048 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.02080 ns/op
 | 
			
		||||
ok  	github.com/onyx-and-iris/aoc2024/day-05	1.471s
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0008615 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0008750 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0008650 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0009446 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0009151 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0008940 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0008744 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0008429 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0008286 ns/op
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0008589 ns/op
 | 
			
		||||
ok  	github.com/onyx-and-iris/aoc2024/day-05	0.085s
 | 
			
		||||
 | 
			
		||||
@ -2,5 +2,5 @@ goos: linux
 | 
			
		||||
goarch: amd64
 | 
			
		||||
pkg: github.com/onyx-and-iris/aoc2024/day-05/internal/one
 | 
			
		||||
cpu: Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.007571 ns/op
 | 
			
		||||
ok  	github.com/onyx-and-iris/aoc2024/day-05/internal/one	0.052s
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0004326 ns/op
 | 
			
		||||
ok  	github.com/onyx-and-iris/aoc2024/day-05/internal/one	0.008s
 | 
			
		||||
 | 
			
		||||
@ -9,33 +9,19 @@ import (
 | 
			
		||||
 | 
			
		||||
func Solve(buf []byte) (int, error) {
 | 
			
		||||
	r := bytes.NewReader(buf)
 | 
			
		||||
	data, err := util.ParseLines(r)
 | 
			
		||||
	updates, orderings, err := util.ParseLines(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var sum int
 | 
			
		||||
 | 
			
		||||
	for i, products := range data[1] {
 | 
			
		||||
		inOrder := true
 | 
			
		||||
		for _, product := range products {
 | 
			
		||||
			for _, rules := range data[0] {
 | 
			
		||||
				if !slices.Contains(rules, product) {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
	for _, update := range updates {
 | 
			
		||||
		beforeSort := slices.Clone(update.Pages)
 | 
			
		||||
		update.Sort(orderings)
 | 
			
		||||
 | 
			
		||||
				indx1, indx2 := slices.Index(products, rules[0]), slices.Index(products, rules[1])
 | 
			
		||||
				if indx1 != -1 && indx2 != -1 && indx2 < indx1 {
 | 
			
		||||
					inOrder = false
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if !inOrder {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if inOrder {
 | 
			
		||||
			sum += data[1][i][len(data[1][i])/2]
 | 
			
		||||
		if slices.Compare(beforeSort, update.Pages) == 0 {
 | 
			
		||||
			sum += update.Pages[len(update.Pages)/2]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,5 +2,5 @@ goos: linux
 | 
			
		||||
goarch: amd64
 | 
			
		||||
pkg: github.com/onyx-and-iris/aoc2024/day-05/internal/two
 | 
			
		||||
cpu: Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.01270 ns/op
 | 
			
		||||
ok  	github.com/onyx-and-iris/aoc2024/day-05/internal/two	0.083s
 | 
			
		||||
BenchmarkSolve-12    	1000000000	         0.0004492 ns/op
 | 
			
		||||
ok  	github.com/onyx-and-iris/aoc2024/day-05/internal/two	0.008s
 | 
			
		||||
 | 
			
		||||
@ -4,62 +4,26 @@ import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"slices"
 | 
			
		||||
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
 | 
			
		||||
	"github.com/onyx-and-iris/aoc2024/day-05/internal/util"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Solve(buf []byte) (int, error) {
 | 
			
		||||
	r := bytes.NewReader(buf)
 | 
			
		||||
	data, err := util.ParseLines(r)
 | 
			
		||||
	updates, orderings, err := util.ParseLines(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var sum int
 | 
			
		||||
 | 
			
		||||
	for i, products := range data[1] {
 | 
			
		||||
		inOrder := true
 | 
			
		||||
		for _, product := range products {
 | 
			
		||||
			for _, rulesets := range data[0] {
 | 
			
		||||
				if !slices.Contains(rulesets, product) {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
	for _, update := range updates {
 | 
			
		||||
		beforeSort := slices.Clone(update.Pages)
 | 
			
		||||
		update.Sort(orderings)
 | 
			
		||||
 | 
			
		||||
				indx1, indx2 := slices.Index(products, rulesets[0]), slices.Index(products, rulesets[1])
 | 
			
		||||
				if indx1 != -1 && indx2 != -1 && indx2 < indx1 {
 | 
			
		||||
					inOrder = false
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if !inOrder {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if !inOrder {
 | 
			
		||||
			sum += midOfFixedOrder(data[1][i], data[0])
 | 
			
		||||
		if slices.Compare(beforeSort, update.Pages) != 0 {
 | 
			
		||||
			sum += update.Pages[len(update.Pages)/2]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sum, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func midOfFixedOrder(products []int, rulesets [][]int) int {
 | 
			
		||||
	log.Debugf("unordered products: %v", products)
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		var sorts int
 | 
			
		||||
		for _, ruleset := range rulesets {
 | 
			
		||||
			indx1, indx2 := slices.Index(products, ruleset[0]), slices.Index(products, ruleset[1])
 | 
			
		||||
			if indx1 != -1 && indx2 != -1 && indx2 < indx1 {
 | 
			
		||||
				products[indx1], products[indx2] = products[indx2], products[indx1]
 | 
			
		||||
				sorts++
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if sorts == 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return products[len(products)/2]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								day-05/internal/update/update.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								day-05/internal/update/update.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
package update
 | 
			
		||||
 | 
			
		||||
import "slices"
 | 
			
		||||
 | 
			
		||||
type Update struct {
 | 
			
		||||
	Pages []int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (u Update) Sort(orderings map[int][]int) {
 | 
			
		||||
	slices.SortFunc(u.Pages, func(p, q int) int {
 | 
			
		||||
		v, ok := orderings[p]
 | 
			
		||||
		if ok {
 | 
			
		||||
			if slices.Contains(v, q) {
 | 
			
		||||
				return -1
 | 
			
		||||
			}
 | 
			
		||||
			return 1
 | 
			
		||||
		}
 | 
			
		||||
		return 1
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
@ -3,47 +3,51 @@ package util
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"io"
 | 
			
		||||
	"log"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/onyx-and-iris/aoc2024/day-05/internal/update"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func MustConv(s string) int {
 | 
			
		||||
func ParseLines(r io.Reader) ([]update.Update, map[int][]int, error) {
 | 
			
		||||
	var updates []update.Update
 | 
			
		||||
	orderings := make(map[int][]int, 0)
 | 
			
		||||
 | 
			
		||||
	var inUpdates bool
 | 
			
		||||
	scanner := bufio.NewScanner(r)
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
		line := scanner.Text()
 | 
			
		||||
		if len(line) == 0 {
 | 
			
		||||
			inUpdates = true
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if inUpdates {
 | 
			
		||||
			var update update.Update
 | 
			
		||||
			for _, n := range strings.Split(line, ",") {
 | 
			
		||||
				update.Pages = append(update.Pages, mustConv(n))
 | 
			
		||||
			}
 | 
			
		||||
			updates = append(updates, update)
 | 
			
		||||
		} else {
 | 
			
		||||
			left, right := func() (int, int) {
 | 
			
		||||
				x := strings.Split(line, "|")
 | 
			
		||||
				return mustConv(x[0]), mustConv(x[1])
 | 
			
		||||
			}()
 | 
			
		||||
			orderings[left] = append(orderings[left], right)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := scanner.Err(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return updates, orderings, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func mustConv(s string) int {
 | 
			
		||||
	n, err := strconv.Atoi(s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ParseLines(r io.Reader) ([][][]int, error) {
 | 
			
		||||
	data := make([][][]int, 2)
 | 
			
		||||
 | 
			
		||||
	filter := func(r rune) bool {
 | 
			
		||||
		return r == '|' || r == ','
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf, err := io.ReadAll(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	parts := strings.Split(string(buf), "\n\n")
 | 
			
		||||
 | 
			
		||||
	for i, part := range parts {
 | 
			
		||||
		scanner := bufio.NewScanner(strings.NewReader(part))
 | 
			
		||||
		for scanner.Scan() {
 | 
			
		||||
			filtered := strings.FieldsFunc(scanner.Text(), filter)
 | 
			
		||||
			var nums []int
 | 
			
		||||
			for _, n := range filtered {
 | 
			
		||||
				nums = append(nums, MustConv(n))
 | 
			
		||||
			}
 | 
			
		||||
			data[i] = append(data[i], nums)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := scanner.Err(); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return data, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user