Part1
const std = @import("std");
const Batteries = struct {
list: std.array_list.Managed(u8),
nbanks: usize,
nperbank: usize,
const Self = @This();
pub fn init(input: []const u8, allocator: std.mem.Allocator) !Self {
var batteries = Self{
.list = std.array_list.Managed(u8).init(allocator),
.nbanks = 0,
.nperbank = 0,
};
var lines = std.mem.tokenizeScalar(u8, input, '\n');
while (lines.next()) |line| : (batteries.nbanks += 1) {
for (line) |battery| {
try batteries.list.append(battery - '0');
}
}
batteries.nperbank = @divExact(batteries.list.items.len, batteries.nbanks);
return batteries;
}
pub fn deinit(self: *Self) void {
self.list.deinit();
}
pub fn joltage(self: Self, ibank: usize) u8 {
var maxjoltage: u8 = 0;
for (0..self.nperbank - 1) |fst| {
const fstjoltage = 10 * self.list.items[ibank * self.nperbank + fst];
if (fstjoltage + 9 < maxjoltage) {
continue;
}
for (fst + 1..self.nperbank) |snd| {
const sndjoltage = self.list.items[ibank * self.nperbank + snd];
if (fstjoltage + sndjoltage > maxjoltage) {
maxjoltage = fstjoltage + sndjoltage;
if (sndjoltage == 9) {
break;
}
}
}
}
return maxjoltage;
}
};
pub fn main() !void {
var dba = std.heap.DebugAllocator(.{}){};
defer _ = dba.deinit();
const allocator = dba.allocator();
var stdout_buffer: [1024]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
const stdout = &stdout_writer.interface;
var stderr_buffer: [1024]u8 = undefined;
var stderr_writer = std.fs.File.stderr().writer(&stderr_buffer);
const stderr = &stderr_writer.interface;
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
if (args.len < 2) {
try stderr.print("Usage: {s} <filename>\n", .{args[0]});
try stderr.flush();
return error.InvalidArguments;
}
const filename = args[1];
const file = try std.fs.cwd().openFile(filename, .{});
defer file.close();
const file_size = try file.getEndPos();
const input = try allocator.alloc(u8, file_size);
defer allocator.free(input);
const bytes_read = try file.readAll(input);
if (bytes_read != file_size) {
try stderr.print("Warning: Read {d} bytes but expected {d}\n", .{ bytes_read, file_size });
}
var batteries = try Batteries.init(input, allocator);
defer batteries.deinit();
var totaljoltage: usize = 0;
for (0..batteries.nbanks) |ibank| {
totaljoltage += batteries.joltage(ibank);
}
try stdout.print("Total output jolatages: {d}\n", .{totaljoltage});
try stdout.flush();
}
Had to do a lot of checks for the first try of part two, in order to break or skip loops early, so that it runs in reasonable time.
Part2 - first try (runtime 2.5s)
const std = @import("std");
const Batteries = struct {
list: std.array_list.Managed(u8),
nbanks: usize,
nperbank: usize,
const Self = @This();
pub fn init(input: []const u8, allocator: std.mem.Allocator) !Self {
var batteries = Self{
.list = std.array_list.Managed(u8).init(allocator),
.nbanks = 0,
.nperbank = 0,
};
var lines = std.mem.tokenizeScalar(u8, input, '\n');
while (lines.next()) |line| : (batteries.nbanks += 1) {
for (line) |battery| {
try batteries.list.append(battery - '0');
}
}
batteries.nperbank = @divExact(batteries.list.items.len, batteries.nbanks);
return batteries;
}
pub fn deinit(self: *Self) void {
self.list.deinit();
}
pub fn joltage(self: Self, ibank: usize) usize {
var maxjoltage: usize = 0;
for (0..self.nperbank - 11) |idx1| {
const joltage1: usize = @as(usize, 100000000000) * self.list.items[ibank * self.nperbank + idx1];
const tmpjoltage1 = joltage1;
if (tmpjoltage1 + 99999999999 < maxjoltage) {
continue;
}
for (idx1 + 1..self.nperbank - 10) |idx2| {
const joltage2: usize = @as(usize, 10000000000) * self.list.items[ibank * self.nperbank + idx2];
const tmpjoltage2 = tmpjoltage1 + joltage2;
if (tmpjoltage2 + 9999999999 < maxjoltage) {
continue;
}
for (idx2 + 1..self.nperbank - 9) |idx3| {
const joltage3: usize = @as(usize, 1000000000) * self.list.items[ibank * self.nperbank + idx3];
const tmpjoltage3 = tmpjoltage2 + joltage3;
if (tmpjoltage3 + 999999999 < maxjoltage) {
continue;
}
for (idx3 + 1..self.nperbank - 8) |idx4| {
const joltage4: usize = @as(usize, 100000000) * self.list.items[ibank * self.nperbank + idx4];
const tmpjoltage4 = tmpjoltage3 + joltage4;
if (tmpjoltage4 + 99999999 < maxjoltage) {
continue;
}
for (idx4 + 1..self.nperbank - 7) |idx5| {
const joltage5: usize = @as(usize, 10000000) * self.list.items[ibank * self.nperbank + idx5];
const tmpjoltage5 = tmpjoltage4 + joltage5;
if (tmpjoltage5 + 9999999 < maxjoltage) {
continue;
}
for (idx5 + 1..self.nperbank - 6) |idx6| {
const joltage6: usize = @as(usize, 1000000) * self.list.items[ibank * self.nperbank + idx6];
const tmpjoltage6 = tmpjoltage5 + joltage6;
if (tmpjoltage6 + 999999 < maxjoltage) {
continue;
}
for (idx6 + 1..self.nperbank - 5) |idx7| {
const joltage7: usize = @as(usize, 100000) * self.list.items[ibank * self.nperbank + idx7];
const tmpjoltage7 = tmpjoltage6 + joltage7;
if (tmpjoltage7 + 99999 < maxjoltage) {
continue;
}
for (idx7 + 1..self.nperbank - 4) |idx8| {
const joltage8: usize = @as(usize, 10000) * self.list.items[ibank * self.nperbank + idx8];
const tmpjoltage8 = tmpjoltage7 + joltage8;
if (tmpjoltage8 + 9999 < maxjoltage) {
continue;
}
for (idx8 + 1..self.nperbank - 3) |idx9| {
const joltage9: usize = @as(usize, 1000) * self.list.items[ibank * self.nperbank + idx9];
const tmpjoltage9 = tmpjoltage8 + joltage9;
if (tmpjoltage9 + 999 < maxjoltage) {
continue;
}
for (idx9 + 1..self.nperbank - 2) |idx10| {
const joltage10: usize = @as(usize, 100) * self.list.items[ibank * self.nperbank + idx10];
const tmpjoltage10 = tmpjoltage9 + joltage10;
if (tmpjoltage10 + 99 < maxjoltage) {
continue;
}
for (idx10 + 1..self.nperbank - 1) |idx11| {
const joltage11: usize = @as(usize, 10) * self.list.items[ibank * self.nperbank + idx11];
const tmpjoltage11 = tmpjoltage10 + joltage11;
if (tmpjoltage11 + 9 < maxjoltage) {
continue;
}
for (idx11 + 1..self.nperbank - 0) |idx12| {
const joltage12: usize = 1 * self.list.items[ibank * self.nperbank + idx12];
const tmpjoltage12 = tmpjoltage11 + joltage12;
if (tmpjoltage12 > maxjoltage) {
maxjoltage = tmpjoltage12;
if (joltage12 == 9) {
break;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
return maxjoltage;
}
};
pub fn main() !void {
var dba = std.heap.DebugAllocator(.{}){};
defer _ = dba.deinit();
const allocator = dba.allocator();
var stdout_buffer: [1024]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
const stdout = &stdout_writer.interface;
var stderr_buffer: [1024]u8 = undefined;
var stderr_writer = std.fs.File.stderr().writer(&stderr_buffer);
const stderr = &stderr_writer.interface;
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
if (args.len < 2) {
try stderr.print("Usage: {s} <filename>\n", .{args[0]});
try stderr.flush();
return error.InvalidArguments;
}
const filename = args[1];
const file = try std.fs.cwd().openFile(filename, .{});
defer file.close();
const file_size = try file.getEndPos();
const input = try allocator.alloc(u8, file_size);
defer allocator.free(input);
const bytes_read = try file.readAll(input);
if (bytes_read != file_size) {
try stderr.print("Warning: Read {d} bytes but expected {d}\n", .{ bytes_read, file_size });
}
var batteries = try Batteries.init(input, allocator);
defer batteries.deinit();
var totaljoltage: usize = 0;
for (0..batteries.nbanks) |ibank| {
const joltage = batteries.joltage(ibank);
totaljoltage += joltage;
}
try stdout.print("Total output jolatages: {d}\n", .{totaljoltage});
try stdout.flush();
}
Part2 - second try (runtime 250 µs)
const std = @import("std");
const Batteries = struct {
list: std.array_list.Managed(u8),
nbanks: usize,
nperbank: usize,
const Self = @This();
pub fn init(input: []const u8, allocator: std.mem.Allocator) !Self {
var batteries = Self{
.list = std.array_list.Managed(u8).init(allocator),
.nbanks = 0,
.nperbank = 0,
};
var lines = std.mem.tokenizeScalar(u8, input, '\n');
while (lines.next()) |line| : (batteries.nbanks += 1) {
for (line) |battery| {
try batteries.list.append(battery - '0');
}
}
batteries.nperbank = @divExact(batteries.list.items.len, batteries.nbanks);
return batteries;
}
pub fn deinit(self: *Self) void {
self.list.deinit();
}
pub fn joltage(self: Self, ibank: usize) usize {
const n_on: usize = 12;
var bestidx: usize = 0;
var bestjoltage: u8 = 0;
var final_joltage: usize = 0;
bestjoltage = 0;
for (0..self.nperbank - n_on) |idx| {
const bat_val = self.list.items[ibank * self.nperbank + idx];
if (bat_val > bestjoltage) {
bestjoltage = bat_val;
bestidx = idx;
}
}
final_joltage = bestjoltage;
for (1..n_on) |idig| {
bestjoltage = 0;
for (bestidx + 1..self.nperbank - (n_on - idig) + 1) |idx| {
const bat_val = self.list.items[ibank * self.nperbank + idx];
if (bat_val > bestjoltage) {
bestjoltage = bat_val;
bestidx = idx;
}
}
final_joltage *= 10;
final_joltage += bestjoltage;
}
return final_joltage;
}
};
pub fn main() !void {
var dba = std.heap.DebugAllocator(.{}){};
defer _ = dba.deinit();
const allocator = dba.allocator();
var stdout_buffer: [1024]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
const stdout = &stdout_writer.interface;
var stderr_buffer: [1024]u8 = undefined;
var stderr_writer = std.fs.File.stderr().writer(&stderr_buffer);
const stderr = &stderr_writer.interface;
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
if (args.len < 2) {
try stderr.print("Usage: {s} <filename>\n", .{args[0]});
try stderr.flush();
return error.InvalidArguments;
}
const filename = args[1];
const file = try std.fs.cwd().openFile(filename, .{});
defer file.close();
const file_size = try file.getEndPos();
const input = try allocator.alloc(u8, file_size);
defer allocator.free(input);
const bytes_read = try file.readAll(input);
if (bytes_read != file_size) {
try stderr.print("Warning: Read {d} bytes but expected {d}\n", .{ bytes_read, file_size });
}
var batteries = try Batteries.init(input, allocator);
defer batteries.deinit();
//batteries.debug_print();
var totaljoltage: usize = 0;
for (0..batteries.nbanks) |ibank| {
const joltage = batteries.joltage(ibank);
//std.debug.print("{d}/{d}: {d}\n", .{ ibank + 1, batteries.nbanks, joltage });
totaljoltage += joltage;
}
try stdout.print("Total output jolatages: {d}\n", .{totaljoltage});
try stdout.flush();
}