From 6afcea0fe495112cfbad92ff54833ba94ced23f9 Mon Sep 17 00:00:00 2001 From: Orfeas <38209077+0xfea5@users.noreply.github.com> Date: Fri, 8 Dec 2023 04:29:48 +0200 Subject: improving day7 solution --- day07/solution.zig | 160 ++++++++++++++++++----------------------------------- 1 file changed, 55 insertions(+), 105 deletions(-) (limited to 'day07/solution.zig') diff --git a/day07/solution.zig b/day07/solution.zig index b452dfb..05224bf 100644 --- a/day07/solution.zig +++ b/day07/solution.zig @@ -24,144 +24,91 @@ const Player = struct { 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 { + fn evalHand(self: *@This(), withJoker: bool) void { var cardF = [_]u32{0} ** 256; var cmax: usize = 0; - for (hand) |c| { + for (self.hand) |c| { cardF[c] += 1; - if (c != 'J' and cardF[c] > cardF[cmax]) { + if (withJoker and c != 'J' and cardF[c] > cardF[cmax]) { cmax = c; } } - cardF[cmax] += cardF['J']; + if (withJoker) { + cardF[cmax] += cardF['J']; + cardF['J'] = 0; + } 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, - }; + for (cardF) |f| { + combo = switch (f) { + 0, 1 => continue, + 2 => switch (combo) { + .pair1 => .pair2, + .triple => .full, + else => .pair1, }, - 3 => combo = if (combo == Combo.pair1) .full else .triple, - 4 => combo = .quad, - 5 => combo = .quint, + 3 => if (combo == Combo.pair1) .full else .triple, + 4 => .quad, + 5 => .quint, else => unreachable, - } + }; } - return combo; + self.combo = 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; + pub fn deinit(self: @This()) void { + allocator.free(self.hand); } }; 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, + return switch (c) { + '2'...'9' => c - '0', + 'T' => 10, + 'J' => 11, + 'Q' => 12, + 'K' => 13, + 'A' => 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, + return switch (c) { + '2'...'9' => c - '0', + 'T' => 10, + 'J' => 0, + 'Q' => 12, + 'K' => 13, + 'A' => 14, else => unreachable, - } + }; } -fn cmpCardWithJoker(_: void, lhs: u8, rhs: u8) bool { - return cardValueWithJoker(lhs) < cardValueWithJoker(rhs); +fn cmpCard(valueFunc: *const fn (u8) u64, lhs: u8, rhs: u8) bool { + return valueFunc(lhs) < valueFunc(rhs); } -fn playerCmpWithJoker(_: void, lhs: Player, rhs: Player) bool { +fn playerCmp(valueFunc: *const fn (u8) u64, 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 cmpCard(valueFunc, l, r); } } @@ -171,7 +118,10 @@ fn playerCmpWithJoker(_: void, lhs: Player, rhs: Player) bool { pub fn part1(players: []Player) void { var ans: u64 = 0; - mem.sort(Player, players, {}, playerCmp); + for (players) |*p| { + p.evalHand(false); + } + mem.sort(Player, players, &cardValue, playerCmp); for (players, 1..) |p, rank| { ans += p.bid * rank; @@ -183,7 +133,10 @@ pub fn part1(players: []Player) void { pub fn part2(players: []Player) void { var ans: u64 = 0; - mem.sort(Player, players, {}, playerCmpWithJoker); + for (players) |*p| { + p.evalHand(true); + } + mem.sort(Player, players, &cardValueWithJoker, playerCmp); for (players, 1..) |p, rank| { ans += p.bid * rank; @@ -194,11 +147,9 @@ pub fn part2(players: []Player) void { 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); + var players = ArrayList(Player).init(allocator); defer { - players_pt1.deinit(); - players_pt2.deinit(); + players.deinit(); } while (splitLines.next()) |line| { @@ -206,10 +157,9 @@ pub fn main() !void { 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)); + try players.append(Player.init(hand, bid)); } - part1(players_pt1.items); - part2(players_pt2.items); + part1(players.items); + part2(players.items); } -- cgit v1.2.3