Noviembre 30, 2018, 03:37:24 AM Ultima modificación: Diciembre 06, 2018, 12:51:13 AM por Johann
Hola a todos, les cuento que me enfrento al bug mas "ficticio" del mundo:
Primero el contexto:
Resulta que tengo varias listas que contienen objetos (instancias de un mismo objeto, para ser mas exacto), estos objetos tienen sus propiedades (variables) con diferentes valores, en algún momento requiero juntar todos esos objetos en una única lista y luego redistribuirlos en listas nuevas luego de haberlos ordenado de acuerdo al valor en una de sus propiedades.
Para eso utilizo el algoritmo de ordenamiento burbuja adaptado a las condiciones particulares, ya lo he probado en un proyecto aislado y no ha tenido inconvenientes:

[gml]
///e_sort(list)
var N = ds_list_size(argument0);
var s = noone;
var j = 0;
for (var i=1; i<N; i++) {
    j = i;
    s = ds_list_find_value(argument0, j);
    while (ds_list_find_value(argument0, j-1).valor > s.valor && j>0) {
        ds_list_replace(argument0, j, ds_list_find_value(argument0, j-1));
        j--;
    }
    ds_list_replace(argument0, j, s);
}
[/gml]

Ahora los casos que se dan luego de juntar todos los objetos en una unica lista:

  • A, B, A, B, B, B
  • B, B, A, B, A, B
Donde A tiene un valor de 3.04 y B tiene un valor de 3.44
En cualquier caso el resultado debería ser A, A, B, B, B, B PERO en el primer caso funciona y en el segundo falla el algoritmo y se cierra la aplicación.
Cuando funciona se crean correctamente dos listas conteniendo A, B, B como se espera que lo haga.


############################################################################################
FATAL ERROR in
action number 1
of Mouse Event for Glob Right Pressed

for object control:


Unable to find any instance for object index '0' name 'table_return'
at gml_Script_e_sort
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_e_sort (line -1)
gml_Script_sintesis2
gml_Object_control_Mouse_54


Es como si los objetos ya no existieran y hace cualquier cosa como buscar un object_index == 0 con el nombre de cualquier otro objeto.
Ya he verificado que efectivamente los objetos si existen y fue asi como obtuve las listas de los casos que puse arriba como ejemplo.
Las veces que he visto que el "error" se encuentra en la linea -1 es porque no logra iniciar el script.
El script sintesis2 es el que une las listas en una sola, aplica el script de ordenamiento y hace la redistribución en las listas nuevas, eso se ejecuta en un evento Global Right Pressed

Me tocó alargar el post debido a la complejidad del proyecto que postearé a mitad de Diciembre, espero que no se me escape nada para que me puedan ayudar con sus comentarios.
Cita de: Fenris78Si 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: CalioSomos desarrolladores independientes y, por lo tanto, no tenemos por qué guiarnos por las tendencias del mercado.

#1 Noviembre 30, 2018, 03:48:27 AM Ultima modificación: Noviembre 30, 2018, 04:06:02 AM por NiuWeb
No veo nada mal con el script, pero de todas formas yo sugeriría utilizar colas de prioridad para organizar las instancias con mayor facilidad y evitar posibles errores.

Tal vez haya algún problema con el script sintesis2() en el que no te hayas fijado, puede ser buena idea imprimir texto en consola en varias partes del código para ver en qué lugar exactamente se produce el fallo.
alaberga regué el café.

BA:STFW&RTFM

Cita de: NiuWeb en Noviembre 30, 2018, 03:48:27 AM
tal vez sea buena idea imprimir texto en consola en varias partes del código para ver en qué lugar exactamente se produce el fallo.
Lo he hecho por todas partes, imprimiendo cada cambio en las listas para ver donde muere, una hipótesis que tenía era que el programa dependía del orden que se fueron creadas las instancias, lo cual es ridiculo XD

Me dejas pensando con lo de las colas de prioridad, así no tendría que usar ordenamiento, pero el cambio a esta altura me puede salir un poquito costoso (o no?, ya se me están ocurriendo cosas)
Cita de: Fenris78Si 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: CalioSomos desarrolladores independientes y, por lo tanto, no tenemos por qué guiarnos por las tendencias del mercado.

