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…
Reference in New Issue
Block a user