2023-12-27 14:07:32 -07:00
|
|
|
package aoc
|
|
|
|
|
|
|
|
type Vector struct {
|
2024-01-01 09:52:49 -07:00
|
|
|
Offset Point[int]
|
2023-12-27 14:07:32 -07:00
|
|
|
Scale int
|
|
|
|
}
|
|
|
|
|
2024-01-01 09:52:49 -07:00
|
|
|
func (v Vector) Point() Point[int] {
|
2023-12-27 14:07:32 -07:00
|
|
|
return v.Offset.Scale(v.Scale)
|
|
|
|
}
|
|
|
|
|
2024-01-01 09:52:49 -07:00
|
|
|
type Point[T integer] [2]T
|
2023-12-27 14:07:32 -07:00
|
|
|
|
2024-01-01 09:52:49 -07:00
|
|
|
func (p Point[T]) Add(a Point[T]) Point[T] {
|
|
|
|
return Point[T]{p[0] + a[0], p[1] + a[1]}
|
2023-12-27 14:07:32 -07:00
|
|
|
}
|
2024-01-01 09:52:49 -07:00
|
|
|
func (p Point[T]) Scale(m T) Point[T] {
|
|
|
|
return Point[T]{p[0] * m, p[1] * m}
|
2023-12-27 14:07:32 -07:00
|
|
|
}
|
2024-01-01 09:52:49 -07:00
|
|
|
func (p Point[T]) Less(b Point[T]) bool {
|
2023-12-28 18:57:22 -07:00
|
|
|
if p[0] != b[0] {
|
|
|
|
return p[0] < b[0]
|
|
|
|
}
|
|
|
|
return p[1] < b[1]
|
|
|
|
}
|
2023-12-27 14:07:32 -07:00
|
|
|
|
|
|
|
func Transpose[T any](matrix [][]T) [][]T {
|
|
|
|
rows, cols := len(matrix), len(matrix[0])
|
|
|
|
|
|
|
|
m := make([][]T, cols)
|
|
|
|
for i := range m {
|
|
|
|
m[i] = make([]T, rows)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < cols; i++ {
|
|
|
|
for j := 0; j < rows; j++ {
|
|
|
|
m[i][j] = matrix[j][i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
|
|
|
// NumPoints the number of the points inside an outline plus the number of points in the outline
|
2024-01-01 09:52:49 -07:00
|
|
|
func NumPoints(outline []Point[int], borderLength int) int {
|
2023-12-27 14:07:32 -07:00
|
|
|
// shoelace - find the float area in a shape
|
|
|
|
sum := 0
|
|
|
|
for _, p := range Pairwise(outline) {
|
|
|
|
row1, col1 := p[0][0], p[0][1]
|
|
|
|
row2, col2 := p[1][0], p[1][1]
|
|
|
|
|
|
|
|
sum += row1*col2 - row2*col1
|
|
|
|
}
|
|
|
|
area := sum / 2
|
|
|
|
|
|
|
|
// pick's theorem - find the number of points in a shape given its area
|
|
|
|
return (ABS(area) - borderLength/2 + 1) + borderLength
|
|
|
|
}
|
2023-12-28 18:57:22 -07:00
|
|
|
|
2024-01-01 09:52:49 -07:00
|
|
|
type Map[I integer, T any] [][]T
|
2023-12-28 18:57:22 -07:00
|
|
|
|
2024-01-01 09:52:49 -07:00
|
|
|
func (m *Map[I,T]) Get(p Point[I]) (Point[I], T, bool) {
|
2023-12-28 18:57:22 -07:00
|
|
|
var zero T
|
|
|
|
if !m.Valid(p) {
|
2024-01-01 09:52:49 -07:00
|
|
|
return [2]I{0, 0}, zero, false
|
2023-12-28 18:57:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return p, (*m)[p[0]][p[1]], true
|
|
|
|
}
|
2024-01-01 09:52:49 -07:00
|
|
|
func (m *Map[I,T]) Size() (I, I) {
|
2023-12-28 18:57:22 -07:00
|
|
|
if m == nil || len(*m) == 0 {
|
|
|
|
return 0, 0
|
|
|
|
}
|
2024-01-01 09:52:49 -07:00
|
|
|
return I(len(*m)), I(len((*m)[0]))
|
2023-12-28 18:57:22 -07:00
|
|
|
}
|
2024-01-01 09:52:49 -07:00
|
|
|
func (m *Map[I,T]) Valid(p Point[I]) bool {
|
2023-12-28 18:57:22 -07:00
|
|
|
rows, cols := m.Size()
|
|
|
|
return p[0] >= 0 && p[0] < rows && p[1] >= 0 && p[1] < cols
|
|
|
|
}
|