GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2019-01-25 00:57:05

lostdarkwolf
Member
Registered: 2015-11-19
Posts: 22

Xot's base_convert script modded to support a higher base (update 3)

I've modified Xot's base_convert script to support a higher base depth. Original functionality retained.
Original: https://www.gmlscripts.com/script/base_convert
I've also made a set of scripts that does almost the same thing as the base_convert script. They are below the base_convert script.

This version of base_convert seems to work without error as far as i have tested, but it can be slow if the base depth is a big number, depending on the system. update 3: displayable character set extended to 94.

/// base_convert(number,oldbase,newbase,tot)
//
//  Returns a string of digits representing the
//  given number converted form one base to another.
//  The largest base supported is unknown.
//  After base94, the character set changes to one that is not meant to be displayed.
//
//      number      integer value to be converted, string
//      oldbase     base of the given number, integer
//      newbase     base of the returned value, integer
//      tot         Total number of places of the returned value to be shown. Use -1 to disable. integer
//
//  The first character in the character set will be inserted
//  to match the number of places specified by "tot".
//  This script will hang temporarily if "oldbase" or
//  "newbase" is set to a high number. 
//
/// GMLscripts.com/license
{
    var number, oldbase, newbase, out, format;
    number = string_upper(argument[0]);
    oldbase = argument[1];
    newbase = argument[2];
    format = -1;
    if (argument_count > 3) format = argument[3];
    out = "";
 
    var len, tab_in, tab_out;
    len = string_length(number);
    tab_in = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"+"abcdefghijklmnopqrstuvwxyz"+'!"'+'$%&'+"'"+"()*+,-./:;<=>?@[]^_`{|}~ "
    if oldbase>94 {
        tab_in="";
        var ii=0;
        do {
            tab_in+=chr(ii);
            ii+=1;
        }
        until string_length(tab_in)=oldbase
    }
    tab_out = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"+"abcdefghijklmnopqrstuvwxyz"+'!"'+'$%&'+"'"+"()*+,-./:;<=>?@[]^_`{|}~ "
    if newbase>94 {
        tab_out="";
        var ii=0;
        do {
            tab_out+=chr(ii);
            ii+=1;
        }
        until string_length(tab_out)=newbase
    }
 
    var i, num;
    for (i=0; i<len; i+=1) {
        num[i] = string_pos(string_char_at(number, i+1), tab_in) - 1;
    }
 
    do {
        var divide, newlen;
        divide = 0;
        newlen = 0;
        for (i=0; i<len; i+=1) {
            divide = divide * oldbase + num[i];
            if (divide >= newbase) {
                num[newlen] = divide div newbase;
                newlen += 1;
                divide = divide mod newbase;
            } else if (newlen  > 0) {
                num[newlen] = 0;
                newlen += 1;
            }
        }
        len = newlen;
        out = string_char_at(tab_out, divide+1) + out;
    } until (len == 0 or string_length(out) == format);
 
    if (format > 0) {
        while (string_length(out) < format) {
            out = string_char_at(tab_out, 0) + out
        }
    }
    return out;
}

My goal was to convert a number into a string that can be safely copied to the clipboard in the most space efficient way. I was successful, but I was unable to optimize the script above. So, after a bit of focus, I've come up with the following scripts instead. To ensure safe operation, I've decided to only use printable characters. Unfortunately, the number sign is excluded because gamemaker converts it into a newline, and it cannot be represented alone.

This script efficiently converts an integer into a clipboard friendly printable string.

///dec_to_print(dec, base*, tot*)
// * not required
//
// Converts an integer into a printable string.
// Printable characters, include space, but exclude number sign.
// Base94 is the highest base supported.
//
// dec    decimal to convert, real (integer)
// base   base depth to use, real (integer)
// tot    total number of places, real (integer)
//
/// GMLscripts.com/license

var var_arg_decimal=argument[0];
var_arg_base_depth=94
if argument_count>1 var_arg_base_depth+=argument[1];
var var_arg_tot=-1;
if argument_count>2 var_arg_tot=argument[2];
var Return='';

var var_key_str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"+"abcdefghijklmnopqrstuvwxyz"+'!"'+'$%&'+"'"+"()*+,-./:;<=>?@[]^_`{|}~ ";
while var_arg_decimal>0 {
 if var_arg_tot>=0 {
  if string_length(Return)<var_arg_tot {
   Return=string_char_at(var_key_str,(var_arg_decimal mod var_arg_base_depth)+1)+Return;
  }
 }
 else {
  Return=string_char_at(var_key_str,(var_arg_decimal mod var_arg_base_depth)+1)+Return;
 }
 var_arg_decimal=floor(var_arg_decimal/var_arg_base_depth);
}

while string_length(Return)<max(var_arg_tot,1) Return='0'+Return;

return Return;

This script efficiently converts a printable string into an integer.

///print_to_dec(clip, base*)
// * not required
//
// Converts a printable string into a decimal.
// Output only uses printable characters, including space.
// Base94 is the highest base supported.
//
// clip   96-bit string to convert, real (integer)
// base   base depth to use, real (integer)
//
/// GMLscripts.com/license

var var_arg_clip=argument[0];
var var_arg_base_depth=94;
if argument_count>1 var_arg_base_depth+=argument[1];

var_key_str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"+"abcdefghijklmnopqrstuvwxyz"+'!"'+'$%&'+"'"+"()*+,-./:;<=>?@[]^_`{|}~ "
var ii=1;
var ii2=string_length(var_arg_clip);
var var_char_num=0;
while ii2>0 {
 var_char_num+=(string_pos(string_char_at(var_arg_clip,ii),var_key_str)-1)*power(var_arg_base_depth,ii2-1);;
 ii+=1;
 ii2-=1;
}

return var_char_num;

Last edited by lostdarkwolf (2019-01-27 20:42:40)

Offline

Board footer

Powered by FluxBB