1
0
Advent-of-Code/day14/part2.zig
2024-12-15 12:57:26 +01:00

136 lines
4.2 KiB
Zig

const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const Int = i16;
const MAP_SIZE: [2]Int = .{ 101, 103 };
// I am pretty sure that I can detect the tree by using the distance of each drone from each drone
// Something like that, some kind of noise
// If they picture a tree, it mean they are close to each other right ? So it is less 'noisy' or less enthropy
const Drone = struct {
x: Int,
y: Int,
vX: Int,
vY: Int,
fn next(self: *Drone) void {
const mapW = MAP_SIZE[0];
const mapH = MAP_SIZE[1];
self.x += self.vX;
self.y += self.vY;
// Dected boundary
if (self.x >= mapW) self.x -= mapW; //Move back to 0 + xt1 - mapW
if (self.x < 0) self.x += mapW;
if (self.y >= mapH) self.y -= mapH;
if (self.y < 0) self.y += mapH;
}
fn detectQuadrant(self: Drone, mapW: Int, mapH: Int) enum { TopLeft, TopRight, BottomLeft, BottomRight, None } {
if (self.x < @divFloor(mapW, 2)) {
if (self.y < @divFloor(mapH, 2)) return .TopLeft;
if (self.y > @divFloor(mapH, 2)) return .BottomLeft;
} else if (self.x > @divFloor(mapW, 2)) {
if (self.y < @divFloor(mapH, 2)) return .TopRight;
if (self.y > @divFloor(mapH, 2)) return .BottomRight;
}
return .None;
}
};
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
const drones = try parseDrone(allocator);
var list = std.ArrayList(u8).init(allocator);
const writer = list.writer();
for (0..10000) |i| {
list.clearRetainingCapacity();
for (drones) |*drone| drone.next();
if (!detectIfDroneClose(drones, 40, 2)) continue;
clearScreen();
try printDrone(writer, drones);
print("{s}\nTime: {d}s", .{ list.items, i });
try waitForInput();
}
}
fn parseDrone(allocator: std.mem.Allocator) ![]Drone {
var list = std.ArrayList(Drone).init(allocator);
var iter = std.mem.splitAny(u8, input, "\n");
while (iter.next()) |line| {
if (std.mem.eql(u8, line, "")) continue;
var iter_space = std.mem.splitAny(u8, line, " ");
const part1 = iter_space.next().?;
var iter_comma = std.mem.splitAny(u8, part1, ",");
const x = try std.fmt.parseInt(Int, iter_comma.next().?[2..], 10);
const y = try std.fmt.parseInt(Int, iter_comma.next().?, 10);
const part2 = iter_space.next().?;
iter_comma = std.mem.splitAny(u8, part2, ",");
const vX = try std.fmt.parseInt(Int, iter_comma.next().?[2..], 10);
const vY = try std.fmt.parseInt(Int, iter_comma.next().?, 10);
try list.append(Drone{ .x = x, .y = y, .vX = vX, .vY = vY });
}
return try list.toOwnedSlice();
}
fn printDrone(writer: anytype, drones: []const Drone) !void {
var buf: [MAP_SIZE[0]][MAP_SIZE[1]]u8 = [_][MAP_SIZE[1]]u8{[_]u8{0} ** MAP_SIZE[1]} ** MAP_SIZE[0];
for (drones) |drone| {
const x = @as(usize, @intCast(drone.x));
const y = @as(usize, @intCast(drone.y));
buf[x][y] += 1;
}
for (buf) |line| {
for (line) |v| {
if (v == 0) {
try writer.writeByte(' ');
} else {
try writer.writeByte('0');
}
}
try writer.writeByte('\n');
}
}
// Detect if at least 10 drones have 10 other drones close it it
fn detectIfDroneClose(drones: []Drone, to_find: usize, distance_max: f64) bool {
var founded1: usize = 0;
for (drones) |drone1| {
var founded2: usize = 0;
for (drones) |drone2| {
if (distance(drone1, drone2) < distance_max) founded2 += 1;
}
if (founded2 > to_find) founded1 += 1;
}
return founded1 > to_find;
}
pub fn distance(drone1: Drone, drone2: Drone) f64 {
const dx = @as(f64, @floatFromInt(drone2.x - drone1.x));
const dy = @as(f64, @floatFromInt(drone1.y - drone1.y));
return std.math.sqrt(dx * dx + dy * dy);
}
fn clearScreen() void {
print("\x1B[2J\x1B[H", .{});
}
fn waitForInput() !void {
var buf: [5]u8 = undefined;
const stdin = std.io.getStdIn().reader();
_ = try stdin.readUntilDelimiter(&buf, '\n');
}