Foro de elhacker.net

Programación => Scripting => Mensaje iniciado por: yoyo2002 en 20 Marzo 2012, 14:10 pm



Título: Es dificil o imposible?
Publicado por: yoyo2002 en 20 Marzo 2012, 14:10 pm
Hola, quisiera pediros ayuda.
Necesito generar todas las combinaciones posibles de cuatro cifras a escoger entre los numeros 1 y 20 inclusives, pero de forma que no se repitan ninguno aunque cambien de orden. Es decir, si tengo
1,2,3,4
aunque cambie el orden, ya el 1 no puede volver a coincidir ni con el 2 ni con el 3 ni con el cuatro en ninguna otra combinación, al igual que el 2 no puede volver a coincidir con el 1 ni con el 3 ni con el 4, y así para todas las combinaciones. Es decir,
2,1,3,4 ya no me valdría, porque coinciden aunque cambie el orden
1,5,6,2, ya no me valdria poque 1 y 2 ya han estado juntos
¿Es esto posible? Por favor, necesito ayuda para un proyecto, y estaré muy agracecida si me la dais.
Gracias a todos, YOLY


Título: Re: Es dificil o imposible?
Publicado por: Eleкtro en 20 Marzo 2012, 14:15 pm
Si que es posible, Pero especifica en que lenguaje necesitas hacerlo porfavor

Batch?


Título: Re: Es dificil o imposible?
Publicado por: yoyo2002 en 20 Marzo 2012, 14:20 pm
El lenguaje en mi caso no importa, yo no estudio programación, es para un proyecto particular para hacer un ranking en una escuela y hacer competir a los 20 alumnos entre todos ellos en partidos de 4.
Acudo a ustedes porque me han aconsejado este foro para lograr una solución como la que necesito. Si se genera en C, o Visual Basic, o cualquier otro... ya buscaré donde ejecutarlo. Muchas gracias.


Título: Re: Es dificil o imposible?
Publicado por: Runex en 20 Marzo 2012, 14:36 pm
En python sería algo así:

import random
y = 0

while y<4:
   x = random.randint(0,20)
   print x,
   y +=1

Con esto te servirá, en ocasiones se repetirá el número pero puedes ir ejecutándolo hasta que salgan los 4 diferentes.

No he tenido tiempo a más, porque me tengo que ir al instituto xd, si no te sirve, esta tarde te escribo el otro o si tienes prisa que te ayude mi compañero EleKtro H@cker :)

Un saludo :)


Título: Re: Es dificil o imposible?
Publicado por: Eleкtro en 20 Marzo 2012, 15:03 pm
Aqui tienes yo te lo he hecho en batch por si lo prefieres

Te sirve para otra ocasion, Solo tienes que configurar el número de alumnos y el de los grupos, EDITO: Aunque en el de code que te dió runex también se puedes facilmente claro.

PD: No repite números

Salu2.

EDITO: Perdón tube un fallo, Me faltó averiguar los alumnos por grupo :P, Ahora si te sirve para otra ocasión:
Código:
@Echo OFF
Setlocal enabledelayedexpansion

:: Configuración ::
Set Alumnos=20
Set Grupos=4
:: :: :: :: :: :: :: :: ::

FOR /L %%G IN (1,1,!Alumnos!) DO (Echo !Random!!Random!!Random!!Random!!Random! %%G >> Ranking.tmp)

Set Num=0
Set GrupoNUM=1
Set /A Alumnosporgrupo=%Alumnos%/%Grupos%

For /F "Tokens=2 Delims= " %%a in ('Type "Ranking.tmp" ^| Sort') Do (
Set /A num+=1
Echo Grupo !GrupoNUM!: %%a
Echo Grupo !GrupoNUM!: %%a >> Ranking.txt
IF !NUM! EQU !Alumnosporgrupo! (Echo+& Set /A GrupoNUM+=1& Set NUM=0)
)

Del /Q Ranking.tmp
pause
Exit

