# Codegolf! a LUA challenge

#1

Hi!

I’ve realised that I only come here when I’m asking for help, which is a little selfish. So, with no further ado, I’d like to invite you to take part in a game of codegolf! Whoever can achieve the outcome with the fewest lines of lua code wins.

The rules?

• self.levmap is a table with 70 entries used to generate a 7 by 10 grid.
• if an entry is greater than 0, it is occupied.
• you need to get the width and height of the full tiles in the grid (self.width, self.height).
• you need to print the width and height once the sorting is complete.

For example.

if self.levmap =
{0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0,0,0,1,1,1,0,
0,0,0,1,1,1,0,
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0,0,0,0,0,0,0}

then
self.width= 3
self.height = 2

Here’s my entry (self taught amateur coder)

``````	local toppest = 1
local bottomest = 11
local leftest = 8
local rightest = 1
for k, v in pairs(self.levmap) do
local x = ((k-1)%7)+1 --1, 7
local y = math.ceil(k/7) --1,10
if v > 0 then
if x < leftest then
leftest = x
end
if x > rightest then
rightest = x
end
if y < bottomest then
bottomest = y
end
if y > toppest then
toppest = y
end
self.height = (toppest-bottomest)+1
self.width =  (rightest-leftest)+1
end
end
if self.levmaps[key+1] == nil then
print("size acquired! (josh don't forget to calculate tilesize here)",self.width,self.height)
end
end``````
3 Likes

#2

after 24 hours I am still in first place.
de-fault! de-fault! de-fault! de-fault!

0 Likes

#3

Here’s another solution:

``````self.width = 0
local first_row = nil
local last_row = nil
for r=1,9 do
local row = table.concat(self.levmap, "", 1+(r-1)*7, 1+(r-1)*7+6) -- concatenate each row into a string
local trimmed_row = row:match("^0*(.-)0*\$") -- trim initial and ending 0's
self.width = math.max(self.width, #trimmed_row) -- width of the row is the length of the remaining string
if #trimmed_row > 0 and not first_row then
first_row = r
end
if #trimmed_row > 0 and (not last_row or last_row < r) then
last_row = r
end
end
self.height = (first_row and last_row) and last_row - first_row + 1 or 0
``````

There must be a better way to figure out the height though…

@88.josh’s solution is more efficient since it doesn’t rely on string manipulation.

1 Like

#4

Hi 88.josh,

you can shorten by using math.max and math.min

If you like you can shorten locals initialization in one line.

You can do the same thing inside the inner loop, but I think is awful
(Or is it a Perl code competition?? )

Is better to move the result evaluation out of the loops,
and compute x and y only if needed

``````	local toppest,rightest,bottomest,leftest=1,1,11,8
for k, v in pairs(self.levmap) do
if v > 0 then
local x = ((k-1)%7)+1 --1, 7
local y = math.ceil(k/7) --1,10
leftest=math.min(x,leftest)
rightest=math.max(x,rightest)
bottomest=math.min(y,bottomest)
toppest=math.max(y,toppest)
end
end
self.height = (toppest-bottomest)+1
self.width =  (rightest-leftest)+1
``````

If you change your level map into a bidimensional array

self.levmap =
{ {0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,1,1,1,0},
{0,0,0,1,1,1,0},
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0} }

you can avoid computing x and y with remainder and math.ceil, but code length is the same

``````	local toppest,rightest,bottomest,leftest=1,1,11,8
for y,row in ipairs(self.level) do
for x,v in ipairs(row) do
if v > 0 then
leftest=math.min(x,leftest)
rightest=math.max(x,rightest)
bottomest=math.min(y,bottomest)
toppest=math.max(y,toppest)
end
end
end
self.height = (toppest-bottomest)+1
self.width =  (rightest-leftest)+1
``````

Without my locals init “cheat”, @britzl’s solution is shorter!

I won’t win the prize

2 Likes

#5

Results are in!
@lrx first place
@88.josh second place
And @britzl is disqualified for using string manipulation. Cruel, but ultimately the student has become the master, just like in star wars.

2 Likes