diff --git a/src/day12.zig b/src/day12.zig index ddee97c..6981b16 100644 --- a/src/day12.zig +++ b/src/day12.zig @@ -14,8 +14,8 @@ const Solution = struct { b: usize, }; -fn hash(alloc: mem.Allocator, pattern: []const u8, groups: []const u8, curr_group: u8) ![]const u8 { - var a = try std.ArrayList(u8).initCapacity(alloc, pattern.len + groups.len + curr_group); +fn hash(alloc: mem.Allocator, pattern: []const u8, groups: []const u8, curr_group: u8) ![]u8 { + var a = try std.ArrayList(u8).initCapacity(alloc, pattern.len + groups.len + 1); try a.appendSlice(pattern); try a.appendSlice(groups); try a.append(curr_group); @@ -25,10 +25,10 @@ fn hash(alloc: mem.Allocator, pattern: []const u8, groups: []const u8, curr_grou // Mystery records to whether they fit. var memo: std.StringHashMap(u32) = undefined; -fn copy(comptime T: type, alloc: mem.Allocator, s: []const T) ![]T { - var a = try std.ArrayList(T).initCapacity(alloc, s.len); - try a.insertSlice(0, s); - return try a.toOwnedSlice(); +fn clone(comptime T: type, alloc: mem.Allocator, s: []const T) ![]T { + var a = try alloc.alloc(T, s.len); + @memcpy(a, s); + return a; } fn solvePattern(alloc: mem.Allocator, pattern: []const u8, groups: []const u8, curr_group: u8) !u32 { @@ -37,12 +37,12 @@ fn solvePattern(alloc: mem.Allocator, pattern: []const u8, groups: []const u8, c const h = try hash(alloc, pattern, groups, curr_group); if (memo.get(h)) |m| { alloc.free(h); - std.debug.print("==> short-circuit {}\n", .{m}); + std.debug.print("== short-circuit {}\n", .{m}); return m; } if (pattern.len == 0) { - std.debug.print("=> done ok: {}\n", .{groups.len == 0}); + std.debug.print("== done {}\n", .{groups.len == 0}); return if (groups.len == 0) 1 else 0; } @@ -56,6 +56,7 @@ fn solvePattern(alloc: mem.Allocator, pattern: []const u8, groups: []const u8, c } // Special-case last # if (pattern.len == 1 and groups.len == 1 and groups[0] == curr_group + 1) { + std.debug.print("== done true\n", .{}); break :b 1; } break :b try solvePattern(alloc, pattern[1..], groups, curr_group + 1); @@ -68,7 +69,6 @@ fn solvePattern(alloc: mem.Allocator, pattern: []const u8, groups: []const u8, c break :b 0; } else { // Group done - std.debug.print("=> group {} ok\n", .{groups[0]}); break :b try solvePattern(alloc, pattern[1..], groups[1..], 0); } } else { @@ -77,9 +77,9 @@ fn solvePattern(alloc: mem.Allocator, pattern: []const u8, groups: []const u8, c } }, '?' => { - const p1 = try copy(u8, alloc, pattern); + const p1 = try clone(u8, alloc, pattern); defer alloc.free(p1); - const p2 = try copy(u8, alloc, pattern); + const p2 = try clone(u8, alloc, pattern); defer alloc.free(p2); p1[0] = '#'; @@ -99,12 +99,24 @@ fn solvePattern(alloc: mem.Allocator, pattern: []const u8, groups: []const u8, c return res; } +fn unfold(alloc: mem.Allocator, input: []const u8, sep: u8) ![]const u8 { + var buf = try std.ArrayList(u8).initCapacity(alloc, input.len * 5 + 5); + for (0..5) |i| { + if (i > 0 and sep > 0) try buf.append(sep); + try buf.appendSlice(input); + } + return try buf.toOwnedSlice(); +} + fn solve(alloc: mem.Allocator, input: []const u8) !Solution { memo = std.StringHashMap(u32).init(alloc); defer memo.deinit(); - var sum: u32 = 0; + var sum1: u32 = 0; + var sum2: u32 = 0; + var it = util.splitLines(input); + var i: u32 = 0; while (it.next()) |line| { if (line.len == 0) continue; @@ -114,9 +126,16 @@ fn solve(alloc: mem.Allocator, input: []const u8) !Solution { const groups = try util.parseIntsScalar(u8, alloc, raw_groups, .{ .sep = ',' }); defer alloc.free(groups); - std.debug.print("-----------------------------------------------\n", .{}); - sum += try solvePattern(alloc, pattern, groups, 0); - std.debug.print("{}\n", .{sum}); + const unfolded_pattern = try unfold(alloc, pattern, '?'); + const unfolded_groups = try unfold(alloc, groups, 0); + defer alloc.free(unfolded_pattern); + defer alloc.free(unfolded_groups); + + std.debug.print("---- {} ----\n", .{i}); + sum1 += try solvePattern(alloc, pattern, groups, 0); + sum2 += try solvePattern(alloc, unfolded_pattern, unfolded_groups, 0); + std.debug.print("{} {}\n", .{ sum1, sum2 }); + i += 1; } var mkeys = memo.keyIterator(); @@ -124,7 +143,7 @@ fn solve(alloc: mem.Allocator, input: []const u8) !Solution { alloc.free(k.*); } - return .{ .a = sum, .b = 0 }; + return .{ .a = sum1, .b = sum2 }; } test "silver" { @@ -140,15 +159,34 @@ test "silver" { try std.testing.expectEqual(@as(usize, 21), sln.a); } -test "gold" { +test "gold-2" { const input = - \\???.### 1,1,3 \\.??..??...?##. 1,1,3 - \\?#?#?#?#?#?#?#? 1,3,1,6 + ; + const sln = try solve(std.testing.allocator, input); + try std.testing.expectEqual(@as(usize, 16384), sln.b); +} + +test "gold-4" { + const input = \\????.#...#... 4,1,1 + ; + const sln = try solve(std.testing.allocator, input); + try std.testing.expectEqual(@as(usize, 16), sln.b); +} + +test "gold-5" { + const input = \\????.######..#####. 1,6,5 + ; + const sln = try solve(std.testing.allocator, input); + try std.testing.expectEqual(@as(usize, 2500), sln.b); +} + +test "gold-6" { + const input = \\?###???????? 3,2,1 ; const sln = try solve(std.testing.allocator, input); - try std.testing.expectEqual(@as(usize, 525152), sln.b); + try std.testing.expectEqual(@as(usize, 506250), sln.b); }