Spent too much time on getting lapack to work. It is total overkill to solve the systems of equation with lapack, but I wanted to learn how to use it in zig.
Solution 1
const std = @import("std");
const lapack = @cImport(@cInclude("lapacke.h"));
const laint = lapack.lapack_int;
//const input = @embedFile("./small.inp");
const input = @embedFile("./big.inp");
const n: laint = 2;
const claw_machine_t = struct {
butA: [n]i32,
butB: [n]i32,
npressA: i32,
npressB: i32,
prizes: [n]i32,
winnable: bool,
const Self = @This();
pub fn read(lines: *std.mem.TokenIterator(u8, .scalar)) ?Self {
var claw_machine = Self{
.butA = undefined,
.butB = undefined,
.npressA = 0,
.npressB = 0,
.prizes = undefined,
.winnable = undefined,
};
for (0..2) |_| {
if (lines.next()) |line| {
var fields = std.mem.tokenizeScalar(u8, line, ' ');
_ = fields.next() orelse return null;
const butname = fields.next() orelse return null;
const Xstr = fields.next() orelse return null;
const Xval = std.fmt.parseInt(i32, Xstr[2 .. Xstr.len - 1], 10) catch |err| {
std.debug.print("{?}\n", .{err});
return null;
};
const Ystr = fields.next() orelse return null;
const Yval = std.fmt.parseInt(i32, Ystr[2..Ystr.len], 10) catch |err| {
std.debug.print("{?}\n", .{err});
return null;
};
if (butname[0] == 'A') {
claw_machine.butA = [n]i32{ Xval, Yval };
} else if (butname[0] == 'B') {
claw_machine.butB = [n]i32{ Xval, Yval };
}
} else {
return null;
}
}
var fields = std.mem.tokenizeScalar(u8, lines.next() orelse "", ' ');
_ = fields.next() orelse return null;
const Xstr = fields.next() orelse return null;
const Xval = std.fmt.parseInt(i32, Xstr[2 .. Xstr.len - 1], 10) catch |err| {
std.debug.print("{?}\n", .{err});
return null;
};
const Ystr = fields.next() orelse return null;
const Yval = std.fmt.parseInt(i32, Ystr[2..Ystr.len], 10) catch |err| {
std.debug.print("{?}\n", .{err});
return null;
};
claw_machine.prizes = [n]i32{ Xval, Yval };
return claw_machine;
}
pub fn solve(self: *Self) void {
const nrhs: laint = 1;
const lda: laint = n;
const ldb: laint = n;
var buttons: [n * n]f64 = undefined;
var prizes: [n]f64 = undefined;
for (0..n) |i| {
buttons[i] = @floatFromInt(self.butA[i]);
buttons[i + n] = @floatFromInt(self.butB[i]);
prizes[i] = @floatFromInt(self.prizes[i]);
}
var ipiv = [n]laint{ 0, 0 };
const info = lapack.LAPACKE_dgesv( //
lapack.LAPACK_COL_MAJOR, // matrix orientation
n, // number of equations in matrix
nrhs, // number of colums in result vector
&buttons, // the matrix to be diagonalized
lda, // leading dimension of matrix
&ipiv, // pivot indices
&prizes, // result vector
ldb); // leading dimension of result vector
if (info == 0) {
self.npressA = @intFromFloat(prizes[0] + 0.5);
self.npressB = @intFromFloat(prizes[1] + 0.5);
self.winnable = self.npressA >= 0 and self.npressA <= 100;
self.winnable = self.winnable and self.npressB >= 0 and self.npressB <= 100;
self.winnable = self.winnable and self.butA[0] * self.npressA + self.butB[0] * self.npressB == self.prizes[0];
self.winnable = self.winnable and self.butA[1] * self.npressA + self.butB[1] * self.npressB == self.prizes[1];
} else {
std.debug.print("diagonalization failed\n", .{});
}
}
pub fn cost(self: Self) i32 {
return 3 * self.npressA + 1 * self.npressB;
}
};
pub fn main() !void {
var lines = std.mem.tokenizeScalar(u8, input, '\n');
var sum: i32 = 0;
while (true) {
//std.debug.print("{d}: {s}\n", .{ i, line });
var claw_machine = claw_machine_t.read(&lines) orelse break;
claw_machine.solve();
const cost = claw_machine.cost();
if (claw_machine.winnable) {
sum += cost;
}
//std.debug.print("{?} -> {d} tokens \n", .{ claw_machine, cost });
}
std.debug.print("Number of required tokens: {d}\n", .{sum});
}
Solution 2
const std = @import("std");
const lapack = @cImport(@cInclude("lapacke.h"));
const laint = lapack.lapack_int;
//const input = @embedFile("./small.inp");
const input = @embedFile("./big.inp");
const n: laint = 2;
const claw_machine_t = struct {
butA: [n]i64,
butB: [n]i64,
npressA: i64,
npressB: i64,
prizes: [n]i64,
winnable: bool,
const Self = @This();
pub fn read(lines: *std.mem.TokenIterator(u8, .scalar)) ?Self {
var claw_machine = Self{
.butA = undefined,
.butB = undefined,
.npressA = 0,
.npressB = 0,
.prizes = undefined,
.winnable = undefined,
};
for (0..2) |_| {
if (lines.next()) |line| {
var fields = std.mem.tokenizeScalar(u8, line, ' ');
_ = fields.next() orelse return null;
const butname = fields.next() orelse return null;
const Xstr = fields.next() orelse return null;
const Xval = std.fmt.parseInt(i64, Xstr[2 .. Xstr.len - 1], 10) catch |err| {
std.debug.print("{?}\n", .{err});
return null;
};
const Ystr = fields.next() orelse return null;
const Yval = std.fmt.parseInt(i64, Ystr[2..Ystr.len], 10) catch |err| {
std.debug.print("{?}\n", .{err});
return null;
};
if (butname[0] == 'A') {
claw_machine.butA = [n]i64{ Xval, Yval };
} else if (butname[0] == 'B') {
claw_machine.butB = [n]i64{ Xval, Yval };
}
} else {
return null;
}
}
var fields = std.mem.tokenizeScalar(u8, lines.next() orelse "", ' ');
_ = fields.next() orelse return null;
const Xstr = fields.next() orelse return null;
var Xval = std.fmt.parseInt(i64, Xstr[2 .. Xstr.len - 1], 10) catch |err| {
std.debug.print("{?}\n", .{err});
return null;
};
const Ystr = fields.next() orelse return null;
var Yval = std.fmt.parseInt(i64, Ystr[2..Ystr.len], 10) catch |err| {
std.debug.print("{?}\n", .{err});
return null;
};
Xval += 10000000000000;
Yval += 10000000000000;
claw_machine.prizes = [n]i64{ Xval, Yval };
return claw_machine;
}
pub fn solve(self: *Self) void {
const nrhs: laint = 1;
const lda: laint = n;
const ldb: laint = n;
var buttons: [n * n]f64 = undefined;
var prizes: [n]f64 = undefined;
for (0..n) |i| {
buttons[i] = @floatFromInt(self.butA[i]);
buttons[i + n] = @floatFromInt(self.butB[i]);
prizes[i] = @floatFromInt(self.prizes[i]);
}
var ipiv = [n]laint{ 0, 0 };
const info = lapack.LAPACKE_dgesv( //
lapack.LAPACK_COL_MAJOR, // matrix orientation
n, // number of equations in matrix
nrhs, // number of colums in result vector
&buttons, // the matrix to be diagonalized
lda, // leading dimension of matrix
&ipiv, // pivot indices
&prizes, // result vector
ldb); // leading dimension of result vector
if (info == 0) {
self.npressA = @intFromFloat(prizes[0] + 0.5);
self.npressB = @intFromFloat(prizes[1] + 0.5);
self.winnable = self.npressA >= 0;
self.winnable = self.winnable and self.npressB >= 0;
self.winnable = self.winnable and self.butA[0] * self.npressA + self.butB[0] * self.npressB == self.prizes[0];
self.winnable = self.winnable and self.butA[1] * self.npressA + self.butB[1] * self.npressB == self.prizes[1];
} else {
std.debug.print("diagonalization failed\n", .{});
}
}
pub fn cost(self: Self) i64 {
return 3 * self.npressA + 1 * self.npressB;
}
};
pub fn main() !void {
var lines = std.mem.tokenizeScalar(u8, input, '\n');
var sum: i64 = 0;
while (true) {
//std.debug.print("{d}: {s}\n", .{ i, line });
var claw_machine = claw_machine_t.read(&lines) orelse break;
claw_machine.solve();
const cost = claw_machine.cost();
if (claw_machine.winnable) {
sum += cost;
}
//std.debug.print("{?} -> {d} tokens \n", .{ claw_machine, cost });
}
std.debug.print("Number of required tokens: {d}\n", .{sum});
}