aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOrfeas <38209077+0xfea5@users.noreply.github.com>2023-12-08 04:29:48 +0200
committerOrfeas <38209077+0xfea5@users.noreply.github.com>2025-10-28 23:20:45 +0200
commit6afcea0fe495112cfbad92ff54833ba94ced23f9 (patch)
treefed9a77402ae21afadf05a4d09fed62aa36d1133
parentday7 (diff)
downloadaoc23-6afcea0fe495112cfbad92ff54833ba94ced23f9.tar.gz
aoc23-6afcea0fe495112cfbad92ff54833ba94ced23f9.zip
improving day7 solution
-rw-r--r--day07/solution.zig160
1 files changed, 55 insertions, 105 deletions
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 {
24 hand: [5]u8, 24 hand: [5]u8,
25 combo: Combo, 25 combo: Combo,
26 26
27 fn evalHand(hand: []const u8) Combo { 27 fn evalHand(self: *@This(), withJoker: bool) void {
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; 28 var cardF = [_]u32{0} ** 256;
57 var cmax: usize = 0; 29 var cmax: usize = 0;
58 30
59 for (hand) |c| { 31 for (self.hand) |c| {
60 cardF[c] += 1; 32 cardF[c] += 1;
61 if (c != 'J' and cardF[c] > cardF[cmax]) { 33 if (withJoker and c != 'J' and cardF[c] > cardF[cmax]) {
62 cmax = c; 34 cmax = c;
63 } 35 }
64 } 36 }
65 37
66 cardF[cmax] += cardF['J']; 38 if (withJoker) {
39 cardF[cmax] += cardF['J'];
40 cardF['J'] = 0;
41 }
67 42
68 var combo = Combo.high; 43 var combo = Combo.high;
69 for (cardF, 0..) |f, c| { 44 for (cardF) |f| {
70 if (c == 'J') { 45 combo = switch (f) {
71 continue; 46 0, 1 => continue,
72 } 47 2 => switch (combo) {
73 switch (f) { 48 .pair1 => .pair2,
74 0, 1 => {}, 49 .triple => .full,
75 2 => { 50 else => .pair1,
76 combo = switch (combo) {
77 .pair1 => .pair2,
78 .triple => .full,
79 else => .pair1,
80 };
81 }, 51 },
82 3 => combo = if (combo == Combo.pair1) .full else .triple, 52 3 => if (combo == Combo.pair1) .full else .triple,
83 4 => combo = .quad, 53 4 => .quad,
84 5 => combo = .quint, 54 5 => .quint,
85 else => unreachable, 55 else => unreachable,
86 } 56 };
87 } 57 }
88 58
89 return combo; 59 self.combo = combo;
90 } 60 }
91 61
92 pub fn init(hand: []const u8, bid: u64) Player { 62 pub fn init(hand: []const u8, bid: u64) Player {
93 var res: Player = undefined; 63 var res: Player = undefined;
64
94 res.bid = bid; 65 res.bid = bid;
95 res.combo = Player.evalHand(hand);
96 mem.copy(u8, &res.hand, hand); 66 mem.copy(u8, &res.hand, hand);
97 67
98 return res; 68 return res;
99 } 69 }
100 70
101 pub fn initWithJoker(hand: []const u8, bid: u64) Player { 71 pub fn deinit(self: @This()) void {
102 var res: Player = undefined; 72 allocator.free(self.hand);
103 res.bid = bid;
104 res.combo = Player.evalHandWithJoker(hand);
105 mem.copy(u8, &res.hand, hand);
106
107 return res;
108 } 73 }
109}; 74};
110 75
111fn cardValue(c: u8) u64 { 76fn cardValue(c: u8) u64 {
112 switch (c) { 77 return switch (c) {
113 '2'...'9' => return c - '0', 78 '2'...'9' => c - '0',
114 'T' => return 10, 79 'T' => 10,
115 'J' => return 11, 80 'J' => 11,
116 'Q' => return 12, 81 'Q' => 12,
117 'K' => return 13, 82 'K' => 13,
118 'A' => return 14, 83 'A' => 14,
119 else => unreachable, 84 else => unreachable,
120 } 85 };
121}
122
123fn cmpCard(_: void, lhs: u8, rhs: u8) bool {
124 return cardValue(lhs) < cardValue(rhs);
125}
126
127fn 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} 86}
140 87
141fn cardValueWithJoker(c: u8) u64 { 88fn cardValueWithJoker(c: u8) u64 {
142 switch (c) { 89 return switch (c) {
143 '2'...'9' => return c - '0', 90 '2'...'9' => c - '0',
144 'T' => return 10, 91 'T' => 10,
145 'J' => return 0, 92 'J' => 0,
146 'Q' => return 12, 93 'Q' => 12,
147 'K' => return 13, 94 'K' => 13,
148 'A' => return 14, 95 'A' => 14,
149 else => unreachable, 96 else => unreachable,
150 } 97 };
151} 98}
152 99
153fn cmpCardWithJoker(_: void, lhs: u8, rhs: u8) bool { 100fn cmpCard(valueFunc: *const fn (u8) u64, lhs: u8, rhs: u8) bool {
154 return cardValueWithJoker(lhs) < cardValueWithJoker(rhs); 101 return valueFunc(lhs) < valueFunc(rhs);
155} 102}
156 103
157fn playerCmpWithJoker(_: void, lhs: Player, rhs: Player) bool { 104fn playerCmp(valueFunc: *const fn (u8) u64, lhs: Player, rhs: Player) bool {
158 if (lhs.combo != rhs.combo) { 105 if (lhs.combo != rhs.combo) {
159 return @intFromEnum(lhs.combo) < @intFromEnum(rhs.combo); 106 return @intFromEnum(lhs.combo) < @intFromEnum(rhs.combo);
160 } 107 }
161 108
162 for (lhs.hand, rhs.hand) |l, r| { 109 for (lhs.hand, rhs.hand) |l, r| {
163 if (l != r) { 110 if (l != r) {
164 return cmpCardWithJoker(undefined, l, r); 111 return cmpCard(valueFunc, l, r);
165 } 112 }
166 } 113 }
167 114
@@ -171,7 +118,10 @@ fn playerCmpWithJoker(_: void, lhs: Player, rhs: Player) bool {
171pub fn part1(players: []Player) void { 118pub fn part1(players: []Player) void {
172 var ans: u64 = 0; 119 var ans: u64 = 0;
173 120
174 mem.sort(Player, players, {}, playerCmp); 121 for (players) |*p| {
122 p.evalHand(false);
123 }
124 mem.sort(Player, players, &cardValue, playerCmp);
175 125
176 for (players, 1..) |p, rank| { 126 for (players, 1..) |p, rank| {
177 ans += p.bid * rank; 127 ans += p.bid * rank;
@@ -183,7 +133,10 @@ pub fn part1(players: []Player) void {
183pub fn part2(players: []Player) void { 133pub fn part2(players: []Player) void {
184 var ans: u64 = 0; 134 var ans: u64 = 0;
185 135
186 mem.sort(Player, players, {}, playerCmpWithJoker); 136 for (players) |*p| {
137 p.evalHand(true);
138 }
139 mem.sort(Player, players, &cardValueWithJoker, playerCmp);
187 140
188 for (players, 1..) |p, rank| { 141 for (players, 1..) |p, rank| {
189 ans += p.bid * rank; 142 ans += p.bid * rank;
@@ -194,11 +147,9 @@ pub fn part2(players: []Player) void {
194 147
195pub fn main() !void { 148pub fn main() !void {
196 var splitLines = mem.splitScalar(u8, fin, '\n'); 149 var splitLines = mem.splitScalar(u8, fin, '\n');
197 var players_pt1 = ArrayList(Player).init(allocator); 150 var players = ArrayList(Player).init(allocator);
198 var players_pt2 = ArrayList(Player).init(allocator);
199 defer { 151 defer {
200 players_pt1.deinit(); 152 players.deinit();
201 players_pt2.deinit();
202 } 153 }
203 154
204 while (splitLines.next()) |line| { 155 while (splitLines.next()) |line| {
@@ -206,10 +157,9 @@ pub fn main() !void {
206 const hand = splitElem.next().?; 157 const hand = splitElem.next().?;
207 const bid = try std.fmt.parseInt(u64, splitElem.next().?, 10); 158 const bid = try std.fmt.parseInt(u64, splitElem.next().?, 10);
208 159
209 try players_pt1.append(Player.init(hand, bid)); 160 try players.append(Player.init(hand, bid));
210 try players_pt2.append(Player.initWithJoker(hand, bid));
211 } 161 }
212 162
213 part1(players_pt1.items); 163 part1(players.items);
214 part2(players_pt2.items); 164 part2(players.items);
215} 165}