160 lines
2.6 KiB
Go
160 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
func mustAtoi(line string) int {
|
|
i, _ := strconv.Atoi(line)
|
|
return i
|
|
}
|
|
|
|
func main() {
|
|
start := time.Now()
|
|
partOne()
|
|
duration := time.Since(start)
|
|
partTwo()
|
|
duration2 := time.Since(start)
|
|
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
|
}
|
|
|
|
func makeScanner(test bool) *bufio.Scanner {
|
|
var f *os.File
|
|
if test {
|
|
f, _ = os.Open("inputs/testinput")
|
|
} else {
|
|
f, _ = os.Open("inputs/input")
|
|
}
|
|
reader := bufio.NewReader(f)
|
|
return bufio.NewScanner(reader)
|
|
}
|
|
|
|
type targetArea struct {
|
|
startx int
|
|
endx int
|
|
starty int
|
|
endy int
|
|
}
|
|
|
|
func ParseInput(line string) targetArea {
|
|
target := targetArea{}
|
|
acc := ""
|
|
for i := 0; i < len(line); i++ {
|
|
switch line[i] {
|
|
case '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-':
|
|
acc += string(line[i])
|
|
case '.':
|
|
i++ // skip the second .
|
|
if target.startx == 0 {
|
|
target.startx = mustAtoi(acc)
|
|
} else {
|
|
target.starty = mustAtoi(acc)
|
|
}
|
|
acc = ""
|
|
case ',':
|
|
target.endx = mustAtoi(acc)
|
|
acc = ""
|
|
default: // all other characters do nothing
|
|
}
|
|
target.endy = mustAtoi(acc)
|
|
}
|
|
return target
|
|
}
|
|
|
|
func InTarget(x, y int, target targetArea) bool {
|
|
return x >= target.startx && x <= target.endx && y <= target.endy && y >= target.starty
|
|
}
|
|
|
|
func BeyondTarget(x, y int, target targetArea) bool {
|
|
return x > target.endx || y < target.starty
|
|
}
|
|
|
|
type probe struct {
|
|
xvelocity int
|
|
yvelocity int
|
|
x int
|
|
y int
|
|
maxy int
|
|
}
|
|
|
|
func (p *probe) Step() {
|
|
p.x += p.xvelocity
|
|
p.y += p.yvelocity
|
|
if p.xvelocity > 0 {
|
|
p.xvelocity--
|
|
} else if p.xvelocity < 0 {
|
|
p.xvelocity++
|
|
}
|
|
p.yvelocity--
|
|
if p.y > p.maxy {
|
|
p.maxy = p.y
|
|
}
|
|
}
|
|
|
|
func partOne() {
|
|
scanner := makeScanner(false)
|
|
|
|
// read line
|
|
scanner.Scan()
|
|
line := scanner.Text()
|
|
target := ParseInput(line)
|
|
highestArc := 0
|
|
for j := 1; j < 50; j++ {
|
|
for k := 1; k < 100; k++ {
|
|
initx := j
|
|
inity := k
|
|
p := &probe{
|
|
xvelocity: initx,
|
|
yvelocity: inity,
|
|
}
|
|
for {
|
|
p.Step()
|
|
if InTarget(p.x, p.y, target) {
|
|
if p.maxy > highestArc {
|
|
highestArc = p.maxy
|
|
}
|
|
}
|
|
if BeyondTarget(p.x, p.y, target) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fmt.Println(highestArc)
|
|
}
|
|
|
|
func partTwo() {
|
|
scanner := makeScanner(false)
|
|
|
|
// read line
|
|
scanner.Scan()
|
|
line := scanner.Text()
|
|
target := ParseInput(line)
|
|
hits := 0
|
|
for j := 0; j < 1000; j++ {
|
|
for k := -200; k < 1000; k++ {
|
|
initx := j
|
|
inity := k
|
|
p := &probe{
|
|
xvelocity: initx,
|
|
yvelocity: inity,
|
|
}
|
|
for {
|
|
p.Step()
|
|
if InTarget(p.x, p.y, target) {
|
|
hits++
|
|
break
|
|
}
|
|
if BeyondTarget(p.x, p.y, target) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fmt.Println(hits)
|
|
}
|