main.zig (1920B)
1const std = @import("std"); 2const aoc = @import("aoc"); 3 4const Entry = struct { a: u16, b: u16, char: u8, pass: []u8 }; 5 6fn freeEntries(allocator: std.mem.Allocator, entries: *const std.ArrayList(Entry)) void { 7 for (entries.items) |item| 8 allocator.free(item.pass); 9 entries.deinit(); 10} 11 12fn parse(allocator: std.mem.Allocator, input: []u8) !std.ArrayList(Entry) { 13 var entries = std.ArrayList(Entry).init(allocator); 14 errdefer freeEntries(allocator, &entries); 15 16 var lineit = std.mem.tokenize(u8, input, "\n"); 17 while (lineit.next()) |line| { 18 var entry: Entry = undefined; 19 var it = std.mem.tokenize(u8, line, " -"); 20 entry.a = try std.fmt.parseInt(u16, it.next().?, 10); 21 entry.b = try std.fmt.parseInt(u16, it.next().?, 10); 22 entry.char = it.next().?[0]; 23 entry.pass = try allocator.dupe(u8, it.next().?); 24 try entries.append(entry); 25 } 26 27 return entries; 28} 29 30fn part1(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 { 31 _ = args; 32 33 const entries = try parse(allocator, input); 34 defer freeEntries(allocator, &entries); 35 36 var valid: u32 = 0; 37 for (entries.items) |entry| { 38 var count: u16 = 0; 39 for (entry.pass) |c| count += @boolToInt(c == entry.char); 40 valid += @boolToInt(count >= entry.a and count <= entry.b); 41 } 42 43 return try std.fmt.allocPrint(allocator, "{d}", .{valid}); 44} 45 46fn part2(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 { 47 _ = args; 48 49 const entries = try parse(allocator, input); 50 defer freeEntries(allocator, &entries); 51 52 var valid: u32 = 0; 53 for (entries.items) |entry| { 54 valid += @boolToInt((entry.pass[entry.a - 1] == entry.char) != 55 (entry.pass[entry.b - 1] == entry.char)); 56 } 57 58 return try std.fmt.allocPrint(allocator, "{d}", .{valid}); 59} 60 61pub const main = aoc.main(part1, part2, .{ "603", "404" });