Ayuda en trabajo de Arreglos/Matrices

Iniciado por JoseBerru, 5 Mayo 2016, 17:26 PM

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

JoseBerru

El ejercicio me pide que haga una matriz 11x11 con una coordenada (x,y) ingresada por el usuario que sea 0. Los numeros adyacentes a la coordenada (x,y) = 0 tienen que ser 1, luego 2 y asi consecutivamente hasta completar la matriz 11x11.

x: 5
y: 5

5 5 5 5 5 5 5 5 5 5 5
5 4 4 4 4 4 4 4 4 4 5
5 4 3 3 3 3 3 3 3 4 5
5 4 3 2 2 2 2 2 3 4 5
5 4 3 2 1 1 1 2 3 4 5
5 4 3 2 1 0 1 2 3 4 5
5 4 3 2 1 1 1 2 3 4 5
5 4 3 2 2 2 2 2 3 4 5
5 4 3 3 3 3 3 3 3 4 5
5 4 4 4 4 4 4 4 4 4 5
5 5 5 5 5 5 5 5 5 5 5


Tengo este codigo que logra parcialmente algo como lo de arriba.

#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <iomanip>

using namespace std;

int main(int argc, char** argv) {
   
   int x, y;
   cout << "X: "; cin >> x;
   cout << "Y: "; cin >> y;
   
   int m[11][11] = {{0}};
   m
  • [y] = 0;
       
       for (int fila = 0; fila < 11; fila++)
       {
             for (int col = 0; col <= fila; col++)
             {
                m[fila][col] = abs(fila - y);
             }   
             for (int col = 11; col >= fila; col--)
                {
                   m[fila][col] = abs(col - x);
                }
       }
       
       for (int fila = 0; fila < 11; fila++)
       {
          for (int col = 0; col < 11; col++)
          {
             cout << setw(4) << m[fila][col];
          }
          cout << endl;
       }
             
       return 0;
    }



    GRACIAS DE ANTEMANO

MAFUS

Si a una mitad del recuadro la tratas de una forma y a la otra mitad la tratas de otra nunca llegarás a una solución coherente.
En vez de usar un cuadro de 11x11 usa uno de 3x3 y sitúate en el centro. Obviamente el anillo exterior todo son 1s.

111
101
111

Reduciendo más el problema, si tomas en cuenta solo la distancia de los puntos en el eje X

101
101
101

y teniendo en cuenta solo la distancia de los puntos en el eje Y

111
000
111

Superponiendo estos dos últimos recuadros y tomando la conjunción lógica de ambos queda

101
000
101

¿Qué operación hace que los 0 del anillo tomen el valor de las esquinas?

WHK

#2
Te sirve en javascript?

Código (javascript) [Seleccionar]
// Cantidad de numeros a utilizar
var payload = 5;

var reverse = false;
// Dos vueltas: superior e inferior, el inferior es un espejo del superior
for(var a = 1; a <= 2; a++){

   if(reverse){
       var minimo         = 1;
       var agregar_centro = 0;
   }else{
       var minimo         = payload;
       var agregar_centro = 1;
   }

   for(var b = 1; b <= payload + agregar_centro; b++){

       var line = '';

       for(var c = payload; 1 <= c; c--){
           if(c < minimo)
               line += minimo + '';
           else
               line += '' + c;
       }

       // Centro
       if((!reverse) && (b == (payload + agregar_centro))){
           // Última vuelta de la mitad del cuadrado.
           line += '0';
           reverse = true;
       }else{
           line += minimo;
       }

       for(var d = 1; d <= payload; d++){
           if(d < minimo)
               line += minimo + '';
           else
               line += '' + d;
       }
       
       if(reverse)
           minimo++;
       else
           minimo--;

       console.log(line);

   }
}


55555555555
54444444445
54333333345
54322222345
54321112345
54321012345
54321112345
54322222345
54333333345
54444444445
55555555555



Ahora, como son dos pisos, uno superior y el de abajo un espejo podrias hacer solo la mitad de la cara y luego replicarlo en algún stack ordenado:

Código (javascript) [Seleccionar]
var payload = 5;
var lines   = [];
var minimo  = payload

for(var b = 1; b <= payload + 1; b++){

   var line = '';

   for(var c = payload; 1 <= c; c--){
       if(c < minimo)
           line += minimo + '';
       else
           line += '' + c;
   }

   if(b == (payload + 1)){
       // Última vuelta de la mitad del cuadrado.
       line += '0';
   }else{
       line += minimo;
   }

   for(var d = 1; d <= payload; d++){
       if(d < minimo)
           line += minimo + '';
       else
           line += '' + d;
   }
   
   minimo--;

   console.log(line);
   lines.push(line + '\n');
}

lines.pop();
lines.reverse();
for(_key in lines)
   console.log(lines[_key]);


55555555555
54444444445
54333333345
54322222345
54321112345
54321012345
54321112345
54322222345
54333333345
54444444445
55555555555



Ahora, si lo piensas mejor son 4 lados, solo dibujas uno y los demas son espejos del mismo, es como tener una hoja de papel doblado en 4 con el cero en común como único centro pero hacer eso en c++ puede que salga mucho mas trabajoso y largo que invertir los for manualmente como te lo mostré anteriormente.



