2023 Day 21 Complete
This commit is contained in:
@@ -17,6 +17,10 @@ type CoordByteMap struct {
|
||||
// Options for the 'String' method
|
||||
StringEmptyIsSpace bool
|
||||
StringEmptyByte byte
|
||||
|
||||
// If 'Repeats' is true, then any coordinate request will be
|
||||
// modded by BRX/BRY
|
||||
Repeats bool
|
||||
}
|
||||
|
||||
func NewCoordByteMap() CoordByteMap {
|
||||
@@ -49,6 +53,9 @@ func (m *CoordByteMap) ColCount() int {
|
||||
return m.BRX - m.TLX
|
||||
}
|
||||
func (m *CoordByteMap) GetRow(y int) []byte {
|
||||
if m.Repeats {
|
||||
y = (y + m.BRY) % m.BRY
|
||||
}
|
||||
var resp []byte
|
||||
for x := m.TLX; x <= m.BRX; x++ {
|
||||
resp = append(resp, m.Get(Coordinate{X: x, Y: y}))
|
||||
@@ -56,6 +63,9 @@ func (m *CoordByteMap) GetRow(y int) []byte {
|
||||
return resp
|
||||
}
|
||||
func (m *CoordByteMap) GetCol(x int) []byte {
|
||||
if m.Repeats {
|
||||
x = (x + m.BRX) % m.BRX
|
||||
}
|
||||
var resp []byte
|
||||
for y := m.TLY; y <= m.BRY; y++ {
|
||||
resp = append(resp, m.Get(Coordinate{X: x, Y: y}))
|
||||
@@ -76,10 +86,18 @@ func (m *CoordByteMap) AddCol(col []byte) {
|
||||
}
|
||||
|
||||
func (m *CoordByteMap) GetPos(x, y int) byte {
|
||||
if m.Repeats {
|
||||
x = (x + m.BRX) % m.BRX
|
||||
y = (y + m.BRY) % m.BRY
|
||||
}
|
||||
return m.Get(Coordinate{X: x, Y: y})
|
||||
}
|
||||
|
||||
func (m *CoordByteMap) Get(pos Coordinate) byte {
|
||||
if m.Repeats {
|
||||
pos.X = (pos.X + m.BRX) % m.BRX
|
||||
pos.Y = (pos.Y + m.BRY) % m.BRY
|
||||
}
|
||||
if v, ok := m.Field[pos]; ok {
|
||||
return v
|
||||
}
|
||||
@@ -87,6 +105,10 @@ func (m *CoordByteMap) Get(pos Coordinate) byte {
|
||||
}
|
||||
|
||||
func (m *CoordByteMap) Opt(pos Coordinate, def byte) byte {
|
||||
if m.Repeats {
|
||||
pos.X = (pos.X + m.BRX) % m.BRX
|
||||
pos.Y = (pos.Y + m.BRY) % m.BRY
|
||||
}
|
||||
if v, ok := m.Field[pos]; ok {
|
||||
return v
|
||||
}
|
||||
@@ -110,6 +132,10 @@ func (m *CoordByteMap) Put(pos Coordinate, val byte) {
|
||||
}
|
||||
|
||||
func (m *CoordByteMap) Delete(pos Coordinate) {
|
||||
if m.Repeats {
|
||||
pos.X = (pos.X + m.BRX) % m.BRX
|
||||
pos.Y = (pos.Y + m.BRY) % m.BRY
|
||||
}
|
||||
delete(m.Field, pos)
|
||||
}
|
||||
|
||||
@@ -135,6 +161,10 @@ func (m *CoordByteMap) ToByteSlices() [][]byte {
|
||||
// ContainsCoord returns true if the passed coordinate is within the bounds
|
||||
// of the map
|
||||
func (m *CoordByteMap) ContainsCoord(c Coordinate) bool {
|
||||
if m.Repeats {
|
||||
c.X = (c.X + m.BRX) % m.BRX
|
||||
c.Y = (c.Y + m.BRY) % m.BRY
|
||||
}
|
||||
return c.X >= m.TLX && c.X <= m.BRX &&
|
||||
c.Y >= m.TLY && c.Y <= m.BRY
|
||||
}
|
||||
|
62
helpers/priorityQueue.go
Normal file
62
helpers/priorityQueue.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package aoc
|
||||
|
||||
type PriorityQueue[T comparable] struct {
|
||||
items []T
|
||||
comparator func(a, b T) int
|
||||
}
|
||||
|
||||
func NewPriorityQueue[T comparable](comparator func(a, b T) int) PriorityQueue[T] {
|
||||
return PriorityQueue[T]{comparator: comparator}
|
||||
}
|
||||
func (pq *PriorityQueue[T]) Push(item T) {
|
||||
pq.items = append(pq.items, item)
|
||||
pq.heapifyUp(len(pq.items) - 1)
|
||||
}
|
||||
func (pq *PriorityQueue[T]) Pop() T {
|
||||
top := pq.items[0]
|
||||
lastIndex := len(pq.items) - 1
|
||||
pq.items[0], pq.items[lastIndex] = pq.items[lastIndex], pq.items[0]
|
||||
pq.items = pq.items[:lastIndex]
|
||||
pq.heapifyDown(0)
|
||||
return top
|
||||
}
|
||||
func (pq *PriorityQueue[T]) Peek() T {
|
||||
return pq.items[0]
|
||||
}
|
||||
func (pq *PriorityQueue[T]) Len() int {
|
||||
return len(pq.items)
|
||||
}
|
||||
func (pq *PriorityQueue[T]) IsEmpty() bool {
|
||||
return len(pq.items) == 0
|
||||
}
|
||||
func (pq *PriorityQueue[T]) IsNotEmpty() bool {
|
||||
return !pq.IsEmpty()
|
||||
}
|
||||
func (pq *PriorityQueue[T]) heapifyUp(index int) {
|
||||
for index > 0 {
|
||||
parentIndex := (index - 1) / 2
|
||||
if pq.comparator(pq.items[index], pq.items[parentIndex]) < 0 {
|
||||
pq.items[index], pq.items[parentIndex] = pq.items[parentIndex], pq.items[index]
|
||||
index = parentIndex
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
func (pq *PriorityQueue[T]) heapifyDown(index int) {
|
||||
for {
|
||||
leftChild, rightChild, smallest := 2*index+1, 2*index+2, index
|
||||
if leftChild < len(pq.items) && pq.comparator(pq.items[leftChild], pq.items[smallest]) < 0 {
|
||||
smallest = leftChild
|
||||
}
|
||||
if rightChild < len(pq.items) && pq.comparator(pq.items[rightChild], pq.items[smallest]) < 0 {
|
||||
smallest = rightChild
|
||||
}
|
||||
if smallest != index {
|
||||
pq.items[index], pq.items[smallest] = pq.items[smallest], pq.items[index]
|
||||
index = smallest
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
78
helpers/queue.go
Normal file
78
helpers/queue.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package aoc
|
||||
|
||||
type Queue[T comparable] struct {
|
||||
items []T
|
||||
}
|
||||
|
||||
func NewQueue[T comparable](items []T) *Queue[T] {
|
||||
return &Queue[T]{
|
||||
items: items,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Queue[T]) Len() int {
|
||||
return len(q.items)
|
||||
}
|
||||
|
||||
func (q *Queue[T]) Push(item T) {
|
||||
q.items = append(q.items, item)
|
||||
}
|
||||
func (q *Queue[T]) Pop() T {
|
||||
var x T
|
||||
x, q.items = q.items[len(q.items)-1], q.items[:len(q.items)-1]
|
||||
return x
|
||||
}
|
||||
func (q *Queue[T]) Unshift(item T) {
|
||||
q.items = append([]T{item}, q.items...)
|
||||
}
|
||||
func (q *Queue[T]) Shift() T {
|
||||
var x T
|
||||
x, q.items = q.items[0], q.items[1:]
|
||||
return x
|
||||
}
|
||||
|
||||
func (q *Queue[T]) Append(items []T) {
|
||||
q.items = append(q.items, items...)
|
||||
}
|
||||
func (q *Queue[T]) Copy() *Queue[T] {
|
||||
ret := &Queue[T]{
|
||||
items: make([]T, len(q.items)),
|
||||
}
|
||||
copy(ret.items, q.items)
|
||||
return ret
|
||||
}
|
||||
func (q *Queue[T]) Cut(at, count int) []T {
|
||||
ret := q.items[at : at+count]
|
||||
q.items = append(q.items[:at], q.items[at+count:]...)
|
||||
return ret
|
||||
}
|
||||
func (q *Queue[T]) Delete(item T) {
|
||||
for i := range q.items {
|
||||
if q.items[i] == item {
|
||||
q.items = append(q.items[:i], q.items[i+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
func (q *Queue[T]) Expand(at, by int) {
|
||||
q.items = append(q.items[:at], append(make([]T, by), q.items[at:]...)...)
|
||||
}
|
||||
func (q *Queue[T]) Extend(by int) {
|
||||
q.items = append(q.items, make([]T, by)...)
|
||||
}
|
||||
func (q *Queue[T]) FilterInPlace(keep func(item T) bool) {
|
||||
n := 0
|
||||
for _, x := range q.items {
|
||||
if keep(x) {
|
||||
q.items[n] = x
|
||||
n++
|
||||
}
|
||||
}
|
||||
q.items = q.items[:n]
|
||||
}
|
||||
func (q *Queue[T]) Insert(item T, location int) {
|
||||
q.InsertVector([]T{item}, location)
|
||||
}
|
||||
func (q *Queue[T]) InsertVector(items []T, location int) {
|
||||
q.items = append(q.items[:location], append(items, q.items[location:]...)...)
|
||||
}
|
Reference in New Issue
Block a user