This commit is contained in:
		
							parent
							
								
									be110c4dea
								
							
						
					
					
						commit
						b6501e80c9
					
				
							
								
								
									
										167
									
								
								day18/main.go
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								day18/main.go
									
									
									
									
									
								
							@ -5,9 +5,12 @@ import (
 | 
				
			|||||||
	_ "embed"
 | 
						_ "embed"
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	aoc "go.sour.is/advent-of-code"
 | 
						aoc "go.sour.is/advent-of-code"
 | 
				
			||||||
 | 
						"golang.org/x/exp/maps"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// var log = aoc.Log
 | 
					// var log = aoc.Log
 | 
				
			||||||
@ -24,6 +27,7 @@ func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
				
			|||||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
					func run(scan *bufio.Scanner) (*result, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var vecs []vec
 | 
						var vecs []vec
 | 
				
			||||||
 | 
						var vecs2 []vec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for scan.Scan() {
 | 
						for scan.Scan() {
 | 
				
			||||||
		text := scan.Text()
 | 
							text := scan.Text()
 | 
				
			||||||
@ -35,7 +39,7 @@ func run(scan *bufio.Scanner) (*result, error) {
 | 
				
			|||||||
		var s string
 | 
							var s string
 | 
				
			||||||
		v := vec{}
 | 
							v := vec{}
 | 
				
			||||||
		s, text, _ = strings.Cut(text, " ")
 | 
							s, text, _ = strings.Cut(text, " ")
 | 
				
			||||||
		v.Direction = direction(s)
 | 
							v.Direction = direction(s[0])
 | 
				
			||||||
		s, text, _ = strings.Cut(text, " ")
 | 
							s, text, _ = strings.Cut(text, " ")
 | 
				
			||||||
		v.Steps = aoc.Atoi(s)
 | 
							v.Steps = aoc.Atoi(s)
 | 
				
			||||||
		_, text, _ = strings.Cut(text, "#")
 | 
							_, text, _ = strings.Cut(text, "#")
 | 
				
			||||||
@ -43,32 +47,47 @@ func run(scan *bufio.Scanner) (*result, error) {
 | 
				
			|||||||
		b, _ := hex.DecodeString(s)
 | 
							b, _ := hex.DecodeString(s)
 | 
				
			||||||
		copy(v.Color[:], b)
 | 
							copy(v.Color[:], b)
 | 
				
			||||||
		vecs = append(vecs, v)
 | 
							vecs = append(vecs, v)
 | 
				
			||||||
 | 
							vecs2 = append(vecs2, fromColor(s))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return &result{
 | 
				
			||||||
 | 
							valuePT1: findArea(vecs),
 | 
				
			||||||
 | 
							valuePT2: skip("AOC_DAY18P2", func() int { return findArea(vecs2) }),
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func findArea(vecs []vec) int {
 | 
				
			||||||
	var points []point
 | 
						var points []point
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var x, y int
 | 
						var x, y int
 | 
				
			||||||
	var minX, minY int
 | 
						var minX, minY int
 | 
				
			||||||
	for i, v := range vecs {
 | 
						last := direction('S')
 | 
				
			||||||
		fmt.Println("pt ", i, v)
 | 
						for _, v := range vecs {
 | 
				
			||||||
 | 
							// fmt.Println("pt ", i, v)
 | 
				
			||||||
		for i := 0; i < v.Steps; i++ {
 | 
							for i := 0; i < v.Steps; i++ {
 | 
				
			||||||
			switch v.Direction {
 | 
								switch v.Direction {
 | 
				
			||||||
			case "U":
 | 
								case 'U':
 | 
				
			||||||
				y++
 | 
									y++
 | 
				
			||||||
			case "D":
 | 
								case 'D':
 | 
				
			||||||
				y--
 | 
									y--
 | 
				
			||||||
			case "R":
 | 
								case 'R':
 | 
				
			||||||
				x++
 | 
									x++
 | 
				
			||||||
			case "L":
 | 
								case 'L':
 | 
				
			||||||
				x--
 | 
									x--
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								// fmt.Println("pt ", i, y, x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			minX = min(minX, x)
 | 
								minX = min(minX, x)
 | 
				
			||||||
			minY = min(minY, y)
 | 
								minY = min(minY, y)
 | 
				
			||||||
			points = append(points, point{d: v.Direction, x: x, y: y, color: v.Color})
 | 
								if len(points) > 0 {
 | 
				
			||||||
 | 
									points[len(points)-1].d = v.Direction
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								points = append(points, point{d: v.Direction, w: opposite(v.Direction), x: x, y: y, color: v.Color})
 | 
				
			||||||
 | 
								last = v.Direction
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						_ = last
 | 
				
			||||||
 | 
						// points[0].w = last
 | 
				
			||||||
 | 
						points[len(points)-1].d = points[0].w
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	adjX := aoc.ABS(min(0, minX))
 | 
						adjX := aoc.ABS(min(0, minX))
 | 
				
			||||||
	adjY := aoc.ABS(min(0, minY))
 | 
						adjY := aoc.ABS(min(0, minY))
 | 
				
			||||||
@ -81,9 +100,10 @@ func run(scan *bufio.Scanner) (*result, error) {
 | 
				
			|||||||
	maxX, maxY := 0, 0
 | 
						maxX, maxY := 0, 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i, p := range points {
 | 
						for i, p := range points {
 | 
				
			||||||
		// fmt.Println("raw", i, p)
 | 
					
 | 
				
			||||||
		p.x += adjX
 | 
							p.x += adjX
 | 
				
			||||||
		p.y += adjY
 | 
							p.y += adjY
 | 
				
			||||||
 | 
							// fmt.Println("raw", i, p.x, p.y, string(p.w), string(p.d))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		maxX = max(maxX, p.x)
 | 
							maxX = max(maxX, p.x)
 | 
				
			||||||
		maxY = max(maxY, p.y)
 | 
							maxY = max(maxY, p.y)
 | 
				
			||||||
@ -98,69 +118,78 @@ func run(scan *bufio.Scanner) (*result, error) {
 | 
				
			|||||||
			trace[p.y] = row
 | 
								trace[p.y] = row
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						fmt.Println("maxX", maxX, "maxY", maxY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	area := 0
 | 
						area := 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for y := 0; y <= maxY; y++ {
 | 
						for y := maxY; y >= 0; y-- {
 | 
				
			||||||
		row, ok := trace[y]
 | 
							row, ok := trace[y]
 | 
				
			||||||
		if !ok {
 | 
							if !ok {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var last direction
 | 
							var last direction
 | 
				
			||||||
		p, inLoop := row[0]
 | 
							p := row[0]
 | 
				
			||||||
		last = p.d
 | 
							last = p.d
 | 
				
			||||||
 | 
							inLoop := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for x := 0; x <= maxX; x++ {
 | 
							for x := 0; x <= maxX; x++ {
 | 
				
			||||||
			if p, ok := row[x]; ok {
 | 
								if p, ok := row[x]; ok {
 | 
				
			||||||
				switch last+p.d {
 | 
									// fmt.Println("vec", string(p.w), string(p.d))
 | 
				
			||||||
				case " U"," L", "UR":
 | 
									switch string([]rune{rune(p.w), rune(p.d)}) {
 | 
				
			||||||
					inLoop = true
 | 
									case "LD", "DL", "UD", "DU", "RD", "UU", "DR":
 | 
				
			||||||
				case "LD", " D", "RD":
 | 
					 | 
				
			||||||
					inLoop = !inLoop
 | 
										inLoop = !inLoop
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if last != p.d {
 | 
									if last != p.d {
 | 
				
			||||||
					last = p.d
 | 
										last = p.d
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				fmt.Print(p.d)
 | 
					
 | 
				
			||||||
				if inLoop {
 | 
									// fmt.Print(string(p.w)+string(p.d))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// On loop
 | 
				
			||||||
				area++
 | 
									area++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									continue // 203338
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
				continue
 | 
								last = direction('0')
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			last = direction(" ")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if inLoop {
 | 
								if inLoop {
 | 
				
			||||||
				area++
 | 
									area++
 | 
				
			||||||
				fmt.Print(".")
 | 
									// fmt.Print("XX")
 | 
				
			||||||
			} else {
 | 
									// } else {
 | 
				
			||||||
				fmt.Print(" ")
 | 
									// 	fmt.Print("..")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fmt.Println("")
 | 
							// fmt.Println("")
 | 
				
			||||||
 | 
							fmt.Println(y, area)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return area
 | 
				
			||||||
	// for y := 0; y < len(trace); y++ {
 | 
					 | 
				
			||||||
	// 	rng := trace[y]
 | 
					 | 
				
			||||||
	// 	sort.Ints(rng)
 | 
					 | 
				
			||||||
	// 	for _, r := range ranges(rng) {
 | 
					 | 
				
			||||||
	// 		area += r[1] - r[0] + 1
 | 
					 | 
				
			||||||
	// 	}
 | 
					 | 
				
			||||||
	// }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &result{valuePT1: area}, nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type direction string
 | 
					type direction rune
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	U direction = "U"
 | 
						U direction = 'U'
 | 
				
			||||||
	D direction = "D"
 | 
						D direction = 'D'
 | 
				
			||||||
	L direction = "L"
 | 
						L direction = 'L'
 | 
				
			||||||
	R direction = "R"
 | 
						R direction = 'R'
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func opposite(d direction) direction {
 | 
				
			||||||
 | 
						switch d {
 | 
				
			||||||
 | 
						case U:
 | 
				
			||||||
 | 
							return D
 | 
				
			||||||
 | 
						case D:
 | 
				
			||||||
 | 
							return U
 | 
				
			||||||
 | 
						case L:
 | 
				
			||||||
 | 
							return R
 | 
				
			||||||
 | 
						case R:
 | 
				
			||||||
 | 
							return L
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return '0'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type vec struct {
 | 
					type vec struct {
 | 
				
			||||||
	Direction direction
 | 
						Direction direction
 | 
				
			||||||
	Steps     int
 | 
						Steps     int
 | 
				
			||||||
@ -174,42 +203,32 @@ type point struct {
 | 
				
			|||||||
	color [3]byte
 | 
						color [3]byte
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ranges(rng []int) [][]int {
 | 
					func fromColor(c string) vec {
 | 
				
			||||||
	// inLoop := true
 | 
						steps, _ := strconv.ParseInt(c[:5], 16, 64)
 | 
				
			||||||
	var mn int = rng[0]
 | 
					 | 
				
			||||||
	var last int = rng[0]
 | 
					 | 
				
			||||||
	var result [][]int
 | 
					 | 
				
			||||||
	result = append(result, []int{mn, mn})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, i := range rng[1:] {
 | 
						d := '_'
 | 
				
			||||||
		if i-last == 1 {
 | 
						switch c[5] {
 | 
				
			||||||
			result[len(result)-1][1] = i
 | 
						case '0':
 | 
				
			||||||
			last = i
 | 
							d = 'R'
 | 
				
			||||||
			continue
 | 
						case '1':
 | 
				
			||||||
 | 
							d = 'D'
 | 
				
			||||||
 | 
						case '2':
 | 
				
			||||||
 | 
							d = 'L'
 | 
				
			||||||
 | 
						case '3':
 | 
				
			||||||
 | 
							d = 'U'
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		last = i
 | 
						return vec{
 | 
				
			||||||
		mn = i
 | 
							Direction: direction(d),
 | 
				
			||||||
		result = append(result, []int{mn, last})
 | 
							Steps:     int(steps),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
	if len(result) == 1 {
 | 
					
 | 
				
			||||||
		return result
 | 
					func skip[T any](env string, fn func() T) T {
 | 
				
			||||||
	}
 | 
						var zero T
 | 
				
			||||||
 | 
						if e, err := strconv.ParseBool(os.Getenv(env)); err == nil && e {
 | 
				
			||||||
	if len(result) == 2 {
 | 
							return zero
 | 
				
			||||||
		return [][]int{{result[0][0], result[1][1]}}
 | 
						}
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
 | 
						return fn()
 | 
				
			||||||
	if len(result)%2 == 0 {
 | 
					 | 
				
			||||||
		var result2 [][]int
 | 
					 | 
				
			||||||
		for i := 0; i < len(result); i += 2 {
 | 
					 | 
				
			||||||
			result2 = append(result2, []int{result[i][0], result[i+1][1]})
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return result2
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fmt.Println("odd ranges", result)
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@ package main
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"bufio"
 | 
						"bufio"
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_ "embed"
 | 
						_ "embed"
 | 
				
			||||||
@ -25,18 +26,20 @@ func TestExample(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	t.Log(result)
 | 
						t.Log(result)
 | 
				
			||||||
	is.Equal(result.valuePT1, 62)
 | 
						is.Equal(result.valuePT1, 62)
 | 
				
			||||||
	is.Equal(result.valuePT2, 0)
 | 
						is.Equal(result.valuePT2, 952408144115)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestSolution(t *testing.T) {
 | 
					func TestSolution(t *testing.T) {
 | 
				
			||||||
	is := is.New(t)
 | 
						is := is.New(t)
 | 
				
			||||||
	scan := bufio.NewScanner(bytes.NewReader(input))
 | 
						scan := bufio.NewScanner(bytes.NewReader(input))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						os.Setenv("AOC_DAY18P2", "1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	result, err := run(scan)
 | 
						result, err := run(scan)
 | 
				
			||||||
	is.NoErr(err)
 | 
						is.NoErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	t.Log(result)
 | 
						t.Log(result)
 | 
				
			||||||
	is.True(result.valuePT1 < 68834) // first attempt too high.
 | 
						is.True(result.valuePT1 < 68834) // first attempt too high.
 | 
				
			||||||
	is.Equal(result.valuePT1, 0)
 | 
						is.Equal(result.valuePT1, 46334)
 | 
				
			||||||
	is.Equal(result.valuePT2, 0)
 | 
						is.Equal(result.valuePT2, 0)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user