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); }