mirror of
https://github.com/MorizzG/aoc-2024.git
synced 2025-12-06 04:22:43 +00:00
day 3 done
also fixed up a bunch of stuff on day 1 and day 2
This commit is contained in:
parent
61d7d0f486
commit
ec56f69ecd
11 changed files with 1907 additions and 330 deletions
282
day3.zig
Normal file
282
day3.zig
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
const std = @import("std");
|
||||
|
||||
const utils = @import("utils.zig");
|
||||
|
||||
const isDigit = std.ascii.isDigit;
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
const alloc = gpa.allocator();
|
||||
|
||||
const filename = "inputs/day3.txt";
|
||||
|
||||
{
|
||||
const file_reader = try utils.FileReader.init(alloc, filename);
|
||||
defer file_reader.deinit();
|
||||
|
||||
const result = try part1(alloc, file_reader.reader());
|
||||
|
||||
try std.io.getStdOut().writer().print("Day 2, part 1: {}\n", .{result});
|
||||
}
|
||||
|
||||
{
|
||||
const file_reader = try utils.FileReader.init(alloc, filename);
|
||||
defer file_reader.deinit();
|
||||
|
||||
const result = try part2(alloc, file_reader.reader());
|
||||
|
||||
try std.io.getStdOut().writer().print("Day 2, part 2: {}\n", .{result});
|
||||
}
|
||||
}
|
||||
|
||||
fn part1(alloc: std.mem.Allocator, reader: anytype) !u64 {
|
||||
const input = try reader.readAllAlloc(alloc, std.math.maxInt(u64));
|
||||
defer alloc.free(input);
|
||||
|
||||
const mul_prefix = "mul(";
|
||||
|
||||
std.debug.assert(mul_prefix.len == 4);
|
||||
|
||||
var total: u64 = 0;
|
||||
|
||||
var idx: usize = 0;
|
||||
var i: usize = 0;
|
||||
|
||||
outer: while (idx < input.len) : (idx += @max(i, 1)) {
|
||||
const rest = input[idx..];
|
||||
|
||||
i = 0;
|
||||
|
||||
while (i < mul_prefix.len) : (i += 1) {
|
||||
if (rest[i] != mul_prefix[i]) {
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
|
||||
// parse first number
|
||||
|
||||
var start: usize = i;
|
||||
|
||||
// next char must be a digit
|
||||
if (isDigit(rest[i])) {
|
||||
i += 1;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
// consume up to 2 more digits
|
||||
for (0..2) |_| {
|
||||
if (isDigit(rest[i])) {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// already validated we're parsing a valid number
|
||||
const left = std.fmt.parseUnsigned(u32, rest[start..i], 10) catch unreachable;
|
||||
|
||||
if (rest[i] != ',') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// consume ','
|
||||
i += 1;
|
||||
|
||||
// parse second number
|
||||
|
||||
start = i;
|
||||
|
||||
// next char must be a digit
|
||||
if (isDigit(rest[i])) {
|
||||
i += 1;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
// consume up to 2 more digits
|
||||
for (0..2) |_| {
|
||||
if (isDigit(rest[i])) {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// already validated we're parsing a valid number
|
||||
const right = std.fmt.parseUnsigned(u32, rest[start..i], 10) catch unreachable;
|
||||
|
||||
if (rest[i] != ')') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// consume ')'
|
||||
i += 1;
|
||||
|
||||
total += left * right;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
fn part2(alloc: std.mem.Allocator, reader: anytype) !u64 {
|
||||
const input = try reader.readAllAlloc(alloc, std.math.maxInt(u64));
|
||||
defer alloc.free(input);
|
||||
|
||||
// std.debug.print("{s}\n", .{input});
|
||||
|
||||
// var tok_it = std.mem.tokenizeSequence(u8, input, "mul(");
|
||||
|
||||
const mul_prefix = "mul(";
|
||||
const do = "do()";
|
||||
const dont = "don't()";
|
||||
|
||||
var total: u64 = 0;
|
||||
|
||||
var idx: usize = 0;
|
||||
var i: usize = 0;
|
||||
|
||||
var enabled = true;
|
||||
|
||||
outer: while (idx < input.len) : (idx += @max(i, 1)) {
|
||||
const rest = input[idx..];
|
||||
|
||||
i = 0;
|
||||
|
||||
if (!enabled) {
|
||||
while (i < do.len) : (i += 1) {
|
||||
if (rest[i] != do[i]) {
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
|
||||
enabled = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rest[i] == 'd') {
|
||||
i += 1;
|
||||
|
||||
while (i < do.len) : (i += 1) {
|
||||
if (rest[i] != dont[i]) {
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
|
||||
enabled = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (i < mul_prefix.len) : (i += 1) {
|
||||
if (rest[i] != mul_prefix[i]) {
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
|
||||
// parse first number
|
||||
|
||||
var start: usize = i;
|
||||
|
||||
// next char must be a digit
|
||||
if (isDigit(rest[i])) {
|
||||
i += 1;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
// consume up to 2 more digits
|
||||
for (0..2) |_| {
|
||||
if (isDigit(rest[i])) {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// already validated we're parsing a valid number
|
||||
const left = std.fmt.parseUnsigned(u32, rest[start..i], 10) catch unreachable;
|
||||
|
||||
if (rest[i] != ',') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// consume ','
|
||||
i += 1;
|
||||
|
||||
// parse second number
|
||||
|
||||
start = i;
|
||||
|
||||
// next char must be a digit
|
||||
if (isDigit(rest[i])) {
|
||||
i += 1;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
// consume up to 2 more digits
|
||||
for (0..2) |_| {
|
||||
if (isDigit(rest[i])) {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// already validated we're parsing a valid number
|
||||
const right = std.fmt.parseUnsigned(u32, rest[start..i], 10) catch unreachable;
|
||||
|
||||
if (rest[i] != ')') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// consume ')'
|
||||
i += 1;
|
||||
|
||||
total += left * right;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
test "part1 example" {
|
||||
const alloc = std.testing.allocator;
|
||||
|
||||
const example = "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))";
|
||||
|
||||
var stream = std.io.fixedBufferStream(example);
|
||||
|
||||
const result = try part1(alloc, stream.reader());
|
||||
|
||||
try std.testing.expect(result == 161);
|
||||
}
|
||||
|
||||
test "part1 input" {
|
||||
const alloc = std.testing.allocator;
|
||||
|
||||
const filename = "inputs/day3.txt";
|
||||
|
||||
const file_reader = try utils.FileReader.init(alloc, filename);
|
||||
defer file_reader.deinit();
|
||||
|
||||
const result = try part1(alloc, file_reader.reader());
|
||||
|
||||
try std.testing.expect(result == 156388521);
|
||||
}
|
||||
|
||||
test "part2 example" {
|
||||
const alloc = std.testing.allocator;
|
||||
|
||||
const example = "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))";
|
||||
|
||||
var stream = std.io.fixedBufferStream(example);
|
||||
|
||||
const result = try part2(alloc, stream.reader());
|
||||
|
||||
try std.testing.expect(result == 48);
|
||||
}
|
||||
|
||||
test "part2 input" {
|
||||
const alloc = std.testing.allocator;
|
||||
|
||||
const filename = "inputs/day3.txt";
|
||||
|
||||
const file_reader = try utils.FileReader.init(alloc, filename);
|
||||
defer file_reader.deinit();
|
||||
|
||||
const result = try part2(alloc, file_reader.reader());
|
||||
|
||||
try std.testing.expect(result == 75920122);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue