Snippet Base

Nestharus

o-o
Reaction score
84
JASS:

library Base /* v1.0.4.1
*************************************************************************************
*
*   A script used for base conversion where integers are represented as strings in
*   another base.
*
*************************************************************************************
*
*   */uses/*
*
*       */ Ascii /*         wc3c.net/showthread.php?t=110153
*       */ Table /*         hiveworkshop.com/forums/jass-functions-413/snippet-new-table-188084/
*
************************************************************************************
*
*   struct Base extends array
*
*       readonly integer size
*           -   number of digits in base
*       readonly string string
*           -   string representing base's character set
*
*       static method operator [] takes string base returns Base
*
*       method convertToString takes integer i returns string
*       method convertToInteger takes string i returns integer
*
*       method ord takes string c returns integer
*       method char takes integer i returns string
*
*       method isValid takes string value returns boolean
*           -   determines if all of the characters in the string are valid base character
*
*************************************************************************************/

/*************************************************************************************
*
*   Code
*
*************************************************************************************/
    globals
        private Table gt=0          //stacks of strings with same hashes
        private integer array n     //next node pointer for gt stack
        private string array b      //base of string
        private Table array t       //base character table
        private integer c=0         //base instance count
        private integer array s     //base size
    endglobals
    private module Init
        private static method onInit takes nothing returns nothing
            set gt=Table.create()
        endmethod
    endmodule
    struct Base extends array
        debug private static boolean array a        //is allocated
        method operator string takes nothing returns string
            return b[this]
        endmethod
        method operator size takes nothing returns integer
            return s[this]
        endmethod
        static method operator [] takes string base returns thistype
            local integer value     //string hash value
            local string char       //iterated character
            local integer i=0       //this
            local integer v         //stack of hashes
            local integer dv        //copy of v
            local integer hv        //copy of value
            debug if (1<StringLength(base)) then
                set value = StringHash(base)    //first get the hash
                set i = gt[value]               //get first node of hash table
                set v = i                       //copy
                if (0!=i) then                  //if stack exists, then loop through
                    loop
                        exitwhen 0==i or base==b<i>
                        set i=n<i>
                    endloop
                endif
                //if this still doesn&#039;t exist, create it
                if (0==i) then
                    //allocate
                    set c=c+1
                    set i=c
                    set dv=v
                    set hv=value
                    debug set a<i>=true
                    set t<i>=Table.create()     //character table
                    set b<i>=base               //base string
                    //value is now used for iterating through the base string
                    set value=StringLength(base)
                    set s<i>=value    
                    loop
                        set value=value-1
                        set char=SubString(base,value,value+1)
                        set v=Char2Ascii(char)
                        //if the character already exists, stop
                        //and deallocate (invalid base)
                        debug if (t<i>.has(v)) then
                            debug call t<i>.destroy()   //destroy character table
                            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,&quot;BASE CREATION ERROR: &quot;+char+&quot; MULTIPLY DEFINED&quot;)
                            debug set c=c-1
                            debug set a<i>=false
                            debug return 0
                        //character doesn&#039;t exist
                        debug else
                            set t<i>[v]=value
                            set t<i>.string[-value]=char
                        debug endif
                        exitwhen 0==value
                    endloop
                    //if dv is 0, then allocate dv
                    if (0==dv) then
                        set gt[hv]=i
                    //otherwise add i to hash stack
                    else
                        set n<i>=n[dv]
                        set n[dv]=i
                    endif
                endif
                return i
            debug endif
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,&quot;BASE CREATION ERROR: &quot;+base+&quot; IS INVALID&quot;)
            debug return 0
        endmethod
        method convertToString takes integer i returns string
            local integer k=s[this]
            local string n=&quot;&quot;
            debug if (a[this]) then
                debug if (0&lt;=i) then
                    loop
                        exitwhen i&lt;k
                        set n=t[this].string[-(i-i/k*k)]+n
                        set i=i/k
                    endloop
                    return t[this].string[-i]+n
                debug endif
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,&quot;BASE CONVERSION ERROR: &quot;+I2S(i)+&quot; IS OUT OF BOUNDS&quot;)
                debug return null
            debug endif
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,&quot;BASE CONVERSION ERROR: &quot;+I2S(this)+&quot; IS NOT ALLOCATED&quot;)
            debug return null
        endmethod
        method convertToInteger takes string i returns integer
            local integer n=0
            local integer p=StringLength(i)
            local integer l=0
            local integer k=s[this]
            local string char
            debug if (a[this]) then
                loop
                    exitwhen 0==p
                    set p=p-1
                    set l=l+1
                    set char=SubString(i,l-1,l)
                    debug if (t[this].has(Char2Ascii(char))) then
                        set n=n+t[this][Char2Ascii(char)]*R2I(Pow(k,p))
                    debug else
                        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,&quot;BASE CONVERSION ERROR: &quot;+char+&quot; IS OUT OF BOUNDS&quot;)
                        debug return 0
                    debug endif
                endloop
                return n
            debug endif
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,&quot;BASE CONVERSION ERROR: &quot;+I2S(this)+&quot; IS NOT ALLOCATED&quot;)
            debug return 0
        endmethod
        method ord takes string c returns integer
            debug if (a[this]) then
                debug if (1&lt;StringLength(c) or &quot;&quot;==c or null==c or not (t[this].has(Char2Ascii(c)))) then
                    debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,&quot;BASE ORD ERROR: &quot;+c+&quot; IS OUT OF BOUNDS&quot;)
                    debug return 0
                debug endif
                return t[this][Char2Ascii(c)]
            debug endif
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,&quot;BASE ORD ERROR: &quot;+I2S(this)+&quot; IS NOT ALLOCATED&quot;)
            debug return 0
        endmethod
        method char takes integer i returns string
            debug if (a[this]) then
                debug if (i&lt;s[this] and 0&lt;=i) then
                    return t[this].string[-i]
                debug endif
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,&quot;BASE CHAR ERROR: &quot;+I2S(i)+&quot; IS OUT OF BOUNDS&quot;)
                debug return null
            debug endif
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,&quot;BASE CHAR ERROR: &quot;+I2S(this)+&quot; IS NOT ALLOCATED&quot;)
            debug return null
        endmethod
        method isValid takes string s returns boolean
            local integer i=StringLength(s)
            local string c
            if (0&lt;i) then
                loop
                    set c=SubString(s,i-1,i)
                    if (not t[this].has(Char2Ascii(c))) then
                        return false
                    endif
                    set i=i-1
                    exitwhen 0==i
                endloop
            else
                return false
            endif
            return true
        endmethod
        implement Init
    endstruct
