Day 13 solution
This commit is contained in:
183
thirteen/manual.go
Normal file
183
thirteen/manual.go
Normal file
@@ -0,0 +1,183 @@
|
||||
package thirteen
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type axis rune
|
||||
|
||||
const (
|
||||
x axis = 'x'
|
||||
y axis = 'y'
|
||||
)
|
||||
|
||||
type fold struct {
|
||||
axis axis
|
||||
index int
|
||||
}
|
||||
|
||||
type manual struct {
|
||||
dots map[int]map[int]bool
|
||||
folds []fold
|
||||
}
|
||||
|
||||
func (m *manual) load(filename string) error {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
m.dots = map[int]map[int]bool{}
|
||||
m.folds = []fold{}
|
||||
scanningDots := true
|
||||
for scanner.Scan() {
|
||||
if scanner.Text() == "" {
|
||||
scanningDots = false
|
||||
continue
|
||||
}
|
||||
|
||||
if scanningDots {
|
||||
var dotX, dotY int
|
||||
if count, err := fmt.Sscanf(scanner.Text(), "%d,%d", &dotX, &dotY); count != 2 || err != nil {
|
||||
return fmt.Errorf("expected 2 values, found %d: %w", count, err)
|
||||
}
|
||||
|
||||
if m.dots[dotX] == nil {
|
||||
m.dots[dotX] = map[int]bool{}
|
||||
}
|
||||
|
||||
m.dots[dotX][dotY] = true
|
||||
} else {
|
||||
var foldAxis axis
|
||||
var foldIndex int
|
||||
|
||||
if count, err := fmt.Sscanf(scanner.Text(), "fold along %c=%d", &foldAxis, &foldIndex); count != 2 || err != nil {
|
||||
return fmt.Errorf("scanning %q, expected 2 values, found %d: %w", scanner.Text(), count, err)
|
||||
}
|
||||
|
||||
m.folds = append(m.folds, fold{
|
||||
axis: foldAxis,
|
||||
index: foldIndex,
|
||||
})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func gridSize(grid map[int]map[int]bool) (xSize, ySize int) {
|
||||
for x, col := range grid {
|
||||
if x > xSize {
|
||||
xSize = x
|
||||
}
|
||||
for y := range col {
|
||||
if y > ySize {
|
||||
ySize = y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // Increment Size to reflect 0 indexed arrays
|
||||
xSize++
|
||||
ySize++
|
||||
|
||||
return xSize, ySize
|
||||
}
|
||||
|
||||
func countDots(grid map[int]map[int]bool) int {
|
||||
dots := 0
|
||||
for _, col := range grid {
|
||||
for _, v := range col {
|
||||
if v {
|
||||
dots++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dots
|
||||
}
|
||||
|
||||
func (m *manual) fold() {
|
||||
grid := m.dots
|
||||
|
||||
for _, inst := range m.folds {
|
||||
grid, _ = foldGrid(inst, grid)
|
||||
}
|
||||
|
||||
printGrid(grid)
|
||||
}
|
||||
|
||||
func foldGrid(inst fold, grid map[int]map[int]bool) (map[int]map[int]bool, int) {
|
||||
newGrid := map[int]map[int]bool{}
|
||||
|
||||
maxX, maxY := gridSize(grid)
|
||||
if inst.axis == x {
|
||||
// Copy the first rows
|
||||
for copyX := 0; copyX < inst.index; copyX++ {
|
||||
if newGrid[copyX] == nil {
|
||||
newGrid[copyX] = map[int]bool{}
|
||||
}
|
||||
|
||||
for copyY := 0; copyY < maxY; copyY++ {
|
||||
newGrid[copyX][copyY] = grid[copyX][copyY]
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the folded values
|
||||
for foldX := inst.index + 1; foldX < maxX; foldX++ {
|
||||
targetX := inst.index - (foldX - inst.index)
|
||||
for targetY := 0; targetY < maxY; targetY++ {
|
||||
if grid[foldX][targetY] {
|
||||
newGrid[targetX][targetY] = grid[foldX][targetY]
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// initialize all X maps
|
||||
for k := range grid {
|
||||
newGrid[k] = map[int]bool{}
|
||||
}
|
||||
|
||||
// Copy the first rows
|
||||
for copyY := 0; copyY < inst.index; copyY++ {
|
||||
for copyX := 0; copyX < maxX; copyX++ {
|
||||
if newGrid[copyX] == nil {
|
||||
newGrid[copyX] = map[int]bool{}
|
||||
}
|
||||
|
||||
newGrid[copyX][copyY] = grid[copyX][copyY]
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the folded values
|
||||
for foldY := inst.index + 1; foldY < maxY; foldY++ {
|
||||
targetY := inst.index - (foldY - inst.index)
|
||||
for targetX := 0; targetX < maxX; targetX++ {
|
||||
if grid[targetX][foldY] {
|
||||
newGrid[targetX][targetY] = grid[targetX][foldY]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newGrid, countDots(newGrid)
|
||||
}
|
||||
|
||||
func printGrid(grid map[int]map[int]bool) {
|
||||
maxX, maxY := gridSize(grid)
|
||||
|
||||
for y := 0; y < maxY; y++ {
|
||||
row := ""
|
||||
for x := 0; x < maxX; x++ {
|
||||
if grid[x][y] {
|
||||
row += "#"
|
||||
} else {
|
||||
row += " "
|
||||
}
|
||||
}
|
||||
fmt.Println(row)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user