3

This question is a parallel to python - How do I decompose a number into powers of 2?. Indeed, it is the same question, but rather than using Python (or Javascript, or C++, as these also seem to exist), I'm wondering how it can be done using Lua. I have a very basic understanding of Python, so I took the code first listed in the site above and attempted to translate it to Lua, with no success. Here's the original, and following, my translation:

Python

def myfunc(x):
    powers = []
    i = 1
    while i <= x:
        if i & x:
            powers.append(i)
        i <<= 1
    return powers

Lua

function powerfind(n)
  local powers = {}
  i = 1
  while i <= n do
    if bit.band(i, n) then -- bitwise and check
      table.insert(powers, i)
    end
    i = bit.shl(i, 1) -- bitwise shift to the left
  end
  return powers
end

Unfortunately, my version locks and "runs out of memory". This was after using the number 12 as a test. It's more than likely that my primitive knowledge of Python is failing me, and I'm not able to translate the code from Python to Lua correctly, so hopefully someone can offer a fresh set of eyes and help me fix it.

Community
  • 1
  • 1
Josh
  • 3,225
  • 7
  • 30
  • 44
  • 3
    `bit.shl(n, 1)` - there are two things wrong with this line. Think about what the line is supposed to do, and what it actually says to do. – user2357112 May 25 '15 at 20:49
  • 1
    Also, Python and Lua differ in what they consider to be true or false. If you're more familiar with Lua, you should see something funny about `if bit.band(i, n)`. Note that Python considers 0 false. – user2357112 May 25 '15 at 20:55
  • Ah, got the `bit.shl(n,1)` changed to `i = bit.shl(i, 1)` now... but not sure what to do about the `if bit.band(i, n)` portion. – Josh May 25 '15 at 21:03
  • And... just like that, I think I figured it out by changing it to `if bit.band(i, n) ~= 0` ... working so far. Thanks! – Josh May 25 '15 at 21:04
  • `bit` is not a standard Lua library. Perhaps you mean `bit32`, in which case it's `lshift` instead of `shl`. Also, in Lua 5.3, you can use the ordinary bitwise operators `&` and `<<`. – lhf May 25 '15 at 21:32
  • For the program I'm using (MUSHclient), it's taken `bit32` and shortened it to `bit`. I don't think it's incorporated 5.3 yet, though, but I'll take a look. Thanks! – Josh May 25 '15 at 21:51

2 Answers2

4

Thanks to the comments from user2357112, I've got it fixed, so I'm posting the answer in case anyone else comes across this issue:

function powerfind(n)
  local powers = {}
  i = 1
  while i <= n do
    if bit.band(i, n) ~= 0 then -- bitwise and check
      table.insert(powers, i)
    end
    i = bit.shl(i, 1) -- bitwise shift to the left
  end
  return powers
end
Josh
  • 3,225
  • 7
  • 30
  • 44
4

I saw that in the other one, it became a sort of speed contest. This one should also be easy to understand.

i is the current power. It isn't used for calculations.
n is the current place in the array.
r is the remainder after a division of x by two.

If the remainder is 1 then you know that i is a power of two which is used in the binary representation of x.

local function powerfind(x)
    local powers={
        nil,nil,nil,nil,
        nil,nil,nil,nil,
        nil,nil,nil,nil,
        nil,nil,nil,nil,
    }
    local i,n=1,0
    while x~=0 do
        local r=x%2
        if r==1 then
            x,n=x-1,n+1
            powers[n]=i
        end
        x,i=x/2,2*i
    end
end

Running a million iterations, x from 1 to 1000000, takes me 0.29 seconds. I initialize the size of the powers table to 16.

Trey Reynolds
  • 693
  • 8
  • 11
  • Your table initialization has no effect (other than creating the empty table that's needed). `nil` cannot be neither the key nor value in a table. When you set a value in a table, the key is added automatically—no need to size the table. – Tom Blodget May 26 '15 at 13:49
  • By all means, don't take my word for it, but please test it yourself. When I don't initialize the first few numerical indices of the table, it runs significantly slower. If you test it, you'll see the same thing. – Trey Reynolds May 26 '15 at 16:01
  • I'm pretty sure it's because garbage collector hasn't had the time to pick up the trash yet. You can use this trick to make table creation significantly faster. Instead of `local o={} o.x=1 o.y=true` you can do `local o={x=1;y=true}` – Trey Reynolds May 26 '15 at 16:08
  • I see the non-functional effect. Of course, it's implementation dependent but that's what it takes sometimes to improve performance. – Tom Blodget May 26 '15 at 16:52