diff --git a/17/main.go b/17/main.go new file mode 100644 index 0000000..5f0d426 --- /dev/null +++ b/17/main.go @@ -0,0 +1,159 @@ +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) +} diff --git a/17/main_test.go b/17/main_test.go new file mode 100644 index 0000000..11313e3 --- /dev/null +++ b/17/main_test.go @@ -0,0 +1,15 @@ +package main + +import "testing" + +func TestInTarget(t *testing.T) { + target := targetArea{ + startx: 20, + endx: 30, + starty: -10, + endy: -5, + } + if !InTarget(28, -7, target) { + t.Fail() + } +}