Es dificil o imposible?

Iniciado por yoyo2002, 20 Marzo 2012, 14:10 PM

0 Miembros y 3 Visitantes están viendo este tema.

explorer

Ya que lo vas a ejecutar en Codepad, prueba esta versión:
Código (perl) [Seleccionar]
#!/usr/bin/perl
use strict;
use warnings;

my $alumnos = 20;                    # Número de alumnos
my $grupos  = 4;                     # Tamaño de los grupos

my @alumnos = 1 .. $alumnos;
my $n_grupo = 1;

while (@alumnos >= $grupos) {

   # Creamos un @nuevo_grupo compuesto de tantos alumnos como de grande
   # sean los $grupos, elegidos al azar de los @alumnos restantes
   my @nuevo_grupo = map { splice @alumnos, rand(@alumnos), 1 } 1 .. $grupos;

   print "Grupo $n_grupo: [@nuevo_grupo]\n";

   $n_grupo++;
}

# Resto que ha quedado sin asignar
if (@alumnos) {
   print "Grupo $n_grupo: [@alumnos]\n";
}

yoyo2002

Exacto, eso es, es decir, quiero todas las combinaciones posibles existentes entre los 20 en grupos de 4, sin que ninguno de los 20 vuelva a coincidir con el resto en la combinacion, sea cual sea el orden, pero que no coincidan 2 ni más numeros en una nueva combinación.

yoyo2002


Gracias, ahora sí funciona. Pero ¿podría ser que salieran todas las combinaciones de 4 números existentes sin repetición, sin importar el orden en que salga? Es decir, si sale la combinación, 3-5-9-11, esta misma con otro orden no me vale (ej: 5-11-9-5) y tampoco me valdria otra donde volvieran a coincidir dos variables o más... Es decir, ya el 3 no puede volver a coincidir ni con el 5 ni con el 9 ni con el 11, al igual que el resto.

Sé que es dificil....


Cita de: explorer en 20 Marzo 2012, 18:47 PM
Ya que lo vas a ejecutar en Codepad, prueba esta versión:
Código (perl) [Seleccionar]
#!/usr/bin/perl
use strict;
use warnings;

my $alumnos = 20;                    # Número de alumnos
my $grupos  = 4;                     # Tamaño de los grupos

my @alumnos = 1 .. $alumnos;
my $n_grupo = 1;

while (@alumnos >= $grupos) {

   # Creamos un @nuevo_grupo compuesto de tantos alumnos como de grande
   # sean los $grupos, elegidos al azar de los @alumnos restantes
   my @nuevo_grupo = map { splice @alumnos, rand(@alumnos), 1 } 1 .. $grupos;

   print "Grupo $n_grupo: [@nuevo_grupo]\n";

   $n_grupo++;
}

# Resto que ha quedado sin asignar
if (@alumnos) {
   print "Grupo $n_grupo: [@alumnos]\n";
}


explorer

#13
Ahora estoy un poco dormido, pero creo que la solución es esta:
Código (perl) [Seleccionar]
my $visto;

for my $a1 (1 .. 20) {
   for my $a2 (1 .. 20) {
       for my $a3 (1 .. 20) {
           for my $a4 (1 .. 20) {

               my @ordenados = sort { $a <=> $b } $a1, $a2, $a3, $a4;

               # salimos si hay coincidencia
               next if $ordenados[0] == $ordenados[1]
                    or $ordenados[0] == $ordenados[2]
                    or $ordenados[0] == $ordenados[3]
                    or $ordenados[1] == $ordenados[2]
                    or $ordenados[1] == $ordenados[3]
                    or $ordenados[2] == $ordenados[3]
               ;

               # salimos si hay coincidencia por pares
               next if $visto{"$ordenados[0]-$ordenados[1]"}
                    or $visto{"$ordenados[0]-$ordenados[2]"}
                    or $visto{"$ordenados[0]-$ordenados[3]"}
                    or $visto{"$ordenados[1]-$ordenados[2]"}
                    or $visto{"$ordenados[1]-$ordenados[3]"}
                    or $visto{"$ordenados[2]-$ordenados[3]"}
               ;

               # recordamos todos los pares nuevos
               $visto{"$ordenados[0]-$ordenados[1]"} =
               $visto{"$ordenados[0]-$ordenados[2]"} =
               $visto{"$ordenados[0]-$ordenados[3]"} =
               $visto{"$ordenados[1]-$ordenados[2]"} =
               $visto{"$ordenados[1]-$ordenados[3]"} =
               $visto{"$ordenados[2]-$ordenados[3]"} = 1;

               # Impresión
               print "[", join('-', @ordenados), "]\n";
           }
       }
   }
}

