136 lines
4.2 KiB
Zig
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');
|
|
}
|