[ Foro de Pascal ]

Escoger un valor aleatorio en un array con random

26-Mar-2014 19:44
Invitado (Marc)
18 Respuestas

Hola!

Pues eso...creo un array con tres valores:


program arreglo_01;

uses
	crt;
var
	arreglo : array[1..3] of byte;
	
begin
	arreglo[1] := 6;
	arreglo[2] := 10;
	arreglo[3] := 24;
end.


Pero no sé como aplicar el random para que me dé aleatoriamente un valor de esos tres.

He probado:


arreglo[random]; // No funciona


Otra cosa es crear el indice del arreglo con una variable:


arreglo[i];


Entonces:


random(arreglo[i]); // Tampoco me va :(


Si usamos la variable del indice se debería usar un For, claro...

En esa estamos... :(


27-Mar-2014 21:07
Invitado (Marc)

Este es el programa que he creado. Pero creo, hago un mal uso del random. Ya que me genera un número aleatorio que no se encuentra entre los escogidos por nosotros...


program arreglo_aleatorio;
uses
	crt;
var
	aleat : array[1..3] of byte;
	i : byte;
	

begin
	for i := 1 to 3 do
		begin
			writeln('Escoge un numero...');
			write(i,'. ');
			readln(aleat[i]);
		end;
	textcolor(yellow);
	writeln('Has escogido...');
	for i := 1 to 3 do
		begin
			write(aleat[i]);
			writeln();
		end;
	textcolor(green);
	writeln('Numero aleatorio: ');
	writeln(random(aleat[i]));
end.



28-Mar-2014 00:00
Luis Torres (+18)

Efectivamente estás usando mal la función random. Lo correcto sería así:


i:= random(3) + 1;  (* De esta forma estaría generando un valor aleatorio comprendido *)
                                  (* entre 1 y 3, el cual lo almacenamos en la variable i *)
writeln(aleat[i]);   (* Al haber generado el índice aleatoriamente, estamos generando  *)
                                (* un valor aleatorio del arreglo aleat[i]   *)


Saludos.


28-Mar-2014 19:20
Invitado (Marc)

No es a lo que me referiría.

Se trata de que nosotros escogemos tres valores por medio de readln(aleat[i]) dentro de un ciclo for. Por ejemplo:

3, 11, 34

Y el random nos debe generar un número aleatorio dentro de esos tres (3,11,34). No del 1 al 3.


28-Mar-2014 19:35
Nacho Cabanes (+84)

En cuanto tienes un valor del 1 al 3, ya puedes obtener los valores 3, 11, 34 del array, porque esos son sus índices.

La respuesta de Luis es correcta.

Puedes pedir los datos al usuario con "readln(dato[i])" y luego escoges uno de ellos al azar de la forma que te ha indicado Luis.



28-Mar-2014 19:43
Invitado (Marc)

Anda! Pues teníais razón los dos. Era yo que no lo había entendido. Muchas gracias y disculpas ;)


29-Mar-2014 13:48
Invitado (Marc)

Ahora me surge un nuevo problema basado en este código. El número aleatorio ya me lo da ¿Pero como puedo pedirle 3 sobre los 6 seleccionados? He probado con un for y un repeat y no me funciona.

El for queda así:


for i := 1 to 3 do
		begin
                        randomize;
			i := random(3) + 1;
			writeln(aleat[i]);
		end;


Pero claro, la varible 'i' se ve alterada por el random y el for no se puede ejecutar. Y con el repeat me da el mismo número 3 veces seguidas:


contador := 0;
	repeat
		randomize;
		i := random(3) + 1;
		writeln(aleat[i]);
		contador := contador + 1;
	until contador = 3;


Cada vez que se soluciona un problema, sale otro. Supongo que esto será el arte de programar ;)


29-Mar-2014 18:34
Luis Torres (+18)

Saca el randomize del repeat - until. Ponlo antes de iniciar ese ciclo.

Saludos.


30-Mar-2014 13:48
Invitado (Marc)

Ok. Como has dicho tú, funciona ¿Pero no debería estar dentro para cambiar la semilla de la aleatoriedad? Por que al estar fuera del ciclo, esa semilla no se regenera o reinicia ¿No...?

Saludos!


30-Mar-2014 16:31
Luis Torres (+18)

El profesor Nacho te podrá explicar más al respecto, pero lo que yo sí sé es que randomize se debe ejecutar una sola vez en el programa. Yo hice un código que genera cada uno de los elementos del arreglo aleat, sin que se repita el elemento que ya se generó, es decir, impide que aparezcan dos veces un mismo elemento. Para ello hice uso de "Conjuntos" en Pascal. Aquí te lo dejo:


program NumerosAleatorios;

const
 aleat: array[1..3] of integer = (6,10,24);

type
 conjNum = set of byte; { Creamos un tipo Conjunto }

var
 i, contador: integer;
 num: conjNum;          { Definimos una variable de un tipo Conjunto }

BEGIN
  randomize;
  contador:= 0;
  num:=[];  { Inicializamos la varible con el conjunto vacío }
  repeat
    i:= random(3) + 1;
    if not(i in num) then { Si el índice del elemento no está en el conjunto }
     begin
       num:= num + [i]; { Incluimos el índice del elemento en el conjunto }
       writeln(aleat[i]);
       contador:= contador + 1;
     end;
  until contador=3;

  readln;
END.

30-Mar-2014 20:22
Invitado (Marc)

