Creacion de matriz

Iniciado por nonokario, 7 Marzo 2018, 23:56 PM

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

nonokario

Hola! Soy nueva en la programación y me llego un problema. No se cuál seria la mejor manera de solucionarlo. Hice un código muy largo y no me parece que este bien aunque funcione.
El problema es el siguiente:

Tengo que crear una matriz de numeros ( 1 a 6) con un ancho X y un largo Y.
El array Z0 debe tener un 5  y el Z-1 un 6. Entonces quedaría algo asi:
XXX5XX
XXXXXX
XXXXXX
6XXXXX

La siguiente condición es que en Zx debe existir un 2 y en Zx+1 un 3.

X2X5XX
X3XX2X
XXXX32
6XXXX3

Y la ultima condición es que :
Entre 2/3/6/5 solo puede haber 1.

X215XX
X3112X
XXXX32
611113

Todo lo demas que no fue seteado pueden ser 1 o 4!



El código no es en C pero me serviría igual ver un pseudocodigo! Si hace falta muestro lo que hice pero es muy feo  :-X  
Si es muy largo el pseudocodigo con que me den algún tip se los agradezco!

MAFUS

Oky, muestra lo que tienes hecho.

nonokario

#2
Código (python) [Seleccionar]

func setter_matrix(x, y):  #a esta funcion la llamo desde un for de afuera para setear numeros de 1 a 6 y la entrada(5) y salida(6)
if x == 0 and entrada_creada == false:
randomize()
var n = randi()%5+1
if n == 5:
entrada_creada = true
if y == WIDTH-1:
entrada_creada = true
return 5
return n
elif x == 3 and salida_creada == false:
randomize()
var n2 = randi()%6+1
if n2 == 6:
salida_creada = true
if y == WIDTH-1:
entrada_creada = true
return 6
if n2 == 5:
return 1
return n2
else:
return randi()%4+1





#Funcion para asegurar que haya: Entrada, Salida y 2/3
func corregir_matrix(matrix):
var encontrado2
var entrada
var bajada
for x in range(WIDTH):
encontrado2 = false
for y in range(HEIGHT):
if x == 0:
if matrix[x][y] == 5:
entrada = y
if x != HEIGHT -1 :
if (matrix[x][y] == 2) and (encontrado2 == false):
matrix[x+1][y] = 3
encontrado2 = true
bajada = y
elif matrix[x][y] == 2 and encontrado2 == true:
matrix[x][y] = 1
elif y == WIDTH-1 and encontrado2 == false:
if x == 0:
if entrada + 2 < WIDTH:
matrix[x][entrada+2] = 2
matrix[x+1][entrada+2] = 3
bajada = entrada + 2
else:
matrix[x][entrada-2] = 2
matrix[x+1][entrada-2] = 3
bajada = entrada - 2
else:
if bajada + 2 < WIDTH:
matrix[x][bajada+2] = 2
matrix[x+1][bajada+2] = 3
bajada = bajada + 2
else:
matrix[x][bajada-2] = 2
matrix[x+1][bajada-2] = 3
bajada = bajada - 2
else:
if matrix[x][y] == 6:
return matrix
for y in range(HEIGHT):
if matrix[3][y] == 3:
if y + 2 < WIDTH:
matrix[3][y+2] = 6
return matrix
else:
matrix[3][y-2] = 6
return matrix
return matrix




#Funcion para asegurar que haya unos entre 2/3/5/6
func corregir_matriz_2(matrix):
var entrada
var salida
var bajada1
var bajada2
var aux
for x in range(WIDTH):
for y in range(HEIGHT):
if x == 0:
if matrix[x][y] == 2: ###
bajada1 = y
if matrix[x][y] == 5:
entrada = y
elif x != 0 and x != HEIGHT -1 :
if matrix[x][y] == 2: ###
bajada1 = y
elif matrix[x][y] == 3 and matrix[x-1][y] == 2:
bajada2 = y
else:
if matrix[x][y] == 3 and matrix[x-1][y] == 2:
bajada2 = y
elif matrix[x][y] == 6:
salida = y


if x == 0:
if bajada1 < entrada:
aux = entrada - (bajada1)
for y in range(aux):
if matrix[x][bajada1+y] == 4:  #Antes: bajada+1 Ahora: bajada+y
matrix[x][bajada1+y] = 1   #Si era + 1 siempre reemplazaba en el mismo lugar
else:
aux = bajada1 - (entrada)
for y in range(aux):
if matrix[x][entrada+y] == 4:
matrix[x][entrada+y] = 1

