diff options
| author | Orfeas <38209077+0xfea5@users.noreply.github.com> | 2023-12-08 01:48:35 +0200 |
|---|---|---|
| committer | Orfeas <38209077+0xfea5@users.noreply.github.com> | 2025-10-28 23:20:45 +0200 |
| commit | d872e4f9f61b2e08dd12cfd8212d1e5abc8a62d2 (patch) | |
| tree | 67804ffda0a44abd8dccdcf66956e41decf3eb17 | |
| parent | day6 (diff) | |
| download | aoc23-d872e4f9f61b2e08dd12cfd8212d1e5abc8a62d2.tar.gz aoc23-d872e4f9f61b2e08dd12cfd8212d1e5abc8a62d2.zip | |
day7
| -rw-r--r-- | day07/example.txt | 5 | ||||
| -rw-r--r-- | day07/solution.zig | 215 |
2 files changed, 220 insertions, 0 deletions
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 @@ | |||
| 1 | 32T3K 765 | ||
| 2 | T55J5 684 | ||
| 3 | KK677 28 | ||
| 4 | KTJJT 220 | ||
| 5 | 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 @@ | |||
| 1 | const std = @import("std"); | ||
| 2 | const print = std.debug.print; | ||
| 3 | const assert = std.debug.assert; | ||
| 4 | const ArrayList = std.ArrayList; | ||
| 5 | const HashMap = std.HashMap; | ||
| 6 | const mem = std.mem; | ||
| 7 | |||
| 8 | const fin = mem.trim(u8, @embedFile("./input.txt"), &std.ascii.whitespace); | ||
| 9 | var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||
| 10 | const allocator = gpa.allocator(); | ||
| 11 | |||
| 12 | const Combo = enum(u32) { | ||
| 13 | high, | ||
| 14 | pair1, | ||
| 15 | pair2, | ||
| 16 | triple, | ||
| 17 | full, | ||
| 18 | quad, | ||
| 19 | quint, | ||
| 20 | }; | ||
| 21 | |||
| 22 | const Player = struct { | ||
| 23 | bid: u64, | ||
| 24 | hand: [5]u8, | ||
| 25 | combo: Combo, | ||
| 26 | |||
| 27 | fn evalHand(hand: []const u8) Combo { | ||
| 28 | var cardF = [_]u32{0} ** 256; | ||
| 29 | |||
| 30 | for (hand) |c| { | ||
| 31 | cardF[c] += 1; | ||
| 32 | } | ||
| 33 | |||
| 34 | var combo = Combo.high; | ||
| 35 | for (cardF) |f| { | ||
| 36 | switch (f) { | ||
| 37 | 0, 1 => {}, | ||
| 38 | 2 => { | ||
| 39 | combo = switch (combo) { | ||
| 40 | .pair1 => .pair2, | ||
| 41 | .triple => .full, | ||
| 42 | else => .pair1, | ||
| 43 | }; | ||
| 44 | }, | ||
| 45 | 3 => combo = if (combo == Combo.pair1) .full else .triple, | ||
| 46 | 4 => combo = .quad, | ||
| 47 | 5 => combo = .quint, | ||
| 48 | else => unreachable, | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | return combo; | ||
| 53 | } | ||
| 54 | |||
| 55 | fn evalHandWithJoker(hand: []const u8) Combo { | ||
| 56 | var cardF = [_]u32{0} ** 256; | ||
| 57 | var cmax: usize = 0; | ||
| 58 | |||
| 59 | for (hand) |c| { | ||
| 60 | cardF[c] += 1; | ||
| 61 | if (c != 'J' and cardF[c] > cardF[cmax]) { | ||
| 62 | cmax = c; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | cardF[cmax] += cardF['J']; | ||
| 67 | |||
| 68 | var combo = Combo.high; | ||
| 69 | for (cardF, 0..) |f, c| { | ||
| 70 | if (c == 'J') { | ||
| 71 | continue; | ||
| 72 | } | ||
| 73 | switch (f) { | ||
| 74 | 0, 1 => {}, | ||
| 75 | 2 => { | ||
| 76 | combo = switch (combo) { | ||
| 77 | .pair1 => .pair2, | ||
| 78 | .triple => .full, | ||
| 79 | else => .pair1, | ||
| 80 | }; | ||
| 81 | }, | ||
| 82 | 3 => combo = if (combo == Combo.pair1) .full else .triple, | ||
| 83 | 4 => combo = .quad, | ||
| 84 | 5 => combo = .quint, | ||
| 85 | else => unreachable, | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | return combo; | ||
| 90 | } | ||
| 91 | |||
| 92 | pub fn init(hand: []const u8, bid: u64) Player { | ||
| 93 | var res: Player = undefined; | ||
| 94 | res.bid = bid; | ||
| 95 | res.combo = Player.evalHand(hand); | ||
| 96 | mem.copy(u8, &res.hand, hand); | ||
| 97 | |||
| 98 | return res; | ||
| 99 | } | ||
| 100 | |||
| 101 | pub fn initWithJoker(hand: []const u8, bid: u64) Player { | ||
| 102 | var res: Player = undefined; | ||
| 103 | res.bid = bid; | ||
| 104 | res.combo = Player.evalHandWithJoker(hand); | ||
| 105 | mem.copy(u8, &res.hand, hand); | ||
| 106 | |||
| 107 | return res; | ||
| 108 | } | ||
| 109 | }; | ||
| 110 | |||
| 111 | fn cardValue(c: u8) u64 { | ||
| 112 | switch (c) { | ||
| 113 | '2'...'9' => return c - '0', | ||
| 114 | 'T' => return 10, | ||
| 115 | 'J' => return 11, | ||
| 116 | 'Q' => return 12, | ||
| 117 | 'K' => return 13, | ||
| 118 | 'A' => return 14, | ||
| 119 | else => unreachable, | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | fn cmpCard(_: void, lhs: u8, rhs: u8) bool { | ||
| 124 | return cardValue(lhs) < cardValue(rhs); | ||
| 125 | } | ||
| 126 | |||
| 127 | fn playerCmp(_: void, lhs: Player, rhs: Player) bool { | ||
| 128 | if (lhs.combo != rhs.combo) { | ||
| 129 | return @intFromEnum(lhs.combo) < @intFromEnum(rhs.combo); | ||
| 130 | } | ||
| 131 | |||
| 132 | for (lhs.hand, rhs.hand) |l, r| { | ||
| 133 | if (l != r) { | ||
| 134 | return cmpCard(undefined, l, r); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | return false; | ||
| 139 | } | ||
| 140 | |||
| 141 | fn cardValueWithJoker(c: u8) u64 { | ||
| 142 | switch (c) { | ||
| 143 | '2'...'9' => return c - '0', | ||
| 144 | 'T' => return 10, | ||
| 145 | 'J' => return 0, | ||
| 146 | 'Q' => return 12, | ||
| 147 | 'K' => return 13, | ||
| 148 | 'A' => return 14, | ||
| 149 | else => unreachable, | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | fn cmpCardWithJoker(_: void, lhs: u8, rhs: u8) bool { | ||
| 154 | return cardValueWithJoker(lhs) < cardValueWithJoker(rhs); | ||
| 155 | } | ||
| 156 | |||
| 157 | fn playerCmpWithJoker(_: void, lhs: Player, rhs: Player) bool { | ||
| 158 | if (lhs.combo != rhs.combo) { | ||
| 159 | return @intFromEnum(lhs.combo) < @intFromEnum(rhs.combo); | ||
| 160 | } | ||
| 161 | |||
| 162 | for (lhs.hand, rhs.hand) |l, r| { | ||
| 163 | if (l != r) { | ||
| 164 | return cmpCardWithJoker(undefined, l, r); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | return false; | ||
| 169 | } | ||
| 170 | |||
| 171 | pub fn part1(players: []Player) void { | ||
| 172 | var ans: u64 = 0; | ||
| 173 | |||
| 174 | mem.sort(Player, players, {}, playerCmp); | ||
| 175 | |||
| 176 | for (players, 1..) |p, rank| { | ||
| 177 | ans += p.bid * rank; | ||
| 178 | } | ||
| 179 | |||
| 180 | print("{d}\n", .{ans}); | ||
| 181 | } | ||
| 182 | |||
| 183 | pub fn part2(players: []Player) void { | ||
| 184 | var ans: u64 = 0; | ||
| 185 | |||
| 186 | mem.sort(Player, players, {}, playerCmpWithJoker); | ||
| 187 | |||
| 188 | for (players, 1..) |p, rank| { | ||
| 189 | ans += p.bid * rank; | ||
| 190 | } | ||
| 191 | |||
| 192 | print("{d}\n", .{ans}); | ||
| 193 | } | ||
| 194 | |||
| 195 | pub fn main() !void { | ||
| 196 | var splitLines = mem.splitScalar(u8, fin, '\n'); | ||
| 197 | var players_pt1 = ArrayList(Player).init(allocator); | ||
| 198 | var players_pt2 = ArrayList(Player).init(allocator); | ||
| 199 | defer { | ||
| 200 | players_pt1.deinit(); | ||
| 201 | players_pt2.deinit(); | ||
| 202 | } | ||
| 203 | |||
| 204 | while (splitLines.next()) |line| { | ||
| 205 | var splitElem = mem.splitScalar(u8, line, ' '); | ||
| 206 | const hand = splitElem.next().?; | ||
| 207 | const bid = try std.fmt.parseInt(u64, splitElem.next().?, 10); | ||
| 208 | |||
| 209 | try players_pt1.append(Player.init(hand, bid)); | ||
| 210 | try players_pt2.append(Player.initWithJoker(hand, bid)); | ||
| 211 | } | ||
| 212 | |||
| 213 | part1(players_pt1.items); | ||
| 214 | part2(players_pt2.items); | ||
| 215 | } | ||
