90 lines
3.2 KiB
Zig
90 lines
3.2 KiB
Zig
const std = @import("std");
|
|
const print = std.debug.print;
|
|
const input = @embedFile("input");
|
|
const vec2 = @Vector(2, usize);
|
|
|
|
// So I need to find out ax + by = c
|
|
// With x and y the number of time I click on a and b respectivly
|
|
// a and b as how much I advance per click
|
|
// And c as total
|
|
// And I have 2 equation, one for prize position x and one for y
|
|
// Which you can easely do, for float, not int =(
|
|
// So how do I approach this ?
|
|
// 1. Brute force: I can do all combinaison of x and y. For like 200 max click. 320 prize, 200 * 200 * 320 = 12_800_000
|
|
// 2. Pretty sure I can do something with a modulo, because the end pos can only be reach by few combinaison
|
|
|
|
const State = enum {
|
|
ReadButtonA,
|
|
ReadButtonB,
|
|
ReadPrize,
|
|
ReadJump,
|
|
};
|
|
|
|
pub fn main() !void {
|
|
var iter = std.mem.splitAny(u8, input, "\n");
|
|
var state = State.ReadButtonA;
|
|
var buttonA: vec2 = undefined;
|
|
var buttonB: vec2 = undefined;
|
|
var prize: vec2 = undefined;
|
|
var total: usize = 0;
|
|
|
|
while (iter.next()) |line| switch (state) {
|
|
.ReadButtonA => {
|
|
var iterLine = std.mem.splitAny(u8, line, " ");
|
|
_ = iterLine.next(); // Skip Button
|
|
_ = iterLine.next(); // Skip A
|
|
const buf = iterLine.next().?;
|
|
buttonA[0] = try std.fmt.parseInt(usize, buf[2 .. buf.len - 1], 10);
|
|
buttonA[1] = try std.fmt.parseInt(usize, iterLine.next().?[2..], 10);
|
|
state = .ReadButtonB;
|
|
},
|
|
.ReadButtonB => {
|
|
var iterLine = std.mem.splitAny(u8, line, " ");
|
|
_ = iterLine.next(); // Skip Button
|
|
_ = iterLine.next(); // Skip B
|
|
const buf = iterLine.next().?;
|
|
buttonB[0] = try std.fmt.parseInt(usize, buf[2 .. buf.len - 1], 10);
|
|
buttonB[1] = try std.fmt.parseInt(usize, iterLine.next().?[2..], 10);
|
|
state = .ReadPrize;
|
|
},
|
|
.ReadPrize => {
|
|
var iterLine = std.mem.splitAny(u8, line, " ");
|
|
_ = iterLine.next(); // Skip Price
|
|
const buf = iterLine.next().?;
|
|
prize[0] = try std.fmt.parseInt(usize, buf[2 .. buf.len - 1], 10);
|
|
prize[1] = try std.fmt.parseInt(usize, iterLine.next().?[2..], 10);
|
|
state = .ReadJump;
|
|
},
|
|
.ReadJump => {
|
|
state = .ReadButtonA;
|
|
const result = bruteforce(buttonA, buttonB, prize, vec2{ 0, 100 });
|
|
if (result.cost != 99999) total += result.cost;
|
|
},
|
|
};
|
|
|
|
try std.testing.expectEqual(33921, total);
|
|
}
|
|
|
|
const Result = struct {
|
|
clickA: usize = 0,
|
|
clickB: usize = 0,
|
|
cost: usize = 999999,
|
|
};
|
|
|
|
fn bruteforce(buttonA: vec2, buttonB: vec2, prize: vec2, range: vec2) Result {
|
|
var minA: usize = 99999;
|
|
var minB: usize = 99999;
|
|
var min_cost: usize = 99999;
|
|
for (range[0]..range[1]) |clickA| for (range[0]..range[1]) |clickB| {
|
|
const end_pos = buttonA * @as(vec2, @splat(clickA)) + buttonB * @as(vec2, @splat(clickB));
|
|
if (!@reduce(.And, end_pos == prize)) continue;
|
|
const cost = clickA * 3 + clickB;
|
|
if (cost < min_cost) {
|
|
minA = clickA;
|
|
minB = clickB;
|
|
min_cost = cost;
|
|
}
|
|
};
|
|
return Result{ .clickA = minA, .clickB = minB, .cost = min_cost };
|
|
}
|