const std = @import("std");
const ArrayList = std.ArrayList;
const Vec2 = struct {
x: i64 = 0,
y: i64 = 0,
};
const LineSegment = struct {
head: Vec2,
tail: Vec2,
};
pub fn solve_part1(allocator: std.mem.Allocator, file: []const u8) !void {
var inputs = try std.fs.cwd().openFile(file, .{});
var buffered_reader = std.io.bufferedReader(inputs.reader());
var in_stream = buffered_reader.reader();
var buffer: [1024]u8 = undefined;
var position: Vec2 = .{};
var position_2: Vec2 = .{};
var polygon = ArrayList(Vec2).init(allocator);
var polygon_2 = ArrayList(Vec2).init(allocator);
var perimeter: u32 = 0;
var perimeter_2: u32 = 0;
while (try in_stream.readUntilDelimiterOrEof(&buffer, '\n')) |line| {
var index_after_amount = std.mem.indexOfScalar(u8, line[2..], ' ').?;
var index_of_hashtag = std.mem.indexOfScalar(u8, line, '#').?;
var amount = try std.fmt.parseInt(i32, line[2 .. index_after_amount + 2], 10);
var amount_2 = try std.fmt.parseInt(i32, line[index_of_hashtag + 1 .. index_of_hashtag + 6], 16);
perimeter += @intCast(amount);
perimeter_2 += @intCast(amount_2);
var dir = convert_to_vec2(line[0]);
var dir_convert = [_]u8{ 'R', 'D', 'L', 'U' };
var dir_2 = convert_to_vec2(dir_convert[line[index_of_hashtag + 6] - '0']);
position.x += dir.x * amount;
position.y += dir.y * amount;
position_2.x += dir_2.x * amount_2;
position_2.y += dir_2.y * amount_2;
try polygon.append(position);
try polygon_2.append(position_2);
}
std.log.info("Area: {d}", .{shoelace_area(polygon.items)});
std.log.info("Area: {d}", .{perimeter});
std.log.info("Part 1: {d}", .{shoelace_area(polygon.items) + perimeter / 2 + 1});
std.log.info("Part 2: {d}", .{shoelace_area(polygon_2.items) + perimeter_2 / 2 + 1});
}
fn convert_to_vec2(dir: u8) Vec2 {
switch (dir) {
'U' => return .{ .x = 0, .y = 1 },
'D' => return .{ .x = 0, .y = -1 },
'L' => return .{ .x = -1, .y = 0 },
'R' => return .{ .x = 1, .y = 0 },
else => return .{ .x = 0, .y = 0 },
}
}
fn shoelace_area(polygon: []Vec2) u64 {
var area: i64 = 0;
for (0..polygon.len) |i| {
var p1 = polygon[i];
var p2 = polygon[(i + 1) % polygon.len];
area += p1.x * p2.y - p2.x * p1.y;
}
return @as(u64, @intCast(std.math.absInt(area) catch unreachable)) / 2;
}