El primer grupo rojo corresponde a lo que realmente debes hacer, el segundo grupo rojo es la columna que unirá el lado derecho con el lado izquierdo, este debe decir que si no es la última línea entonces debe ser igual al último número de la fila, en caso contrario es cero. Luego de eso el restante derecho es el mismo contenido del izquierdo pero al reves, luego la parte inferior es igual a la superior pero al reves menos la última fila que corresponde al concatenador cero.

De todas maneras acá está el código del papel doblado en 4:

Código (javascript) [Seleccionar]
var payload = 5;
var lines   = [];
var min     = payload

for(var a = 1; a <= payload + 1; a++){
   var line = [];
   for(var b = payload; 1 <= b; b--)
       line.push((b < min) ? min : b);
   lines.push(line);
   min--;
}

var lines_str = [];
for(a in lines){
   var out  = lines[a].join('');
   out += (a == (lines.length - 1)) ? 0 : lines[a][lines[a].length - 1];
   lines[a].reverse();
   out += lines[a].join('');
   lines_str.push(out);
}

var tmp = lines_str.slice(0);
lines_str.pop();
lines_str.reverse();
for(a in lines_str)
   tmp.push(lines_str[a]);
lines_str = tmp;

for(a in lines_str)
   console.log(lines_str[a]);


55555555555
54444444445
54333333345
54322222345
54321112345
54321012345
54321112345
54322222345
54333333345
54444444445
55555555555



Lo que puedes hacer es tomar estos códigos como conceptos, estudiarlos y hacer tu propio código en c++. La práctica es la mejor ayuda cuando necesitas estudiar y aprender, por eso no te hice el código en c++, para que lo tengas que hacer tu entendiendo la lógica.

Saludos.

MAFUS

Está bien lo de la optimización, pero te has saltado lo de que el usuario entra la coordenada de donde quiere el 0. Si lo pone en una esquina no puede haber espejos y el máximo valor del recuadro es 10.

WHK

#4
Cita de: MAFUS en  5 Mayo 2016, 20:38 PM
Está bien lo de la optimización, pero te has saltado lo de que el usuario entra la coordenada de donde quiere el 0. Si lo pone en una esquina no puede haber espejos y el máximo valor del recuadro es 10.

Esa parte no lo habia leido xD pero se me ocurre que si el cuadro es de un máximo de 10x10 es porque solo puedes escribir hasta el 9, no puedes dibujar un 10 o se te corre la línea, en ese caso lo que yo haría es hacer un cuadrado de 9x9, es solo cuestión de modificar el script que hice y reemplazar el 5 por el 9 y despues hacer un padding xy eliminando lo sobrante dejando el 0 en la posicion donde tu quieras, pero la malla ya está hecha, solo faltaría mover y cortar con un padding y un shift.

class_OpenGL

Es sencillo. Puedes ver el patrón restando la posición del carácter que estás escribiendo menos la fila y la columna en la que esté el 0. El valor de la casilla será el mayor valor de esas dos restas. Por supuesto, tendrás que hacer el valor absoluto si no quieres números negativos

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL

WHK

#6
Vamos, acá va:

Código (javascript) [Seleccionar]
// Pointer XY
var pointer_x         = 6;                   // X (1 to 11)
var pointer_y         = 6;                   // Y (1 to 11)

var payload           = 9;                   // Max number. Total rows * 2 + 1 (xy:9876543210123456789)
var max_rows          = 11;                  // Max width & height rows to show
var current_pointer_x = ((payload * 2) + 1); // Current pointer X
var current_pointer_y = ((payload * 2) + 1); // Current pointer Y
var lines             = [];                  // Array
var floor             = payload;             // Dinamic floor
var clon              = [];                  // Array


// Buffer
for(var a = 1; a <= payload + 1; a++){
   var line = [];    // Empty line (array)
   for(var b = payload; 1 <= b; b--)
       line.push((b < floor) ? floor : b); // If number is < to floor: number, else: floor
   lines.push(line); // Append line to lines
   floor--;          // Floor reduction
}


// Horizontal mirror (right)
clon  = lines.slice(0); // Clone array
lines = [];             // Clear array
for(a in clon){
   var final_line = clon[a].slice(0); // Clone line to final line (left half)
   final_line.push((a == (clon.length - 1)) ? 0 : clon[a][clon[a].length - 1]); // Center (n or 0)
   clon[a].reverse();      // Invert line
   for(b in clon[a])       // Append inverted line to final line
       final_line.push(clon[a][b]);
   lines.push(final_line); // Push final line
}


// Vertical mirror (bottom)
clon = lines.slice(0); // Clone array
clon.pop();            // Remove center line (the pointer)
clon.reverse();        // Invert array
for(a in clon)         // Append array inverted into lines array
   lines.push(clon[a]);


// Move area [[]]
shift_left = (payload - pointer_x);
shift_top  = (payload - pointer_y);

