package main
import (
"fmt"
"strings"
)
const (
gridX = 300
gridY = 300
)
var gridSize = gridX * gridY
type Puzzle struct {
Serial int
Cells []int
}
func FuelAtCell(serial, x, y int) int {
id := x + 10
fuel := id * y
fuel += serial
fuel *= id
fuel /= 100
fuel %= 10
fuel &= 0xf
fuel -= 5
return fuel
}
func NewPuzzle(serial int) Puzzle {
p := Puzzle{
Serial: serial,
Cells: make([]int, gridSize),
}
for y := 1; y < gridY+1; y++ {
for x := 1; x < gridX+1; x++ {
i := ((y - 1) * gridX) + (x - 1)
p.Cells[i] = FuelAtCell(p.Serial, x, y)
}
}
return p
}
func (p Puzzle) String() string {
output := strings.Builder{}
for y := 0; y < gridY; y++ {
for x := 0; x < gridX; x++ {
i := (y * gridX) + x
output.WriteString(fmt.Sprintf("%3d", p.Cells[i]))
}
output.WriteByte('\n')
}
return output.String()
}
func (p *Puzzle) Solution1() (int, int) {
var rx, ry int
largest := 0
for y := 0; y < gridY-3; y++ {
for x := 0; x < gridX-3; x++ {
total := 0
for yy := y; yy < y+3; yy++ {
for xx := x; xx < x+3; xx++ {
i := (yy * gridY) + xx
total += p.Cells[i]
}
}
if total > largest {
largest = total
rx = x + 1
ry = y + 1
}
}
}
return rx, ry
}
func (p *Puzzle) Solution2() (int, int, int) {
var rx, ry int
largestTotal := 0
largestGrid := 0
type chanStruct struct {
total int
x, y, s int
}
done := make(chan chanStruct)
for grid := 0; grid < 300; grid++ {
go (func(grid int) {
var rx, ry int
largestTotal := 0
fmt.Printf("Grid %dx%d\n", grid, grid)
for y := 0; y < gridY-grid; y++ {
for x := 0; x < gridX-grid; x++ {
total := 0
for yy := y; yy < y+grid; yy++ {
for xx := x; xx < x+grid; xx++ {
i := (yy * gridY) + xx
total += p.Cells[i]
}
}
if total > largestTotal {
largestTotal = total
rx = x + 1
ry = y + 1
}
}
}
done <- chanStruct{
total: largestTotal,
x: rx,
y: ry,
s: grid,
}
})(grid)
}
count := 0
for count < 300 {
result := <-done
if result.total > largestTotal {
largestTotal = result.total
largestGrid = result.s
rx = result.x
ry = result.y
}
fmt.Printf("%d %dx%d -> %d,%d(%d)\n", count, result.s, result.s, result.x, result.y, result.total)
count++
}
return rx, ry, largestGrid
}
func main() {
p := NewPuzzle(7315)
// p := NewPuzzle(42)
fmt.Println(p.Solution1())
fmt.Println(p.Solution2())
}