Files
advent-of-code/11/src/main.zig

123 lines
2.9 KiB
Zig

const std = @import("std");
const intcode = @import("intcode");
const boardX = 1024;
const boardY = 1024;
const Point = struct {
x: usize,
y: usize,
fn go(self: Point, d: Compass) Point {
var out = Point{.x = self.x, .y = self.y};
switch (d) {
.North => out.y -= 1,
.East => out.x += 1,
.South => out.y += 1,
.West => out.x -= 1,
}
return out;
}
};
const Compass = enum(u8) {
North = 0,
East = 1,
South = 2,
West = 3,
fn turn(self: Compass, direction: intcode.Word) Compass {
return switch (direction) {
0 => self.widdershins(),
1 => self.deasil(),
else => unreachable,
};
}
fn deasil(self: Compass) Compass {
if (self == .West) return .North;
return @intToEnum(Compass, @enumToInt(self)+1);
}
fn widdershins(self: Compass) Compass {
if (self == .North) return .West;
return @intToEnum(Compass, @enumToInt(self)-1);
}
};
const Colour = enum(u8) {
Black = 0,
White = 1,
};
const Cell = struct {
colour: Colour,
touched: bool = false,
};
const Board = [boardY][boardX]Cell;
fn runMachine(m: *intcode.Machine) void {
if (m.run()) {} else |err| {
std.debug.warn("Machine failed to run successfully: {}\n", err);
}
}
pub fn main() anyerror!void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const alloc = &arena.allocator;
var board: Board = undefined;
for (board) |*row| {
for (row) |*cell| {
cell.* = Cell{.colour = .Black, .touched = false};
}
}
// Current state of the robot
var pos = Point{.x = boardX / 2, .y = boardY / 2};
var direction = Compass.North;
var program = try intcode.loadFromStdIn(alloc);
var machine = try intcode.Machine.init(alloc, program);
var robot = try std.Thread.spawn(&machine, runMachine);
// Robot event loop
while (!machine.halted) {
// Feed it the colour at its current position
try machine.writeToInput(@enumToInt(board[pos.y][pos.x].colour));
// Read back instructions
var paintColour = try machine.readFromOutput();
var turnDirection = try machine.readFromOutput();
// Paint
board[pos.y][pos.x].colour = @intToEnum(Colour, @intCast(u8, paintColour));
board[pos.y][pos.x].touched = true;
// Turn in the specified direction and move forward one square
direction = direction.turn(turnDirection);
pos = pos.go(direction);
// Ugh. Give the other thread some time to decide to halt or not.
std.time.sleep(1000);
}
robot.wait();
var touched: usize = 0;
for (board) |row| {
for (row) |cell| {
if (cell.touched) touched += 1;
}
}
std.debug.warn("Day 11, Part 1: {}\n", touched);
}