¡Anda! Pues muchas gracias. Precisamente ahora estaba liado con eso. Es decir, que de los tres números que nos generara el código, no se repitiera ninguno de ellos. Había pensado usar un while. Mas que nada por que todavía no he llegado a la lección de conjuntos. Y he visto cosas en tu código que aún no conozco. De todas formas, muy agradecido. Me lo guardo para cuando llegue ahí.

Saludos!


30-Mar-2014 20:31
Nacho Cabanes (+84)

Efectivamente: randomize inicia la generación de números aleatorios, a partir de una semilla tomada del reloj interno del equipo. Si repites el randomize, obtendrás varias secuencias iguales, en vez de una única secuencia cambiante.


30-Mar-2014 21:32
Invitado (Marc)

Ok.

Sobre este mismo ejemplo (Luis a usado conjuntos), ¿Cómo debería ser para no repetir los tres números? ¿Usando una variable auxiliar?

Por que no puedo comparar la variable 'i' consigo misma. Se trata que dentro del repeat use un while o un if para comparar dicho indice de 'i'. Si lo hago, el programa se para y no da ningún resultado.


contador := 0;
	randomize;
	
	repeat
		
		i := random(6) + 1;
		while i = i do
			i := random(6) + 1;
	        writeln(i, ' ',aleat[i]);
		contador := contador + 1;
		
	until contador = 3 ;


Le pido que si el indice es igual al salido anteriormente, me genere otro indice. De esa forma, no se repetiría el número. Pero dudo que esto sea correcto.  De todas formas, lo he probado con una variable auxiliar y tampoco me va.


31-Mar-2014 01:12
Luis Torres (+18)

La solución que encontré fue crear un nuevo vector de la misma dimensión que el vector aleat, este vector va a almacenar datos booleanos, si ya se generó el número en la posición i, entonces el vector adquiere el valor "true" en esa posición. A mí me parece que solucionarlo con conjuntos queda mucho más claro, no necesitas aprenderte toda la teoría de conjuntos, en poco tiempo la dominarás. Bueno, aquí te dejo el código:


program NumerosAleatorios;
 
const
 aleat: array[1..3] of integer = (6,10,24);
 Vector_encontrados: array[1..3] of boolean =(false,false,false); 
 
var
 i, contador: integer;
 
BEGIN
  randomize;
  contador:= 0;
  repeat
    i:= random(3) + 1;
	if Vector_encontrados[i]=false then
	 begin
	   Vector_encontrados[i]:= true;
	   writeln(aleat[i]);
	   contador:= contador + 1;
	 end;  
  until contador=3;
 
  readln;
END.

31-Mar-2014 17:24
Invitado (fer97)

hola amigos del foro, me atrajo este ejercicio y las soluciones que da luis y el profesor.
queria preguntarle al compañero luis, si pudiera explicarme una cuestion respecto a su primer codigo completo con conjuntos:

num:=[];  { Inicializamos la varible con el conjunto vacío }
 repeat
   i:= random(3) + 1;
   if not(i in num) then
...

cuando entras al repeat y haces el if, en ese instante conque valor de num , se esta comparando el i aleatorio obtenido? osea que valor tiene num,¿vacio?, se puede comparar un valor indice con el valor vacio?


31-Mar-2014 18:17
Luis Torres (+18)

Num es un "conjunto" (debes recordar toda la teoría de conjuntos que viste en la educación primaria). Num es un conjunto vacío que puede albergar números desde el 0 hasta 255 (tipo byte).
Cuando escribimos  if not(i in num) then , simplemente estamos preguntando si el elemento guardado en la variable i "pertenece" (teoría de conjuntos, recuérdala!) al conjunto Num. O sea, sería más o menos así:
                 i ? Num ?
Debes ver a Num NO como una variable, sino más bien como lo que tú conoces de lo que es un conjunto. Si el elemento guardado en i no está en ese conjunto, entonces hay una instrucción que agrega ese elemento al conjunto Num, el cual ya dejará de ser vacío para contener a su primer elemento.
Eso es todo, de allí que sea más sencillo hacer el programa con conjuntos, claro está, una vez que te familiarices con esta forma nueva de expresarte.
Saludos.


31-Mar-2014 19:43
Invitado (fer97)

hola muchisimas gracias luis, eres un compañero bastante colaborativo para quienes estamos iniciandonos, gracias por tu paciencia , entiendo lo que me dices ahora, pero porfa dame un si o un no a quiza lo mismo aunque entendiendolo ahora mejor, en ese caso la primera vez que:
escribimos  if not(i in num) then , simplemente estamos preguntando si el elemento guardado en la variable i "pertenece" al conjunto num, estaria preguntando si ese i aleatorio generado( 1, 2 o 3) esta en el conjunto num=[], lo cual seria falso inicialmente, estoy en lo correcto luis? disculpame pero asi estaria tranquilo de haber entendido esto de conjuntos gracias a ti.un saludo compañero


31-Mar-2014 20:45
Invitado (Marc)

Gracias de nuevo, Luis. Intentaré "copiar" tu sistema de conjuntos y aplicarlo sin ellos. Mas que nada para no avanzar mas que el curso de Nacho. Cuando me funcione, lo posteo. Aunque viendo que tu has aplicado los conjuntos, deduzco, que como lo quiero hacer yo, será mas complicado :(

Saludos!


31-Mar-2014 20:50
Nacho Cabanes (+84)

Marc, si quieres practicar un poco más con conjuntos, aquí tienes las ideas básicas:

http://nachocabanes.com/pascal/cupas5/cupas04d.php






(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)