239 lines
4.4 KiB
Go
239 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
"image/png"
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
const FILE_PATH = "./input.txt"
|
|
const WIDTH = 101
|
|
const HEIGHT = 103
|
|
|
|
//const FILE_PATH = "./sample.txt"
|
|
//const WIDTH = 11
|
|
//const HEIGHT = 7
|
|
|
|
func LoadInput(filename string) ([]string, error) {
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer file.Close()
|
|
|
|
var lines []string
|
|
scanner := bufio.NewScanner(file)
|
|
for scanner.Scan() {
|
|
lines = append(lines, scanner.Text())
|
|
}
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return lines, nil
|
|
}
|
|
|
|
type Vector2 struct {
|
|
x int
|
|
y int
|
|
}
|
|
|
|
type Robot struct {
|
|
p Vector2
|
|
v Vector2
|
|
}
|
|
|
|
type structuredInput = []Robot
|
|
|
|
func TransformInput(lines []string) structuredInput {
|
|
var result = make([]Robot, 0)
|
|
var j int
|
|
var m int
|
|
var numbX int
|
|
var numbY int
|
|
var position Vector2
|
|
var temp Robot
|
|
for i := 0; i < len(lines); i++ {
|
|
j = 2
|
|
for ; j < len(lines[i]); j++ {
|
|
if lines[i][j] == ',' {
|
|
break
|
|
}
|
|
}
|
|
|
|
numbX, _ = strconv.Atoi(lines[i][2:j])
|
|
m = j + 1
|
|
for ; j < len(lines[i]); j++ {
|
|
if lines[i][j] == ' ' {
|
|
break
|
|
}
|
|
}
|
|
numbY, _ = strconv.Atoi(lines[i][m:j])
|
|
|
|
position = Vector2{numbX, numbY}
|
|
|
|
m = j + 3
|
|
|
|
for ; j < len(lines[i]); j++ {
|
|
if lines[i][j] == ',' {
|
|
break
|
|
}
|
|
}
|
|
|
|
numbX, _ = strconv.Atoi(lines[i][m:j])
|
|
numbY, _ = strconv.Atoi(lines[i][j+1:])
|
|
temp = Robot{position, Vector2{numbX, numbY}}
|
|
result = append(result, temp)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func Part1(input structuredInput) int {
|
|
var result = 0
|
|
|
|
var robots = make([]Robot, 0)
|
|
var temp Robot
|
|
for _, robot := range input {
|
|
temp = Robot{Vector2{robot.p.x, robot.p.y}, Vector2{robot.v.x, robot.v.y}}
|
|
robots = append(robots, temp)
|
|
}
|
|
|
|
for i := 0; i < len(input); i++ {
|
|
robots[i].p.x += 100 * robots[i].v.x
|
|
robots[i].p.y += 100 * robots[i].v.y
|
|
|
|
for robots[i].p.x < 0 {
|
|
robots[i].p.x += WIDTH
|
|
}
|
|
|
|
for robots[i].p.y < 0 {
|
|
robots[i].p.y += HEIGHT
|
|
}
|
|
for robots[i].p.x >= WIDTH {
|
|
robots[i].p.x -= WIDTH
|
|
}
|
|
|
|
for robots[i].p.y >= HEIGHT {
|
|
robots[i].p.y -= HEIGHT
|
|
}
|
|
}
|
|
|
|
var count = 0
|
|
var quads = make([]int, 0)
|
|
for offsetY := 0; offsetY < 2; offsetY++ {
|
|
for offsetX := 0; offsetX < 2; offsetX++ {
|
|
count = 0
|
|
for y := 0 + (offsetY * (HEIGHT/2 + 1)); y < (HEIGHT/2)+(offsetY*(HEIGHT/2+1)); y++ {
|
|
for x := 0 + (offsetX * (WIDTH/2 + 1)); x < (WIDTH/2)+(offsetX*(WIDTH/2+1)); x++ {
|
|
for _, robot := range robots {
|
|
if robot.p.x == x && robot.p.y == y {
|
|
count++
|
|
}
|
|
}
|
|
}
|
|
}
|
|
quads = append(quads, count)
|
|
}
|
|
}
|
|
result = 1
|
|
|
|
for _, quadCount := range quads {
|
|
result *= quadCount
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func simulateSecond(robots []Robot) []Robot {
|
|
for i := 0; i < len(robots); i++ {
|
|
robots[i].p.x += robots[i].v.x
|
|
robots[i].p.y += robots[i].v.y
|
|
|
|
for robots[i].p.x < 0 {
|
|
robots[i].p.x += WIDTH
|
|
}
|
|
|
|
for robots[i].p.y < 0 {
|
|
robots[i].p.y += HEIGHT
|
|
}
|
|
for robots[i].p.x >= WIDTH {
|
|
robots[i].p.x -= WIDTH
|
|
}
|
|
|
|
for robots[i].p.y >= HEIGHT {
|
|
robots[i].p.y -= HEIGHT
|
|
}
|
|
}
|
|
return robots
|
|
}
|
|
|
|
func Part2(input structuredInput) int {
|
|
var result = 0
|
|
|
|
var robots = make([]Robot, 0)
|
|
var temp Robot
|
|
var count int
|
|
|
|
for _, robot := range input {
|
|
temp = Robot{Vector2{robot.p.x, robot.p.y}, Vector2{robot.v.x, robot.v.y}}
|
|
robots = append(robots, temp)
|
|
}
|
|
var img *image.Gray
|
|
for i := 0; i < 10000; i++ {
|
|
img = image.NewGray(image.Rect(0, 0, WIDTH, HEIGHT))
|
|
robots = simulateSecond(robots)
|
|
count = 0
|
|
for y := 0; y < HEIGHT; y++ {
|
|
for x := 0; x < WIDTH; x++ {
|
|
count = 0
|
|
for _, robot := range robots {
|
|
if robot.p.x == x && robot.p.y == y {
|
|
count++
|
|
}
|
|
}
|
|
if count == 0 {
|
|
img.Set(x, y, color.White)
|
|
} else {
|
|
img.Set(x, y, color.Black)
|
|
}
|
|
}
|
|
}
|
|
f, _ := os.Create("./images/" + strconv.Itoa(i+1) + ".png")
|
|
defer f.Close()
|
|
|
|
png.Encode(f, img)
|
|
}
|
|
// Find result manualy
|
|
result = 6876
|
|
return result
|
|
}
|
|
|
|
func main() {
|
|
var start time.Time
|
|
var elapsed time.Duration = 0
|
|
input, err := LoadInput(FILE_PATH)
|
|
if err != nil {
|
|
fmt.Println("Error loading input:", err)
|
|
return
|
|
}
|
|
|
|
structuredInput := TransformInput(input)
|
|
fmt.Println("Structured Input:", structuredInput)
|
|
|
|
start = time.Now()
|
|
fmt.Println("Solution Part 1: ", Part1(structuredInput))
|
|
elapsed = time.Since(start)
|
|
fmt.Printf("Part 1 took %s\n", elapsed)
|
|
|
|
start = time.Now()
|
|
fmt.Println("Solution Part 2: ", Part2(structuredInput))
|
|
elapsed = time.Since(start)
|
|
fmt.Printf("Part 2 took %s\n", elapsed)
|
|
}
|