113 lines
2.2 KiB
Go
113 lines
2.2 KiB
Go
package aoc
|
|
|
|
import (
|
|
"math"
|
|
)
|
|
|
|
type GrowUpCoordByteMap struct {
|
|
Field map[Coordinate]byte
|
|
Height int
|
|
Width int
|
|
// The Top-Left-most X/Y
|
|
// (Low X, High Y)
|
|
TLX, TLY int
|
|
// The Bottom-Right-most X/Y
|
|
// (High X, Low Y)
|
|
BRX, BRY int
|
|
|
|
// Options for the 'String' method
|
|
StringEmptyIsSpace bool
|
|
StringEmptyByte byte
|
|
}
|
|
|
|
func NewGrowUpCoordByteMap() *GrowUpCoordByteMap {
|
|
return &GrowUpCoordByteMap{
|
|
Field: make(map[Coordinate]byte),
|
|
TLX: math.MaxInt,
|
|
TLY: math.MinInt,
|
|
BRX: math.MinInt,
|
|
BRY: math.MaxInt,
|
|
StringEmptyByte: ' ',
|
|
}
|
|
}
|
|
|
|
func (m *GrowUpCoordByteMap) FindAll(b ...byte) []Coordinate {
|
|
var ret []Coordinate
|
|
for y := m.TLY; y >= m.BRY; y-- {
|
|
for x := m.TLX; x <= m.BRX; x++ {
|
|
c := Coordinate{X: x, Y: y}
|
|
for i := range b {
|
|
if m.Get(c) == b[i] {
|
|
ret = append(ret, c)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (m *GrowUpCoordByteMap) Get(pos Coordinate) byte {
|
|
if v, ok := m.Field[pos]; ok {
|
|
return v
|
|
}
|
|
return 0
|
|
}
|
|
func (m *GrowUpCoordByteMap) Opt(pos Coordinate, def byte) byte {
|
|
if v, ok := m.Field[pos]; ok {
|
|
return v
|
|
}
|
|
return def
|
|
}
|
|
func (m *GrowUpCoordByteMap) Put(pos Coordinate, val byte) {
|
|
m.Field[pos] = val
|
|
m.Measure()
|
|
}
|
|
func (m *GrowUpCoordByteMap) PutBytes(bytes [][]byte, at Coordinate) {
|
|
for y := range bytes {
|
|
for x := range bytes[y] {
|
|
m.Put(Coordinate{X: at.X + x, Y: at.Y + y}, bytes[y][x])
|
|
}
|
|
}
|
|
m.Measure()
|
|
}
|
|
func (m *GrowUpCoordByteMap) Delete(pos Coordinate) {
|
|
delete(m.Field, pos)
|
|
m.Measure()
|
|
}
|
|
func (m *GrowUpCoordByteMap) Measure() {
|
|
m.TLX, m.TLY = math.MaxInt, math.MinInt
|
|
m.BRX, m.BRY = math.MinInt, math.MaxInt
|
|
for c := range m.Field {
|
|
if c.X < m.TLX {
|
|
m.TLX = c.X
|
|
}
|
|
if c.Y < m.BRY {
|
|
m.BRY = c.Y
|
|
}
|
|
if c.X > m.BRX {
|
|
m.BRX = c.X
|
|
}
|
|
if c.Y > m.TLY {
|
|
m.TLY = c.Y
|
|
}
|
|
m.Width = m.BRX - m.TLX + 1
|
|
m.Height = m.TLY - m.BRY + 1
|
|
}
|
|
}
|
|
func (m GrowUpCoordByteMap) String() string {
|
|
var ret string
|
|
for y := m.TLY; y >= m.BRY; y-- {
|
|
for x := m.TLX; x <= m.BRX; x++ {
|
|
if m.StringEmptyIsSpace {
|
|
ret = ret + string(m.Opt(Coordinate{X: x, Y: y}, m.StringEmptyByte))
|
|
} else {
|
|
ret = ret + string(m.Field[Coordinate{X: x, Y: y}])
|
|
}
|
|
}
|
|
if y > m.BRY {
|
|
ret = ret + "\n"
|
|
}
|
|
}
|
|
return ret
|
|
}
|