Funcion que intecarmbie valores de una matriz en matlab

Escribe una funcion que reciba como argumento de entrada una matriz, seleccione al azar dos de sus
elementos, e intercambie sus valores. Debera evitarse que un elemento se cambie por si mismo.
Ese es mi enunciado... no se por donde cogerlo.
Deberia quedar algo asi:

> A = [ 1 1 0 0 ; 1 1 0 0 ; 1 1 0 0 ]
A =
1 1 0 0
1 1 0 0
1 1 0 0
> B = cambio (A)
B =
1 1 0 1
1 1 0 0
0 1 0 0


No quiero que me lo deis hecho, me gustaria que me abrierais un camino para yo seguir por ahi, gracias adelantadas!
function A = cambioaleatorio(A)

N = size(A, 1);
M = size(A, 2);

pos1x = rand(N);
pos1y = rand(M);

iguales = true;
while (iguales)
pos2x = rand(N);
pos2y = rand(M);

if (pos1x ~= pos2x || pos1y ~= pos2y)
iguales = false;
end
end

temp = A(pos1x, pos1y);
A(pos2x, pos2y) = A(pos1x, pos1y);
A(pos1x, pos1y) = temp;

end


La notación puede estar mal, tengo el matlab un poco oxidado.
A ver, te lo digo así un poco general y seguramente con alguna pega, que hace tiempo que no hago nada en matlab.

1.-Empiezas con lo típico, que te pida la matriz de entrada, asignas variables para el tamaño.
2.-Generas cuatro números al azar (i j) (k t) menores o iguales a los respectivos tamaños de las matrices.
3.-Con un if compruebas que no es la misma casilla, y si lo es, con algún tipo de bucle genera una nueva pareja de números y que vuelva a comprobar hasta que sea distintos.
4.-Usa una variable temporal para almacenar el valor de A(i j), asignas a A(i j) el valor de A(k t) y por ultimo a A(k t) el valor de la temporal.

Seguramente se puede hacer algo mas sencillo(iniciando el programa con valores para las variables tales que i=j=k=t y así empezar con el bucle y ahorrarte el if). De todas formas no se tenías problemas en estructurar el programa o buscabas algo de código...

Revisando, chant ya te ha puesto todo el código que necesitas. [+risas]
chant escribió:
function A = cambioaleatorio(A)

N = size(A, 1);
M = size(A, 2);

pos1x = rand(N);
pos1y = rand(M);

iguales = true;
while (iguales)
pos2x = rand(N);
pos2y = rand(M);

if (pos1x ~= pos2x || pos1y ~= pos2y)
iguales = false;
end
end

temp = A(pos1x, pos1y);
A(pos2x, pos2y) = A(pos1x, pos1y);
A(pos1x, pos1y) = temp;

end


La notación puede estar mal, tengo el matlab un poco oxidado.


Tu solucion es muy "fea" pero como ayuda no esta mal. Otro par de ayuditas para mejorarlo:

Hint 1: mejor acceder a la matriz con un solo indice.
Hint 2: mejor que tener un bucle para detectar si la segunda posicion es igual a la primera, es hacer un random entre 0 y numero de elementos -2, y si este indice es mayor o igual que el primero le sumas 1.
Muchas gracias a todos, me habeis servido de mucha ayuda [oki]
DemonR escribió:
chant escribió:
function A = cambioaleatorio(A)

N = size(A, 1);
M = size(A, 2);

pos1x = rand(N);
pos1y = rand(M);

iguales = true;
while (iguales)
pos2x = rand(N);
pos2y = rand(M);

if (pos1x ~= pos2x || pos1y ~= pos2y)
iguales = false;
end
end

temp = A(pos1x, pos1y);
A(pos2x, pos2y) = A(pos1x, pos1y);
A(pos1x, pos1y) = temp;

end


La notación puede estar mal, tengo el matlab un poco oxidado.


Tu solucion es muy "fea" pero como ayuda no esta mal.

Tú sí que eres feo :o

Es broma :p
Hoy me he puesto enserio con el proyecto este y revisando mas a fondo el codigo que me han dando no entiendo las siguientes cosas:

