const std = @import("std");
const path = "../data/day17/input.txt";
const RetType = u12;
const CoordType = isize;
const TargetValue = i9;
const TargetArea = struct {
xmin: TargetValue,
xmax: TargetValue,
ymin: TargetValue,
ymax: TargetValue,
fn hit(self: @This(), x: CoordType, y: CoordType) bool {
if (x >= self.xmin and x <= self.xmax and y >= self.ymin and y <= self.ymax) {
return true;
}
return false;
}
};
fn parseInput() !TargetArea {
const input = @embedFile(path);
const in = std.mem.trimRight(u8, input, "\n");
var ta: TargetArea = undefined;
var coords = std.mem.tokenize(u8, in[13..], ", ");
var xpart = coords.next().?[2..];
var xcords = std.mem.tokenize(u8, xpart, "..");
ta.xmin = try std.fmt.parseInt(TargetValue, xcords.next().?, 10);
ta.xmax = try std.fmt.parseInt(TargetValue, xcords.next().?, 10);
var ypart = coords.next().?[2..];
var ycords = std.mem.tokenize(u8, ypart, "..");
ta.ymin = try std.fmt.parseInt(TargetValue, ycords.next().?, 10);
ta.ymax = try std.fmt.parseInt(TargetValue, ycords.next().?, 10);
return ta;
}
pub fn second() !RetType {
// const ta = TargetArea{.xmin = 20, .xmax = 30, .ymin = -10, .ymax = -5};
const ta = try parseInput();
var counter: RetType = 0;
const vxmin = std.math.sqrt(@intCast(usize, ta.xmin));
const vxmax = ta.xmax;
const vymin = ta.ymin;
const vymax = try std.math.absInt(ta.ymin);
const tmax = try std.math.absInt(@as(CoordType, ta.ymin) * 2);
var vx: CoordType = vxmin;
while (vx <= vxmax) : (vx += 1) {
var vy: CoordType = vymin;
while (vy <= vymax) : (vy += 1) {
var x: CoordType = 0;
var y: CoordType = 0;
var t: CoordType = 0;
while (t < tmax) : (t += 1) {
const dx = velX(vx, t);
x += dx;
y += vy - t;
// this makes it slower :-)
// if (dx == 0 and x < ta.xmin) break;
// already missed the target
if (x > ta.xmax and y < ta.ymin) break;
if (ta.hit(x, y)) {
counter += 1;
break;
}
}
}
}
return counter;
}
fn velX(vx: CoordType, t: CoordType) CoordType {
var vel = vx - t;
if (vel > 0) {
return vel;
}
return 0;
}
pub fn main() !void {
var timer = try std.time.Timer.start();
const ret = try second();
const t = timer.lap() / 1000;
try std.testing.expectEqual(@as(RetType, 2576), ret);
std.debug.print("Day 17b result: {d} \t\ttime: {d}µs\n", .{ ret, t });
}
test "day17b" {
try std.testing.expectEqual(@as(RetType, 2576), try second());
}