La salida es algo corta:
[1-2-3-4]
[1-5-6-7]
[1-8-9-10]
[1-11-12-13]
[1-14-15-16]
[1-17-18-19]
[2-5-8-11]
[2-6-9-12]
[2-7-10-13]
[2-14-17-20]
[3-5-9-13]
[3-6-8-14]
[3-7-11-15]
[3-10-12-16]
[4-5-10-14]
[4-6-11-16]
[4-7-8-12]
[4-9-15-17]
[4-13-18-20]
[5-12-15-18]
[5-16-19-20]
[6-10-15-19]
[7-9-14-18]
[8-13-16-17]


Curiosamente, el alumno 1 nunca estará con el número 20. ¿Por qué?
Supongamos que queremos la combinación [1-a-b-20]. ¿Qué valores serían a o b?. Pues cualquiera entre 2 y 19... pero eso no es posible, porque todos los números entre 2 y 19 ya han salido con el 1 antes (mirar las 6 primeras combinaciones). Y se cumpliría la condición de que el 1 ya se ha visto con cualquiera de esos números.

Me temo que esto no es lo que quieres...

Según las condiciones que has puesto, la segunda es la que limita la salida de todas las combinaciones: «tampoco me valdría otra donde volvieran a coincidir dos variables o más...». Como los grupos son de 4, eso quiere decir que habrá alumnos que estarán en más combinaciones (el 1, seis veces), pero otras, menos (el 20, tres veces) por la razón explicada antes.

yoyo2002

Muchísimas gracias. Aunque no salgan todas, ya el resto de combinaciones las intentaré hacer manualmente, aunque tenga que usar una "Variable comodín".

Cita de: explorer en 22 Marzo 2012, 00:21 AM
Ahora estoy un poco dormido, pero creo que la solución es esta:
Código (perl) [Seleccionar]
my $visto;

for my $a1 (1 .. 20) {
   for my $a2 (1 .. 20) {
       for my $a3 (1 .. 20) {
           for my $a4 (1 .. 20) {

               my @ordenados = sort { $a <=> $b } $a1, $a2, $a3, $a4;

               # salimos si hay coincidencia
               next if $ordenados[0] == $ordenados[1]
                    or $ordenados[0] == $ordenados[2]
                    or $ordenados[0] == $ordenados[3]
                    or $ordenados[1] == $ordenados[2]
                    or $ordenados[1] == $ordenados[3]
                    or $ordenados[2] == $ordenados[3]
               ;

               # salimos si hay coincidencia por pares
               next if $visto{"$ordenados[0]-$ordenados[1]"}
                    or $visto{"$ordenados[0]-$ordenados[2]"}
                    or $visto{"$ordenados[0]-$ordenados[3]"}
                    or $visto{"$ordenados[1]-$ordenados[2]"}
                    or $visto{"$ordenados[1]-$ordenados[3]"}
                    or $visto{"$ordenados[2]-$ordenados[3]"}
               ;

               # recordamos todos los pares nuevos
               $visto{"$ordenados[0]-$ordenados[1]"} =
               $visto{"$ordenados[0]-$ordenados[2]"} =
               $visto{"$ordenados[0]-$ordenados[3]"} =
               $visto{"$ordenados[1]-$ordenados[2]"} =
               $visto{"$ordenados[1]-$ordenados[3]"} =
               $visto{"$ordenados[2]-$ordenados[3]"} = 1;

               # Impresión
               print "[", join('-', @ordenados), "]\n";
           }
       }
   }
}

La salida es algo corta:
[1-2-3-4]
[1-5-6-7]
[1-8-9-10]
[1-11-12-13]
[1-14-15-16]
[1-17-18-19]
[2-5-8-11]
[2-6-9-12]
[2-7-10-13]
[2-14-17-20]
[3-5-9-13]
[3-6-8-14]
[3-7-11-15]
[3-10-12-16]
[4-5-10-14]
[4-6-11-16]
[4-7-8-12]
[4-9-15-17]
[4-13-18-20]
[5-12-15-18]
[5-16-19-20]
[6-10-15-19]
[7-9-14-18]
[8-13-16-17]