- Me parece o sobra un end?
- pese a hacer el if (pos1x ~= pos2x || pos1y ~= pos2y) , hay veces que la matriz coincide
- Y yo creia que se intercambiaban, pero no , es algo aleatorio.. es decir me explico:

Con ese programa de una matriz asi:

1 1 0 0
1 1 0 0
1 1 0 0
1 1 0 0

sale:

1 1 0 1
1 1 0 0
1 1 0 0
1 1 0 0

Cuando teoricamente deberia salir con este codigo A(pos2x, pos2y) = A(pos1x, pos1y);:

1 1 0 1
1 1 0 0
0 1 0 0
1 1 0 0

No se si me explico... gracias adelantadas!
function X=cambioaleatorio(M)

a=1;
b=1;

while a==b

a=randi(prod(size(M)),1);
b=randi(prod(size(M)),1);

end

temp1=M(a);

M(a)=M(b);
M(b)=temp1;

X=M;

end



A ver si este código lo entiendes mejor (siempre que no me haya equivocado al escribirlo :P).
function ca = cambio(A)
    a = 1;
    b = 1;
   
    while a==b
       a = rand(prod(size (A,1))*1)
       b = rand(prod(size (A,2))*1)
    end
   
    temp1 = A(a);
    A(a) = A(b)
    A(b) = temp 1
   
    X=A
    end
   

Bien, asi lo veo algo más claro, lo he modificado minimante en el size, juraria que asi seria mas correcto no?... aun asi me da un error un poco.... Unexpected input at line number: 12 y me señala esto:
A(a) = A(b)
A(b) = temp 1
Un apunte, el argumento de salida tal y como lo estás escribiendo es ca, entonces ca=A al final.
Te da error porque lo del size lo estás usando mal, estás cogiendo la dimensión de filas solo así, usando size(A,1), si no quieres usar el prod para multiplicar las dos dimensiones como he hecho yo antes, también podrías hacer size(A,1)*size(A,2).

Fíjate que he usado randi en vez de rand, porque rand da un número que no es entero, y los indices de las matrices son enteros, de ahí el randi(tamañomatriz,1), que da como salida un número entero entre 1 y el tamañomatriz.

Espero que te ayude ^^.

Edit: en vez de usar el indice de un número de la matriz, podrías usar el de las dos dimensiones, pero no hace falta.

Con eso me refiero a que es lo mismo, dada una matriz A=[1 2 3;4 5 6], usar A(2) que usar A(2,1), o usar A(3) que usar A(1,2).
vale... parece que me funciona... perooooooooooooooooooo me sale un bucle infinito, ya que a= 1 yb = 1 y estamos poniendo un while a==b, como podria parar eso para que solo saliera un resultado??

El error no me da por el size, me da porque muy listo de mi me habia dejado un espacio entre temp y 1 xDDD , Si lo hag con un size (A), sin el (A,1) me salen matrices enormes, sin embargo con el size (A,1) me salen intercambios como los que quiero..

En cuanto lo del randi no lo conocia, yo he usado el comando round, que creo que hace lo mismo y es el que conozco, aqui mi codigo:
function ca = cambio(A)
    a = 1;
    b = 1;
   
    while a==b
       a = round(rand(size (A,1))*1)
       b = round(rand(size (A,2))*1)
    end
   
    temp1 = A(a);
    A(a) = A(b)
    A(b) = temp1
   
    ca=A
    end
   
   
Pero tal y como pones el codigo solo haces una matriz de números aleatorios de tamaño el número de filas de tu matriz A, que luego redondeas.
Además, no estableces ningún tipo de límites a los índices, de manera que pueden salirte indíces más grandes que tu matriz.

Si te fijas, lo que yo hago, es coger el número de elementos de la matriz original A multiplicando la dimensión vertical por la horizontal. Una vez hecho eso, pido un número aleatorio entre 1 y el número de elementos con el comando randi(límitesuperior,dimensióndelamatrizdenúmerosaleatorios) --->randi(prod(size(A)),1), porque solo quiero un elemento y lo quiero entre 1 y el elemento de índice más alto de la matriz.

El while no es un bucle infinito, porque aunque lo inicializo con los valores a=b=1 para que al menos dé una vuelta, después de sobreescribirlos con los números aleatorios ya no se cumple la condición (a no ser que de la casualidad que salga el mismo, entonces corre otra vez).

