day24, example
This commit is contained in:
147
day24/lines.go
Normal file
147
day24/lines.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package day24
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
CoordMin int = 7
|
||||
CoordMax int = 27
|
||||
)
|
||||
|
||||
type Point struct {
|
||||
x, y, Z int
|
||||
}
|
||||
|
||||
type HailParam struct {
|
||||
p0, p1 Point
|
||||
Dx, Dy, Dz int
|
||||
line string
|
||||
}
|
||||
func (h HailParam)String() string {
|
||||
return "(" + h.line + ")"
|
||||
}
|
||||
|
||||
func CheckPairwiseIntersections(hails []HailParam) (totalIntersections int) {
|
||||
for i, hail := range hails {
|
||||
for j := i+1; j < len(hails); j++ {
|
||||
otherHail := hails[j]
|
||||
intersect := CheckTaskIntersection(hail, otherHail)
|
||||
if intersect {
|
||||
totalIntersections += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func CheckTaskIntersection(h1, h2 HailParam) (doIntersect bool) {
|
||||
log.Printf("intersecting %+v and %+v\n", h1, h2)
|
||||
x, y, intersectAtAll := IntersectByTwoPoints(h1, h2)
|
||||
if !intersectAtAll {
|
||||
log.Printf("no intersection at all\n")
|
||||
return false
|
||||
}
|
||||
if x < float64(CoordMin) || x > float64(CoordMax) ||
|
||||
y < float64(CoordMin) || y > float64(CoordMax) {
|
||||
log.Printf("intersect at %f %f but outside of area\n", x, y)
|
||||
return false // outside of area
|
||||
}
|
||||
isH1Future := h1.FloatPointInFuture(x,y)
|
||||
isH2Future := h2.FloatPointInFuture(x,y)
|
||||
|
||||
if !isH1Future {
|
||||
log.Printf("in the past for h1\n")
|
||||
}
|
||||
if !isH2Future {
|
||||
log.Printf("in the past for h2\n")
|
||||
}
|
||||
|
||||
if !isH1Future || !isH2Future {
|
||||
return false
|
||||
}
|
||||
|
||||
log.Println("intersect inside of the area")
|
||||
return true
|
||||
}
|
||||
|
||||
// in 2d only
|
||||
func IntersectByTwoPoints(h1, h2 HailParam) (intersectionX, intersectoinY float64, isIntersecting bool) {
|
||||
p1 := h1.p0
|
||||
p2 := h1.p1
|
||||
p3 := h2.p0
|
||||
p4 := h2.p1
|
||||
|
||||
denominator := (p1.x - p2.x)*(p3.y - p4.y) - (p1.y - p2.y)*(p3.x - p4.x)
|
||||
if denominator == 0 {
|
||||
return 0, 0, false
|
||||
}
|
||||
|
||||
divisibleX := (p1.x * p2.y - p1.y * p2.x)*(p3.x - p4.x) - (p1.x - p2.x)*(p3.x * p4.y - p3.y * p4.x)
|
||||
divisibleY := (p1.x * p2.y - p1.y * p2.x)*(p3.y - p4.y) - (p1.y - p2.y)*(p3.x * p4.y - p3.y * p4.x)
|
||||
|
||||
x := float64(divisibleX) / float64(denominator)
|
||||
y := float64(divisibleY) / float64(denominator)
|
||||
|
||||
return x, y, true
|
||||
}
|
||||
|
||||
func (h HailParam)PointInFuture(p Point) bool {
|
||||
xPositiveSteps := (p.x - h.p0.x) * h.Dx >= 0
|
||||
yPositiveSteps := (p.y - h.p0.y) * h.Dy >= 0
|
||||
zPositiveSteps := (p.Z - h.p0.Z) * h.Dz >= 0
|
||||
return xPositiveSteps && yPositiveSteps && zPositiveSteps
|
||||
}
|
||||
func (h HailParam)FloatPointInFuture(x, y float64) bool {
|
||||
xPositiveSteps := (x - float64(h.p0.x)) * float64(h.Dx) >= 0
|
||||
yPositiveSteps := (y - float64(h.p0.y)) * float64(h.Dy) >= 0
|
||||
return xPositiveSteps && yPositiveSteps
|
||||
}
|
||||
|
||||
// 19, 13, 30 @ -2, 1, -2
|
||||
func ReadHailLine(line string) (h HailParam) {
|
||||
h.line = line
|
||||
line = strings.ReplaceAll(line, "@", "")
|
||||
line = strings.ReplaceAll(line, ",", "")
|
||||
fields := strings.Fields(line)
|
||||
|
||||
h.p0.x = AtoIOrPanic(fields[0])
|
||||
h.p0.y = AtoIOrPanic(fields[1])
|
||||
h.p0.Z = AtoIOrPanic(fields[2])
|
||||
h.Dx = AtoIOrPanic(fields[3])
|
||||
h.Dy = AtoIOrPanic(fields[4])
|
||||
h.Dz = AtoIOrPanic(fields[5])
|
||||
|
||||
h.p1.x = h.p0.x + h.Dx
|
||||
h.p1.y = h.p0.y + h.Dy
|
||||
h.p1.Z = h.p0.Z + h.Dz
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func ReadHailFile(filename string) []HailParam {
|
||||
bytes, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
text := strings.TrimSpace(string(bytes))
|
||||
lines := strings.Split(text, "\n")
|
||||
result := make([]HailParam, len(lines))
|
||||
|
||||
for i, line := range lines {
|
||||
result[i] = ReadHailLine(line)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func AtoIOrPanic(str string) (num int) {
|
||||
num, err := strconv.Atoi(str)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user