Curiosamente, el alumno 1 nunca estará con el número 20. ¿Por qué?
Supongamos que queremos la combinación [1-a-b-20]. ¿Qué valores serían a o b?. Pues cualquiera entre 2 y 19... pero eso no es posible, porque todos los números entre 2 y 19 ya han salido con el 1 antes (mirar las 6 primeras combinaciones). Y se cumpliría la condición de que el 1 ya se ha visto con cualquiera de esos números.

Me temo que esto no es lo que quieres...

Según las condiciones que has puesto, la segunda es la que limita la salida de todas las combinaciones: «tampoco me valdría otra donde volvieran a coincidir dos variables o más...». Como los grupos son de 4, eso quiere decir que habrá alumnos que estarán en más combinaciones (el 1, seis veces), pero otras, menos (el 20, tres veces) por la razón explicada antes.


Runex

Código (python) [Seleccionar]
#!/usr/bin/env python
import random,os
class partidos:

def __init__(self,alumnos,grupos,grupox):
self.alumnos = alumnos
self.grupos = grupos
self.grupox = grupox
self.creagrupos(alumnos,grupos,grupox)
def creagrupos(self,alumnos,grupos,grupox):
print "La cantidad de alumnos es: " + str(self.alumnos)
print "La cantidad de alumnos por grupo es: " + str(self.grupos)
print "La cantidad de grupos es: " + str(self.grupox)
self.x = 0
self.v = 0
while self.v < self.grupox:
print "Grupo " + str(self.v)
while self.x < self.grupos:
y = random.randint(0,20)
print y,
self.x +=1
self.x = 0
print "\n"
self.v += 1

print "Inserte numero alumnos: "
alumnos = input("Alumnos>")
print "Inserte numero de alumnos por grupo: "
grupos = input("Alumnos x Grupo>")
print "Inserte la cantidad de grupos que desea:"
grupox = input("Grupos>")
os.system("clear")
if __name__ == "__main__":
t = partidos(alumnos,grupos,grupox)


Hasta ahí he llegado, se me ocurre una posible solución, añadiendo cada numero aleatorio que se genere en una lista y comparando después cada elemento, sin embargo eso se escapa a mi capacidad de escritura de código XD. En el programa que te he escrito yo, puedes añadir tu manualmente el numero de alumnos total, la cantidad de alumnos por grupo y la cantidad de grupos que deseas crear, así te puede servir para otras veces que desees hacer equipos con una cantidad diferente de alumnos :)

De todas formas creo que la solución ofrecida por explorer es bastante buena para tu objetivo :)
"No renunciaría al bambú.
Nunca renuciaría a ti.
No te compares con otros" "El me dijo:
El bambú tenía un propósito diferente al del
helecho, sin embargo eran necesarios y
hacían del bosque un lugar hermoso".

Eleкtro

Cita de: Runex en 22 Marzo 2012, 14:59 PM
se me ocurre una posible solución, añadiendo cada numero aleatorio que se genere en una lista y comparando después cada elemento

Yo probé otra cosa parecida:

1º - Escribir las 20 combinaciones aleatorias (20 .txt)
2º - comparar cada texto con el primer texto, Y Si algún número se repite, vuelve a crear el texto, y lo vuelve a comparar, hasta que no se repita ningún número y ningún texto séa igual.

Pero ese método puede tardar demasiado, es poco efectivo, la verdad es que en 20 min no consiguió crear un texto aleatorio que no repita ningún número en algún grupo... (¿Mala suerte?)

Quizás les sirva como idea.

Salu2








yoyo2002

Muchísimas gracias de nuevo a EleKtro H@cker y Runex, sé que no es facil lo que quiero, pero me habéis ayudado bastante y bien.

Gracias.

Runex

Yoyo si aun necesitas el programa avisa, que ya se me ha ocurrido una forma factible de hacerlo :).

Un saludo :)
"No renunciaría al bambú.
Nunca renuciaría a ti.
No te compares con otros" "El me dijo:
El bambú tenía un propósito diferente al del
helecho, sin embargo eran necesarios y
hacían del bosque un lugar hermoso".