[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: optimisation question
- From: RLake@...
- Date: Thu, 3 Jul 2003 10:49:16 -0500
> I have a function I would like to optimize (yes, I've done profiling).
> it transforms string like "3-7" into "3,4,5,6,7".
Try this:
function transform(str)
  local _, _, from, to = string.find(str, "^(%d+)%-(%d+)$")
  assert(from, "Transform needs a string in the format i-j")
  local n1, n2 = tonumber(from), tonumber(to)
  if n1 >= n2 then return from end
  local template = from .. string.rep(", ", n2 - n1)
  return (string.gsub(template, " ", function() n1 = n1 + 1; return n1 
end))
end
Philippe had a good idea about memoising results; the above can be 
improved
(slightly) by memoising the template string. (It only helps on largish 
ranges.)
-- A useful tool:
function memoise(fn)
  return setmetatable({}, {
    __index = function(t, k)
                local rv = fn(k)
                t[k] = rv
                return rv
              end
  })
end
do
  local function make_template(k)
    return " " .. string.rep(", ", k)
  end
  local template = memoise(make_template)
  function transform2(str)
    local _, _, from, to = string.find(str, "^(%d+)%-(%d+)$")
    assert(from, "Transform needs a string in the format i-j")
    local n1, n2 = tonumber(from), tonumber(to)
    if n1 >= n2 then return from end
    return (string.gsub(template[n2 - n1], " ",
            function() local rv = n1; n1 = n1 + 1; return rv end))
  end
end
The test for n1 >= n2 is actually unnecessary, but that counts on a
particular behaviour of string.rep. In fact, the conversion of from
and to to numbers is also unnecessary (if the comparison is removed),
because it will happen automatically. So making those changes, we
could reduce the code to the following: (shorter, if not faster)
do
  local function make_template(k)
    return " " .. string.rep(", ", k)
  end
  local template = memoise(make_template)
  function transform3(str)
    local _, _, from, to = string.find(str, "^(%d+)%-(%d+)$")
    assert(from, "Transform needs a string in the format i-j")
    return (string.gsub(template[to - from], " ",
            function() local rv = from; from = from + 1; return rv end))
  end
end