Coding Challenge #5: Rotating 90-degrees

Coding Challenge #5

Welcome back, to another coding challenge! Let’s do this as usual.

As usual, same requirements:

• Has to be written in Lua 5.1 (the version roblox uses)
• The program has to be compatible with Roblox Studio, meaning you can’t use features vanilla Lua has but rbxlua disabled
• You can’t use httpservice to cheat the challenge

Given a 2D table, write a function `Rotate(t)` which will rotate the table 90 degrees.

Let’s see what I mean. This is a 2D table, which some other people would like to call a matrix.

``````{{1,2,3},
{4,5,6},
{7,8,9}}
``````

You need to rotate it 90 degrees, which in linear algebra is a matrix operation known as transposing (although transposing is actually rotating 90 degrees clockwise and not anti-clockwise) what emily said.

``````{{7,4,1},
{8,5,2},
{9,6,3}}
``````

If you want to check if your code is working by printing the output, here is a function which will print the 2D table for you.

``````local function Print(t)
for i, v in pairs(t) do
print(unpack(v))
print("")
end
end
``````

Goodluck! You can find a list of all the challenges here or a github version here.

Here is my solution! I have a great feeling everybody gonna have the same setup.

``````local function Rotate(t)
local output = {{}, {}, {}}

for i, row in pairs(t) do
for j = 1,3 do
output[j][4-i] = row[j]
end
end

return output
end
``````
14 Likes

So cool and simple! Thank you for the quick challenge.

1 Like

That was pretty simple, matrices rotation isn’t the hardest thing in the world to do. just some simple math

Now time to extend my code to work with any square because that’s looks possible

My solution if anyone wants to know :3

``````function rotate90(tab)
local out = {{},{},{}}

for yIndex, x in pairs(tab) do
for y = 1, 3 do
out[y][4-yIndex] = x[y]
end
end

return out
end
``````
4 Likes

I did two approaches, since this was another relatively simple problem. Here’s the lazy approach:

code
``````function Rotate(t)
local rotatedT = {}

for i = 1, 3 do
rotatedT[i] = {t[3][i], t[2][i], t[1][i]}
end

return rotatedT
end
``````

And I’ll edit in a more flexible one that lets you input a number of degrees, soon.

Edit: It’s a bit messy, but here it is. Blame @starmaq for recommending I use ternary instead of a more readable if-else chain.

code
``````function Rotate(t, deg)
deg = deg or 90 -- default of 90 so it fits specs of challenge

if type(t) ~= "table" or type(deg) ~= "number" then
error("Typing must be `Rotate(table, number)`")
end

assert(deg % 90 == 0, "argument #2 must be divisible by 90")

local rotatedT = {{}, {}, {}}
deg = deg and (math.sign(deg) > 0 and deg or deg + 360) -- allow negative degrees

-- the actual function part:
local d = (deg / 90) % 4

for x = 1, 3 do
for y = 1, 3 do
rotatedT[x][y] = t[(d % 3 > 0 and 4 or 2 * (d % 2 == 1 and y or x)) - (d % 2 == 1 and y or x)][(d > 1 and 4 or 2 * (d % 2 == 1 and x or y)) - (d % 2 == 1 and x or y)]
end
end

return rotatedT
end
``````
3 Likes

Here’s my take at it

``````function Rotate(t)
local t2 = { {},{},{}}

for i,v in pairs(t) do
for k = 1,3,1 do
table.insert(t2[i],4-k,t[k][i])
end
end

return t2
end
``````
1 Like

I’ve never done matrix math before but this was my take on it, I couldn’t figure out how to rotate it clockwise so if anybody can make adjustments to my code so I can see how it should be done that’d be much appreciated

``````local function rotateMatrix90(arr)
local matrix_tbl
-- if we haven't provided a matrix then use the example from the tutorial
if arr then
matrix_tbl = arr
else
matrix_tbl = {
{1,2,3},
{4,5,6},
{7,8,9}
}
end