(http://img851.imageshack.us/img851/3002/prtscrcapturea.jpg)


Título: Re: Es dificil o imposible?
Publicado por: explorer en 20 Marzo 2012, 16:47 pm
Esta es mi versión:

Código
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. print "Número de alumnos: ";
  6. my $alumnos = <>;
  7.  
  8. print "Tamaño de los grupos: ";
  9. my $grupos  = <>;
  10.  
  11. my @alumnos = 1 .. $alumnos;
  12. my $n_grupo = 1;
  13.  
  14. while (@alumnos >= $grupos) {
  15.  
  16.    # Creamos un @nuevo_grupo compuesto de tantos alumnos como de grande
  17.    # sean los $grupos, elegidos al azar de los @alumnos restantes
  18.    my @nuevo_grupo = map { splice @alumnos, rand(@alumnos), 1 } 1 .. $grupos;
  19.  
  20.    print "Grupo $n_grupo: [@nuevo_grupo]\n";
  21.  
  22.    $n_grupo++;
  23. }
  24.  
  25. # Resto que ha quedado sin asignar
  26. if (@alumnos) {
  27.    print "Grupo $n_grupo: [@alumnos]\n";
  28. }
  29.  
  30. __END__
  31. Número de alumnos: 23
  32. Tamaño de los grupos: 4
  33. Grupo 1: [23 1 3 7]
  34. Grupo 2: [14 20 13 22]
  35. Grupo 3: [15 8 10 6]
  36. Grupo 4: [4 12 18 11]
  37. Grupo 5: [21 17 5 2]
  38. Grupo 6: [9 16 19]


Título: Re: Es dificil o imposible?
Publicado por: yoyo2002 en 20 Marzo 2012, 17:07 pm
Gracias, pero lo he ejecutado en la página de Codepad, ya que no me dedico a la programación, y la versión que coge es la v5.8.0, y no pasa dela linea 2. Una lástima, creo que me hubiese servido a la perfección.
Sabes si hay algun sitio online donde pueda ejecutar tu versión? Muchas gracias.



Para Runex:

Muchas gracias, tu código en python funciona, solo que da una sola combinación al azar, y yo necesitaria saber todas las combinaciones posibles. ¿Podria ser? Muchísimas gracias.


Título: Re: Es dificil o imposible?
Publicado por: yoyo2002 en 20 Marzo 2012, 17:32 pm
Para EleKtro H@cker.

Muchas gracias. me he buscado un compilador de batch, y me funciona como a tí, pero sería posible que diese todas las combinacione posibles sin repetir y sin importar el orden? Sé que estoy pidiendo mucho, pero de veras a todos os agradezco muchísimo el esfuerzo que estais haciendo.

Gracias


Título: Re: Es dificil o imposible?
Publicado por: explorer en 20 Marzo 2012, 17:45 pm
Ya está cambiado para los Perl antiguos.


Título: Re: Es dificil o imposible?
Publicado por: Eleкtro en 20 Marzo 2012, 18:20 pm
Para EleKtro H@cker.

sería posible que diese todas las combinacione posibles sin repetir y sin importar el orden?

Si no entiendo mal lo que quieres son 20 combinaciones (una por alumno) aleatorias pero distintas, de 4 grupos, Y que no se repita el orden de ningún número de ningún grupo al comparar las plantillas?

Por ejemplo:

plantilla 1 > Grupo 1: 6,10,2,18
plantilla 2 > Grupo 1: DISTINTOS NÚMEROS
plantilla 3 > Grupo 1: DISTINTOS NÚMEROS DE PLANTILLA 1 Y PLANTILLA 2
Etc...?

Lo pones dificil, Veré lo que puedo hacer si no se me adelanta alguien.

Salu2


Título: Re: Es dificil o imposible?
Publicado por: explorer en 20 Marzo 2012, 18:47 pm
Ya que lo vas a ejecutar en Codepad, prueba esta versión:
Código
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. my $alumnos = 20;                    # Número de alumnos
  6. my $grupos  = 4;                     # Tamaño de los grupos
  7.  
  8. my @alumnos = 1 .. $alumnos;
  9. my $n_grupo = 1;
  10.  
  11. while (@alumnos >= $grupos) {
  12.  
  13.    # Creamos un @nuevo_grupo compuesto de tantos alumnos como de grande
  14.    # sean los $grupos, elegidos al azar de los @alumnos restantes
  15.    my @nuevo_grupo = map { splice @alumnos, rand(@alumnos), 1 } 1 .. $grupos;
  16.  
  17.    print "Grupo $n_grupo: [@nuevo_grupo]\n";
  18.  
  19.    $n_grupo++;
  20. }
  21.  
  22. # Resto que ha quedado sin asignar
  23. if (@alumnos) {
  24.    print "Grupo $n_grupo: [@alumnos]\n";
  25. }
  26.  


Título: Re: Es dificil o imposible?
Publicado por: yoyo2002 en 21 Marzo 2012, 11:46 am
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.


Título: Re: Es dificil o imposible?
Publicado por: yoyo2002 en 21 Marzo 2012, 17:31 pm

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....


Ya que lo vas a ejecutar en Codepad, prueba esta versión:
Código
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. my $alumnos = 20;                    # Número de alumnos
  6. my $grupos  = 4;                     # Tamaño de los grupos
  7.  
  8. my @alumnos = 1 .. $alumnos;
  9. my $n_grupo = 1;
  10.  
  11. while (@alumnos >= $grupos) {
  12.  
  13.    # Creamos un @nuevo_grupo compuesto de tantos alumnos como de grande
  14.    # sean los $grupos, elegidos al azar de los @alumnos restantes
  15.    my @nuevo_grupo = map { splice @alumnos, rand(@alumnos), 1 } 1 .. $grupos;
  16.  
  17.    print "Grupo $n_grupo: [@nuevo_grupo]\n";
  18.  
  19.    $n_grupo++;
  20. }
  21.  
  22. # Resto que ha quedado sin asignar
  23. if (@alumnos) {
  24.    print "Grupo $n_grupo: [@alumnos]\n";
  25. }
  26.  


Título: Re: Es dificil o imposible?
Publicado por: explorer en 22 Marzo 2012, 00:21 am
Ahora estoy un poco dormido, pero creo que la solución es esta:
Código
  1. my $visto;
  2.  
  3. for my $a1 (1 .. 20) {
  4.    for my $a2 (1 .. 20) {
  5.        for my $a3 (1 .. 20) {
  6.            for my $a4 (1 .. 20) {
  7.  
  8.                my @ordenados = sort { $a <=> $b } $a1, $a2, $a3, $a4;
  9.  
  10.                # salimos si hay coincidencia
  11.                next if $ordenados[0] == $ordenados[1]
  12.                     or $ordenados[0] == $ordenados[2]
  13.                     or $ordenados[0] == $ordenados[3]
  14.                     or $ordenados[1] == $ordenados[2]
  15.                     or $ordenados[1] == $ordenados[3]
  16.                     or $ordenados[2] == $ordenados[3]
  17.                ;
  18.  
  19.                # salimos si hay coincidencia por pares
  20.                next if $visto{"$ordenados[0]-$ordenados[1]"}
  21.                     or $visto{"$ordenados[0]-$ordenados[2]"}
  22.                     or $visto{"$ordenados[0]-$ordenados[3]"}
  23.                     or $visto{"$ordenados[1]-$ordenados[2]"}
  24.                     or $visto{"$ordenados[1]-$ordenados[3]"}
  25.                     or $visto{"$ordenados[2]-$ordenados[3]"}
  26.                ;
  27.  
  28.                # recordamos todos los pares nuevos
  29.                $visto{"$ordenados[0]-$ordenados[1]"} =
  30.                $visto{"$ordenados[0]-$ordenados[2]"} =
  31.                $visto{"$ordenados[0]-$ordenados[3]"} =
  32.                $visto{"$ordenados[1]-$ordenados[2]"} =
  33.                $visto{"$ordenados[1]-$ordenados[3]"} =
  34.                $visto{"$ordenados[2]-$ordenados[3]"} = 1;
  35.  
  36.                # Impresión
  37.                print "[", join('-', @ordenados), "]\n";
  38.            }
  39.        }
  40.    }
  41. }
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.


Título: Re: Es dificil o imposible?
Publicado por: yoyo2002 en 22 Marzo 2012, 12:02 pm
Muchísimas gracias. Aunque no salgan todas, ya el resto de combinaciones las intentaré hacer manualmente, aunque tenga que usar una "Variable comodín".

Ahora estoy un poco dormido, pero creo que la solución es esta:
Código
  1. my $visto;
  2.  
  3. for my $a1 (1 .. 20) {
  4.    for my $a2 (1 .. 20) {
  5.        for my $a3 (1 .. 20) {
  6.            for my $a4 (1 .. 20) {
  7.  
  8.                my @ordenados = sort { $a <=> $b } $a1, $a2, $a3, $a4;
  9.  
  10.                # salimos si hay coincidencia
  11.                next if $ordenados[0] == $ordenados[1]
  12.                     or $ordenados[0] == $ordenados[2]
  13.                     or $ordenados[0] == $ordenados[3]
  14.                     or $ordenados[1] == $ordenados[2]
  15.                     or $ordenados[1] == $ordenados[3]
  16.                     or $ordenados[2] == $ordenados[3]
  17.                ;
  18.  
  19.                # salimos si hay coincidencia por pares
  20.                next if $visto{"$ordenados[0]-$ordenados[1]"}
  21.                     or $visto{"$ordenados[0]-$ordenados[2]"}
  22.                     or $visto{"$ordenados[0]-$ordenados[3]"}
  23.                     or $visto{"$ordenados[1]-$ordenados[2]"}
  24.                     or $visto{"$ordenados[1]-$ordenados[3]"}
  25.                     or $visto{"$ordenados[2]-$ordenados[3]"}
  26.                ;
  27.  
  28.                # recordamos todos los pares nuevos
  29.                $visto{"$ordenados[0]-$ordenados[1]"} =
  30.                $visto{"$ordenados[0]-$ordenados[2]"} =
  31.                $visto{"$ordenados[0]-$ordenados[3]"} =
  32.                $visto{"$ordenados[1]-$ordenados[2]"} =
  33.                $visto{"$ordenados[1]-$ordenados[3]"} =
  34.                $visto{"$ordenados[2]-$ordenados[3]"} = 1;
  35.  
  36.                # Impresión
  37.                print "[", join('-', @ordenados), "]\n";
  38.            }
  39.        }
  40.    }
  41. }
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.



Título: Re: Es dificil o imposible?
Publicado por: Runex en 22 Marzo 2012, 14:59 pm
Código
  1. #!/usr/bin/env python
  2. import random,os
  3. class partidos:
  4.  
  5. def __init__(self,alumnos,grupos,grupox):
  6. self.alumnos = alumnos
  7. self.grupos = grupos
  8. self.grupox = grupox
  9. self.creagrupos(alumnos,grupos,grupox)
  10. def creagrupos(self,alumnos,grupos,grupox):
  11. print "La cantidad de alumnos es: " + str(self.alumnos)
  12. print "La cantidad de alumnos por grupo es: " + str(self.grupos)
  13. print "La cantidad de grupos es: " + str(self.grupox)
  14. self.x = 0
  15. self.v = 0
  16. while self.v < self.grupox:
  17. print "Grupo " + str(self.v)
  18. while self.x < self.grupos:
  19. y = random.randint(0,20)
  20. print y,
  21. self.x +=1
  22. self.x = 0
  23. print "\n"
  24. self.v += 1
  25.  
  26. print "Inserte numero alumnos: "
  27. alumnos = input("Alumnos>")
  28. print "Inserte numero de alumnos por grupo: "
  29. grupos = input("Alumnos x Grupo>")
  30. print "Inserte la cantidad de grupos que desea:"
  31. grupox = input("Grupos>")
  32. os.system("clear")
  33. if __name__ == "__main__":
  34. 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 :)


Título: Re: Es dificil o imposible?
Publicado por: Eleкtro en 22 Marzo 2012, 15:32 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


Título: Re: Es dificil o imposible?
Publicado por: yoyo2002 en 23 Marzo 2012, 12:11 pm
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.


Título: Re: Es dificil o imposible?
Publicado por: Runex en 3 Abril 2012, 15:57 pm
Yoyo si aun necesitas el programa avisa, que ya se me ha ocurrido una forma factible de hacerlo :).

Un saludo :)