Cita de: Johann en Noviembre 30, 2018, 04:13:40 AM
pero el cambio a esta altura me puede salir un poquito costoso
Ni tanto, unas cuantas líneas (tal vez menos de las que se utiliza en el script actual) bastarían.

Lo que no entiendo es, ¿qué criterio usas para separar las instancias en listas diferentes (después de haberlas organizado en una única lista)?
alaberga regué el café.

BA:STFW&RTFM

Pues ya estando ordenada, recorro la lista con un for, y como es seguro que habrá un numero par de instancias de cada tipo (sea A o B o incluso C o mas) cuando el indice del for es par (i mod 2 == 0) meto la instancia en la primera lista y cuando es impar, en la segunda, asi se distribuyen en partes iguales y quedan ordenados de una vez, porque necesito que también estén ordenados para crear relaciones entre ellos (dentro de una misma lista) utilizando un grid que contiene esas relaciones.
Cita de: Fenris78Si 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: CalioSomos desarrolladores independientes y, por lo tanto, no tenemos por qué guiarnos por las tendencias del mercado.

Intenta modificar el script utilizando colas de prioridad, a ver si hay alguna mejora.
[gml]
///Algún evento que se ejecute una sola vez
globalvar sorted_list;
sorted_list = ds_priority_create();
[/gml]
[gml]
///e_sort(list)
var N = ds_list_size(argument0);
var i, inst;

//Primer ciclo para añadir los elementos a la cola
for(i = 0; i < N; i++) {
    inst = argument0[| i];
    ds_priority_add( sorted_list, inst, inst.valor);
}
ds_list_clear(argument0);

//Segundo ciclo para obtenerlos organizados
for(i = 0; i < N; i++) {
    inst = ds_priority_delete_min(sorted_list);
    ds_list_add(argument0, inst);
}
[/gml]

Si sigue habiendo errores, sería bueno que imprimeras el contenido de las estructuras de datos (json_encode()) para ver si hay problemas con la información.

También ayudaría ver el contenido del script sintesis2().
alaberga regué el café.

BA:STFW&RTFM

#6 Noviembre 30, 2018, 07:56:52 PM Ultima modificación: Noviembre 30, 2018, 08:11:47 PM por Johann
No, lo que me toca hacer es simplificar todo con el uso de las colas de prioridad, así ese algoritmo se vuelve innecesario.
De todas formas comparto el script Sintesis2 que hace lo que explicaba al principio:
Cita de: Johann
... juntar todos esos objetos en una única lista y luego redistribuirlos en listas nuevas luego de haberlos ordenado de acuerdo al valor en una de sus propiedades.
[gml]
///sintesis2(new1, new2, others)
// argument0: Primera nueva lista
// argument1: Segunda nueva lista
// argument2: lista de objetos que contienen las listas a unir

var mol, elm, i, j;
var elems = ds_list_create();
// primero se meten todos los objetos de las listas en argument2 en una sola lista
for (i=0; i<ds_list_size(argument2); i++) {
    mol = argument2[| i];
    for (var j=0; j<ds_list_size(mol.lista); j++) {
        ds_list_add(elems, mol.lista[| j]);
    }
    ds_list_clear(mol.lista);
}
// luego esa lista se ordena
e_sort(elems); // aquí es donde falla algunas veces, cuando se le da la gana si funciona XD
// los objetos ordenados se distribuyen de manera equitativa en 2 listas nuevas
for (i=0; i<ds_list_size(elems); i++) {
    elm = elems[| i];
    if (i mod 2 == 0) {
        elm.padre = argument0.id;
        ds_list_add(argument0.lista, elm);
    } else {
        elm.padre = argument1.id;
        ds_list_add(argument1.lista, elm);
    }
}

ds_list_clear(elems);
ds_list_destroy(elems);
[/gml]

Alguno dirá que son muchos ciclos for, pero como una lista no va a llegar a tener mas de 10 objetos no le veo problema.
Y bueno, tampoco me voy a cerrar, voy a probar los de la cola de prioridad para ordenar haber que pasa.


Edit pocos minutos después: ha funcionado perfectamente el ordenamiento por medio de colas de prioridad y me ahorra modificar todo el proyecto como habia pensado al principio :D
Cita de: Fenris78Si 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: CalioSomos desarrolladores independientes y, por lo tanto, no tenemos por qué guiarnos por las tendencias del mercado.