Added shitty day 13
This commit is contained in:
parent
3cd677bbaf
commit
26a517c7a3
@ -24,6 +24,7 @@ const d111 = @import("day11/part1.zig");
|
||||
const d112 = @import("day11/part2.zig");
|
||||
const d121 = @import("day12/part1.zig");
|
||||
const d122 = @import("day12/part2.zig");
|
||||
const d131 = @import("day13/part1.zig");
|
||||
|
||||
const NUMBER_OF_RUN = 50;
|
||||
|
||||
@ -72,6 +73,9 @@ pub fn main() !void {
|
||||
try benchmark(d121.main, 12, 1);
|
||||
try benchmark(d122.main, 12, 2);
|
||||
separator();
|
||||
try benchmark(d131.main, 13, 1);
|
||||
print("| 13 | 2 | Too long ~6h | 0 | 0 |\n", .{});
|
||||
separator();
|
||||
print("| Total | {d: >8} ± {d: <6.2} | {d:>8} | {d:>8} |\n", .{ total_mean, total_std_dev, total_min, total_max });
|
||||
separator();
|
||||
}
|
||||
|
1279
day13/input
Normal file
1279
day13/input
Normal file
File diff suppressed because it is too large
Load Diff
89
day13/part1.zig
Normal file
89
day13/part1.zig
Normal file
@ -0,0 +1,89 @@
|
||||
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 };
|
||||
}
|
135
day13/part2.zig
Normal file
135
day13/part2.zig
Normal file
@ -0,0 +1,135 @@
|
||||
const std = @import("std");
|
||||
const print = std.debug.print;
|
||||
const input = @embedFile("input");
|
||||
const Usize = std.atomic.Value(usize);
|
||||
const vec2 = @Vector(2, usize);
|
||||
|
||||
// I am not proud of this solution, it take like 6h to run on 16 thread :/
|
||||
// I am sure I can change the bruteForce function to use modulo to reduce the number of clickA
|
||||
// But it was late, I was tired so I juste started this version and the next morning it was complete soooo
|
||||
// I will no go futher, I am already 2 days behind :/
|
||||
|
||||
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.init(0);
|
||||
var finished = Usize.init(0);
|
||||
var to_wait: usize = 0;
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
var thread_arena = std.heap.ThreadSafeAllocator{
|
||||
.child_allocator = allocator,
|
||||
};
|
||||
|
||||
var thread_pool: std.Thread.Pool = undefined;
|
||||
thread_pool.init(std.Thread.Pool.Options{
|
||||
.allocator = thread_arena.allocator(),
|
||||
.n_jobs = 16,
|
||||
}) catch @panic("=(");
|
||||
|
||||
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) + 10000000000000;
|
||||
prize[1] = try std.fmt.parseInt(usize, iterLine.next().?[2..], 10) + 10000000000000;
|
||||
state = .ReadJump;
|
||||
},
|
||||
.ReadJump => {
|
||||
state = .ReadButtonA;
|
||||
try thread_pool.spawn(bruteforce, .{ buttonA, buttonB, prize, &total, &finished, to_wait });
|
||||
to_wait += 1;
|
||||
},
|
||||
};
|
||||
|
||||
while (to_wait > finished.load(.monotonic)) {
|
||||
std.time.sleep(1000000);
|
||||
printProgressOverall(finished.load(.monotonic), to_wait);
|
||||
}
|
||||
|
||||
print("Total: {d}\n", .{total.load(.monotonic)});
|
||||
}
|
||||
|
||||
const Result = struct {
|
||||
clickA: usize = 0,
|
||||
clickB: usize = 0,
|
||||
cost: usize = 999999,
|
||||
};
|
||||
|
||||
fn bruteforce(buttonA: vec2, buttonB: vec2, prize: vec2, total: *Usize, finished: *Usize, id: usize) void {
|
||||
var min_cost: usize = std.math.maxInt(usize);
|
||||
const max_clickA = @min(@divFloor(prize[0], buttonA[0]), @divFloor(prize[1], buttonA[1])) + 10;
|
||||
|
||||
var clickA: usize = 0;
|
||||
while (clickA <= max_clickA) : (clickA += 1) {
|
||||
if (clickA % 1000000000 == 0) printProgress(clickA, max_clickA, id);
|
||||
|
||||
const remaining = prize - buttonA * @as(vec2, @splat(clickA));
|
||||
if (@reduce(.Or, remaining < @as(vec2, @splat(0)))) continue;
|
||||
|
||||
const clickB = @divFloor(remaining, buttonB);
|
||||
if (clickB[0] != clickB[1]) continue;
|
||||
|
||||
if (@reduce(.Or, remaining % buttonB != @as(vec2, @splat(0)))) continue;
|
||||
|
||||
const cost = clickA * 3 + clickB[0];
|
||||
if (cost < min_cost) min_cost = cost;
|
||||
}
|
||||
|
||||
if (min_cost != std.math.maxInt(usize)) {
|
||||
_ = total.fetchAdd(min_cost, .monotonic);
|
||||
}
|
||||
_ = finished.fetchAdd(1, .monotonic);
|
||||
}
|
||||
|
||||
fn printProgress(value: usize, max: usize, id: usize) void {
|
||||
print("Thread {d}: {d}% | {d}/{d}\n", .{ id, @divFloor(value * 100, max), value, max });
|
||||
}
|
||||
|
||||
fn printProgressOverall(finished: usize, total: usize) void {
|
||||
std.debug.print("Overall: {d}/{d} ({d}%) \r", .{ finished, total, @divFloor(finished * 100, total) });
|
||||
}
|
||||
|
||||
fn gcd(a: u64, b: u64) u64 {
|
||||
if (b == 0) {
|
||||
return a;
|
||||
} else {
|
||||
return gcd(b, a % b);
|
||||
}
|
||||
}
|
||||
|
||||
fn isPossible(a: u64, b: u64, c: u64) bool {
|
||||
return c % gcd(a, b) == 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user