Noticias

¡Ayuda a la Comunidad GM, haz una donación!

Comunidad Game Maker

Bienvenid@ a la comunidad hispana de Game Maker. Nuestro objetivo es crear videojuegos y dar soporte en castellano de GM. Para mejorar nuestro servicio hemos implantado, como adicion al reglamento general, algunas normas especificas en los subforos más comunes. ¡No olvides informarte antes de participar!.

Autor Tema: Acortar y alargar strings segun caracteres repetidos  (Leído 577 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Johann

  • Las cosas como son!
  • Moderadores globales
  • Okupa
  • *
  • Puntos: 753
  • Mensajes: 862
  • Agradecido: 117 veces
  • Sexo: Masculino
  • First Class Soldier... 10 años en CGM, 5 como mod
    • Ver Perfil
en: Noviembre 02, 2018, 03:15:22 am
  • Nombre del creador: Johann
  • Breve descripción de su función: Acortar y alargar una cadena de texto que tiene caracteres repetidos sucesivamente
  • Versión GM utilizada: Game maker: Studio 1.4.9999
  • Código del Script:

Script para acortar una cadena de texto resumiendo la cantidad de caracteres repetidos sucesivos:
///shorten(str)
//
// (ESP)
// Reduce el tamaño de una cadena de texto
// reemplazando un conjunto de caracteres sucesivos
// por el numero de veces que se repite.
//
//     str      cadena de caracteres muy larga
//
// (ENG)
// Reduces the size of a text replacing a set of
// consecutive characters with the number of times
// it is present.
//
//     str      a very large string
//
//
/// GMLscripts.com/license
{
    var str = argument0
    var newStr = "";
    var currentChar;
    var nextChar;
    var size = string_length(str);
    var amount = 0;
    for (var i=1; i<=size; i++) {
        currentChar = string_char_at(str, i);
        if (i!=size) {
            nextChar = string_char_at(str, i+1);
        } else {
            nextChar = "";
        }
        if (currentChar == nextChar) {
            amount = 1;
            newStr += currentChar;
            while (currentChar == nextChar) {
                amount++;
                i++;
                nextChar = string_char_at(str, i+1);
            }
            newStr += ("(" + string(amount) + ")");
        } else {
            newStr += currentChar;
        }
    }
    return newStr;
}

Script para recuperar una cadena de texto reestableciendo la cantidad de caracteres repetidos sucesivos:
///enlarge(str)
//
// (ESP)
// Recupera el tamaño de una cadena de texto
// agregando un conjunto de caracteres sucesivos
// a partir del numero de veces que se repite.
//
//     str      cadena de caracteres a alargar
//
// (ENG)
// Recovers the size of a text adding a set of
// consecutive characters with the number of times
// it is needed.
//
//     str      a string to enlarge
//
//
/// GMLscripts.com/license
{
    var str = argument0;
    var oldStr = "";
    var currentChar;
    var nextChar;
    var size = string_length(str);
    var amount = "";
    for (var i=1; i<=size; i++) {
        currentChar = string_char_at(str, i);
        if (i!=size) {
            nextChar = string_char_at(str, i+1);
        } else {
            nextChar = "";
        }
        if (nextChar == "(") {
            amount = "";
            while (nextChar != ")") {
                i++;
                nextChar = string_char_at(str, i+1);
                amount += nextChar;
                show_debug_message(amount);
            }
            repeat(real(amount)) {
                oldStr += currentChar;
            }
            i++;
        } else {
            oldStr += currentChar;
        }
    }
    return oldStr;
}

Estos algoritmos se basan (se inspiran, mejor) en el algoritmo Run-length_encoding y he tenido que hacerlos para acortar y recuperar las cadenas de texto generadas por las funciones ds_*_write() donde el * es el nombre de una estructura de datos en GM, estas funciones retornan un string como el siguiente y su tamaño depende del contenido en la estructura de datos:

//Ejemplo
var text = ds_grid_write(my_grid);
show_debug_message(text);
var text2 = shorten(text);
show_debug_message(text2);

Código: [Seleccionar]
5A0200000400000004000000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000
408 caracteres

5A020(5)40(7)40(52)40(23)40(23)40(23)40(95)40(95)40(73)
55 caracteres

Ya que requiero almacenar estos datos en una base de datos sqlite3 para generar unas estructuras visualmente en mi proyecto y no quería almacenar algo muy largo.
En resumen, el tamaño del texto se reduce en un 86.5% mejorando el consumo de memoria en disco, esto es importante para aplicaciones móviles.

Ojalá les gusten y puedan usarlos.
Mañana los posteo en https://www.gmlscripts.com y en el foro de yoyo, haber como me va por allá, por eso usé ese encabezado de comentarios.
« última modificación: Noviembre 02, 2018, 03:24:43 am por Johann »

Cita de: Fenris78
Si un tema os resulta de interes y veis que hay poca información, la mejor solucion no es quejarse o pedir sin pensar, sino sugerir algo bien planteado o aportarlo vosotros mismos.
Cita de: Calio
Somos desarrolladores independientes y, por lo tanto, no tenemos por qué guiarnos por las tendencias del mercado.
 
Los siguientes usuarios dieron las gracias a este tema: Goganpis


No Tienes Permisos Para Dar Puntos
point 8 Puntos

Usuarios que puntuaron el tema » Clamud (8 Pts) 


Desconectado Ashe de Freljord

Respuesta #1 en: Noviembre 02, 2018, 03:49:17 am
Buenos scripts.

En el decodificador me parece que sería más optimo operar 10^N que hacer el ciclo N veces. Al menos las veces donde la seguidilla es de ceros.

Edit: Estuve pasando el codigo a C++ solo para practicar para la universidad XD
Y me dí cuenta que el código alarga la cadena para coincidencias de 2 y 3 caracteres, mientras que con 4 simplemente no hay optimizacion.

Ej:
a003315588800
13
a0(2)3(2)15(2)8(3)0(2)
22

Creo que sería bueno tener en cuenta esos casos en particular. 
« última modificación: Noviembre 02, 2018, 04:55:51 am por Ashe de Freljord »

 
Los siguientes usuarios dieron las gracias a este tema: Goganpis


Desconectado Goganpis

Respuesta #2 en: Noviembre 02, 2018, 02:27:04 pm
No pense, ni me imaginaba algo asi, unos de los algoritmos de gran utilidad, no pense en algo asi nunca xD... Que buen trabajo de script para adaptar Good Job!  ;D

 


Desconectado Johann

  • Las cosas como son!
  • Moderadores globales
  • Okupa
  • *
  • Puntos: 753
  • Mensajes: 862
  • Agradecido: 117 veces
  • Sexo: Masculino
  • First Class Soldier... 10 años en CGM, 5 como mod
    • Ver Perfil
Respuesta #3 en: Noviembre 02, 2018, 10:24:43 pm
Ashe de Freljord, has obtenido lo que podríamos llamar el umbral de optimización del algoritmo, lo que me gustaría conocer es el tiempo de ejecución en diferentes casos.

Como lo hice pensando en los strings que genera ds_*_write() no caí en cuenta de esos casos, tienes razón, si los caracteres se repiten 4 veces o menos ya no vale la pena aplicar el algoritmo.

Pero si se fijan en los strings para todas las estructuras de datos del GM si que será muy útil, o al menos interesante.

Cita de: Fenris78
Si un tema os resulta de interes y veis que hay poca información, la mejor solucion no es quejarse o pedir sin pensar, sino sugerir algo bien planteado o aportarlo vosotros mismos.
Cita de: Calio
Somos desarrolladores independientes y, por lo tanto, no tenemos por qué guiarnos por las tendencias del mercado.