136 lines
3.9 KiB
Zig
136 lines
3.9 KiB
Zig
const std = @import("std");
|
|
const print = std.debug.print;
|
|
const file = @embedFile("input");
|
|
|
|
const UP = Position{ .x = -1, .y = 0 };
|
|
const RIGHT = Position{ .x = 0, .y = 1 };
|
|
const DOWN = Position{ .x = 1, .y = 0 };
|
|
const LEFT = Position{ .x = 0, .y = -1 };
|
|
|
|
const Point = enum { Empty, Obstacle, Visited, End };
|
|
|
|
const Position = struct {
|
|
x: i16,
|
|
y: i16,
|
|
|
|
fn move(self: *Position, to: Position) void {
|
|
self.x += to.x;
|
|
self.y += to.y;
|
|
}
|
|
|
|
fn rotate(self: *Position) void {
|
|
if (std.meta.eql(self.*, UP)) {
|
|
self.* = RIGHT;
|
|
return;
|
|
}
|
|
if (std.meta.eql(self.*, RIGHT)) {
|
|
self.* = DOWN;
|
|
return;
|
|
}
|
|
if (std.meta.eql(self.*, DOWN)) {
|
|
self.* = LEFT;
|
|
return;
|
|
}
|
|
if (std.meta.eql(self.*, LEFT)) {
|
|
self.* = UP;
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
const Map = struct {
|
|
buff: [132][132]Point = undefined,
|
|
gard_position: Position = undefined,
|
|
gard_orientation: Position = UP,
|
|
|
|
fn next(self: *Map) ?bool {
|
|
// Check upfront
|
|
var new_visite: ?bool = false;
|
|
switch (self.look()) {
|
|
.End => return null,
|
|
.Empty => {
|
|
new_visite = true;
|
|
self.gard_position.move(self.gard_orientation);
|
|
self.buff[@as(usize, @intCast(self.gard_position.x))][@as(usize, @intCast(self.gard_position.y))] = .Visited;
|
|
},
|
|
.Visited => self.gard_position.move(self.gard_orientation),
|
|
.Obstacle => {
|
|
self.gard_orientation.rotate();
|
|
new_visite = self.next();
|
|
},
|
|
}
|
|
return new_visite;
|
|
}
|
|
|
|
fn printMap(self: Map, writer: anytype) !void {
|
|
for (self.buff, 0..) |row, x| {
|
|
try writer.writeByte('\n');
|
|
for (row, 0..) |cell, y| {
|
|
if (self.gard_position.x == x and self.gard_position.y == y) {
|
|
try writer.writeByte('X');
|
|
continue;
|
|
}
|
|
switch (cell) {
|
|
.Obstacle => try writer.writeByte('#'),
|
|
.Empty => try writer.writeByte(' '),
|
|
.Visited => try writer.writeByte('.'),
|
|
.End => try writer.writeByte('E'),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn get(self: Map, position: Position) Point {
|
|
return self.buff[@as(usize, @intCast(position.x))][@as(usize, @intCast(position.y))];
|
|
}
|
|
|
|
fn look(self: Map) Point {
|
|
return self.buff[@as(usize, @intCast(self.gard_position.x + self.gard_orientation.x))][@as(usize, @intCast(self.gard_position.y + self.gard_orientation.y))];
|
|
}
|
|
};
|
|
|
|
pub fn main() !void {
|
|
// ========= Parse map ===========
|
|
var iter = std.mem.split(u8, file, "\n");
|
|
var map = Map{};
|
|
|
|
for (0..132) |x| {
|
|
for (0..132) |y| {
|
|
map.buff[x][y] = .End;
|
|
}
|
|
}
|
|
|
|
var x: usize = 1;
|
|
while (iter.next()) |line| {
|
|
for (line, 1..) |c, y| switch (c) {
|
|
'.' => map.buff[x][y] = .Empty,
|
|
'#' => map.buff[x][y] = .Obstacle,
|
|
'^' => {
|
|
map.gard_position = .{ .x = 1 + @as(i16, @intCast(x)), .y = @as(i16, @intCast(y)) };
|
|
map.buff[x][y] = .Empty;
|
|
},
|
|
else => unreachable,
|
|
};
|
|
x += 1;
|
|
}
|
|
|
|
// ========= Make the gard move to the end ===========
|
|
//var map_array = std.ArrayList(u8).init(allocator);
|
|
//defer map_array.deinit();
|
|
var total: usize = 0;
|
|
while (map.next()) |new_visite| {
|
|
//defer map_array.clearRetainingCapacity();
|
|
//try map.printMap(map_array.writer());
|
|
if (new_visite) total += 1;
|
|
//clearScreen();
|
|
//print("{s}", .{map_array.items});
|
|
//std.time.sleep(2000000);
|
|
}
|
|
|
|
try std.testing.expectEqual(5516, total);
|
|
}
|
|
|
|
fn clearScreen() void {
|
|
print("\x1B[2J\x1B[H", .{});
|
|
}
|