aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOrfeas <38209077+0xfea5@users.noreply.github.com>2023-12-15 07:06:46 +0200
committerOrfeas <38209077+0xfea5@users.noreply.github.com>2025-10-28 23:20:45 +0200
commit6cc767fe206b7eb27bf5ee9f049414ebd8628f1c (patch)
tree191812bca445b49c1b57dea7e747ae6fa81fc653
parentday14 (diff)
downloadaoc23-6cc767fe206b7eb27bf5ee9f049414ebd8628f1c.tar.gz
aoc23-6cc767fe206b7eb27bf5ee9f049414ebd8628f1c.zip
day12 revamped
thanks anemo
-rw-r--r--day12/solution.zig164
1 files changed, 33 insertions, 131 deletions
diff --git a/day12/solution.zig b/day12/solution.zig
index bb335ba..30b0926 100644
--- a/day12/solution.zig
+++ b/day12/solution.zig
@@ -14,139 +14,45 @@ const Record = struct {
14 arrangement: []const u64, 14 arrangement: []const u64,
15}; 15};
16 16
17const State = struct { 17// Credit: https://github.com/RestrictedPower/Advent-of-Code-2023/blob/main/Day12/main.py
18 i: u8, 18fn evaluate(springs: []const u8, arrangement: []const u64) u64 {
19 j: u8, 19 const DPSIZE = 200;
20 streak: u8, 20 var dp = [_][DPSIZE][2]u64{[_][2]u64{[_]u64{0} ** 2} ** DPSIZE} ** DPSIZE;
21 prev: u8,
22
23 pub fn print(self: @This(), springs: []const u8, arrangement: []const u64) void {
24 std.debug.print("streak = {d}, prev = {c} springs = '{s}' | ", .{ self.streak, self.prev, springs[self.i..] });
25 if (self.j <= arrangement.len) {
26 for (arrangement[self.j..]) |arr| {
27 std.debug.print("{d}, ", .{arr});
28 }
29 std.debug.print("\n", .{});
30 }
31 }
32 21
33 pub const ctx = struct { 22 dp[0][0][0] = 1;
34 pub fn hash(_: @This(), s: State) u64 {
35 return (@as(u32, s.i) << 24 | @as(u32, s.j) << 16 | @as(u32, s.prev) << 8 | s.streak);
36 }
37 23
38 pub fn eql(_: @This(), lhs: State, rhs: State) bool { 24 for (springs, 1..) |c, i| {
39 return lhs.i == rhs.i and 25 if (c == '.' or c == '?') {
40 lhs.j == rhs.j and 26 for (0..arrangement.len + 1) |j| {
41 lhs.prev == rhs.prev and 27 dp[i][j][0] = dp[i - 1][j][0] + dp[i - 1][j][1];
42 lhs.streak == rhs.streak; 28 }
43 } 29 }
44 };
45};
46
47const DPHashMap = HashMap(State, u64, State.ctx, 80);
48 30
49fn evaluate(dp: *DPHashMap, springs: []const u8, arrangement: []const u64, state: State) u64 { 31 for (arrangement, 1..) |n, j| {
50 var ans: u64 = 0; 32 const begidx: u64 = if (i >= n) i - n else 0;
51 var prev = state.prev; 33 const segment = springs[begidx..i];
52 var streak = state.streak; 34 const possible = mem.indexOfScalar(u8, segment, '.') == null;
53 var j = state.j;
54
55 if (dp.get(state)) |val| {
56 return val;
57 }
58
59 defer {
60 dp.put(state, ans) catch unreachable;
61 }
62
63 if (j > arrangement.len or
64 j == arrangement.len and streak > 0 or
65 j < arrangement.len and streak > arrangement[j])
66 {
67 ans = 0;
68 return 0;
69 }
70 35
71 for (springs[state.i..], state.i..) |c, i| { 36 if (possible and i >= n) {
72 switch (c) { 37 dp[i][j][1] = dp[begidx][j - 1][0];
73 '?' => { 38 }
74 // Assume current = '.'
75 const e1 = if (prev == '.')
76 evaluate(dp, springs, arrangement, State{
77 .i = @as(u8, @intCast(i)) + 1,
78 .j = j,
79 .streak = 0,
80 .prev = '.',
81 })
82 else if (j < arrangement.len and streak == arrangement[j])
83 evaluate(dp, springs, arrangement, State{
84 .i = @as(u8, @intCast(i)) + 1,
85 .j = j + 1,
86 .streak = 0,
87 .prev = '.',
88 })
89 else
90 0;
91
92 // Assume current = '#'
93 const e2 = evaluate(dp, springs, arrangement, State{
94 .i = @as(u8, @intCast(i)) + 1,
95 .j = j,
96 .streak = streak + 1,
97 .prev = '#',
98 });
99
100 ans = e1 + e2;
101 return ans;
102 },
103 '#' => {
104 streak += 1;
105 },
106 '.' => {
107 if (prev == '#') {
108 if (j < arrangement.len and streak != arrangement[j] or j >= arrangement.len) {
109 ans = 0;
110 return ans;
111 }
112 j += 1;
113 }
114 streak = 0;
115 },
116 else => unreachable,
117 } 39 }
118
119 prev = c;
120 } 40 }
121 41
122 ans = if (j >= arrangement.len and streak == 0 or 42 return dp[springs.len][arrangement.len][0] +
123 j == arrangement.len - 1 and streak == arrangement[j]) 43 dp[springs.len][arrangement.len][1];
124 1
125 else
126 0;
127
128 return ans;
129} 44}
130 45
131pub fn solve(records: []const Record) !void { 46fn part1(records: []const Record) void {
132 var part1: u64 = 0; 47 var ans: u64 = 0;
133
134 for (records) |record| { 48 for (records) |record| {
135 const state = State{ 49 ans += evaluate(record.springs, record.arrangement);
136 .i = 0,
137 .j = 0,
138 .streak = 0,
139 .prev = '.',
140 };
141 var dp = DPHashMap.init(allocator);
142 const e = evaluate(&dp, record.springs, record.arrangement, state);
143 part1 += e;
144 } 50 }
51 print("{d}\n", .{ans});
52}
145 53
146 print("{d}\n", .{part1}); 54fn part2(records: []const Record) !void {
147 55 var ans: u64 = 0;
148 var part2: u64 = 0;
149
150 for (records) |record| { 56 for (records) |record| {
151 const unfolded_springs = try allocator.alloc(u8, record.springs.len * 5 + 4); 57 const unfolded_springs = try allocator.alloc(u8, record.springs.len * 5 + 4);
152 _ = try std.fmt.bufPrint(unfolded_springs, "{s}?{s}?{s}?{s}?{s}", .{ 58 _ = try std.fmt.bufPrint(unfolded_springs, "{s}?{s}?{s}?{s}?{s}", .{
@@ -161,18 +67,14 @@ pub fn solve(records: []const Record) !void {
161 for (0..5) |_| { 67 for (0..5) |_| {
162 try unfolded_arrangement.appendSlice(record.arrangement); 68 try unfolded_arrangement.appendSlice(record.arrangement);
163 } 69 }
164 70 ans += evaluate(unfolded_springs, unfolded_arrangement.items);
165 const state = State{
166 .i = 0,
167 .j = 0,
168 .streak = 0,
169 .prev = '.',
170 };
171 var dp = DPHashMap.init(allocator);
172 const e = evaluate(&dp, unfolded_springs, unfolded_arrangement.items, state);
173 part2 += e;
174 } 71 }
175 print("{d}\n", .{part2}); 72 print("{d}\n", .{ans});
73}
74
75pub fn solve(records: []const Record) !void {
76 part1(records);
77 try part2(records);
176} 78}
177 79
178pub fn main() !void { 80pub fn main() !void {