lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]




Em sáb., 5 de dez. de 2020 às 10:31, Egor Skriptunoff <egor.skriptunoff@gmail.com> escreveu:
On Sat, Dec 5, 2020 at 3:00 PM Xmilia Hermit wrote:

function solution4(level)
    -- Fast calculation of last_index, see https://oeis.org/A000325
    local last_index = (2 << level) - level - 1

    -- Preallocation of the array, so everything is in the array part
    local t = {"Lua"}
    for j = 2, last_index do
        t[j] = "Lua"
    end

    -- Removal of values from indices that should contain nil
    local p = 3
    for j = 1, (1 << (level - 1)) - 1 do
        local s = j ~ (j - 1)
        while s > 0 do
            -- Implicitly calculation of log without a table lookup
            -- Since we already looping this is better
            s = s >> 1
            t[p] = nil
            p = p + 1
        end
        p = p + 2
    end

    return t, last_index
end

local level = tonumber(arg[1])
local t, last_index = solution4(level)



Congratulations!
Your solution is the fastest.

$ time lua student3.lua 20
real    0m0.294s

$ time lua pierre.lua 20
real    0m0.158s

$ time lua student4.lua 20
real    0m0.140s

$ time lua xmilia.lua 20
real    0m0.127s


My version:

$ cat student4.lua
-- Unfortunately, there is no function table.new() in Lua to allocate a room for the array part.
-- Workaround: create a table and make it grow by inserting fake values, all of them will be overwritten later
function solution4(level)
   if level == 0 then
      return {"Lua"}, 1
   end
   local t = {"Lua", "Lua"}
   local last_index = 2
   for j = 4, 2^level + level do
      t[j] = true  -- inserting fake values
   end
   for n = 2, level do
      last_index = last_index + 1
      t[last_index] = nil
      table.move(t, 1, last_index, last_index + 1)
      last_index = 2 * last_index
   end
   last_index = last_index - level + 1
   return t, last_index
end

local level = tonumber(arg[1])
local t, last_index = solution4(level)


The crucial part is "Preallocation of the array, so everything is in the array part"
That's what every Lua programmer should be aware of while optimising for speed.

Conclusion:
We need something like table.rebuild()/table.new() in Lua to avoid inserting fake values.
I agree.
Could look something like:

ltablib.c
static int tnew (lua_State *L) {
  int narray = luaL_checkinteger(L, 1);
  int nrec = luaL_optinteger(L, 2, 1);  
  lua_createtable(L, narray, nrec);  /* create result table */
  return 1;  /* return table */
}

static int tresize (lua_State *L) {
  int nasize = luaL_checkinteger(L, 2);
  int nhsize = luaL_optinteger(L, 3, 1);
  if (nasize != 0 || nhsize != 0)
    Table *t = gettable(L, 1);
    luaH_resize(L, t, nasize, nhasize);
  return 0;
}

Lua C api, could also benefit from the use of unsigned int, uniform, in table functions.
I don't know why use int type when LuaH_resize uses unsigned int.

Ranier Vilela