elif x != 0 and x != HEIGHT -1 :
if bajada1 < bajada2:
aux = bajada2 - (bajada1)
for y in range(aux):
if matrix[x][bajada1+y] == 4:
matrix[x][bajada1+y] = 1
else:
aux = bajada1 - (bajada2)
for y in range(aux):
if matrix[x][bajada2+y] == 4:
matrix[x][bajada2+y] = 1

else:
if bajada2 < salida:
aux = salida - (bajada2)
for y in range(aux):
if matrix[x][bajada2+y] == 4:
matrix[x][bajada2+y] = 1
else:
aux = bajada2 - (salida)
for y in range(aux):
if matrix[x][salida+y] == 4:
matrix[x][salida+y] = 1
return matrix




Perdón, es muy feo el código pero funciona. Por eso queria saber si hay una manera mas elegante o mejor de hacerlo. Con pseudocodigo me arreglo!

MAFUS

#3
Bueno, creo que te has complicado un poco.
Empieza instalando un valor que indique que la casilla está vacía, yo he usado el 0 (aprovechando que 0 significa también false y cualquier otro número true).

El primer paso de meter el 5 y el 6 en la primera y última fila es muy sencillo ya que la matriz está vacía. Caigan donde caigan están bien.

Para incluir el 2 y el 3 tampoco tiene mucha complicación. Se corre la matriz por filas desde el inicio hasta penúltima fila. Por fila:
· Buscar una misma columna vacía para y e y+1
· En y incluir el 2.
· En y+1 incluir el 3.

Para incluir los entre números aprovecha las marcas de casilla vacía. Prepara una bandera para indicar si debes escribir los unos o no.

Por cada fila:
· desactiva la badnera
· Por cada columna:
  · Si la bandera está desactivada y la casilla no está vacía:
     · activa la bandera (Después de activar esa bandera no debes hacer nada y esperar a la siguiente iteración)
  · Y si no:
     · Si la casilla está vacía:
        · escribe un 1 en ella
     · Y si no:
        · termina el bucle columna

Para terminar de rellenar la matriz recórrela casilla por casilla. Si la casilla está vacía introduce 1 o 4 aleatoriamente.

Esto en C11 quedaría así:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

/* Matriz global por lo que
* al crearla se llena de ceros ( 0 )
* así que aprovecharé eso para
* marcar la posición vacía
*/
#define FILAS 4u
#define COLUMNAS 6u

int matriz[FILAS][COLUMNAS];

// devuelve una casilla vacia aleatoria
// en la fila y del array
unsigned columna_vacia_en_fila(unsigned fila) {
    unsigned x;

    do {
        x = rand()%COLUMNAS;
    } while(matriz[fila][x] && matriz[fila+1][x]);

    return x;
}

// incluir el 5 en la primera fila
// y el 6 en la última fila
void incluir_5_6() {
    unsigned x;

    x = rand()%COLUMNAS;
    matriz[0][x] = 5;

    x = rand()%COLUMNAS;
    matriz[FILAS-1][x] = 6;
}

// incluir el 2 en fila y+1
// y el 3 en la fila y+1
void incluir_2_3() {
    unsigned x, y;

    for(y=0; y<FILAS-1; ++y) {
        x = columna_vacia_en_fila(y);
        matriz[y][x] = 2;
        matriz[y+1][x] = 3;
    }
}

// incluir el 1 entre dos números en una fila
// por cada fila
void incluir_1_entre() {
    unsigned x, y;
    bool escribir;

    for(y=0; y<FILAS; ++y) {
        escribir = false;
        for(x=0; x<COLUMNAS; ++x) {
            if(!escribir && matriz[y][x]) {
                escribir = true;
            }
            else {
                if(matriz[y][x]) break;
                else matriz[y][x] = 1;
            }
        }
    }
}

// rellenar indistintamente con 1
// y 4 las casillas que faltan
void incluir_1_4() {
    unsigned x, y;

    for(y=0; y<FILAS; ++y) {
        for(x=0; x<COLUMNAS; ++x) {
            if(matriz[y][x] == 0) {
                matriz[y][x] = rand()%2? 4 : 1;
            }
        }
    }
}

// imprimir la matriz
void imprimir() {
    unsigned x, y;

    for(y=0; y<FILAS; ++y) {
        for(x=0; x<COLUMNAS; ++x) {
            printf("%d ", matriz[y][x]);
        }
        puts("\n");
    }
}