// Cut area
clon = lines.slice(0); // Clone array
lines = [];            // Reset array
for(var a = 0; a <= clon.length - 1; a++){
   var line = [];
   for(var b = 0; b <= clon[a].length - 1; b++){
       if(
           ( a > shift_top)  &&                   // Cut top
           ((a - shift_top)  < (max_rows + 1)) && // Cut bottom
           ( b > shift_left) &&                   // Cut left
           ((b - shift_left) < (max_rows + 1))    // Cut right
       ){
           line.push(clon[a][b]);
       }
   }
   if(line.length)       // Have line?
       lines.push(line); // Append line to lines
}


// Print result
str = '';
for(a in lines)
   str += lines[a].join(' ') + '\n';
console.log(str);


5 5 5 5 5 5 5 5 5 5 5
5 4 4 4 4 4 4 4 4 4 5
5 4 3 3 3 3 3 3 3 4 5
5 4 3 2 2 2 2 2 3 4 5
5 4 3 2 1 1 1 2 3 4 5
5 4 3 2 1 0 1 2 3 4 5
5 4 3 2 1 1 1 2 3 4 5
5 4 3 2 2 2 2 2 3 4 5
5 4 3 3 3 3 3 3 3 4 5
5 4 4 4 4 4 4 4 4 4 5
5 5 5 5 5 5 5 5 5 5 5


Si cambio las posiciones XY queda así:

Código (javascript) [Seleccionar]
var pointer_x         = 1;                   // X (1 to 11)
var pointer_y         = 1;                   // Y (1 to 11)

0 1 2 3 4 5 6 7 8 9
1 1 2 3 4 5 6 7 8 9
2 2 2 3 4 5 6 7 8 9
3 3 3 3 4 5 6 7 8 9
4 4 4 4 4 5 6 7 8 9
5 5 5 5 5 5 6 7 8 9
6 6 6 6 6 6 6 7 8 9
7 7 7 7 7 7 7 7 8 9
8 8 8 8 8 8 8 8 8 9
9 9 9 9 9 9 9 9 9 9


Código (javascript) [Seleccionar]
var pointer_x         = 7;                   // X (1 to 11)
var pointer_y         = 3;                   // Y (1 to 11)

6 5 4 3 2 2 2 2 2 3 4
6 5 4 3 2 1 1 1 2 3 4
6 5 4 3 2 1 0 1 2 3 4
6 5 4 3 2 1 1 1 2 3 4
6 5 4 3 2 2 2 2 2 3 4
6 5 4 3 3 3 3 3 3 3 4
6 5 4 4 4 4 4 4 4 4 4
6 5 5 5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6 6 6 6
7 7 7 7 7 7 7 7 7 7 7
8 8 8 8 8 8 8 8 8 8 8


Ahora la explicación:

Lo que hace es crear un buffer inicial, un cuarto de todo el cuadrado, luego solamente lo clona vertical y luego horizontal tal como lo expliqué en el post anterior. Se crea un cuadrado de 19 columnas y filas, esto quiere decir del 9 al 9 mas un centro = 18 + 1, después de esto se crea una segunda capa imaginaria de 11x11 (del 5 al 5 mas el centro) y recorta los bordes restantes, de esta manera se obtiene el puntero en la posición requerida. Imagina dos capas donde una capa superior es el recuadro y debajo de ella un cuadrado mucho mas grande con un punto al centro, si mueves la capa que está debajo podrás posicionar el punto donde tu quieras con el tamaño del recuadro de encima.

En esta imagen el puntero se localiza en la posición X:8 Y:7


De todas maneras como dijo MAFUS el resultado no siempre será coherente ya que no existe una mitad exacta, para simular una mitad colocando el cero al centro debes agregar una columna adicional por lo cual cuando quieres posicionar el puntero en X:1 Y:1 te faltará un número después del 9 (y no puede ser 10) ya que en el ejemplo que pusiste dices que el ancho total es de 5 a 1, el centro y luego de 1 a 5 por lo cual son 11, asi que si posicionas el cero en la primera columna te quedan 10 para rellenar, del 1 al 9 y luego que?, falta un número. En mi caso lo omití, si pones el puntero en X:1 Y:1 aparece una columna menos y una fila menos, el cuadrado deja de ser de 11x11 para ser de 10x10 (0 al 9). Para solucionar esto el tamaño del cuadrado a mostrar debiera ser de 9 (4 al 1 mas el centro y del 1 al 4), de esta manera si posiciono el cero en la primera columna solo debo rellenar 8 espacios (del 1 al 8). En el script se soluciona cambiando [payload] de 9 a 8 y [max_rows] de 11 a 9. El problema de raiz está en que el número máximo es impar y debiera ser el mayor par que pueda soportar una area de números del 0 al 9, o sea el 8 y no el 9.

0 1 2 3 4 5 6 7 8
1 1 2 3 4 5 6 7 8
2 2 2 3 4 5 6 7 8
3 3 3 3 4 5 6 7 8
4 4 4 4 4 5 6 7 8
5 5 5 5 5 5 6 7 8
6 6 6 6 6 6 6 7 8
7 7 7 7 7 7 7 7 8
8 8 8 8 8 8 8 8 8



Espero que hayas podido comprender bien.

Saludos.