From d872e4f9f61b2e08dd12cfd8212d1e5abc8a62d2 Mon Sep 17 00:00:00 2001 From: Orfeas <38209077+0xfea5@users.noreply.github.com> Date: Fri, 8 Dec 2023 01:48:35 +0200 Subject: day7 --- day07/example.txt | 5 ++ day07/solution.zig | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100644 day07/example.txt create mode 100644 day07/solution.zig (limited to 'day07') diff --git a/day07/example.txt b/day07/example.txt new file mode 100644 index 0000000..e3500c3 --- /dev/null +++ b/day07/example.txt @@ -0,0 +1,5 @@ +32T3K 765 +T55J5 684 +KK677 28 +KTJJT 220 +QQQJA 483 diff --git a/day07/solution.zig b/day07/solution.zig new file mode 100644 index 0000000..b452dfb --- /dev/null +++ b/day07/solution.zig @@ -0,0 +1,215 @@ +const std = @import("std"); +const print = std.debug.print; +const assert = std.debug.assert; +const ArrayList = std.ArrayList; +const HashMap = std.HashMap; +const mem = std.mem; + +const fin = mem.trim(u8, @embedFile("./input.txt"), &std.ascii.whitespace); +var gpa = std.heap.GeneralPurposeAllocator(.{}){}; +const allocator = gpa.allocator(); + +const Combo = enum(u32) { + high, + pair1, + pair2, + triple, + full, + quad, + quint, +}; + +const Player = struct { + bid: u64, + hand: [5]u8, + combo: Combo, + + fn evalHand(hand: []const u8) Combo { + var cardF = [_]u32{0} ** 256; + + for (hand) |c| { + cardF[c] += 1; + } + + var combo = Combo.high; + for (cardF) |f| { + switch (f) { + 0, 1 => {}, + 2 => { + combo = switch (combo) { + .pair1 => .pair2, + .triple => .full, + else => .pair1, + }; + }, + 3 => combo = if (combo == Combo.pair1) .full else .triple, + 4 => combo = .quad, + 5 => combo = .quint, + else => unreachable, + } + } + + return combo; + } + + fn evalHandWithJoker(hand: []const u8) Combo { + var cardF = [_]u32{0} ** 256; + var cmax: usize = 0; + + for (hand) |c| { + cardF[c] += 1; + if (c != 'J' and cardF[c] > cardF[cmax]) { + cmax = c; + } + } + + cardF[cmax] += cardF['J']; + + var combo = Combo.high; + for (cardF, 0..) |f, c| { + if (c == 'J') { + continue; + } + switch (f) { + 0, 1 => {}, + 2 => { + combo = switch (combo) { + .pair1 => .pair2, + .triple => .full, + else => .pair1, + }; + }, + 3 => combo = if (combo == Combo.pair1) .full else .triple, + 4 => combo = .quad, + 5 => combo = .quint, + else => unreachable, + } + } + + return combo; + } + + pub fn init(hand: []const u8, bid: u64) Player { + var res: Player = undefined; + res.bid = bid; + res.combo = Player.evalHand(hand); + mem.copy(u8, &res.hand, hand); + + return res; + } + + pub fn initWithJoker(hand: []const u8, bid: u64) Player { + var res: Player = undefined; + res.bid = bid; + res.combo = Player.evalHandWithJoker(hand); + mem.copy(u8, &res.hand, hand); + + return res; + } +}; + +fn cardValue(c: u8) u64 { + switch (c) { + '2'...'9' => return c - '0', + 'T' => return 10, + 'J' => return 11, + 'Q' => return 12, + 'K' => return 13, + 'A' => return 14, + else => unreachable, + } +} + +fn cmpCard(_: void, lhs: u8, rhs: u8) bool { + return cardValue(lhs) < cardValue(rhs); +} + +fn playerCmp(_: void, lhs: Player, rhs: Player) bool { + if (lhs.combo != rhs.combo) { + return @intFromEnum(lhs.combo) < @intFromEnum(rhs.combo); + } + + for (lhs.hand, rhs.hand) |l, r| { + if (l != r) { + return cmpCard(undefined, l, r); + } + } + + return false; +} + +fn cardValueWithJoker(c: u8) u64 { + switch (c) { + '2'...'9' => return c - '0', + 'T' => return 10, + 'J' => return 0, + 'Q' => return 12, + 'K' => return 13, + 'A' => return 14, + else => unreachable, + } +} + +fn cmpCardWithJoker(_: void, lhs: u8, rhs: u8) bool { + return cardValueWithJoker(lhs) < cardValueWithJoker(rhs); +} + +fn playerCmpWithJoker(_: void, lhs: Player, rhs: Player) bool { + if (lhs.combo != rhs.combo) { + return @intFromEnum(lhs.combo) < @intFromEnum(rhs.combo); + } + + for (lhs.hand, rhs.hand) |l, r| { + if (l != r) { + return cmpCardWithJoker(undefined, l, r); + } + } + + return false; +} + +pub fn part1(players: []Player) void { + var ans: u64 = 0; + + mem.sort(Player, players, {}, playerCmp); + + for (players, 1..) |p, rank| { + ans += p.bid * rank; + } + + print("{d}\n", .{ans}); +} + +pub fn part2(players: []Player) void { + var ans: u64 = 0; + + mem.sort(Player, players, {}, playerCmpWithJoker); + + for (players, 1..) |p, rank| { + ans += p.bid * rank; + } + + print("{d}\n", .{ans}); +} + +pub fn main() !void { + var splitLines = mem.splitScalar(u8, fin, '\n'); + var players_pt1 = ArrayList(Player).init(allocator); + var players_pt2 = ArrayList(Player).init(allocator); + defer { + players_pt1.deinit(); + players_pt2.deinit(); + } + + while (splitLines.next()) |line| { + var splitElem = mem.splitScalar(u8, line, ' '); + const hand = splitElem.next().?; + const bid = try std.fmt.parseInt(u64, splitElem.next().?, 10); + + try players_pt1.append(Player.init(hand, bid)); + try players_pt2.append(Player.initWithJoker(hand, bid)); + } + + part1(players_pt1.items); + part2(players_pt2.items); +} -- cgit v1.2.3