diff --git a/src/day07.zig b/src/day07.zig new file mode 100644 index 0000000..968d416 --- /dev/null +++ b/src/day07.zig @@ -0,0 +1,136 @@ +const std = @import("std"); +const util = @import("util.zig"); +const mem = std.mem; + +pub fn main() !void { + const input = @embedFile("data/day07.txt"); + const sln = try solve(util.gpa, input); + std.debug.print("{d}\n", .{sln.a}); + std.debug.print("{d}\n", .{sln.b}); +} + +const Cards = [5]u8; + +const Solution = struct { + a: usize, + b: usize, +}; + +const Score = enum(u8) { + fiveKind, + fourKind, + fullHouse, + threeKind, + twoPair, + onePair, + high, +}; + +const Hand = struct { + cards: [5]u8, + bid: u32, + score: Score, +}; + +fn fixCards(cards: *[5]u8) void { + for (cards, 0..) |card, i| { + cards[i] = switch (card) { + 'A' => 13, + 'K' => 12, + 'Q' => 11, + 'J' => 10, + 'T' => 9, + '2'...'9' => card - '2', + else => unreachable, + }; + } +} + +fn u8gt(context: void, a: u8, b: u8) bool { + _ = context; + return a > b; +} + +fn scoreHand(cards: Cards) Score { + var dups: [14]u8 = undefined; + @memset(&dups, 0); + for (cards) |a| { + dups[a] += 1; + } + std.mem.sort(u8, &dups, {}, u8gt); + return switch (dups[0]) { + 5 => .fiveKind, + 4 => .fourKind, + 3 => if (dups[1] == 2) .fullHouse else .threeKind, + 2 => if (dups[1] == 2) .twoPair else .onePair, + else => .high, + }; +} + +fn compareHand(context: void, a: Hand, b: Hand) bool { + _ = context; + if (a.score != b.score) { + return @intFromEnum(a.score) > @intFromEnum(b.score); + } else { + for (a.cards, b.cards) |cardA, cardB| { + if (cardA != cardB) return cardA < cardB; + } + } + unreachable; +} + +fn sortHands(hands: *std.ArrayList(Hand)) !void { + std.mem.sort(Hand, hands.items, {}, compareHand); +} + +fn solve(alloc: mem.Allocator, input: []const u8) !Solution { + var hands = try std.ArrayList(Hand).initCapacity(alloc, 1001); + defer hands.deinit(); + + var it = util.splitLines(input); + while (it.next()) |line| { + if (line.len == 0) continue; + + var cards = line[0..5].*; + fixCards(&cards); + const bid = try std.fmt.parseInt(u32, line[6..], 10); + const score = scoreHand(cards); + const hand = Hand{ .cards = cards, .bid = bid, .score = score }; + try hands.append(hand); + } + + // std.debug.print("{any}\n", .{hands.items}); + try sortHands(&hands); + + var partA: usize = 0; + for (hands.items, 1..) |hand, rank| { + // std.debug.print("{d} * {d}\n", .{ hand.bid, rank }); + partA += hand.bid * rank; + } + + return .{ .a = partA, .b = 0 }; +} + +test "silver" { + const input = + \\32T3K 765 + \\T55J5 684 + \\KK677 28 + \\KTJJT 220 + \\QQQJA 483 + ; + const sln = try solve(std.testing.allocator, input); + try std.testing.expectEqual(@as(usize, 6440), sln.a); +} + +test "gold" { + const input = + \\32T3K 765 + \\T55J5 684 + \\KK677 28 + \\KTJJT 220 + \\QQQJA 483 + ; + const sln = try solve(std.testing.allocator, input); + try std.testing.expectEqual(@as(usize, 0), sln.b); +}