• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Convert this Python function to lua please?

Status
Not open for further replies.
Level 15
Joined
Aug 7, 2013
Messages
1,337
Hi,

Can someone give me the Lua version of this python function?

I've lost so much hair trying to turn this into a lua function...

Code:
def add(value, baseDigits, result = ""):
    if value == "":
        value = "0"
    if value[-1] != baseDigits[-1]:
        next_digit = baseDigits.find(value[-1]) + 1
        return value[:-1] + baseDigits[next_digit] + result
    else:
        return add(value[:-1], baseDigits, result + "0")

Edit: a lua version

Code:
	//! i function add(value, result)
		//! i if value == "" then
			//! i value = "0"
		//! i end
		//! i lastValue = string.sub(value, string.len(value), string.len(value))
		//! i lastBase = string.sub(BASE_62, string.len(BASE_62), string.len(BASE_62))
		//! i if lastValue ~= lastBase then
			//! i nextBase = string.sub(BASE_62, string.find(BASE_62, lastValue) + 1, string.find(BASE_62, lastValue) + 1)
			//! i return string.sub(value, 1, string.len(value) - 1) .. nextBase .. result
		//! i else
			//! i return add(string.sub(value, 1, string.len(value) - 1), result .. "0")
		//! i end
	//! i end
 
Last edited:
Level 29
Joined
Jul 29, 2007
Messages
5,174
Yes, because not caching values is obviously Lua's problem.
Either way, it is not obvious in the least what your function actually does...

And yes, Lua is small and simple, which is why it's also fast. This adds complexity in some places (especially strings and lack of general purpose regular expressions) by not giving you syntax sugar with extra coating that other languages give.

Lastly, your code isn't even valid. You need to declare your variables as locals.
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
It's an ad-hoc way to increment any number in any base by 1. I doubt it's even close to an elegant solution, but it works.

I did not think of it in terms of caching. How does Lua treat strings then? In Python they are essentially lists AFAIK.



I misread Lua's "about" (see http://www.lua.org/about.html) page about why it is used versus something like Python. What I summarize from it is that among high level languages like Python, Lua is among the fastest?

But performance isn't an issue here. I'm just interested in readable, high level code that does what it needs to do.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
By caching I mean actually setting the repetitive values to local variables.

Lua:
function add(value, result)
  if value == "" then
    value = "0"
  end
  
  local lenValue = value:len()
  local lastValue = value:sub(lenValue, lenValue)
  -- These two aren't even a part of this function
  local lenBase = BASE_62:len()
  local lastBase = BASE_62:sub(lenBase, lenBase)
  local match
  
  if lastValue ~= lastBase then
    match = BASE_62:find(lastValue) + 1
    
    return value:sub(1, lenValue - 1) .. BASE_62:sub(match, match) .. result
  else
    return add(value:sub(1, lenValue - 1), result .. "0")
  end
end
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
Oh I see...Well I guess I avoided "caching" due to my ignorance of Lua string manipulation.

Still the Python version feels more concise, perhaps this is because I do not need to call a substring function to access an individual character each time.

Oh wow I did not realize Lua also had a local keyword for variables. Thank you for pointing this out. Odd that it did compile on the Lua online interpreter?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I don't see how caching is related to Lua or strings. As a rule of thumb, if you are using some value more than one time, it might be a good idea to set it as a local, in any language.

Yes, Python, like most languages, gives you syntax sugar. Lua doesn't.
That said, I am not sure why Lua doesn't have at least a character-based getter. Possibly because the whole design is around not letting the user create objects without being aware of it (which is very common in other languages).

E.g.
Lua:
string.char(string.byte(str, byte)) -- will create a new string object

Your code worked because those variables bled into the global scope, which is something you probably don't want. I might have overreacted with calling it not valid, rather it's just not good.
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
I don't suppose you could give me an elegant solution as well?

Like how is incrementing done for non decimal bases in industry standard programming?
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
It's probably not done, because in what scenario is that useful?
When does one not use (hexa)decimal numbers?

Well I was hoping for a solution that captures some general / deep facts about bases.

Well apparently WC3 uses base 62 for object raw codes, if I'm not mistaken?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Yes, but it just interprets them as decimal numbers (also it's not base 62, but some half-working base 256).

Here are my Ruby functions for Warcraft's IDs:
Ruby:
def id_to_integer(id)
  integer = 0
  
  (1...id.length - 1).each { |i|
    integer = integer * 256 + id[i].ord()
  }
  
  integer
end

def integer_to_id(integer)
  map = ".................................!.#$%&'()*+,-./0123456789:;<=>.@ABCDEFGHIJKLMNOPQRSTUVWXYZ[.]^_`abcdefghijklmnopqrstuvwxyz{|}~................................................................................................................................."
  id = ""
  
  (0...4).each { |i|
    char = integer % 256
    integer = (integer / 256).floor()
    
    id += map[char]
  }
  
  "'#{id.reverse()}'"
end

The character map is in fact copied directly from Cheats.j:
JASS:
function DebugIdInteger2IdString takes integer value returns string
    local string charMap = ".................................!.#$%&'()*+,-./0123456789:;<=>.@ABCDEFGHIJKLMNOPQRSTUVWXYZ[.]^_`abcdefghijklmnopqrstuvwxyz{|}~................................................................................................................................."
    local string result = ""
    local integer remainingValue = value
    local integer charValue
    local integer byteno

    set byteno = 0
    loop
        set charValue = ModuloInteger(remainingValue, 256)
        set remainingValue = remainingValue / 256
        set result = SubString(charMap, charValue, charValue + 1) + result

        set byteno = byteno + 1
        exitwhen byteno == 4
    endloop
    return result
endfunction
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
It is not base 62? It appears all raw codes use the following characters/symbols:

0123456789 = 10

abcdefghijklmnopqrstuvwxyz = 26

ABCDEFGHIJKLMNOPQRSTUVWXYZ = 26

10 + 26 + 26 = 62

What other characters are valid in raw codes?

Or is that char map 256 characters long? I have never seen raw codes use non alphanumeric characters. Why did they include them?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Every character in the character map is valid.

The base is 256 since it just uses bytes, those characters are used as C++ character integrals.
For example, 'A' and 'AAAA' are both valid 1 byte and 4 byte integers in C++ (the latter needs an extension to be enabled).
They only mapped some of the characters since the rest are all sorts of control characters and the locale-dependent extended ASCII.

The game uses just letters since they allow the IDs to make sense, in a way that you can read them and figure what that object is.
If you see "hfoo", it is easy to know it's a human footman.
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
I've gone through the raw codes thousands of times, I know they try to make them sound like the object or word, or they come up with prefixes, e.g. I usually means an item, while AI is for item based abilities.

So if I kept making millions of objects, eventually they would use the non-alphanumeric characters in the char map, like "[" ?
 
Status
Not open for further replies.
Top