Files
advent-of-code-2025/cmd/09/edge/edge.go
T

98 lines
2.6 KiB
Go

// Package edge provides a model and methods for representing and manipulating edges.
package edge
import (
"math"
"github.com/StevanFreeborn/advent-of-code-2025/cmd/09/rectangle"
"github.com/StevanFreeborn/advent-of-code-2025/internal/position"
)
type Edge interface {
Start() position.Position
End() position.Position
VerticallyContains(position.Position) bool
IntersectsHorizontalLineAt(position.Position) bool
Intersects(rect rectangle.Rectangle) bool
}
type edge struct {
start position.Position
end position.Position
totalHeight int
totalWidth int
minRow float64
maxRow float64
minColumn float64
maxColumn float64
}
func From(start position.Position, end position.Position) Edge {
totalHeight := int(math.Abs(float64(end.Row() - start.Row())))
totalWidth := int(math.Abs(float64(end.Column() - start.Column())))
minRow := math.Min(float64(start.Row()), float64(end.Row()))
maxRow := math.Max(float64(start.Row()), float64(end.Row()))
minColumn := math.Min(float64(start.Column()), float64(end.Column()))
maxColumn := math.Max(float64(start.Column()), float64(end.Column()))
return edge{
start: start,
end: end,
totalHeight: totalHeight,
totalWidth: totalWidth,
minRow: minRow,
maxRow: maxRow,
minColumn: minColumn,
maxColumn: maxColumn,
}
}
func (e edge) Start() position.Position {
return e.start
}
func (e edge) End() position.Position {
return e.end
}
func (e edge) VerticallyContains(p position.Position) bool {
return (e.start.Row() <= p.Row()) && (p.Row() <= e.end.Row())
}
func (e edge) IntersectsHorizontalLineAt(p position.Position) bool {
centerPercentageOfEdgeHeight := int(float64(p.Row()-e.start.Row()) / float64(e.totalHeight))
edgeColumnAtCenterRow := e.start.Column() + centerPercentageOfEdgeHeight*e.totalWidth
return p.Row() <= edgeColumnAtCenterRow
}
func (e edge) Intersects(rect rectangle.Rectangle) bool {
isVerticalEdge := e.start.Column() == e.end.Column()
if isVerticalEdge {
isRectBetweenEdgeColumns := e.start.Column() > rect.MinColumn() && e.start.Column() < rect.MaxColumn()
if isRectBetweenEdgeColumns {
overlapStart := int(math.Max(e.minRow, float64(rect.MinRow())))
overlapEnd := int(math.Min(e.maxRow, float64(rect.MaxRow())))
if overlapEnd > overlapStart {
return true
}
}
} else {
isRectBetweenEdgeRows := e.start.Row() > rect.MinRow() && e.start.Row() < rect.MaxRow()
if isRectBetweenEdgeRows {
overlapStart := int(math.Max(e.minColumn, float64(rect.MinColumn())))
overlapEnd := int(math.Min(e.maxColumn, float64(rect.MaxColumn())))
if overlapEnd > overlapStart {
return true
}
}
}
return false
}