diff --git a/src/days/day1.zig b/src/days/day1.zig new file mode 100644 index 0000000..88061cd --- /dev/null +++ b/src/days/day1.zig @@ -0,0 +1,105 @@ +const std = @import("std"); + +const parseInt = std.fmt.parseInt; + +// fn mightFail() anyerror!void +// ^^^^^^^^ we don't know the error, so any error might be returned +// fn mightFail() !void +// ^ error type is inferred from the compiler +// fn mightFail() error{OutOfMemory}!void +// ^^^^^^^^^^^^^^^^^^ error type is basically just an enum, in this case with only one value: OutOfMemory +// Goals: +// x Write helper to load input text as buffer of some kind +// - Write test to assert for day 1 testinput + +// const as_cast: usize = @as(usize, @(u16, 1337)); +// const int_cast: isize = @intCast(@as(usize, 1337)); +// const ptr_cast: *usize = @ptrCast(@as(*isize, @ptrFromInt(0x1337))); +// const float_from_int: f32 = @floatFromInt(1337); +// const int_from_float: i32 = @intFromFloat(1337.66); +// @alignCast, @constCast, @bitCast, @addrSpaceCast, @errorCast, @floatCast and @volatileCast i won't explain, as it's not +// really necessary for now, and if you need it, you typically know it already + +pub fn day1pt1(dial_movements: []const u8) !usize { + var position: isize = 50; // without type hint: comptime_int + var counter: usize = 0; + var iter = std.mem.splitScalar(u8, dial_movements, '\n'); + while (iter.next()) |line| { + if (line[0] == 'L') { + // slicing: + // line[1..] - returns new slice from position: 1 until end + // line[0..1] - returns a slice from start with length 1 + // base 8 = octal + // base 10 = decimal + // base 16 = hex + // vvvvvvvvvvvvvvvv TYPE v return value :3 + // pub fn parseInt(comptime T: type, buf: []const u8, base: u8) ParseIntError!T + // vvvvvvvv do you think this function might fail? + position = position - try parseInt(isize, line[1..], 10); + } else { // ^^ wollen wir wirklich ein u8 als PARSED RESULT haben? + position = position + try parseInt(isize, line[1..], 10); + } + position = @mod(position, 100); + if (position == 0) { + // post / pre increment / decrement doesn't exist + counter += 1; + } + } + return counter; +} + +pub fn day1pt2(dial_movements: []const u8) !usize { + var position: isize = 50; + var counter: usize = 0; + var iter = std.mem.splitScalar(u8, dial_movements, '\n'); + while (iter.next()) |line| { + const movement = try parseInt(isize, line[1..], 10); + + if (line[0] == 'L') { + // Moving left (counter-clockwise) + if (position > 0 and movement >= position) { // greater equals to hit landings + // crossing 0 + const crosses_after_first: usize = @intCast(@divFloor(movement - position, 100)); + counter += 1 + crosses_after_first; + } else if (position == 0 and movement >= 100) { + // starting at 0 -> only full rotations + const full_rotations: usize = @intCast(@divFloor(movement, 100)); + counter += full_rotations; + } + position = position - movement; + } else { + // Moving right (clockwise) + if (position > 0) { + const distance_to_zero = 100 - position; + if (movement >= distance_to_zero) { + const crosses_after_first: usize = @intCast(@divFloor(movement - distance_to_zero, 100)); + counter += 1 + crosses_after_first; + } + } else if (position == 0 and movement >= 100) { + const full_rotations: usize = @intCast(@divFloor(movement, 100)); + counter += full_rotations; + } + position = position + movement; + } + + position = @mod(position, 100); + } + return counter; +} + +test "Day 1 example testing" { + const example_input = + \\L68 + \\L30 + \\R48 + \\L5 + \\R60 + \\L55 + \\L1 + \\L99 + \\R14 + \\L82 + ; + try std.testing.expectEqual(try day1pt1(example_input), 3); + try std.testing.expectEqual(try day1pt2(example_input), 6); +} diff --git a/src/main.zig b/src/main.zig index 79ac6ba..594ce17 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,10 +1,17 @@ const std = @import("std"); -const aoc25 = @import("aoc25"); +const loadpuzzle = @import("utils/loadpuzzle.zig"); +const day1 = @import("days/day1.zig"); pub fn main() !void { // Prints to stderr, ignoring potential errors. + const gpa = std.heap.smp_allocator; + std.debug.print("All your {s} are belong to us.\n", .{"codebase"}); - try aoc25.bufferedPrint(); + std.debug.print("Starting AoC\n", .{}); + + const day1_input = try loadpuzzle.readFile(gpa, "puzzle_input/day1.txt"); + std.debug.print("Day 1 Part 1: {any}\n", .{try day1.day1pt1(day1_input)}); + std.debug.print("Day 1 Part 2: {any}\n", .{try day1.day1pt2(day1_input)}); } test "simple test" {