You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
2.5 KiB
Zig
91 lines
2.5 KiB
Zig
12 months ago
|
const std = @import("std");
|
||
|
|
||
|
const Card = struct { winning: std.ArrayList(u8), have: std.ArrayList(u8), copies: u64 };
|
||
|
|
||
|
pub fn main() !void {
|
||
|
const content = @embedFile("data.txt");
|
||
|
var cards = try parseCards(content);
|
||
|
defer cards.deinit();
|
||
|
|
||
|
var score1 = try findScore(&cards, 1);
|
||
|
std.debug.print("part 1: {d}\n", .{score1});
|
||
|
|
||
|
_ = try findScore(&cards, 2);
|
||
|
var numCards: u128 = 0;
|
||
|
for (cards.items) |c| {
|
||
|
numCards += c.copies;
|
||
|
}
|
||
|
|
||
|
std.debug.print("part 2: {any}\n", .{numCards});
|
||
|
}
|
||
|
|
||
|
fn findScore(cards: *std.ArrayList(Card), part: u8) !u64 {
|
||
|
var total: u64 = 0;
|
||
|
// iterate over all cards
|
||
|
for (cards.items, 0..) |card, i| {
|
||
|
var numWinners: usize = 0;
|
||
|
var score: u32 = 0;
|
||
|
// iterate over the numbers we have
|
||
|
for (card.have.items) |n| {
|
||
|
// and the winning numbers
|
||
|
for (card.winning.items) |w| {
|
||
|
if (n == w) {
|
||
|
numWinners += 1;
|
||
|
score = if (score == 0) 1 else score * 2;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (part == 2) {
|
||
|
for (0..numWinners) |j| {
|
||
|
cards.items[i + j + 1].copies += card.copies;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
total += score;
|
||
|
}
|
||
|
|
||
|
return total;
|
||
|
}
|
||
|
|
||
|
fn parseCards(content: []const u8) !std.ArrayList(Card) {
|
||
|
var lines = std.mem.split(u8, content, "\n");
|
||
|
|
||
|
var cards = std.ArrayList(Card).init(std.heap.page_allocator);
|
||
|
|
||
|
while (lines.next()) |line| {
|
||
|
if (line.len == 0) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// break line up on :
|
||
|
var parts = std.mem.split(u8, line, ": ");
|
||
|
_ = parts.next();
|
||
|
// break the 2nd part up by |
|
||
|
var sections = std.mem.split(u8, parts.next().?, " | ");
|
||
|
// split the left part up on spaces
|
||
|
var nums = std.mem.split(u8, sections.next().?, " ");
|
||
|
|
||
|
var winning = std.ArrayList(u8).init(std.heap.page_allocator);
|
||
|
while (nums.next()) |d| {
|
||
|
if (d.len > 0) {
|
||
|
try winning.append(try std.fmt.parseInt(u8, d, 10));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// split the right part up on spaces
|
||
|
nums = std.mem.split(u8, sections.next().?, " ");
|
||
|
|
||
|
var have = std.ArrayList(u8).init(std.heap.page_allocator);
|
||
|
while (nums.next()) |d| {
|
||
|
if (d.len > 0) {
|
||
|
try have.append(try std.fmt.parseInt(u8, d, 10));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
try cards.append(Card{ .winning = winning, .have = have, .copies = 1 });
|
||
|
}
|
||
|
|
||
|
return cards;
|
||
|
}
|