-- creates a new matrix
local new_matrix = {}
-- for every column in the matrix provided we create a new column in our new matrix
for i = 1, #matrix_tbl do
new_matrix[i] = {}
-- iterate through the provided matrix and find the elements that correspond to the current
-- column we're in
for index, arr in pairs(matrix_tbl) do
-- insert these elements in the column of our new matrix
table.insert(new_matrix[i], #new_matrix[i] + 1, arr[i])
end
end

--For displaying the ordered matrix in console
for all, som in pairs(new_matrix) do
local rows = "{"
for _, column in pairs(som) do
rows = rows..","..column
end
rows = rows.."}".."\n"
print(rows)
end
end

rotateMatrix90()``````
2 Likes

I know that this isn’t inherent with the challenge, but after completing it I felt like it wasn’t enough, and I’ve decided to make a 180 degrees rotation function, and here is the result (put a spoiler just in case you want to figure it out by yourself):

``````
local function rotate180(t)
local output = {{},{},{}}

for i, Table in pairs(t) do
for i = 1,3 do
for i2 = 3,1,-1 do
output[i][i2] = M[4-i][4-i2]
end
end
end

return output
end

``````
1 Like
The redundant and messy way
``````   local function Rotate(t)

local temp = {

{};
{};
{};

};

temp[1][1] = t[3][1]
temp[1][2] = t[2][1]
temp[1][3] = t[1][1]

temp[2][1] = t[3][2]
temp[2][2] = t[2][2]
temp[2][3] = t[1][2]

temp[3][1] = t[3][3]
temp[3][2] = t[2][3]
temp[3][3] = t[1][3]

return temp

end

for _, v in ipairs(Rotate(
{{1,2,3}, {4,5,6}, {7,8,9}})) do
print(unpack(v))
end
``````

What I was originally going to do was taken by Posatta in his first one.

Works only as a solution to the current problem.

1 Like

Hay so I did the n-degrees rotation bonus challenge as well! I basically used the fact that rotating 180 matrix is the same as rotating 90 degrees,then rotating 90 degrees again, and called the function recursively. To omit deepcopying I just made the rotating part a function on its own.

``````local function Rotate(t, r)
assert(r%90==0, "rotation must be multiple of 90")

local function rotate(t,r)
local t = t
if r ~= 90 then
t = rotate(t, r-90)
end
local output = {{}, {}, {}}
for x, v1 in pairs(t) do
for y, v2 in pairs(v1) do
output[y][4-x] = v2
end
end
return output
end

return rotate(t, r)
end
``````
2 Likes

Matrix transposition is not a 90-degree rotation of the matrix in either direction, except by coincidence for matrices with specific symmetry. The transpose of:

``````{{1, 2, 3},
{4, 5, 6},
{7, 8, 9}}
``````

is

``````{{1, 4, 7},
2, 5, 8},
3, 6, 9}}
``````

P.S. I think Syharaa’s is the only solution that actually solves the general question asked, rather than being hard-coded to only work for a 3-row or 3-column matrix. I think if he just changed one pairs to ipairs it would be guaranteed to preserve order in any compliant Lua VM too. IIRC using pairs technically allows for an interpreter to iterate the array part of the table in any order while still being compliant to the Lua standard, right? In practice, I think most–if not all–will still iterate in index order.

2 Likes

Most of the solutions here only solve for the case you have given and not an n×n matrix.

Anyway, here is my solution:

``````local function col(t)
local i, h = 0, #t
return function ()
i = i + 1
local column = {}
for j = 1, h do
local val = t[j][i]
if not val then return end
column[j] = val
end
return i, column
end
end

local function rev(t)
local n = #t
for i = 1, math.floor(n / 2) do
local j = n - i + 1
t[i], t[j] = t[j], t[i]
end
return t
end

local function rotateCW(t)
local t2 = {}
for i, column in col(t) do
t2[i] = rev(column)
end
return t2
end

local function rotateCCW(t)
local t2 = {}
for i, column in col(t) do
t2[i] = column
end
return rev(t2)
end
``````

There are certainly simpler solutions, I just thought it might be fun to use iterators for this. `col` returns a function which allows the table to be iterated as columns rather than rows. `rev` is used to reverse a table.

3 Likes

Thank you for the feedback! I was wondering what you exactly meant by pairs iterating over the array part with any order, but still respect lua’s standards. Does that mean it can iterate through indices in the logical numerical order but still obey lua’s rules?

From the Lua FAQ:

`pairs(t)` gives a general iterator over all the keys and values in a table, numerical or not, in no particular order; `ipairs(t)` goes over the array part, in order.

What this means is that if you want to write code for this challenge that will work in any Lua runtime with a standards-compliant implementation, you need to use the ipairs() iterator to rotate a matrix that is stored in the array parts of Lua tables, otherwise the columns of your supposed-to-be-rotated matrix could end up shuffled arbitrarily.

ipairs() must iterate over the array part of the Lua table in numerical order of the indices. pairs() need only iterate over all of the keys (array indices and dictionary keys), but it’s free to do so in any order the implementor pleases.

In practice, most (if not all) Lua interpreters probably implement pairs() to iterate over the array part using [almost] the same code as ipairs(), because why would you want to intentionally write that code twice or intentionally iterate over an ordered array randomly? It’s just not technically guaranteed by the standard.

1 Like

I did it!!!

local gg = {{1,2,3},
{4,5,6},
{7,8,9}}

local t = {{},
{},
{}}

function rotate(t)
for a,b in pairs(gg) do
local e , f , g = unpack(b)

``````local v1 = table.insert(t[1], e)
local v2 = table.insert(t[2], f)
local v3 = table.insert(t[3], g)
for i , v in pairs(t) do
table.sort(v, function(lol,ez)
return (lol > ez)
end)
end
end
end
``````

rotate(t)

for i, v in pairs(t) do
print(unpack(v))
print(“”)
end

1 Like

I thank you a lot for your contribution! Although the code sadly doesn’t seem to work, and I can’t find the issue. The result isn’t what’s intended. This video should help, please watch it!

I wrote code that I think works with all matrixes also some replies are quite messy(not saying it isn’t well coded, just saying it is over-complicated imo), I made something simple. Correct me if I made any mistakes.

``````local matrix =
{{1,2,3},
{4,5,6},
{7,8,9}}

function rotate(m)
local res = {}
local n = 0
for i,v in pairs(matrix) do
local tableSize = #v
table.insert(res,{})
n+=1
for x = tableSize,1,-1 do
table.insert(res[n],m[x][i])
end
end
return res
end

print(matrix)

print(rotate(matrix))
``````
1 Like