El comando round lo que hace es redondear, no es lo mismo :P.
Solución a la que he llegado. Creo es fea también pero funciona sin excepción xD


A = [ 1 2 3 4 ; 5 6 7 8 ; 9 10 11 12 ];
B=A(:);
pos1=1+randint(1,1,length(B));
iguales=1;
while iguales
pos2=1+randint(1,1,length(B));
if pos1~=pos2
iguales=0;
end
end
aux=B(pos1);
B(pos1)=B(pos2);
B(pos2)=aux;
A=reshape(B,size(A,1),size(A,2))
danilc1007 escribió:Solución a la que he llegado. Creo es fea también pero funciona sin excepción xD


A = [ 1 2 3 4 ; 5 6 7 8 ; 9 10 11 12 ];
B=A(:);
pos1=1+randint(1,1,length(B));
iguales=1;
while iguales
pos2=1+randint(1,1,length(B));
if pos1~=pos2
iguales=0;
end
end
aux=B(pos1);
B(pos1)=B(pos2);
B(pos2)=aux;
A=reshape(B,size(A,1),size(A,2))


Esto funciona, pero eso de convertir la matriz a vector para usar el size, teniendo en cuenta que puedes hacerlo multiplicando dos dimensiones xD, además que al final tienes que volver a crear una matriz con reshape...
Pero funcionar funciona xD.
Muchas gracias danilc1007, pero en freemat no me reconoce randint, y sie n vez de randint pongo rand, lo unico que me sale es esta matriz:

1 1 0 0
1 1 0 0
1 1 0 0
1 1 0 0

Siempre....

Y en cuanto a la solucion de Serguma, no me deja usar randi en freemat, tal cual lo pones tu me da este error:

Error: RANLIB Error: low > high in ignuin - ABORT

Asi que me quedo con el round aunque sea solo para probar el programa, asi que tal y como me dices tu:

round(rand(prod(size(A))))

y me sale:

1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 1
1 1 0 1 0 0 1 0 1 0 1 1 1 1 1 1
0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 1
1 0 1 0 1 1 0 0 1 0 1 0 0 1 1 0
0 0 0 0 0 0 1 1 0 0 0 1 1 0 1 0
1 0 1 1 1 1 1 0 1 1 0 1 1 0 1 0
1 0 1 0 0 0 1 1 0 0 1 1 1 0 1 1
1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 1
1 0 0 1 0 1 1 0 0 0 0 0 1 1 0 0
0 0 1 1 0 0 0 1 0 0 0 1 0 0 1 0
1 1 0 1 1 1 1 1 1 1 1 1 1 0 0 0
0 1 1 0 0 1 0 0 1 1 0 0 0 1 0 1
0 0 0 0 1 1 0 1 0 1 1 0 0 1 0 1
0 1 1 0 1 0 0 0 1 1 0 0 1 0 0 0
0 0 0 0 0 1 0 1 0 1 1 0 1 1 0 0
1 1 1 1 1 1 1 0 0 0 1 0 0 1 0 1

y al darle a la function me sale otra vez un bucle que no para, PD: uso freemat

codigo actual:
function ca = cambio(A)
    a = 1;
    b = 1;
   
    while a==b
        a = round(rand(prod(size(A))))
        b = round(rand(prod(size(A))))
    end
   
    temp1 = A(a);
   
    A(a) = A(b)
    A(b) = temp1
   
    ca=A
   
    end
   
   
Squallete escribió:Muchas gracias danilc1007, pero en freemat no me reconoce randint, y sie n vez de randint pongo rand, lo unico que me sale es esta matriz:

1 1 0 0
1 1 0 0
1 1 0 0
1 1 0 0

Siempre....

Y en cuanto a la solucion de Serguma, no me deja usar randi en freemat, tal cual lo pones tu me da este error:

Error: RANLIB Error: low > high in ignuin - ABORT

Asi que me quedo con el round aunque sea solo para probar el programa, asi que tal y como me dices tu:

round(rand(prod(size(A))))

y me sale:

