chore: add day 10 #8
							
								
								
									
										157
									
								
								day10/main.go
									
									
									
									
									
								
							
							
						
						
									
										157
									
								
								day10/main.go
									
									
									
									
									
								
							@ -8,7 +8,7 @@ import (
 | 
				
			|||||||
	aoc "go.sour.is/advent-of-code-2023"
 | 
						aoc "go.sour.is/advent-of-code-2023"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var log = aoc.Log
 | 
					// var log = aoc.Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
					func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -20,7 +20,7 @@ type result struct {
 | 
				
			|||||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
					func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
					func run(scan *bufio.Scanner) (*result, error) {
 | 
				
			||||||
	m := Path{s: -1}
 | 
						m := &Path{s: -1}
 | 
				
			||||||
	for scan.Scan() {
 | 
						for scan.Scan() {
 | 
				
			||||||
		text := scan.Text()
 | 
							text := scan.Text()
 | 
				
			||||||
		_ = text
 | 
							_ = text
 | 
				
			||||||
@ -28,39 +28,77 @@ func run(scan *bufio.Scanner) (*result, error) {
 | 
				
			|||||||
		m.readLine(text)
 | 
							m.readLine(text)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dist := m.buildPath()
 | 
						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
 | 
				
			||||||
	return &result{valuePT1: dist}, nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type node struct {
 | 
					type node struct {
 | 
				
			||||||
	value       rune
 | 
						value  rune
 | 
				
			||||||
	pos         int
 | 
						pos    int
 | 
				
			||||||
	whence      int8
 | 
						whence int8
 | 
				
			||||||
	left, right *node
 | 
						left   *node
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (n *node) add(a *node) *node {
 | 
					func (n *node) add(a *node) *node {
 | 
				
			||||||
	if a == nil {
 | 
						if a == nil {
 | 
				
			||||||
		return n
 | 
							return n
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	n.left, a.right = a, n
 | 
						n.left = a
 | 
				
			||||||
	return a
 | 
						return a
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (n *node) String() string {
 | 
					func (n *node) String() string {
 | 
				
			||||||
 | 
						if n == nil {
 | 
				
			||||||
 | 
							return "EOL"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return fmt.Sprintf("node %s from %s", string(n.value), enum(n.whence))
 | 
						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 {
 | 
					type Path struct {
 | 
				
			||||||
	m []rune
 | 
						m []rune
 | 
				
			||||||
	w int
 | 
						w int
 | 
				
			||||||
	s int
 | 
						s int
 | 
				
			||||||
	l int
 | 
					
 | 
				
			||||||
	n *node
 | 
						*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) {
 | 
					func (m *Path) readLine(text string) {
 | 
				
			||||||
	if m.w == 0 {
 | 
						if m.w == 0 {
 | 
				
			||||||
		m.w = len(text)
 | 
							m.w = len(text)
 | 
				
			||||||
@ -75,29 +113,22 @@ func (m *Path) readLine(text string) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
func (m *Path) buildPath() int {
 | 
					func (m *Path) buildPath() int {
 | 
				
			||||||
	m.start()
 | 
						m.start()
 | 
				
			||||||
	// log(m.n)
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for m.next() {
 | 
						for m.next() {
 | 
				
			||||||
		// log(m.n)
 | 
					 | 
				
			||||||
		i++
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// log(m.n)
 | 
						return (len(m.p) + 1) / 2
 | 
				
			||||||
	// log("length", (m.l+2)/2)
 | 
					 | 
				
			||||||
	return (m.l+2)/2
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (m *Path) start() {
 | 
					func (m *Path) start() {
 | 
				
			||||||
	m.n = &node{value: 'S', pos: m.s}
 | 
						m.List = NewList(&node{value: 'S', pos: m.s})
 | 
				
			||||||
	// log(m.n)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch {
 | 
						switch {
 | 
				
			||||||
	case m.peek(UP) != nil:
 | 
						case m.peek(UP) != nil:
 | 
				
			||||||
		m.n = m.n.add(m.peek(UP))
 | 
							m.add(m.peek(UP))
 | 
				
			||||||
	case m.peek(DN) != nil:
 | 
						case m.peek(DN) != nil:
 | 
				
			||||||
		m.n = m.n.add(m.peek(DN))
 | 
							m.add(m.peek(DN))
 | 
				
			||||||
	case m.peek(LF) != nil:
 | 
						case m.peek(LF) != nil:
 | 
				
			||||||
		m.n = m.n.add(m.peek(LF))
 | 
							m.add(m.peek(LF))
 | 
				
			||||||
	case m.peek(RT) != nil:
 | 
						case m.peek(RT) != nil:
 | 
				
			||||||
		m.n = m.n.add(m.peek(RT))
 | 
							m.add(m.peek(RT))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (m *Path) next() bool {
 | 
					func (m *Path) next() bool {
 | 
				
			||||||
@ -141,12 +172,38 @@ func (m *Path) next() bool {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if n == nil {
 | 
						if n == nil {
 | 
				
			||||||
 | 
							return false 
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if n.value == 'S' {
 | 
				
			||||||
 | 
							last := n.whence
 | 
				
			||||||
 | 
							next := m.head.left.whence
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch (last<<4)|next {
 | 
				
			||||||
 | 
							case 0x11, 0x22: m.n.value = '|' // UP UP, DN DN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case 0x13: m.head.value = 'J' // UP LF
 | 
				
			||||||
 | 
							case 0x14: m.head.value = 'L' // UP RT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case 0x23: m.head.value = '7' // DN LF
 | 
				
			||||||
 | 
							case 0x24: m.head.value = 'F' // DN RT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case 0x33, 0x44: m.head.value = '-' // LF LF, RT RT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case 0x31: m.head.value = '7' // LF UP 
 | 
				
			||||||
 | 
							case 0x32: m.head.value = 'J' // LF DN 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case 0x41: m.head.value = 'F' // RT UP
 | 
				
			||||||
 | 
							case 0x42: m.head.value = 'L' // RT DN 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m.n = m.n.add(n)
 | 
						m.add(n)
 | 
				
			||||||
	m.l++
 | 
					
 | 
				
			||||||
	return m.n.value != 'S'
 | 
					
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
@ -184,7 +241,7 @@ func (m *Path) peek(d int8) *node {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		p := fromXY(x, y-1, m.w)
 | 
							p := fromXY(x, y-1, m.w)
 | 
				
			||||||
		r := m.m[p]
 | 
							r := m.m[p]
 | 
				
			||||||
		if any(r, '7', '|', 'F') {
 | 
							if any(r, '7', '|', 'F', 'S') {
 | 
				
			||||||
			return &node{value: r, whence: DN, pos: p}
 | 
								return &node{value: r, whence: DN, pos: p}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case DN:
 | 
						case DN:
 | 
				
			||||||
@ -195,7 +252,7 @@ func (m *Path) peek(d int8) *node {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		p := fromXY(x, y+1, m.w)
 | 
							p := fromXY(x, y+1, m.w)
 | 
				
			||||||
		r := m.m[p]
 | 
							r := m.m[p]
 | 
				
			||||||
		if any(r, 'J', '|', 'L') {
 | 
							if any(r, 'J', '|', 'L', 'S') {
 | 
				
			||||||
			return &node{value: r, whence: UP, pos: p}
 | 
								return &node{value: r, whence: UP, pos: p}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -207,7 +264,7 @@ func (m *Path) peek(d int8) *node {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		p := fromXY(x-1, y, m.w)
 | 
							p := fromXY(x-1, y, m.w)
 | 
				
			||||||
		r := m.m[p]
 | 
							r := m.m[p]
 | 
				
			||||||
		if any(r, 'F', '-', 'L') {
 | 
							if any(r, 'F', '-', 'L', 'S') {
 | 
				
			||||||
			return &node{value: r, whence: RT, pos: p}
 | 
								return &node{value: r, whence: RT, pos: p}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -218,7 +275,7 @@ func (m *Path) peek(d int8) *node {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		p := fromXY(x+1, y, m.w)
 | 
							p := fromXY(x+1, y, m.w)
 | 
				
			||||||
		r := m.m[p]
 | 
							r := m.m[p]
 | 
				
			||||||
		if any(r, '7', '-', 'J') {
 | 
							if any(r, '7', '-', 'J', 'S') {
 | 
				
			||||||
			return &node{value: r, whence: LF, pos: p}
 | 
								return &node{value: r, whence: LF, pos: p}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -240,3 +297,41 @@ func any[T comparable](n T, stack ...T) bool {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return found
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -102,8 +102,9 @@ func TestInput(t *testing.T) {
 | 
				
			|||||||
	is.True(result.valuePT1 != 51)
 | 
						is.True(result.valuePT1 != 51)
 | 
				
			||||||
	is.Equal(result.valuePT1, 6649)
 | 
						is.Equal(result.valuePT1, 6649)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// t.Log(result.valuePT2)
 | 
						t.Log(result.valuePT2)
 | 
				
			||||||
	is.True(result.valuePT2 != 0)
 | 
						is.True(result.valuePT2 != 0)
 | 
				
			||||||
 | 
						is.Equal(result.valuePT2, 601)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// first: 51 false
 | 
					// first: 51 false
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user