1
0

Compare commits

...

2 Commits

Author SHA1 Message Date
052bf70095
Add template
Some checks failed
Build and test / test (push) Failing after 2m37s
2023-12-04 18:05:09 +11:00
9c64d710a3
day04: solve
Add a few util functions now that I'm getting sick of typing
std.mem.splitScalar.
2023-12-04 18:02:54 +11:00
3 changed files with 174 additions and 0 deletions

99
src/day04.zig Normal file
View File

@ -0,0 +1,99 @@
const std = @import("std");
const util = @import("util.zig");
const mem = std.mem;
pub fn main() !void {
const input = @embedFile("data/day04.txt");
const sln = try solve(util.gpa, input);
std.debug.print("{d}\n", .{sln.value});
std.debug.print("{d}\n", .{sln.copies});
}
const Solution = struct {
value: usize,
copies: usize,
};
fn solve(alloc: mem.Allocator, input: []const u8) !Solution {
var value: usize = 0;
var card_counts = std.AutoHashMap(usize, usize).init(alloc);
defer card_counts.deinit();
var card: usize = 0;
var it = util.splitLines(input);
while (it.next()) |line| : (card += 1) {
if (line.len == 0) continue;
const sep = mem.indexOfScalar(u8, line, ':').?;
var line_it = util.split(line[sep + 1 ..], '|');
const winning = try util.parseIntsScalar(usize, alloc, line_it.next().?, .{});
defer alloc.free(winning);
const mine = try util.parseIntsScalar(usize, alloc, line_it.next().?, .{});
defer alloc.free(mine);
var matches: usize = 0;
for (mine) |n| {
if (mem.containsAtLeast(usize, winning, 1, &[_]usize{n})) {
matches += 1;
}
}
if (matches > 0) {
value += std.math.pow(usize, 2, matches - 1);
}
// Initialise with 1 copy of current card
const copies = blk: {
const entry = try card_counts.getOrPut(card);
if (entry.found_existing) {
entry.value_ptr.* += 1;
} else {
entry.value_ptr.* = 1;
}
break :blk entry.value_ptr.*;
};
// 1 additional card for each match, multiplied by copies of this card
for (1..matches + 1) |offset| {
const winning_card_entry = try card_counts.getOrPut(card + offset);
if (winning_card_entry.found_existing) {
winning_card_entry.value_ptr.* += copies;
} else {
winning_card_entry.value_ptr.* = copies;
}
}
}
var copy_count: usize = 0;
var copy_it = card_counts.valueIterator();
while (copy_it.next()) |v| {
copy_count += v.*;
}
return .{ .value = value, .copies = copy_count };
}
test "silver" {
const input =
\\Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
\\Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
\\Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
\\Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
\\Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
\\Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
;
const sln = try solve(std.testing.allocator, input);
try std.testing.expectEqual(@as(usize, 13), sln.value);
}
test "gold" {
const input =
\\Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
\\Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
\\Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
\\Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
\\Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
\\Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
;
const sln = try solve(std.testing.allocator, input);
try std.testing.expectEqual(@as(usize, 30), sln.copies);
}

View File

@ -1,4 +1,37 @@
const std = @import("std"); const std = @import("std");
const mem = std.mem;
var gpa_impl = std.heap.GeneralPurposeAllocator(.{}){}; var gpa_impl = std.heap.GeneralPurposeAllocator(.{}){};
/// General purpose allocator.
pub const gpa = gpa_impl.allocator(); pub const gpa = gpa_impl.allocator();
pub const ParseIntsOptions = struct {
base: u8 = 10,
sep: u8 = ' ',
};
/// Parses separated integers. Sequential separators are treated as one. Caller owns memory.
pub fn parseIntsScalar(comptime T: type, alloc: std.mem.Allocator, input: []const u8, opts: ParseIntsOptions) ![]T {
var items = std.ArrayList(T).init(alloc);
errdefer items.deinit();
var it = split(input, opts.sep);
while (it.next()) |i| {
if (i.len == 0) continue;
try items.append(try std.fmt.parseInt(T, i, opts.base));
}
return try items.toOwnedSlice();
}
/// Shortcut to splitScalar with a byte buffer.
pub fn split(buffer: []const u8, sep: u8) mem.SplitIterator(u8, .scalar) {
return mem.splitScalar(u8, buffer, sep);
}
pub fn splitLines(buffer: []const u8) mem.SplitIterator(u8, .scalar) {
return split(buffer, '\n');
}
pub fn splitSpace(buffer: []const u8) mem.SplitIterator(u8, .scalar) {
return split(buffer, ' ');
}

42
template.zig Normal file
View File

@ -0,0 +1,42 @@
const std = @import("std");
const util = @import("util.zig");
const mem = std.mem;
pub fn main() !void {
const input = @embedFile("data/dayXX.txt");
const sln = try solve(util.gpa, input);
std.debug.print("{d}\n", .{sln.a});
std.debug.print("{d}\n", .{sln.b});
}
const Solution = struct {
a: usize,
b: usize,
};
fn solve(alloc: mem.Allocator, input: []const u8) !Solution {
_ = alloc;
var it = util.splitLines(input);
while (it.next()) |line| {
if (line.len == 0) continue;
}
return .{ .a = 0, .b = 0 };
}
test "silver" {
const input =
\\
;
const sln = try solve(std.testing.allocator, input);
try std.testing.expectEqual(@as(usize, 0), sln.a);
}
test "gold" {
const input =
\\
;
const sln = try solve(std.testing.allocator, input);
try std.testing.expectEqual(@as(usize, 0), sln.b);
}