Created
July 2, 2013 23:42
-
-
Save weswigham/5914243 to your computer and use it in GitHub Desktop.
O(1) Matrix Rotation. I think.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local rawget = rawget | |
local rawset = rawset | |
local setmetatable = setmetatable | |
local tostring = tostring | |
local error = error | |
local type = type | |
local print = print | |
module("matrix") | |
local InternalMeta = {} | |
function InternalMeta:__index(key) | |
if type(key) ~= "number" then return rawget(self.matrix[self.selection], key) end | |
local mat = self.matrix | |
local x,y = self.selection, key | |
return mat(x, y) | |
end | |
function InternalMeta:__newindex(key, val) | |
if type(key) ~= "number" then rawset(self.matrix[self.selection], key, val) end | |
local mat = self.matrix | |
local x,y = self.selection, key | |
return mat(x, y, val) | |
end | |
local Matrix = {} | |
function Matrix:__index(key) | |
if type(key) ~= "number" then return (rawget(self, key) or Matrix[key]) end | |
local metahack = {} | |
metahack.selection = key | |
metahack.matrix = self | |
return setmetatable(metahack, InternalMeta) | |
end | |
function Matrix:__call(x, y, ...) | |
if x<=0 or y<=0 or x>self.size or y>self.size then error("Matrix index out of bounds") end | |
local val = {...} --Just some trickery to make it so you can put multiple things in the same position in the matrix | |
if val and #val == 0 then val = nil end | |
if val and #val == 1 then val = val[1] end | |
if val then --Set | |
if self.rotation==0 then --Read normally | |
self.internal[x][y] = val | |
elseif self.rotation==1 then --Rotated once to the right | |
self.internal[self.size-y+1][x] = val | |
elseif self.rotation==2 then --Rotated 180 degrees from original | |
self.internal[self.size-x+1][self.size-y+1] = val | |
elseif self.rotation==3 then --Rotated once to the left | |
self.internal[y][self.size-x+1] = val | |
else | |
error("Matrix has an invalid rotation number") | |
end | |
else --Get | |
if self.rotation==0 then --Read normally | |
return self.internal[x][y] | |
elseif self.rotation==1 then --Rotated once to the right | |
return self.internal[self.size-y+1][x] | |
elseif self.rotation==2 then --Rotated 180 degrees from original | |
return self.internal[self.size-x+1][self.size-y+1] | |
elseif self.rotation==3 then --Rotated once to the left | |
return self.internal[y][self.size-x+1] | |
else | |
error("Matrix has an invalid rotation number") | |
end | |
end | |
end | |
function Matrix:Zero(size) | |
if size<1 then error("A Matrix was zeroed to a size of 0 or less.") end | |
self.rotation = 0 | |
self.size = size or self.size | |
self.internal = {} | |
for i=1,size do | |
local row = {} | |
for j=1,size do | |
row[j] = 0 | |
end | |
self.internal[i] = row | |
end | |
end | |
function Matrix:__tostring() | |
local ret = "" | |
for i=1,self.size do | |
for j=1,self.size do | |
ret = ret.."["..tostring(self(i, j)).."]" | |
end | |
ret = ret.."\n" | |
end | |
return ret | |
end | |
function Matrix:RotateLeft() | |
self.rotation = (self.rotation-1)%4 | |
end | |
function Matrix:RotateRight() | |
self.rotation = (self.rotation+1)%4 | |
end | |
return function(size) | |
local m = {} | |
m = setmetatable(m, Matrix) | |
m:Zero(size or 1) | |
return m | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment