diff options
author | Mathias Magnusson <mathias@magnusson.space> | 2024-12-04 13:25:01 +0100 |
---|---|---|
committer | Mathias Magnusson <mathias@magnusson.space> | 2024-12-04 13:25:06 +0100 |
commit | 26063c022ae7d1bef1575cf1487053a2ecd9445f (patch) | |
tree | f0d3da9fc4b44037437d423a5b220b86dee0a114 /aoc24 | |
parent | 45c79eb6508a523f760352c4eb273ec1c9d42b16 (diff) | |
download | programming-problem-solving-26063c022ae7d1bef1575cf1487053a2ecd9445f.tar.gz |
aoc2024: day 4
Diffstat (limited to 'aoc24')
-rw-r--r-- | aoc24/src/day4.zig | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/aoc24/src/day4.zig b/aoc24/src/day4.zig new file mode 100644 index 0000000..13df02d --- /dev/null +++ b/aoc24/src/day4.zig @@ -0,0 +1,109 @@ +const std = @import("std"); + +fn cast(n: usize) i32 { + return @intCast(n); +} + +const Input = struct { + buf: []const u8, + w: usize, + h: usize, + + pub fn at(self: Input, x: i32, y: i32) ?u8 { + if (x < 0 or x >= self.w or y < 0 or y >= self.h) return null; + return self.buf[@intCast(y * (@as(i32, @intCast(self.w)) + 1) + x)]; + } +}; + +pub fn parse(_: std.mem.Allocator, data: []const u8) !Input { + const width = std.mem.indexOf(u8, data, "\n") orelse return error.InvalidInput; + const height = data.len / (width + 1); + std.debug.assert((width + 1) * height == data.len); + return .{ .buf = data, .w = width, .h = height }; +} + +test "part1" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + + const output = try part1(arena.allocator(), try parse(arena.allocator(), + \\MMMSXXMASM + \\MSAMXMSMSA + \\AMXSXMAAMM + \\MSAMASMSMX + \\XMASAMXAMM + \\XXAMMXXAMA + \\SMSMSASXSS + \\SAXAMASAAA + \\MAMMMXMMMM + \\MXMXAXMASX + \\ + )); + std.debug.print("got {}\n", .{output}); + std.debug.assert(output == 18); +} + +pub fn part1(_: std.mem.Allocator, input: Input) !u32 { + var count: u32 = 0; + for (0..input.h) |y| for (0..input.w) |x| for ([_]@Vector(2, i32){ + .{ 1, 0 }, + .{ 1, -1 }, + .{ 0, -1 }, + .{ -1, -1 }, + .{ -1, 0 }, + .{ -1, 1 }, + .{ 0, 1 }, + .{ 1, 1 }, + }) |dir| { + for (0.., "XMAS") |dist, c| { + if (input.at(cast(x) + dir[0] * cast(dist), cast(y) + cast(dist) * dir[1]) != c) { + break; + } + } else { + count += 1; + } + }; + + return count; +} + +test "part2" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + + const output = try part2(arena.allocator(), try parse(arena.allocator(), + \\MMMSXXMASM + \\MSAMXMSMSA + \\AMXSXMAAMM + \\MSAMASMSMX + \\XMASAMXAMM + \\XXAMMXXAMA + \\SMSMSASXSS + \\SAXAMASAAA + \\MAMMMXMMMM + \\MXMXAXMASX + \\ + )); + std.debug.print("got {}\n", .{output}); + std.debug.assert(output == 9); +} + +fn isOther(a: ?u8, b: ?u8) bool { + return switch (a orelse return false) { + 'M' => b == 'S', + 'S' => b == 'M', + else => false, + }; +} + +pub fn part2(_: std.mem.Allocator, input: Input) !u32 { + var count: u32 = 0; + for (0..input.h) |y| for (0..input.w) |x| { + if (input.at(cast(x), cast(y)) != 'A') continue; + if (!isOther(input.at(cast(x) - 1, cast(y) - 1), input.at(cast(x) + 1, cast(y) + 1))) continue; + if (!isOther(input.at(cast(x) + 1, cast(y) - 1), input.at(cast(x) - 1, cast(y) + 1))) continue; + count += 1; + }; + + return count; +} |