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