Codegolf! a LUA challenge

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

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

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

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 :face_vomiting:
(Or is it a Perl code competition?? :rofl:)

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 :sweat_smile:

2 Likes

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