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 > ret.Width { ret.Width = x } } } 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 } 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 }