1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 1
1 1 0 1 0 0 1 0 1 0 1 1 1 1 1 1
0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 1
1 0 1 0 1 1 0 0 1 0 1 0 0 1 1 0
0 0 0 0 0 0 1 1 0 0 0 1 1 0 1 0
1 0 1 1 1 1 1 0 1 1 0 1 1 0 1 0
1 0 1 0 0 0 1 1 0 0 1 1 1 0 1 1
1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 1
1 0 0 1 0 1 1 0 0 0 0 0 1 1 0 0
0 0 1 1 0 0 0 1 0 0 0 1 0 0 1 0
1 1 0 1 1 1 1 1 1 1 1 1 1 0 0 0
0 1 1 0 0 1 0 0 1 1 0 0 0 1 0 1
0 0 0 0 1 1 0 1 0 1 1 0 0 1 0 1
0 1 1 0 1 0 0 0 1 1 0 0 1 0 0 0
0 0 0 0 0 1 0 1 0 1 1 0 1 1 0 0
1 1 1 1 1 1 1 0 0 0 1 0 0 1 0 1

y al darle a la function me sale otra vez un bucle que no para, PD: uso freemat

codigo actual:
function ca = cambio(A)
    a = 1;
    b = 1;
   
    while a==b
        a = round(rand(prod(size(A))))
        b = round(rand(prod(size(A))))
    end
   
    temp1 = A(a);
   
    A(a) = A(b)
    A(b) = temp1
   
    ca=A
   
    end
   
   


La sintaxis es diferente, usa randi(1,size(prod(A))).
P.D.: Haber avisado que usabas otras cosas xD, de todos modos siempre puedes mirar la documentación de cada función.
P.D.2.: No he mirado el resto de comandos, doy por supuesto que funcionan y que lo de los indices de matrices va igual, si no te tocará revisarlo :).
P.D.3.: Si no va pon una ejecución step-by-step y miramos que falla.
SerGuMa escribió:
danilc1007 escribió:Solución a la que he llegado. Creo es fea también pero funciona sin excepción xD


A = [ 1 2 3 4 ; 5 6 7 8 ; 9 10 11 12 ];
B=A(:);
pos1=1+randint(1,1,length(B));
iguales=1;
while iguales
pos2=1+randint(1,1,length(B));
if pos1~=pos2
iguales=0;
end
end
aux=B(pos1);
B(pos1)=B(pos2);
B(pos2)=aux;
A=reshape(B,size(A,1),size(A,2))


Esto funciona, pero eso de convertir la matriz a vector para usar el size, teniendo en cuenta que puedes hacerlo multiplicando dos dimensiones xD, además que al final tienes que volver a crear una matriz con reshape...
Pero funcionar funciona xD.


Ya, ya, soy muy unidimensional de mente xD y tampoco lo he pensado mucho. Es más coherente lo tuyo ahora que lo veo xD

PD: Joder, pues no sabía que poniendo sólo un índice podías acceder a cualquier valor de la matriz aunque no fuera unidimensional. Pa matarme xD
function ca = cambio(A)
    a = 1;
    b = 1;
   
    while a==b
        a = randi(1,size(prod(A)))
             b = randi(1,size(prod(A)))
             % b = round(rand(prod(size(A))))
       
    end
   
    temp1 = A(a);
   
    A(a) = A(b)
    A(b) = temp1
   
    ca=A
   
    end
   


Con este codigo me da un bluce infinito de dos numeros, menudo descojone xDD

Me voy un rato esta noche volvere a seguir dandole a ver si ha y suerte....
Squallete escribió:
function ca = cambio(A)
    a = 1;
    b = 1;
   
    while a==b
        a = randi(1,size(prod(A)))
             b = randi(1,size(prod(A)))
             % b = round(rand(prod(size(A))))
       
    end
   
    temp1 = A(a);
   
    A(a) = A(b)
    A(b) = temp1
   
    ca=A
   
    end
   


Con este codigo me da un bluce infinito de dos numeros, menudo descojone xDD

Me voy un rato esta noche volvere a seguir dandole a ver si ha y suerte....


Oki, cuando vuelvas pon los resultados paso por paso y lo revisamos si quieres xD.
Con este codigo :

function ca = cambio(A)
a = 1;
b = 1;

