const std = @import("std"); fn StackList(comptime T: type, comptime capacity_type: type, comptime capacity: capacity_type) type { return struct { const Self = @This(); mem: [capacity]T, length: capacity_type, fn add(self: *Self, value: T) void { self.mem[self.length] = value; self.length += 1; } fn has(self: *Self, needle: T) bool { for (0..self.length) |i| { if (self.mem[i] == needle) { return true; } } return false; } fn getMutableSlice(self: *Self) []T { return (&self.mem)[0..self.length]; } fn getSlice(self: *const Self) []const T { return self.mem[0..self.length]; } fn init() Self { return Self{ .mem = undefined, .length = 0, }; } }; } const Rank = enum(u8) { Five = 6, Four = 5, FullHouse = 4, Three = 3, TwoPair = 2, OnePair = 1, HighCard = 0, }; const Hand = packed struct(u64) { bid: u16, card5: u8, card4: u8, card3: u8, card2: u8, card1: u8, rank: Rank, }; const HandSet = StackList(Hand, usize, 1000); fn parseCard(char: u8) u8 { return switch (char) { '2'...'9' => char - '0', 'T' => 10, 'J' => 11, 'Q' => 12, 'K' => 13, 'A' => 14, else => unreachable, }; } fn getRank(cards: [5]u8) Rank { var quantities = std.mem.zeroes([6]u8); for (cards) |first_card| { var matches: u4 = 0; for (cards) |second_card| { if (first_card == second_card) { matches += 1; } } quantities[matches] += 1; } if (quantities[5] != 0) { return .Five; } if (quantities[4] != 0) { return .Four; } if (quantities[3] != 0) { if (quantities[2] != 0) { return .FullHouse; } else { return .Three; } } if (quantities[2] == 4) { return .TwoPair; } if (quantities[2] != 0) { return .OnePair; } return .HighCard; } fn addDigit(result: anytype, digit: u8) void { result.* = (result.* * 10) + (digit - '0'); } fn parseHand(line: []u8) Hand { var cards: [5]u8 = undefined; var i: usize = 0; while (i < 5) : (i += 1) { cards[i] = parseCard(line[i]); } var bid: u16 = 0; i = 6; while (i < line.len) : (i += 1) { addDigit(&bid, line[i]); } return .{ .rank = getRank(cards), .card1 = cards[0], .card2 = cards[1], .card3 = cards[2], .card4 = cards[3], .card5 = cards[4], .bid = bid, }; } fn cmpByValue(context: void, a: Hand, b: Hand) bool { return std.sort.asc(u64)(context, @bitCast(a), @bitCast(b)); } fn solve(hands: *HandSet) u64 { std.sort.heap(Hand, hands.getMutableSlice(), {}, cmpByValue); var result: u64 = 0; for (hands.getSlice(), 1..) |hand, i| { result += i * hand.bid; } return result; } pub fn main() !void { const stdout = std.io.getStdOut().writer(); const raw_in = std.io.getStdIn(); var buffered_reader = std.io.bufferedReader(raw_in.reader()); var reader = buffered_reader.reader(); var hands = HandSet.init(); var line_buffer: [1000]u8 = undefined; while (try reader.readUntilDelimiterOrEof(&line_buffer, '\n')) |line| { hands.add(parseHand(line)); } try stdout.print("{d}\n", .{solve(&hands)}); }