int main() {
    srand(time(NULL));

    incluir_5_6();
    incluir_2_3();
    incluir_1_entre();
    incluir_1_4();

    imprimir();
}





Gracias a un dato apuntado por NEBIRE en la siguiente respuesta me he dado cuenta de algo que se me había pasado por alto: el 2 y el 3 deben estar en la misma columna.
Solucionado en la reedición.

Serapis

#4
Cita de: nonokario en  7 Marzo 2018, 23:56 PM
Tengo que crear una matriz de numeros ( 1 a 6) con un ancho X y un largo Y
en tu ejemplo 6x4, x=6 y=4, ok...


Cita de: nonokario en  7 Marzo 2018, 23:56 PM
El array Z0 debe tener un 5  y el Z-1 un 6. Entonces quedaría algo asi:
XXX5XX
XXXXXX
XXXXXX
6XXXXX


Elige al azar una columna en sendas filas y la rellenas con el susodcho valor.

   n = Random(entre 0 y x-1)
   Array(0, n) = 5  // línea 0 posición n, un 5

   n = Random(entre 0 y x-1)
   Array(y-1, n) = 6  // linea 3, posicion n, un 6.



Cita de: nonokario en  7 Marzo 2018, 23:56 PM
La siguiente condición es que en Zx debe existir un 2 y en Zx+1 un 3.
X2X5XX
X3XX2X
XXXX32
6XXXX3
Esta parte, no acabo de entenderlo.

No sé a que llamas Zx, mirando el array... ¿una fila, una columna, una columna de una fila, de varias?

Vale, tras mirarlo más veces, creo entender que lo que tratas de hacer es crear un 2 en cada línea excepto la última y asignar un 3 en la misma columna pero en la siguiente fila.
Si es así, este sería el pseudocódigo:

   bucle para k desde 0 hasta y-2
       hacer
           n = random(entre 0 y x-1)
       repetir mientras array(k,n) distinto de 0  // no queremos que sobrescriba el 5 ni el 6

       Array(k,n)=2
       Array(k+1, n)=3
   siguiente en bucle



Cita de: nonokario en  7 Marzo 2018, 23:56 PM
Y la ultima condición es que :
Entre 2/3/6/5 solo puede haber 1.
X215XX
X3112X
XXXX32
611113

Entiendo que entre 2 y 2,3,5,6; entre 3 y 2,3,5,6; entre 5 y 2,3 y entre 6 y 2,3. Pero no entre 5 y 6, porque no están en la misma línea (ni pueden estarlo), Así como tampoco 2 cincos ni 2 seis.

   bucle para k desde 0 a y-1 // por cada linea
       // buscar punto de comienzo
       bucle para j desde 0 a x-2  // por cada columna  
           Si array(k,j) = 2,3,5 ó 6 luego //buscamos un valor en la fila (2,3,5,6)
               ini= j    // y lo recordamos.
               salir del bucle
           fin si
       siguiente en bucle
       
       // buscar punto final
       bucle para j desde ini+1 a x-1  
           Si array(k,j) = 2,3 ó 5 luego buscamos un valor en la fila (2,3,5,6)
               fin= j
               salir del bucle
           fin si
       siguiente en bucle

       // rellenar entre medias (de inicio y final)...
       bucle para j desde (ini +1) hasta (fin-1)
            array(k, j) = 1
       siguiente en bucle
   siguiente en bucle

El código en esta sección se puede optimizar (yo lo dejo así por claridad), por ejemplo:
    - recorriendo el bucle segundo desde el final hacia atrás...
    - mientras no se encuentre el valor final, escribir YA el 1, haciendo innecesario el bucle final.
    - en vez de salir de un bucle, anidar dentro de él el siguiente bucle (aunque en líea ganan en claridad).

Cita de: nonokario en  7 Marzo 2018, 23:56 PM
Todo lo demas que no fue seteado pueden ser 1 ó 4

Se supone que lo que no tiene 'valor' es 0... es decir que inicialmente el contenido del array era todos ceros.

bucle para k desde 0 a y-1  // por cada linea
   bucle para j desde 0 a x-1 // por cada columna
       Si Array(k,j) = 0
          n= random(entre 0 y 1)  //elegir 1 de 2 opciones
          n = ((n * 3) +1)   // Si False = 1, si TRUE=4
          Array(k,j) = n
       fin si
   siguiente en bucle
siguiente en bucle



nonokario

Muchas gracias! Aprendí mucho  :D