FEAT: Day12
This commit is contained in:
@ -1,6 +1,198 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const print = std.debug.print;
|
const print = std.debug.print;
|
||||||
|
const expect = std.testing.expect;
|
||||||
|
|
||||||
|
var MEMOIZED: std.StringHashMap(usize) = undefined;
|
||||||
|
|
||||||
|
fn rec_solve(allocator: std.mem.Allocator, input: []const u8, config: []u8) !usize {
|
||||||
|
var inputConfigArr = [2][]const u8{ input, config };
|
||||||
|
var inputConfig = try std.mem.concat(allocator, u8, &inputConfigArr);
|
||||||
|
// defer allocator.free(inputConfig);
|
||||||
|
|
||||||
|
if (MEMOIZED.get(inputConfig)) |num| {
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.len == 0) {
|
||||||
|
if (config.len == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.len == 0) {
|
||||||
|
var hash = [_]u8{'#'};
|
||||||
|
if (std.mem.containsAtLeast(u8, input, 1, &hash)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input[0] == '.') {
|
||||||
|
var res = try rec_solve(allocator, input[1..], config[0..]);
|
||||||
|
|
||||||
|
try MEMOIZED.put(inputConfig, res);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If unknown, try both.
|
||||||
|
if (input[0] == '?') {
|
||||||
|
var dotInput = try allocator.alloc(u8, input.len);
|
||||||
|
var hashInput = try allocator.alloc(u8, input.len);
|
||||||
|
|
||||||
|
std.mem.copy(u8, dotInput, input);
|
||||||
|
std.mem.copy(u8, hashInput, input);
|
||||||
|
|
||||||
|
dotInput[0] = '.';
|
||||||
|
hashInput[0] = '#';
|
||||||
|
|
||||||
|
defer allocator.free(dotInput);
|
||||||
|
defer allocator.free(hashInput);
|
||||||
|
|
||||||
|
var res = try rec_solve(allocator, dotInput[0..], config[0..]) + try rec_solve(allocator, hashInput[0..], config[0..]);
|
||||||
|
|
||||||
|
try MEMOIZED.put(inputConfig, res);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #? -> {1, 1}
|
||||||
|
// ### -> {3}
|
||||||
|
|
||||||
|
if (input[0] == '#') {
|
||||||
|
var current = config[0];
|
||||||
|
|
||||||
|
// ### -> {3}
|
||||||
|
// Not long enough to match
|
||||||
|
if (input.len < current) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var containsDots = false;
|
||||||
|
for (0..current) |i| {
|
||||||
|
if (input[i] == '.') {
|
||||||
|
containsDots = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Doesnt match the current one
|
||||||
|
// #.# -> {3}
|
||||||
|
if (containsDots) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ### -> {3}
|
||||||
|
// ##?. -> {3}
|
||||||
|
// [] -> {}
|
||||||
|
|
||||||
|
if (input.len == current) {
|
||||||
|
var res = try rec_solve(allocator, "", config[1..]);
|
||||||
|
|
||||||
|
try MEMOIZED.put(inputConfig, res);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input[current] == '#') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = try rec_solve(allocator, input[current + 1 ..], config[1..]);
|
||||||
|
|
||||||
|
try MEMOIZED.put(inputConfig, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn solve(input: [][]const u8) !void {
|
pub fn solve(input: [][]const u8) !void {
|
||||||
_ = input;
|
var allocator = std.heap.page_allocator;
|
||||||
|
|
||||||
|
var part1: usize = 0;
|
||||||
|
var part2: usize = 0;
|
||||||
|
|
||||||
|
MEMOIZED = std.StringHashMap(usize).init(allocator);
|
||||||
|
|
||||||
|
for (input) |line| {
|
||||||
|
var splitIter = std.mem.splitSequence(u8, line, " ");
|
||||||
|
|
||||||
|
var pattern = splitIter.next().?;
|
||||||
|
var config = splitIter.next().?;
|
||||||
|
|
||||||
|
var used: usize = 0;
|
||||||
|
var numberConfig = try allocator.alloc(u8, 20);
|
||||||
|
|
||||||
|
var commaIter = std.mem.splitSequence(u8, config, ",");
|
||||||
|
while (commaIter.next()) |num| {
|
||||||
|
numberConfig[used] = try std.fmt.parseInt(u8, num, 10);
|
||||||
|
|
||||||
|
used += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fivePattern = std.ArrayList(u8).init(allocator);
|
||||||
|
|
||||||
|
try fivePattern.appendSlice(pattern);
|
||||||
|
try fivePattern.append('?');
|
||||||
|
try fivePattern.appendSlice(pattern);
|
||||||
|
try fivePattern.append('?');
|
||||||
|
try fivePattern.appendSlice(pattern);
|
||||||
|
try fivePattern.append('?');
|
||||||
|
try fivePattern.appendSlice(pattern);
|
||||||
|
try fivePattern.append('?');
|
||||||
|
try fivePattern.appendSlice(pattern);
|
||||||
|
|
||||||
|
var fiveConfig = std.ArrayList(u8).init(allocator);
|
||||||
|
|
||||||
|
try fiveConfig.appendSlice(numberConfig[0..used]);
|
||||||
|
try fiveConfig.appendSlice(numberConfig[0..used]);
|
||||||
|
try fiveConfig.appendSlice(numberConfig[0..used]);
|
||||||
|
try fiveConfig.appendSlice(numberConfig[0..used]);
|
||||||
|
try fiveConfig.appendSlice(numberConfig[0..used]);
|
||||||
|
|
||||||
|
var fivePatternSlice = try fivePattern.toOwnedSlice();
|
||||||
|
var fiveConfigSlice = try fiveConfig.toOwnedSlice();
|
||||||
|
|
||||||
|
part1 += try rec_solve(allocator, pattern, numberConfig[0..used]);
|
||||||
|
part2 += try rec_solve(allocator, fivePatternSlice, fiveConfigSlice);
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Part 1: {}\n", .{part1});
|
||||||
|
print("Part 2: {}\n", .{part2});
|
||||||
|
}
|
||||||
|
|
||||||
|
test "Basic easy example" {
|
||||||
|
var example1 = "#.#.###";
|
||||||
|
var example1Config = [_]u16{ 1, 1, 3 };
|
||||||
|
var allocator = std.heap.page_allocator;
|
||||||
|
|
||||||
|
try expect(try rec_solve(allocator, example1, &example1Config) == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "More complicated example" {
|
||||||
|
var example1 = "???.###";
|
||||||
|
var example1Config = [_]u16{ 1, 1, 3 };
|
||||||
|
var allocator = std.heap.page_allocator;
|
||||||
|
|
||||||
|
var res = try rec_solve(allocator, example1, &example1Config);
|
||||||
|
|
||||||
|
print("Result: {}\n", .{res});
|
||||||
|
|
||||||
|
try std.testing.expectEqual(res, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "Even more complex" {
|
||||||
|
var example1 = "?###????????";
|
||||||
|
var example1Config = [_]u16{ 3, 2, 1 };
|
||||||
|
var allocator = std.heap.page_allocator;
|
||||||
|
|
||||||
|
var res = try rec_solve(allocator, example1, &example1Config);
|
||||||
|
|
||||||
|
print("Result: {}\n", .{res});
|
||||||
|
|
||||||
|
try std.testing.expectEqual(res, 10);
|
||||||
}
|
}
|
||||||
|
@ -9,20 +9,20 @@ const std = @import("std");
|
|||||||
// const day9 = @import("./day9/day9.zig");
|
// const day9 = @import("./day9/day9.zig");
|
||||||
// const day10 = @import("./day10/day10.zig");
|
// const day10 = @import("./day10/day10.zig");
|
||||||
// const day11 = @import("./day11/day11.zig");
|
// const day11 = @import("./day11/day11.zig");
|
||||||
// const day12 = @import("./day12/day12.zig");
|
const day = @import("./day12/day12.zig");
|
||||||
// const day15 = @import("./day15/day15.zig");
|
// const day15 = @import("./day15/day15.zig");
|
||||||
// const day16 = @import("./day16/day16.zig");
|
// const day16 = @import("./day16/day16.zig");
|
||||||
// const day18 = @import("./day18/day18.zig");
|
// const day18 = @import("./day18/day18.zig");
|
||||||
// const day19 = @import("./day19/day19.zig");
|
// const day19 = @import("./day19/day19.zig");
|
||||||
// const day21 = @import("./day21/day21.zig");
|
// const day21 = @import("./day21/day21.zig");
|
||||||
// const day23 = @import("./day23/day23.zig");
|
// const day23 = @import("./day23/day23.zig");
|
||||||
const day24 = @import("./day24/day24.zig");
|
// const day24 = @import("./day24/day24.zig");
|
||||||
const utils = @import("utils.zig");
|
const utils = @import("utils.zig");
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
const allocator = std.heap.page_allocator;
|
const allocator = std.heap.page_allocator;
|
||||||
var input = try utils.getInput("./src/day24/input.txt", allocator);
|
var input = try utils.getInput("./src/day12/input.txt", allocator);
|
||||||
defer allocator.free(input);
|
defer allocator.free(input);
|
||||||
|
|
||||||
try day24.solve(input);
|
try day.solve(input);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user