while a==b
a = randi(1,size(prod(A)))
b = randi(1,size(prod(A)))
% b = round(rand(prod(size(A))))

end

temp1 = A(a);

A(a) = A(b)
A(b) = temp1

ca=A

end



Me da:
Un bclue infinito de dos numeros algo asi como :

a=
1 3

b =

1 4

etc etc, donde el primer numero siempre es uno y los otros se intercambian...

Que salgan dos nu meros creo que es culpa del randi , con el round(rand( eso no sucede
umhh, size(prod) no deberia ser prod(size)?
mmmmm... tienes toda la razon del mundo... ahora sale perfecto xDD Ahora solo quedaria el problema de que A ~= a la matriz de salida... muchas gracias a todos, de verdad!
He vuelto ahora xD, entonces cuál es el problema que queda? Que no tengo ganas de leer código ahora mismo :/.
Ningun problema, solo que no se me ocurre como poner que la matriz de entrada sea diferente a la de salida, osea que A y la matriz creada no coincidan (Si , lo se, soy un matado para programacion :( )
No te entiendo, la matriz de salida ya es diferente a la de entrada, no?
O sea, el output de la función es ca, que bueno, puedes ponerle el nombre que quieras al llamar la función, y la entrada es A.

Entonces, por ejemplo Acambiada=cambio(A) te da una nueva matriz Acambiada, no?
Pero el azar hay veces que hace que A = ca y ese es el caso que debo evitar , podria hacerse con un if... pero no se por donde meterselo sin joder el while ni nada....
No no, el bucle de while a==b esta precisamente para evitar eso, si los indices a intercambiar son los mismos vuelve a sacar otros, no debería nunca ser posible A=ca, a no ser que intercambie dos elementos que sean iguales y estén en dos posiciones, lo cual es correcto, no?
Por ejemplo, en el caso de [1 0;2 1] si se cambia el primero con el cuarto, A=ca, pero es correcto, no?
Mi matriz siempre es [1 1 0 0; 1 1 0 0 ; 1 1 0 0; 1 1 0 0]

Como puedes ver:

Imagen

En ese caso se me repite la matriz [mamaaaaa]
Pero porque cambiará dos 1 o dos 0, prueba una matriz con todos los números diferentes, ya verás.
Entonces ahi esta la gracia del ejercicio.... que no suceda eso que me esta pasando , la matriz del enunciado es [1 1 0 0; 1 1 0 0 ; 1 1 0 0; 1 1 0 0], no puedo poner otra xD

Yo habia pensado en poner un if A == ca
y repetir el codigo de antes... pero esque si las casualidades de la vida quieren que se vuelve a repetir la misma matriz no me serviria de nada... osea algo asi:

function ca = cambio(A)
a = 1;
b = 1;

while a==b
a = randi(1,prod(size(A)))
b = randi(1,prod(size(A)))


end

temp1 = A(a);

A(a) = A(b)
A(b) = temp1
ca = A

if A == ca

a = 1;
b = 1;

while a==b
a = randi(1,prod(size(A)))
b = randi(1,prod(size(A)))


end

temp1 = A(a);

A(a) = A(b)
A(b) = temp1

end



Solucion cutre e ineficaz made in squallete xD
Pues yo del enunciado había deducido otra cosa xD.

Si de verdad es como tu dices es tan sencillo como hacer

a1=randi(1,prod(size(A)));
a=A(a1);
b1=randi(1,prod(size(A)));
b=A(b1);

y fuera del bucle

temp1=A(a1);

A(a1)=A(b1);
A(b1)=temp1;

Revisa, pero es eso ^^.
Vale ahora que lo miro tienes razon, el enunciado da a entender otra cosa... le preguntare el profesor a ver que in terpretacion me dice que tengo que hacer, muchas gracias por la ayuda!
De nada, ya que estás responde cuando te lo diga, y si dan una solución a ver si se parece! xD
No se nada de mathlab pero seguro que tiene do-while

inicializar
do
cálculos e intercambios
while A==ca

Y si no tiene do-while, antes de los cálculos inicializas ac=A y encieras todo en un while normal

Saludos
Me ha dicho que el programa está perfecto, muchas gracias a todos ! :)
34 respuestas