SubMatrixes
This commit is contained in:
+89
-27
@@ -6,6 +6,12 @@ const Allocator = mem.Allocator;
|
||||
pub const Point = struct {
|
||||
x: usize,
|
||||
y: usize,
|
||||
|
||||
/// index returns the index in a flat array of the point givent he
|
||||
/// provided width.
|
||||
pub fn index(self: *const Point, width: usize) usize {
|
||||
return (self.y * width) + self.x;
|
||||
}
|
||||
};
|
||||
|
||||
/// Rect is a rectangle
|
||||
@@ -18,32 +24,27 @@ pub const Rect = struct {
|
||||
}
|
||||
};
|
||||
|
||||
/// Area is the area
|
||||
pub const Area = struct {
|
||||
location: Point,
|
||||
size: Rect,
|
||||
};
|
||||
|
||||
/// Matrix is a part of the game board
|
||||
pub fn Matrix(comptime T: type, size: Rect) type {
|
||||
const MatrixRowIterator = RowIterator(T, size.width);
|
||||
|
||||
pub fn Matrix(comptime T: type) type {
|
||||
return struct {
|
||||
/// data is the game board itself.
|
||||
data: []T,
|
||||
|
||||
///
|
||||
size: Rect,
|
||||
|
||||
/// init creates the chunk, storing the bytes in memory.
|
||||
pub fn initZero(gpa: Allocator) !@This() {
|
||||
pub fn initZero(gpa: Allocator, size: Rect) !@This() {
|
||||
const data = try gpa.alloc(T, size.area());
|
||||
@memset(data, mem.zeroes(T));
|
||||
return .{ .data = data };
|
||||
return .{ .data = data, .size = size };
|
||||
}
|
||||
|
||||
/// init creates the chunk, storing the bytes in memory.
|
||||
pub fn init(gpa: Allocator, zero: T) !@This() {
|
||||
pub fn init(gpa: Allocator, zero: T, size: Rect) !@This() {
|
||||
const data = try gpa.alloc(T, size.area());
|
||||
@memset(data, zero);
|
||||
return .{ .data = data };
|
||||
return .{ .data = data, .size = size };
|
||||
}
|
||||
|
||||
/// deinit frees the memory utilized to create the chunk
|
||||
@@ -53,18 +54,23 @@ pub fn Matrix(comptime T: type, size: Rect) type {
|
||||
|
||||
// set sets the value of the specified location in memory
|
||||
pub fn set(self: *@This(), loc: Point, val: T) void {
|
||||
const index = (size.width * loc.y) + loc.x;
|
||||
const index = (self.size.width * loc.y) + loc.x;
|
||||
self.data[index] = val;
|
||||
}
|
||||
|
||||
// set sets the value of the specified location in memory
|
||||
pub fn get(self: *const @This(), loc: Point) T {
|
||||
const index = (size.width * loc.y) + loc.x;
|
||||
const index = (self.size.width * loc.y) + loc.x;
|
||||
return self.data[index];
|
||||
}
|
||||
|
||||
pub fn row_iterator(self: *@This()) MatrixRowIterator {
|
||||
return .init(self.data);
|
||||
pub fn row_iterator(self: *@This()) RowIterator(T) {
|
||||
return .init(self);
|
||||
}
|
||||
|
||||
/// submatrix returns a [SubMatrix]
|
||||
pub fn submatrix(self: *@This(), gpa: Allocator, loc: Point, area: Rect) !SubMatrix(T) {
|
||||
return SubMatrix(T).init(gpa, self, loc, area);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -72,25 +78,25 @@ pub fn Matrix(comptime T: type, size: Rect) type {
|
||||
test "TestMatrix" {
|
||||
const testing = std.testing;
|
||||
|
||||
var mat = try Matrix(u64, Rect{ .width = 10, .height = 10 }).initZero(testing.allocator);
|
||||
var mat = try Matrix(u64).initZero(testing.allocator, Rect{ .width = 10, .height = 10 });
|
||||
defer mat.deinit(testing.allocator);
|
||||
|
||||
mat.set(Point{ .x = 1, .y = 1 }, 100);
|
||||
try testing.expectEqual(100, mat.get(Point{ .x = 1, .y = 1 }));
|
||||
}
|
||||
|
||||
pub fn RowIterator(comptime T: type, width: usize) type {
|
||||
pub fn RowIterator(comptime T: type) type {
|
||||
return struct {
|
||||
_index: usize,
|
||||
/// data is a reference to the board game data, now we will return it as
|
||||
/// each row
|
||||
_data: []T,
|
||||
|
||||
fn init(data: []T) @This() {
|
||||
return .{
|
||||
._index = 0,
|
||||
._data = data,
|
||||
};
|
||||
// The width of each row of data
|
||||
_width: usize,
|
||||
|
||||
fn init(m: *Matrix(T)) @This() {
|
||||
return .{ ._index = 0, ._data = m.data, ._width = m.size.width };
|
||||
}
|
||||
|
||||
/// next returns the next row until we have exhausted the slice
|
||||
@@ -100,8 +106,8 @@ pub fn RowIterator(comptime T: type, width: usize) type {
|
||||
}
|
||||
|
||||
// increment a line at a time
|
||||
defer self._index += width;
|
||||
return self._data[self._index .. self._index + width];
|
||||
defer self._index += self._width;
|
||||
return self._data[self._index .. self._index + self._width];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -109,7 +115,7 @@ pub fn RowIterator(comptime T: type, width: usize) type {
|
||||
test "TestRowIterator" {
|
||||
const testing = std.testing;
|
||||
|
||||
var chunk = try Matrix(usize, Rect{ .height = 10, .width = 10 }).initZero(testing.allocator);
|
||||
var chunk = try Matrix(usize).initZero(testing.allocator, Rect{ .height = 10, .width = 10 });
|
||||
defer chunk.deinit(testing.allocator);
|
||||
|
||||
for (0..10) |x| {
|
||||
@@ -124,3 +130,59 @@ test "TestRowIterator" {
|
||||
x += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// SubMatrix is a subset of a matrix which you can traverse to
|
||||
pub fn SubMatrix(comptime T: type) type {
|
||||
return struct {
|
||||
// Data is made up of different sections of the
|
||||
_data: [][]T,
|
||||
|
||||
/// init takes the underlying data from the upstream matrix and creates
|
||||
/// a submatrix of it
|
||||
pub fn init(gpa: Allocator, m: *Matrix(T), loc: Point, size: Rect) !@This() {
|
||||
var subData = try gpa.alloc([]T, size.height);
|
||||
var index = loc.index(m.size.width);
|
||||
|
||||
for (0..size.height) |x| {
|
||||
const ending_index = index + size.width;
|
||||
subData[x] = m.data[index..ending_index];
|
||||
index += m.size.width;
|
||||
}
|
||||
|
||||
return .{
|
||||
._data = subData,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *@This(), gpa: Allocator) void {
|
||||
gpa.free(self._data);
|
||||
}
|
||||
|
||||
/// get returns the type in the specified point
|
||||
pub fn get(self: *const @This(), loc: Point) T {
|
||||
return self._data[loc.y][loc.x];
|
||||
}
|
||||
|
||||
/// set sets the value of the specified point
|
||||
pub fn set(self: *@This(), loc: Point, val: T) void {
|
||||
self._data[loc.y][loc.x] = val;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test "SubMatrix" {
|
||||
const testing = std.testing;
|
||||
|
||||
// create our matrix and submatrix
|
||||
var m = try Matrix(u64).initZero(testing.allocator, .{ .height = 10, .width = 10 });
|
||||
defer m.deinit(testing.allocator);
|
||||
var sub = try m.submatrix(testing.allocator, .{ .x = 4, .y = 4 }, .{ .height = 5, .width = 5 });
|
||||
defer sub.deinit(testing.allocator);
|
||||
|
||||
// set the value
|
||||
sub.set(.{ .x = 0, .y = 0 }, 100);
|
||||
|
||||
// it should be set in both locations
|
||||
try testing.expectEqual(100, sub.get(.{ .x = 0, .y = 0 }));
|
||||
try testing.expectEqual(100, m.get(.{ .x = 4, .y = 4 }));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user