endlibrary
</i></i></i></i></i></i></i></i></i></i></i></i>
 

tooltiperror

Super Moderator
Reaction score
231
That may be actually the ugliest syntax I have ever seen in a vJASS system. Ever.

JASS:
call ConvertBase(integer which, integer base)
 

Sevion

The DIY Ninja
Reaction score
424
tooltiperror, there is actually a difference between your syntax and his syntax. Yours requires the system to have a predefined alphabet. His does not. And to my knowledge, allowing for user-defined bases different than how he has it setup right now would be much less efficient.
 

tooltiperror

Super Moderator
Reaction score
231
Here, same functionality but prettier.

JASS:
globals
    private Base Octal=CreateBase(&quot;01234567&quot;)
    private Base Decimal=CreateBase(&quot;0123456789&quot;)
endglobals

private function foofunction takes nothing returns nothing
    local integer int=10203
    set int=ConvertBase(int,Decimal,Octal) // function ConvertBase takes integer which, Base current base, Base conversion 
endfunction
 

Sevion

The DIY Ninja
Reaction score
424
That includes a function call which reduces efficiency. At any rate, I do think that something could be done about that [ljass]baseN.to()[/ljass] and [ljass]baseN.from()[/ljass] syntax. That part is ugly as hell.
 

Nestharus

o-o
Reaction score
84
Yea, this is really about I2S and S2I where the string isn't necessarily in base 10.

Could do like s2i and i2s ;o.

edit
Updated API, tell me what you think.
 

Nestharus

o-o
Reaction score
84
Updated this as apparently [ljass]StringHash("d") == StringHash("D")[/ljass] ... will now work, but had to add this bs [ljass]if (c == StringCase(c, true)) then[/ljass].
 

Nestharus

o-o
Reaction score
84
Updated to run off of Ascii and Table.

Also changed the way requirements were listed in the documentation. Moved the uses keyword down to signify when requirements list starts ;D. Pretty spiffy huh? : P

Also, Bases no longer have any chance of colliding. StringHash can return 2 of the same hashes for two different strings =P.
 

Bribe

vJass errors are legion
Reaction score
67
Half of this is using a hashtable, the other half Table, and the TableArray you declared like Table array :O
 

Nestharus

o-o
Reaction score
84
Nevermind, just came up with a way that can replace the hashtable with a table. I'll update it today.

The hashtable itself points to an array of values. So one large range (requiring 1 full index) and one limited range. That array of values can also be put into a stack inside where the hashtable points to the pointer of that stack. This means then that only 1 full index is required, thus a Table can be used instead of a hashtable if using a stack instead of an array =).

Should be slightly faster and still have a max instance count of 8191.

The reason a TableArray was because it wasn't needed for this. A TableArray would be useful if I had like a 3D collection (my array + table array).

edit
updated
 

tooltiperror

Super Moderator
Reaction score
231
There are a wide variety of uses for this.

Base manipulation is important in most programming languages. I found myself needing a way to replicate the Exclusive-Or (XOR) function in JASS, and converting to binary with this was the best way.

Other things like shortening integers by converting bases is simple with this, too.

As always, your code is optimal, quite possibly some of the best ever written performance-wise for Warcraft III.

Approved.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top