175 lines
3.3 KiB
Go
175 lines
3.3 KiB
Go
package aoc
|
|
|
|
type CoordByteMap struct {
|
|
Field map[Coordinate]byte
|
|
Height int
|
|
Width int
|
|
}
|
|
|
|
func StringSliceToCoordByteMap(input []string) CoordByteMap {
|
|
ret := CoordByteMap{
|
|
Field: make(map[Coordinate]byte),
|
|
Height: len(input),
|
|
Width: 0,
|
|
}
|
|
for y := range input {
|
|
for x := range input[y] {
|
|
ret.Field[Coordinate{X: x, Y: y}] = input[y][x]
|
|
if x+1 > ret.Width {
|
|
ret.Width = x + 1
|
|
}
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (m *CoordByteMap) Get(pos Coordinate) byte {
|
|
if v, ok := m.Field[pos]; ok {
|
|
return v
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func (m *CoordByteMap) Opt(pos Coordinate, def byte) byte {
|
|
if v, ok := m.Field[pos]; ok {
|
|
return v
|
|
}
|
|
return def
|
|
}
|
|
|
|
func (m *CoordByteMap) Put(pos Coordinate, val byte) {
|
|
m.Field[pos] = val
|
|
if pos.X+1 > m.Width {
|
|
m.Width = pos.X + 1
|
|
}
|
|
if pos.Y+1 > m.Height {
|
|
m.Height = pos.Y + 1
|
|
}
|
|
}
|
|
|
|
func (m CoordByteMap) String() string {
|
|
var ret string
|
|
for y := 0; y <= m.Height; y++ {
|
|
for x := 0; x <= m.Width; x++ {
|
|
ret = ret + string(m.Field[Coordinate{X: x, Y: y}])
|
|
}
|
|
ret = ret + "\n"
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// And the 3d Version
|
|
type Coord3dByteMap struct {
|
|
Field map[Coordinate3d]byte
|
|
MinX, MaxX int
|
|
MinY, MaxY int
|
|
MinZ, MaxZ int
|
|
}
|
|
|
|
func StringSliceToCoord3dByteMap(input []string) Coord3dByteMap {
|
|
ret := Coord3dByteMap{
|
|
Field: make(map[Coordinate3d]byte),
|
|
}
|
|
for y := range input {
|
|
for x := range input[y] {
|
|
ret.Put(Coordinate3d{X: x, Y: y, Z: 0}, input[y][x])
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (m *Coord3dByteMap) Copy() Coord3dByteMap {
|
|
ret := Coord3dByteMap{
|
|
Field: make(map[Coordinate3d]byte),
|
|
MinX: m.MinX, MaxX: m.MaxX,
|
|
MinY: m.MinY, MaxY: m.MaxY,
|
|
MinZ: m.MinZ, MaxZ: m.MaxZ,
|
|
}
|
|
for z := m.MinZ; z <= m.MaxZ; z++ {
|
|
for y := m.MinY; y <= m.MaxY; y++ {
|
|
for x := m.MinX; x <= m.MaxX; x++ {
|
|
c := Coordinate3d{X: x, Y: y, Z: z}
|
|
ret.Field[c] = m.Get(c)
|
|
}
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (m *Coord3dByteMap) Get(pos Coordinate3d) byte {
|
|
if _, ok := m.Field[pos]; !ok {
|
|
return 0
|
|
}
|
|
return m.Field[pos]
|
|
}
|
|
func (m *Coord3dByteMap) Opt(pos Coordinate3d, def byte) byte {
|
|
if v, ok := m.Field[pos]; ok {
|
|
return v
|
|
}
|
|
return def
|
|
}
|
|
|
|
func (m *Coord3dByteMap) Put(pos Coordinate3d, val byte) {
|
|
m.Field[pos] = val
|
|
if pos.X < m.MinX {
|
|
m.MinX = pos.X
|
|
}
|
|
if pos.X > m.MaxX {
|
|
m.MaxX = pos.X
|
|
}
|
|
if pos.Y < m.MinY {
|
|
m.MinY = pos.X
|
|
}
|
|
if pos.Y > m.MaxY {
|
|
m.MaxY = pos.Y
|
|
}
|
|
if pos.Z < m.MinZ {
|
|
m.MinZ = pos.Z
|
|
}
|
|
if pos.Z > m.MaxZ {
|
|
m.MaxZ = pos.Z
|
|
}
|
|
}
|
|
|
|
func (m *Coord3dByteMap) CountNeighbors(pos Coordinate3d, val byte) int {
|
|
var res int
|
|
for z := pos.Z - 1; z <= pos.Z+1; z++ {
|
|
for y := pos.Y - 1; y <= pos.Y+1; y++ {
|
|
for x := pos.X - 1; x <= pos.X+1; x++ {
|
|
if m.Get(Coordinate3d{X: x, Y: y, Z: z}) == val {
|
|
res++
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res
|
|
}
|
|
|
|
func (m Coord3dByteMap) Count(val byte) int {
|
|
var ret int
|
|
for z := m.MinZ; z <= m.MaxZ; z++ {
|
|
for y := m.MinY; y <= m.MaxY; y++ {
|
|
for x := m.MinX; x <= m.MaxX; x++ {
|
|
if m.Get(Coordinate3d{X: x, Y: y, Z: z}) == val {
|
|
ret++
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (m Coord3dByteMap) String() string {
|
|
var ret string
|
|
for z := m.MinZ; z <= m.MaxZ; z++ {
|
|
for y := m.MinY; y <= m.MaxY; y++ {
|
|
for x := m.MinX; x <= m.MaxX; x++ {
|
|
ret = ret + string(m.Field[Coordinate3d{X: x, Y: y, Z: z}])
|
|
}
|
|
ret = ret + "\n"
|
|
}
|
|
ret = ret + "\n\n"
|
|
}
|
|
return ret
|
|
}
|