2018-12-03 19:40:42 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
MaxInt = int(^uint(0) >> 1)
|
|
|
|
MinInt = -MaxInt - 1
|
|
|
|
)
|
|
|
|
|
|
|
|
var timeMachine *TimeMachine
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
if len(os.Args) < 2 {
|
|
|
|
fmt.Println("Usage: day11 <serial #>")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
timeMachine = &TimeMachine{
|
|
|
|
serial: Atoi(os.Args[1]),
|
|
|
|
fuelLevels: make(map[string]int),
|
|
|
|
}
|
2018-12-03 21:30:30 +00:00
|
|
|
timeMachine.fillGrid()
|
|
|
|
part1()
|
|
|
|
part2()
|
|
|
|
}
|
|
|
|
|
|
|
|
func part1() {
|
|
|
|
top := MinInt
|
|
|
|
topX, topY := 0, 0
|
|
|
|
for i := 1; i < 300; i++ {
|
|
|
|
for j := 1; j < 300; j++ {
|
|
|
|
w := timeMachine.getSquareFuelLevel(i, j, 3)
|
|
|
|
if w > top {
|
|
|
|
top = w
|
|
|
|
topX, topY = i, j
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt.Printf("%d,%d : %d\n", topX, topY, top)
|
|
|
|
fmt.Println("= Part 1 =")
|
|
|
|
timeMachine.printSquare(topX, topY, 3)
|
|
|
|
}
|
|
|
|
|
|
|
|
func part2() {
|
|
|
|
top := MinInt
|
|
|
|
topX, topY, topS := 1, 1, 1
|
|
|
|
for i := 1; i <= 300; i++ {
|
|
|
|
for j := 1; j <= 300; j++ {
|
|
|
|
maxSize := 300 - (i - 1)
|
|
|
|
if i < j {
|
|
|
|
maxSize = 300 - (j - 1)
|
|
|
|
}
|
|
|
|
for s := 1; s <= maxSize; s++ {
|
|
|
|
wrk := timeMachine.getSquareFuelLevel(i, j, s)
|
|
|
|
if wrk > top {
|
|
|
|
top = wrk
|
|
|
|
topX, topY, topS = i, j, s
|
2018-12-03 19:40:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-12-03 21:30:30 +00:00
|
|
|
fmt.Println("= Part 2 =")
|
|
|
|
fmt.Printf("%d,%d,%d : %d\n", topX, topY, topS, top)
|
2018-12-03 19:40:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type TimeMachine struct {
|
|
|
|
serial int
|
|
|
|
fuelLevels map[string]int
|
|
|
|
}
|
|
|
|
|
2018-12-03 21:30:30 +00:00
|
|
|
func (t *TimeMachine) printSquare(x, y, size int) {
|
|
|
|
for j := y; j < y+size; j++ {
|
|
|
|
for i := x; i < x+size; i++ {
|
|
|
|
fmt.Printf("%2d ", t.getSquareFuelLevel(i, j, 1))
|
|
|
|
}
|
|
|
|
fmt.Println("")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TimeMachine) fillGrid() {
|
|
|
|
for i := 1; i <= 300; i++ {
|
|
|
|
for j := 1; j <= 300; j++ {
|
|
|
|
t.fuelLevels[t.getKeyForSquare(i, j, 1)] = t.calcFuelLevel(i, j)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-03 19:40:42 +00:00
|
|
|
func (t *TimeMachine) getKeyForSquare(x, y, size int) string {
|
|
|
|
bx := strconv.Itoa(x)
|
|
|
|
by := strconv.Itoa(y)
|
|
|
|
bs := strconv.Itoa(size)
|
|
|
|
return bx + "," + by + "," + bs
|
|
|
|
}
|
|
|
|
|
2018-12-13 01:17:16 +00:00
|
|
|
func (t *TimeMachine) getSquareFuelLevel(x, y, size int) int {
|
|
|
|
k := t.getKeyForSquare(x, y, size)
|
|
|
|
if v, ok := t.fuelLevels[k]; ok {
|
|
|
|
return v
|
2018-12-03 19:40:42 +00:00
|
|
|
}
|
|
|
|
if size == 1 {
|
2018-12-03 21:30:30 +00:00
|
|
|
// We shouldn't be here if we filled the grid before running
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
var ret int
|
|
|
|
ret = t.getSquareFuelLevel(x, y, size-1)
|
|
|
|
// Add the right-most cells
|
|
|
|
for i := 0; i < size; i++ {
|
|
|
|
ret += t.calcFuelLevel(x+(size-1), y+i)
|
|
|
|
}
|
|
|
|
// Add the bottom cells
|
|
|
|
for i := 0; i < size-1; i++ {
|
|
|
|
ret += t.calcFuelLevel(x+i, y+(size-1))
|
2018-12-03 19:40:42 +00:00
|
|
|
}
|
2018-12-13 01:17:16 +00:00
|
|
|
t.fuelLevels[k] = ret
|
2018-12-03 19:40:42 +00:00
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2018-12-13 01:17:16 +00:00
|
|
|
// calcFuelLevel calculates one cells fuel level
|
2018-12-03 19:40:42 +00:00
|
|
|
func (t *TimeMachine) calcFuelLevel(x, y int) int {
|
|
|
|
rackId := x + 10
|
|
|
|
startingLevel := rackId * y
|
|
|
|
currLevel := startingLevel + t.serial
|
|
|
|
currLevel *= rackId
|
|
|
|
var ret int
|
|
|
|
if currLevel < 100 {
|
|
|
|
ret = -5
|
|
|
|
} else {
|
|
|
|
ret = ((currLevel / 100) % 10) - 5
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2018-12-13 01:17:16 +00:00
|
|
|
// calcSquareFuelLevel calculates all cells from x, y -> x+size, y+size
|
2018-12-03 19:49:23 +00:00
|
|
|
func (t *TimeMachine) calcSquareFuelLevel(x, y, size int) int {
|
2018-12-03 19:40:42 +00:00
|
|
|
var ret int
|
|
|
|
for i := 0; i < size; i++ {
|
|
|
|
for j := 0; j < size; j++ {
|
2018-12-13 01:17:16 +00:00
|
|
|
ret += t.calcFuelLevel(x+i, y+j)
|
2018-12-03 19:40:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
func Atoi(i string) int {
|
|
|
|
var ret int
|
|
|
|
var err error
|
|
|
|
if ret, err = strconv.Atoi(i); err != nil {
|
|
|
|
log.Fatal("Invalid Atoi")
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|