chore: fix day 07
This commit is contained in:
		
							parent
							
								
									50f1016372
								
							
						
					
					
						commit
						f1ac3ea35f
					
				
							
								
								
									
										172
									
								
								day07/main.go
									
									
									
									
									
								
							
							
						
						
									
										172
									
								
								day07/main.go
									
									
									
									
									
								
							@ -3,30 +3,20 @@ package main
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"sort"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	if len(os.Args) != 2 {
 | 
			
		||||
		fmt.Fprintln(os.Stderr, "Usage: day07 FILE")
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 uint64
 | 
			
		||||
	valuePT2 uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	input, err := os.Open(os.Args[1])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Fprintln(os.Stderr, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scan := bufio.NewScanner(input)
 | 
			
		||||
 | 
			
		||||
	score1, score2 := run(scan)
 | 
			
		||||
 | 
			
		||||
	fmt.Println("score 1", score1)
 | 
			
		||||
	fmt.Println("score 2", score2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (uint64, uint64) {
 | 
			
		||||
	var game1, game2 Game
 | 
			
		||||
func run(scan *bufio.Scanner) (result, error) {
 | 
			
		||||
	var game Game
 | 
			
		||||
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		var cards string
 | 
			
		||||
@ -37,20 +27,17 @@ func run(scan *bufio.Scanner) (uint64, uint64) {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		fmt.Println("cards", cards, "bid", bid)
 | 
			
		||||
		game1.Append(cards, bid)
 | 
			
		||||
		game2.Append(cards, bid)
 | 
			
		||||
		game.plays = append(game.plays, Play{bid, []rune(cards), &game})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	game1.cardTypes = cardTypes1
 | 
			
		||||
	game1.cardOrder = getOrder(cardTypes1)
 | 
			
		||||
	product1 := calcProduct(game1)
 | 
			
		||||
	game.cardOrder = getOrder(cardTypes1)
 | 
			
		||||
	product1 := calcProduct(game)
 | 
			
		||||
 | 
			
		||||
	game2.cardTypes = cardTypes2
 | 
			
		||||
	game2.cardOrder = getOrder(cardTypes2)
 | 
			
		||||
	game2.wildCard = 'J'
 | 
			
		||||
	product2 := calcProduct(game2)
 | 
			
		||||
	game.cardOrder = getOrder(cardTypes2)
 | 
			
		||||
	game.wildCard = 'J'
 | 
			
		||||
	product2 := calcProduct(game)
 | 
			
		||||
 | 
			
		||||
	return product1, product2
 | 
			
		||||
	return result{product1, product2}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var cardTypes1 = []rune{'A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2'}
 | 
			
		||||
@ -79,108 +66,92 @@ func getOrder(cardTypes []rune) map[rune]int {
 | 
			
		||||
type Game struct {
 | 
			
		||||
	plays     Plays
 | 
			
		||||
	cardOrder map[rune]int
 | 
			
		||||
 | 
			
		||||
	cardTypes []rune
 | 
			
		||||
	wildCard  rune
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (g *Game) Append(cards string, bid int) {
 | 
			
		||||
	p := Play{bid: bid, hand: []rune(cards), game: g}
 | 
			
		||||
	g.plays = append(g.plays, p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Play struct {
 | 
			
		||||
	bid  int
 | 
			
		||||
	hand Hand
 | 
			
		||||
	cardCounts map[rune]int
 | 
			
		||||
    strength int
 | 
			
		||||
 | 
			
		||||
	game *Game
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Hand []rune
 | 
			
		||||
 | 
			
		||||
func (h *Play) HandType() string {
 | 
			
		||||
	hs := h.HandStrength()
 | 
			
		||||
	kind := hs& 0xf00000
 | 
			
		||||
	hc := h.game.cardTypes[13-hs&0xf0000>>16]
 | 
			
		||||
	switch kind {
 | 
			
		||||
	case 0x700000:
 | 
			
		||||
func (h Play) HandType() string {
 | 
			
		||||
	hc, _ := h.HighCard()
 | 
			
		||||
	switch {
 | 
			
		||||
	case h.IsFiveOfKind():
 | 
			
		||||
		return "5K-" + string(hc)
 | 
			
		||||
	case 0x600000:
 | 
			
		||||
	case h.IsFourOfKind():
 | 
			
		||||
		return "4K-" + string(hc)
 | 
			
		||||
	case 0x500000:
 | 
			
		||||
	case h.IsFullHouse():
 | 
			
		||||
		return "FH-" + string(hc)
 | 
			
		||||
	case 0x400000:
 | 
			
		||||
	case h.IsThreeOfKind():
 | 
			
		||||
		return "3K-" + string(hc)
 | 
			
		||||
	case 0x300000:
 | 
			
		||||
	case h.IsTwoPair():
 | 
			
		||||
		return "2P-" + string(hc)
 | 
			
		||||
	case 0x200000:
 | 
			
		||||
	case h.IsOnePair():
 | 
			
		||||
		return "1P-" + string(hc)
 | 
			
		||||
	case 0x100000:
 | 
			
		||||
	case h.IsHighCard():
 | 
			
		||||
		return "HC-" + string(hc)
 | 
			
		||||
	}
 | 
			
		||||
	return "Uno"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Play) HandStrength() int {
 | 
			
		||||
	_, v := p.HighCard()
 | 
			
		||||
 | 
			
		||||
func (h Play) HandStrength() int {
 | 
			
		||||
	_, v := h.HighCard()
 | 
			
		||||
	switch {
 | 
			
		||||
	case p.IsFiveOfKind():
 | 
			
		||||
		p.strength = 0x700000 | v
 | 
			
		||||
	case p.IsFourOfKind():
 | 
			
		||||
		p.strength = 0x600000 | v
 | 
			
		||||
	case p.IsFullHouse():
 | 
			
		||||
		p.strength = 0x500000 | v
 | 
			
		||||
	case p.IsThreeOfKind():
 | 
			
		||||
		p.strength = 0x400000 | v
 | 
			
		||||
	case p.IsTwoPair():
 | 
			
		||||
		p.strength = 0x300000 | v
 | 
			
		||||
	case p.IsOnePair():
 | 
			
		||||
		p.strength = 0x200000 | v
 | 
			
		||||
	case p.IsHighCard():
 | 
			
		||||
		p.strength = 0x100000 | v
 | 
			
		||||
	case h.IsFiveOfKind():
 | 
			
		||||
		return 0x700000 | v
 | 
			
		||||
	case h.IsFourOfKind():
 | 
			
		||||
		return 0x600000 | v
 | 
			
		||||
	case h.IsFullHouse():
 | 
			
		||||
		return 0x500000 | v
 | 
			
		||||
	case h.IsThreeOfKind():
 | 
			
		||||
		return 0x400000 | v
 | 
			
		||||
	case h.IsTwoPair():
 | 
			
		||||
		return 0x300000 | v
 | 
			
		||||
	case h.IsOnePair():
 | 
			
		||||
		return 0x200000 | v
 | 
			
		||||
	case h.IsHighCard():
 | 
			
		||||
		return 0x100000 | v
 | 
			
		||||
	}
 | 
			
		||||
	return p.strength
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h Play) IsFiveOfKind() bool {
 | 
			
		||||
	_, _, _, _, has5 := h.game.hasSame(h.cardCounts)
 | 
			
		||||
	_, _, _, _, has5 := h.game.hasSame(h.hand)
 | 
			
		||||
	return has5
 | 
			
		||||
}
 | 
			
		||||
func (h Play) IsFourOfKind() bool {
 | 
			
		||||
	_, _, _, has4, _ := h.game.hasSame(h.cardCounts)
 | 
			
		||||
	_, _, _, has4, _ := h.game.hasSame(h.hand)
 | 
			
		||||
	return has4
 | 
			
		||||
}
 | 
			
		||||
func (h Play) IsFullHouse() bool {
 | 
			
		||||
	_, has2, has3, _, _ := h.game.hasSame(h.cardCounts)
 | 
			
		||||
	_, has2, has3, _, _ := h.game.hasSame(h.hand)
 | 
			
		||||
	return has3 && has2
 | 
			
		||||
}
 | 
			
		||||
func (h Play) IsThreeOfKind() bool {
 | 
			
		||||
	has1, _, has3, _, _ := h.game.hasSame(h.cardCounts)
 | 
			
		||||
	has1, _, has3, _, _ := h.game.hasSame(h.hand)
 | 
			
		||||
	return has3 && has1
 | 
			
		||||
}
 | 
			
		||||
func (h Play) IsTwoPair() bool {
 | 
			
		||||
	_, has2, has3, _, _ := h.game.hasSame(h.cardCounts)
 | 
			
		||||
	return !has3 && has2 && h.game.pairs(h.cardCounts) == 2
 | 
			
		||||
	_, has2, has3, _, _ := h.game.hasSame(h.hand)
 | 
			
		||||
	return !has3 && has2 && h.game.pairs(h.hand) == 2
 | 
			
		||||
}
 | 
			
		||||
func (h Play) IsOnePair() bool {
 | 
			
		||||
	_, has2, has3, _, _ := h.game.hasSame(h.cardCounts)
 | 
			
		||||
	return !has3 && has2 && h.game.pairs(h.cardCounts) == 1
 | 
			
		||||
	_, has2, has3, _, _ := h.game.hasSame(h.hand)
 | 
			
		||||
	return !has3 && has2 && h.game.pairs(h.hand) == 1
 | 
			
		||||
}
 | 
			
		||||
func (h Play) IsHighCard() bool {
 | 
			
		||||
	has1, has2, has3, has4, _ := h.game.hasSame(h.cardCounts)
 | 
			
		||||
	has1, has2, has3, has4, _ := h.game.hasSame(h.hand)
 | 
			
		||||
	return has1 && !has2 && !has3 && !has4
 | 
			
		||||
}
 | 
			
		||||
func (h *Play) HighCard() (rune, int) {
 | 
			
		||||
	if h.cardCounts == nil {
 | 
			
		||||
		h.generateCounts()
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
func (h Play) HighCard() (rune, int) {
 | 
			
		||||
	var i int
 | 
			
		||||
	pairs := make(Pairs, 5)
 | 
			
		||||
	for r, c := range h.cardCounts {
 | 
			
		||||
	cnt := h.game.Counts(h.hand)
 | 
			
		||||
	for r, c := range cnt {
 | 
			
		||||
		pairs[i].c = c
 | 
			
		||||
		pairs[i].r = r
 | 
			
		||||
		pairs[i].o = h.game.cardOrder[r]
 | 
			
		||||
@ -223,32 +194,29 @@ func (p Plays) Len() int           { return len(p) }
 | 
			
		||||
func (p Plays) Less(i, j int) bool { return p[i].HandStrength() < p[j].HandStrength() }
 | 
			
		||||
func (p Plays) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
 | 
			
		||||
 | 
			
		||||
func (p *Play) generateCounts() {
 | 
			
		||||
	cardOrder := p.game.cardOrder
 | 
			
		||||
	wildCard := p.game.wildCard
 | 
			
		||||
 | 
			
		||||
	p.cardCounts = make(map[rune]int, len(cardOrder))
 | 
			
		||||
	for _, c := range p.hand {
 | 
			
		||||
		p.cardCounts[c]++
 | 
			
		||||
func (g *Game) Counts(cards []rune) map[rune]int {
 | 
			
		||||
	m := make(map[rune]int, len(g.cardOrder))
 | 
			
		||||
	for _, c := range cards {
 | 
			
		||||
		m[c]++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if wildCard != 0 && p.cardCounts[wildCard] > 0 {
 | 
			
		||||
	if g.wildCard != 0 && m[g.wildCard] > 0 {
 | 
			
		||||
		var maxK rune
 | 
			
		||||
		var maxV int
 | 
			
		||||
		for k, v := range p.cardCounts {
 | 
			
		||||
			if k != wildCard && v > maxV {
 | 
			
		||||
		for k, v := range m {
 | 
			
		||||
			if k != g.wildCard && v > maxV {
 | 
			
		||||
				maxK, maxV = k, v
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if maxK != 0 {
 | 
			
		||||
			p.cardCounts[maxK] += p.cardCounts[wildCard]
 | 
			
		||||
			delete(p.cardCounts, wildCard)
 | 
			
		||||
			m[maxK] += m[g.wildCard]
 | 
			
		||||
			delete(m, g.wildCard)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
func (g *Game) hasSame(counts map[rune]int) (has1, has2, has3, has4, has5 bool) {
 | 
			
		||||
	for _, c := range counts {
 | 
			
		||||
func (g *Game) hasSame(cards []rune) (has1, has2, has3, has4, has5 bool) {
 | 
			
		||||
	cnt := g.Counts(cards)
 | 
			
		||||
	for _, c := range cnt {
 | 
			
		||||
		switch c {
 | 
			
		||||
		case 1:
 | 
			
		||||
			has1 = true
 | 
			
		||||
@ -268,9 +236,9 @@ func (g *Game) hasSame(counts map[rune]int) (has1, has2, has3, has4, has5 bool)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
func (g *Game) pairs(counts map[rune]int) int {
 | 
			
		||||
func (g *Game) pairs(cards []rune) int {
 | 
			
		||||
	pairs := 0
 | 
			
		||||
	for _, n := range counts {
 | 
			
		||||
	for _, n := range g.Counts(cards) {
 | 
			
		||||
		if n == 2 {
 | 
			
		||||
			pairs++
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -26,21 +26,18 @@ func TestHands(t *testing.T) {
 | 
			
		||||
	var game Game
 | 
			
		||||
	game.cardOrder = getOrder(cardTypes1)
 | 
			
		||||
 | 
			
		||||
	h := Play{hand: []rune("AAA23"), game: &game}
 | 
			
		||||
	// h.generateCounts()
 | 
			
		||||
	h := Play{0, []rune("AAA23"), &game}
 | 
			
		||||
	is.Equal(h.HandType(), "3K-A")
 | 
			
		||||
 | 
			
		||||
	h = Play{hand: []rune("JJJJJ"), game:&game}
 | 
			
		||||
	h.generateCounts()
 | 
			
		||||
 | 
			
		||||
	h = Play{0, []rune("JJJJJ"), &game}
 | 
			
		||||
	is.Equal(h.HandType(), "5K-J")
 | 
			
		||||
	is.Equal(fmt.Sprintf("%x", h.HandStrength()), "7aaaaa")
 | 
			
		||||
 | 
			
		||||
	h = Play{hand: []rune("KKKKJ"), game: &game}
 | 
			
		||||
	h = Play{0, []rune("KKKKJ"), &game}
 | 
			
		||||
	is.Equal(h.HandType(), "4K-K")
 | 
			
		||||
	is.Equal(fmt.Sprintf("%x", h.HandStrength()), "6cccca")
 | 
			
		||||
 | 
			
		||||
	h = Play{hand: []rune("QQQJA"), game: &game}
 | 
			
		||||
	h = Play{0, []rune("QQQJA"), &game}
 | 
			
		||||
	is.Equal(h.HandType(), "3K-Q")
 | 
			
		||||
	is.Equal(fmt.Sprintf("%x", h.HandStrength()), "4bbbad")
 | 
			
		||||
}
 | 
			
		||||
@ -57,19 +54,21 @@ func TestExample(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(example))
 | 
			
		||||
 | 
			
		||||
	score1, score2 := run(scan)
 | 
			
		||||
	is.Equal(score1, uint64(6440))
 | 
			
		||||
	is.Equal(score2, uint64(5905))
 | 
			
		||||
	r, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
	is.Equal(r.valuePT1, uint64(6440))
 | 
			
		||||
	is.Equal(r.valuePT2, uint64(5905))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestSolution(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(input))
 | 
			
		||||
 | 
			
		||||
	score1, score2 := run(scan)
 | 
			
		||||
	t.Log("score1", score1)
 | 
			
		||||
	is.Equal(score1, uint64(248559379))
 | 
			
		||||
	r, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
	t.Log("score1", r.valuePT1)
 | 
			
		||||
	is.Equal(r.valuePT1, uint64(248559379))
 | 
			
		||||
 | 
			
		||||
	t.Log("score2", score2)
 | 
			
		||||
	is.Equal(score2, uint64(249631254))
 | 
			
		||||
	t.Log("score2", r.valuePT2)
 | 
			
		||||
	is.Equal(r.valuePT2, uint64(249631254))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@ -1,4 +1,4 @@
 | 
			
		||||
module go.sour.is/advent-of-code-2023
 | 
			
		||||
module go.sour.is/advent-of-code
 | 
			
		||||
 | 
			
		||||
go 1.21.3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										395
									
								
								tools.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										395
									
								
								tools.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,395 @@
 | 
			
		||||
package aoc
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"cmp"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Runner[R any, F func(*bufio.Scanner) (R, error)](run F) (R, error) {
 | 
			
		||||
	if len(os.Args) != 2 {
 | 
			
		||||
		Log("Usage:", filepath.Base(os.Args[0]), "FILE")
 | 
			
		||||
		os.Exit(22)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	input, err := os.Open(os.Args[1])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		Log(err)
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scan := bufio.NewScanner(input)
 | 
			
		||||
	return run(scan)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MustResult[T any](result T, err error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println("ERR", err)
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Log("result", result)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Log(v ...any) { fmt.Fprintln(os.Stderr, v...) }
 | 
			
		||||
func Logf(format string, v ...any) {
 | 
			
		||||
	if !strings.HasSuffix(format, "\n") {
 | 
			
		||||
		format += "\n"
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Fprintf(os.Stderr, format, v...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Reverse[T any](arr []T) []T {
 | 
			
		||||
	for i := 0; i < len(arr)/2; i++ {
 | 
			
		||||
		arr[i], arr[len(arr)-i-1] = arr[len(arr)-i-1], arr[i]
 | 
			
		||||
	}
 | 
			
		||||
	return arr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type uinteger interface {
 | 
			
		||||
	uint | uint8 | uint16 | uint32 | uint64
 | 
			
		||||
}
 | 
			
		||||
type sinteger interface {
 | 
			
		||||
	int | int8 | int16 | int32 | int64
 | 
			
		||||
}
 | 
			
		||||
type integer interface {
 | 
			
		||||
	sinteger | uinteger
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// type float interface {
 | 
			
		||||
// 	complex64 | complex128 | float32 | float64
 | 
			
		||||
// }
 | 
			
		||||
// type number interface{ integer | float }
 | 
			
		||||
 | 
			
		||||
// greatest common divisor (GCD) via Euclidean algorithm
 | 
			
		||||
func GCD[T integer](a, b T) T {
 | 
			
		||||
	for b != 0 {
 | 
			
		||||
		t := b
 | 
			
		||||
		b = a % b
 | 
			
		||||
		a = t
 | 
			
		||||
	}
 | 
			
		||||
	return a
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// find Least Common Multiple (LCM) via GCD
 | 
			
		||||
func LCM[T integer](integers ...T) T {
 | 
			
		||||
	if len(integers) == 0 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	if len(integers) == 1 {
 | 
			
		||||
		return integers[0]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	a, b := integers[0], integers[1]
 | 
			
		||||
	result := a * b / GCD(a, b)
 | 
			
		||||
 | 
			
		||||
	for _, c := range integers[2:] {
 | 
			
		||||
		result = LCM(result, c)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ReadStringToInts(fields []string) []int {
 | 
			
		||||
	return SliceMap(Atoi, fields...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Node[T any] struct {
 | 
			
		||||
	value T
 | 
			
		||||
	pos   int
 | 
			
		||||
	left  *Node[T]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (n *Node[T]) add(a *Node[T]) *Node[T] {
 | 
			
		||||
	if a == nil {
 | 
			
		||||
		return n
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if n == nil {
 | 
			
		||||
		return a
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	n.left = a
 | 
			
		||||
	return a
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (n *Node[T]) Value() (value T, ok bool) {
 | 
			
		||||
	if n == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return n.value, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (n *Node[T]) Position() int {
 | 
			
		||||
	if n == nil {
 | 
			
		||||
		return -1
 | 
			
		||||
	}
 | 
			
		||||
	return n.pos
 | 
			
		||||
}
 | 
			
		||||
func (n *Node[T]) SetPosition(i int) {
 | 
			
		||||
	if n == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	n.pos = i
 | 
			
		||||
}
 | 
			
		||||
func (n *Node[T]) Next() *Node[T] {
 | 
			
		||||
	if n == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return n.left
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (n *Node[T]) String() string {
 | 
			
		||||
	if n == nil {
 | 
			
		||||
		return "EOL"
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("node %v", n.value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type List[T any] struct {
 | 
			
		||||
	head *Node[T]
 | 
			
		||||
	n    *Node[T]
 | 
			
		||||
	p    map[int]*Node[T]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewList[T any](a *Node[T]) *List[T] {
 | 
			
		||||
	lis := &List[T]{
 | 
			
		||||
		head: a,
 | 
			
		||||
		n:    a,
 | 
			
		||||
		p:    make(map[int]*Node[T]),
 | 
			
		||||
	}
 | 
			
		||||
	lis.add(a)
 | 
			
		||||
 | 
			
		||||
	return lis
 | 
			
		||||
}
 | 
			
		||||
func (l *List[T]) Add(value T, pos int) {
 | 
			
		||||
	a := &Node[T]{value: value, pos: pos}
 | 
			
		||||
	l.add(a)
 | 
			
		||||
}
 | 
			
		||||
func (l *List[T]) add(a *Node[T]) {
 | 
			
		||||
	if l.head == nil {
 | 
			
		||||
		l.head = a
 | 
			
		||||
	}
 | 
			
		||||
	if a == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l.n = l.n.add(a)
 | 
			
		||||
	l.p[a.pos] = a
 | 
			
		||||
}
 | 
			
		||||
func (l *List[T]) Get(pos int) *Node[T] {
 | 
			
		||||
	return l.p[pos]
 | 
			
		||||
}
 | 
			
		||||
func (l *List[T]) GetN(pos ...int) []*Node[T] {
 | 
			
		||||
	lis := make([]*Node[T], len(pos))
 | 
			
		||||
	for i, p := range pos {
 | 
			
		||||
		lis[i] = l.p[p]
 | 
			
		||||
	}
 | 
			
		||||
	return lis
 | 
			
		||||
}
 | 
			
		||||
func (l *List[T]) Head() *Node[T] {
 | 
			
		||||
	return l.head
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SliceMap[T, U any](fn func(T) U, in ...T) []U {
 | 
			
		||||
	lis := make([]U, len(in))
 | 
			
		||||
	for i := range lis {
 | 
			
		||||
		lis[i] = fn(in[i])
 | 
			
		||||
	}
 | 
			
		||||
	return lis
 | 
			
		||||
}
 | 
			
		||||
func SliceIMap[T, U any](fn func(int, T) U, in ...T) []U {
 | 
			
		||||
	lis := make([]U, len(in))
 | 
			
		||||
	for i := range lis {
 | 
			
		||||
		lis[i] = fn(i, in[i])
 | 
			
		||||
	}
 | 
			
		||||
	return lis
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Atoi(s string) int {
 | 
			
		||||
	i, _ := strconv.Atoi(s)
 | 
			
		||||
	return i
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Repeat[T any](s T, i int) []T {
 | 
			
		||||
	lis := make([]T, i)
 | 
			
		||||
	for i := range lis {
 | 
			
		||||
		lis[i] = s
 | 
			
		||||
	}
 | 
			
		||||
	return lis
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Sum[T integer](arr ...T) T {
 | 
			
		||||
	var acc T
 | 
			
		||||
	for _, a := range arr {
 | 
			
		||||
		acc += a
 | 
			
		||||
	}
 | 
			
		||||
	return acc
 | 
			
		||||
}
 | 
			
		||||
func SumFunc[T any, U integer](fn func(T) U, input ...T) U {
 | 
			
		||||
	return Sum(SliceMap(fn, input...)...)
 | 
			
		||||
}
 | 
			
		||||
func SumIFunc[T any, U integer](fn func(int, T) U, input ...T) U {
 | 
			
		||||
	return Sum(SliceIMap(fn, input...)...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Power2(n int) int {
 | 
			
		||||
	if n == 0 {
 | 
			
		||||
		return 1
 | 
			
		||||
	}
 | 
			
		||||
	p := 2
 | 
			
		||||
	for ; n > 1; n-- {
 | 
			
		||||
		p *= 2
 | 
			
		||||
	}
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ABS(i int) int {
 | 
			
		||||
	if i < 0 {
 | 
			
		||||
		return -i
 | 
			
		||||
	}
 | 
			
		||||
	return i
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Transpose[T any](matrix [][]T) [][]T {
 | 
			
		||||
	rows, cols := len(matrix), len(matrix[0])
 | 
			
		||||
 | 
			
		||||
	m := make([][]T, cols)
 | 
			
		||||
	for i := range m {
 | 
			
		||||
		m[i] = make([]T, rows)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < cols; i++ {
 | 
			
		||||
		for j := 0; j < rows; j++ {
 | 
			
		||||
			m[i][j] = matrix[j][i]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Reduce[T, U any](fn func(int, T, U) U, u U, list ...T) U {
 | 
			
		||||
	for i, t := range list {
 | 
			
		||||
		u = fn(i, t, u)
 | 
			
		||||
	}
 | 
			
		||||
	return u
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PQElem[T any, I integer] struct {
 | 
			
		||||
	Value    T
 | 
			
		||||
	Priority I
 | 
			
		||||
}
 | 
			
		||||
type PQList[T any, I integer] []PQElem[T, I]
 | 
			
		||||
 | 
			
		||||
func (pq PQList[T, I]) Len() int {
 | 
			
		||||
	return len(pq)
 | 
			
		||||
}
 | 
			
		||||
func (pq PQList[T, I]) Less(i int, j int) bool {
 | 
			
		||||
	return pq[i].Priority < pq[j].Priority
 | 
			
		||||
}
 | 
			
		||||
func (pq PQList[T, I]) Swap(i int, j int) {
 | 
			
		||||
	pq[i], pq[j] = pq[j], pq[i]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ sort.Interface = (*PQList[rune, int])(nil)
 | 
			
		||||
 | 
			
		||||
type PriorityQueue[T any, I integer] struct {
 | 
			
		||||
	elem PQList[T, I]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pq *PriorityQueue[T, I]) Enqueue(elem T, priority I) {
 | 
			
		||||
	pq.elem = append(pq.elem, PQElem[T, I]{elem, priority})
 | 
			
		||||
	sort.Sort(pq.elem)
 | 
			
		||||
}
 | 
			
		||||
func (pq *PriorityQueue[T, I]) IsEmpty() bool {
 | 
			
		||||
	return len(pq.elem) == 0
 | 
			
		||||
}
 | 
			
		||||
func (pq *PriorityQueue[T, I]) Dequeue() (T, bool) {
 | 
			
		||||
	var elem T
 | 
			
		||||
	if pq.IsEmpty() {
 | 
			
		||||
		return elem, false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	elem, pq.elem = pq.elem[0].Value, pq.elem[1:]
 | 
			
		||||
	return elem, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Vertex[V comparable, I integer] struct {
 | 
			
		||||
	to    V
 | 
			
		||||
	score I
 | 
			
		||||
}
 | 
			
		||||
type graph[V comparable, I uinteger] struct {
 | 
			
		||||
	adj map[V][]Vertex[V, I]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Graph[V comparable, I uinteger](size int) *graph[V, I] {
 | 
			
		||||
	return &graph[V, I]{
 | 
			
		||||
		adj: make(map[V][]Vertex[V, I], size),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (g *graph[V, I]) AddEdge(u, v V, w I) {
 | 
			
		||||
	g.adj[u] = append(g.adj[u], Vertex[V, I]{to: v, score: w})
 | 
			
		||||
	g.adj[v] = append(g.adj[v], Vertex[V, I]{to: u, score: w})
 | 
			
		||||
}
 | 
			
		||||
func (g *graph[V, I]) Dijkstra(m interface{Get()}, src V) map[V]I {
 | 
			
		||||
	pq := PriorityQueue[V, I]{}
 | 
			
		||||
	dist := make(map[V]I, len(g.adj))
 | 
			
		||||
	visited := make(map[V]bool, len(g.adj))
 | 
			
		||||
	var INF I
 | 
			
		||||
	INF = ^INF
 | 
			
		||||
 | 
			
		||||
	pq.Enqueue(src, 0)
 | 
			
		||||
	dist[src] = 0
 | 
			
		||||
 | 
			
		||||
	for !pq.IsEmpty() {
 | 
			
		||||
		u, _ := pq.Dequeue()
 | 
			
		||||
 | 
			
		||||
		if _, ok := visited[u]; ok {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		visited[u] = true
 | 
			
		||||
 | 
			
		||||
		for _, v := range g.adj[u] {
 | 
			
		||||
			_, ok := visited[v.to]
 | 
			
		||||
			var du, dv I
 | 
			
		||||
			if d, inf := dist[u]; !inf {
 | 
			
		||||
				du = INF
 | 
			
		||||
			} else {
 | 
			
		||||
				du = d
 | 
			
		||||
			}
 | 
			
		||||
			if d, inf := dist[v.to]; !inf {
 | 
			
		||||
				dv = INF
 | 
			
		||||
			} else {
 | 
			
		||||
				dv = d
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !ok && du+v.score < dv {
 | 
			
		||||
				dist[v.to] = du + v.score
 | 
			
		||||
				pq.Enqueue(v.to, du+v.score)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return dist
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user