2019-12-03 22:34:17 +00:00
|
|
|
const std = @import("std");
|
|
|
|
|
|
|
|
const Error = error{ParseError};
|
|
|
|
|
2019-12-03 23:11:58 +00:00
|
|
|
const Point = struct {
|
|
|
|
X: i32,
|
|
|
|
Y: i32,
|
2019-12-03 22:34:17 +00:00
|
|
|
};
|
|
|
|
|
2019-12-03 23:11:58 +00:00
|
|
|
const Points = std.ArrayList(Point);
|
|
|
|
|
2019-12-03 22:34:17 +00:00
|
|
|
const Direction = enum(u8) {
|
|
|
|
Up = 'U',
|
|
|
|
Right = 'R',
|
|
|
|
Down = 'D',
|
|
|
|
Left = 'L',
|
|
|
|
|
|
|
|
pub fn parse(in: u8) anyerror!Direction {
|
|
|
|
return switch (in) {
|
|
|
|
'U' => .Up,
|
|
|
|
'R' => .Right,
|
|
|
|
'D' => .Down,
|
|
|
|
'L' => .Left,
|
|
|
|
else => Error.ParseError,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const Step = struct {
|
|
|
|
d: Direction,
|
2019-12-03 23:11:58 +00:00
|
|
|
l: i32,
|
2019-12-03 22:34:17 +00:00
|
|
|
|
|
|
|
pub fn parse(in: []const u8) anyerror!Step {
|
|
|
|
if (in.len < 2) {
|
|
|
|
return error.ParseError;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Step{
|
|
|
|
.d = try Direction.parse(in[0]),
|
2019-12-03 23:11:58 +00:00
|
|
|
.l = try std.fmt.parseInt(i32, in[1..in.len], 10),
|
2019-12-03 22:34:17 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const World = struct {
|
2019-12-03 23:11:58 +00:00
|
|
|
entries: Points,
|
|
|
|
pos: Point,
|
2019-12-03 22:34:17 +00:00
|
|
|
|
2019-12-03 23:11:58 +00:00
|
|
|
pub fn step(self: *World, in: Step) anyerror!void {
|
2019-12-03 22:34:17 +00:00
|
|
|
std.debug.warn("Step: {}\n", in);
|
|
|
|
|
|
|
|
switch (in.d) {
|
|
|
|
.Up => {
|
2019-12-03 23:11:58 +00:00
|
|
|
try self.lineY(self.pos.Y - in.l, self.pos.Y - 1);
|
|
|
|
self.pos.Y -= in.l;
|
2019-12-03 22:34:17 +00:00
|
|
|
},
|
|
|
|
.Down => {
|
2019-12-03 23:11:58 +00:00
|
|
|
try self.lineY(self.pos.Y + 1, self.pos.Y + in.l);
|
|
|
|
self.pos.Y += in.l;
|
2019-12-03 22:34:17 +00:00
|
|
|
},
|
|
|
|
.Left => {
|
2019-12-03 23:11:58 +00:00
|
|
|
try self.lineX(self.pos.X - in.l, self.pos.X - 1);
|
|
|
|
self.pos.X -= in.l;
|
2019-12-03 22:34:17 +00:00
|
|
|
},
|
|
|
|
.Right => {
|
2019-12-03 23:11:58 +00:00
|
|
|
try self.lineX(self.pos.X + 1, self.pos.X + in.l);
|
|
|
|
self.pos.X += in.l;
|
2019-12-03 22:34:17 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-03 23:11:58 +00:00
|
|
|
fn lineX(self: *World, start: i32, end: i32) anyerror!void {
|
|
|
|
var x: i32 = start;
|
2019-12-03 22:34:17 +00:00
|
|
|
while (x <= end) : (x += 1) {
|
2019-12-03 23:11:58 +00:00
|
|
|
try self.fill(x, self.pos.Y);
|
2019-12-03 22:34:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-03 23:11:58 +00:00
|
|
|
fn lineY(self: *World, start: i32, end: i32) anyerror!void {
|
|
|
|
var y: i32 = start;
|
2019-12-03 22:34:17 +00:00
|
|
|
while (y <= end) : (y += 1) {
|
2019-12-03 23:11:58 +00:00
|
|
|
try self.fill(self.pos.X, y);
|
2019-12-03 22:34:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-03 23:11:58 +00:00
|
|
|
fn fill(self: *World, x: i32, y: i32) anyerror!void {
|
|
|
|
//self.entries = try self.alloc.realloc(self.entries, self.entries.len+1);
|
|
|
|
self.entries.appendAssumeCapacity(Point{ .X = x, .Y = y });
|
2019-12-03 22:34:17 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
fn getLine(stream: *std.fs.File.InStream.Stream) anyerror![]Step {
|
|
|
|
var buf: [10240]u8 = undefined;
|
|
|
|
var out: [1000]Step = undefined;
|
|
|
|
var i: u32 = 0;
|
|
|
|
|
|
|
|
var line = (try stream.readUntilDelimiterOrEof(&buf, '\n')) orelse return Error.ParseError;
|
|
|
|
var iter = std.mem.separate(line, ",");
|
|
|
|
|
|
|
|
while (iter.next()) |value| {
|
|
|
|
std.debug.assert(i < out.len);
|
|
|
|
|
|
|
|
out[i] = try Step.parse(value);
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return out[0..i];
|
|
|
|
}
|
|
|
|
|
|
|
|
fn manhattan(x: i32, y: i32) u32 {
|
2019-12-03 23:11:58 +00:00
|
|
|
return std.math.absCast(x) + std.math.absCast(y);
|
2019-12-03 22:34:17 +00:00
|
|
|
}
|
|
|
|
|
2019-12-03 23:11:58 +00:00
|
|
|
const maxEntries = 1024 * 1024;
|
|
|
|
|
2019-12-03 22:34:17 +00:00
|
|
|
pub fn main() anyerror!void {
|
|
|
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
|
|
|
defer arena.deinit();
|
|
|
|
|
|
|
|
const alloc = &arena.allocator;
|
|
|
|
const file = std.io.getStdIn();
|
|
|
|
const stream = &file.inStream().stream;
|
|
|
|
|
|
|
|
var world: World = World{
|
2019-12-03 23:11:58 +00:00
|
|
|
.entries = try Points.initCapacity(alloc, maxEntries),
|
|
|
|
.pos = Point{ .X = 0, .Y = 0 },
|
2019-12-03 22:34:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Line 1
|
|
|
|
for (try getLine(stream)) |item| {
|
2019-12-03 23:11:58 +00:00
|
|
|
try world.step(item);
|
2019-12-03 22:34:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// reset to origin
|
2019-12-03 23:11:58 +00:00
|
|
|
const entriesA = world.entries;
|
|
|
|
world.entries = try Points.initCapacity(alloc, maxEntries);
|
|
|
|
world.pos = Point{ .X = 0, .Y = 0 };
|
2019-12-03 22:34:17 +00:00
|
|
|
|
|
|
|
// Line 2
|
|
|
|
for (try getLine(stream)) |item| {
|
2019-12-03 23:11:58 +00:00
|
|
|
try world.step(item);
|
2019-12-03 22:34:17 +00:00
|
|
|
}
|
|
|
|
|
2019-12-03 23:11:58 +00:00
|
|
|
const entriesB = world.entries;
|
|
|
|
|
|
|
|
std.debug.warn("A: {} entries\nB: {} entries\n", entriesA.len, entriesB.len);
|
|
|
|
|
|
|
|
for (entriesA.toSlice()) |a| {
|
|
|
|
for (entriesB.toSlice()) |b| {
|
|
|
|
if (a.X == b.X and a.Y == b.Y) {
|
|
|
|
std.debug.warn("Match! {} => {}\n", a, manhattan(a.X, a.Y));
|
2019-12-03 22:34:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|