Ir al contenido


Foto

Combinaciones con repeticion para una tirada de dardos


  • Por favor identifícate para responder
6 respuestas en este tema

#1 Rox77

Rox77

    Member

  • Miembros
  • PipPip
  • 30 mensajes

Escrito 11 junio 2012 - 11:18

Hola, no se si habrá algún dardero (jugador de dardos) en el foro, si lo hay, seguro que alguna vez se ha preguntado cuantas formas distintas de hacer 26 puntos pueden existir, porque jugando al 501 es una de las puntuaciones que más veces se repite (sobre todo si eres malo  :D ).

Pues bien, yo soy dardero y en mi equipo y con otros jugadores y equipos la pregunta ha surgido mil y una vez y me propuse averiguarlo científicamente.

Rebuscando por internet encontré un código en C++ para listar permutaciones de número cogidos de 3 en 3 (casi casi lo que yo quería) lo he modificado (y eso que de C++ ando muy justo) y he conseguido lo siguiente:


cpp
  1. // Combinaciones para el juego de los dardos
  2. // Modificado por Roberto Pulido © 2012 del original
  3. // program k3b4.CPP - page 62
  4. // Permutations.
  5. // c++ exercices book - dr. gershon kagan (first edition : 2001)
  6. // written in Borland CPP ver 3.1
  7.  
  8. #include <conio.h>
  9. #include <iostream.h>
  10. #include <iomanip.h>
  11.  
  12. #define N 62
  13.  
  14. int a[N];
  15. int T;
  16.  
  17. void Init()
  18. {
  19. // el dardo fallado
  20. a[0] = 0;
  21. // dardo sencillo
  22. for(int i = 1; i < 21; a[i++] = i-1);
  23. a[21] = 25;
  24. // los dobles
  25. for(int j = 21; j < 42; a[j++] = a[42-j]*2);
  26. // los triples
  27. for(int k = 42; k < 62; a[k++] = a[62-k]*3);
  28.  
  29. } // INIT
  30.  
  31. void Show()
  32. {
  33. for(int i = 0; i < N; i++)
  34. cout << setw(5) <<a[i];
  35. cout << endl << endl;
  36. } // SHOW
  37.  
  38. // No se usa de momento
  39. void Permutations()
  40. {
  41. float p,combi;
  42. p = 0;
  43. combi = 0;
  44.  
  45. for(int i = 0; i < N; i++)
  46.   for(int j = 0; j < N; j++)
  47.   {
  48.   if(i == j)
  49.   continue;
  50.   for(int k = 0; k < N; k++)
  51.   {
  52.     if (k == i || k == j)
  53.     continue;
  54.  
  55.     if (a[i] + a[j] + a[k] == T)
  56.     {
  57.     combi++;
  58.     cout << setw(23) << a[i] << setw(5) << a[j]
  59.     << setw(5) << a[k] << endl;
  60.     }
  61.     p++;
  62.   }
  63.   }
  64.   cout << endl;
  65.   cout << "Total permutaciones : " << p << endl;
  66.   cout << "Total combinaciones para " << T << " puntos : " << combi << endl;
  67. }
  68.  
  69.  
  70. void Combinations()
  71. {
  72. float combi;
  73. combi = 0;
  74.  
  75. for(int i = 0; i < N; i++)
  76.   for(int j = 0; j < N; j++)
  77.   for(int k = 0; k < N; k++)
  78.     if (a[i] + a[j] + a[k] == T)
  79.     {
  80.     combi++;
  81.     cout << setw(23) << a[i] << setw(5) << a[j]
  82.     << setw(5) << a[k] << endl;
  83.     }
  84.   cout << endl;
  85.   cout << "Total combinaciones para " << T << " puntos : " << combi << endl;
  86. }
  87.  
  88.  
  89.  
  90.  
  91. void main()
  92. {
  93. clrscr();
  94. cout << "¨Qu‚ tirada deseas calcular? : ";
  95. cin >> T;
  96. cout << "Vamos a calcular las combinaciones con repetici¢n para "
  97.     <<<< " puntos";
  98. getch();
  99. cout << endl;
  100. cout << "Combinaciones de : " << endl;
  101. Init();
  102. Show();
  103. getch();
  104. Combinations();
  105. //Permutations();
  106. cout << endl;
  107. cout << "** FIN DEL PROGRAMA **";
  108. getch();
  109. } // MAIN


Funcionar funciona, o eso creo, y me gustaría que opinarais sobre el código o si hay algún error para corregirlo antes de fardar con los amigos darderos de que hay 1857 combinaciones para hacer 26 puntos en una tirada  ;)

P.D. No seais muy duros ;)

Gracias por adelantado.
  • 0

#2 Rox77

Rox77

    Member

  • Miembros
  • PipPip
  • 30 mensajes

Escrito 20 junio 2012 - 11:14

Hola a todos, veo que nadie ha contestado nada  :| , o a nadie le ha interesado  :.

De todas maneras yo por mi cuenta he reescrito el programa desde cero leyendo algún libro de C/C++  para mejorar (creo) algunas cosillas.

Si a alguien le interesa os dejo el código para compartirlo con la comunidad.

Saludos.


cpp
  1. // Combinaciones para el juego de los dardos
  2. // Roberto Pulido © 2012
  3. //
  4. // Explicacion: El programa calcula el número de combinaciones posibles
  5. //              que podemos realizar en una tirada de 3 dardos para conseguir
  6. //              la puntuacion deseada.
  7. //
  8. // P.D. El programa se creo para comprobar cuantas formas distintas de hacer
  9. //      26 puntos existian porque es un número que se sale mucho, pero resulta
  10. // que no es el que más combinaciones tiene, cosas que pasan :)
  11. //
  12.  
  13.  
  14. #include <conio.h>
  15. #include <iostream.h>
  16. #include <iomanip.h>
  17.  
  18. #define ppuntos 63
  19.  
  20.  
  21. int lanzamiento [ ] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,25,
  22. 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,50,
  23.   3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60};
  24. char *tlanzamiento [ ] = {"0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20", "25",
  25.     "D1","D2","D3","D4","D5","D6","D7","D8","D9","D10","D11","D12","D13","D14","D15","D16","D17","D18","D19","D20", "BULL",
  26.     "T1","T2","T3","T4","T5","T6","T7","T8","T9","T10","T11","T12","T13","T14","T15","T16","T17","T18","T19","T20" };
  27. int T;
  28.  
  29.  
  30. void combi()
  31. {
  32. float combinaciones;
  33. combinaciones = 0;
  34.  
  35. for(int i = 0; i < ppuntos; i++)
  36.   for(int j = 0; j < ppuntos; j++)
  37.   for(int k = 0; k < ppuntos; k++)
  38.     if (lanzamiento[i] + lanzamiento[j] + lanzamiento[k] == T)
  39.     { combinaciones++;
  40.       cout.setf (ios::left, ios::adjustfield);
  41.       cout << "[ " << setw(5) << tlanzamiento[i]
  42.   << setw(5) << tlanzamiento[j]  << setw(5)
  43.   << tlanzamiento[k] << "]" << endl;
  44.     }
  45.   cout << endl;
  46.   cout << "Combinaciones posibles para " << T << " puntos: " << combinaciones << endl;
  47.  
  48. }
  49.  
  50.  
  51. void main()
  52. {
  53. int salir;
  54. salir = 1;
  55.  
  56.   do
  57.   {
  58.     clrscr();
  59.     cout << "Calculo de combinaciones posibles para puntuacion en dardos" << endl;
  60.     cout << "-----------------------------------------------------------" << endl;
  61.     cout << endl;
  62.     cout << "¨Que puntuacion calculamos?: ";
  63.     cin >> T;
  64.     cout << endl;
  65.     combi();
  66.     cout << endl;
  67.     cout << "-----------------------------------------------------------" << endl;
  68.     cout << "Para salir 0, cualquier otro para continuar. ¨Salir?: ";
  69.     cin >> salir;
  70.   }
  71.   while (salir != 0);
  72. }


  • 0

#3 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.092 mensajes
  • LocationMurcia, España

Escrito 22 junio 2012 - 05:23

No llores hombre, he hecho el "calculo" en delphi que te da las combinaciones individuales que encuentra, y creo que tienes algo mal: hay 1862 combinaciones (si el orden en que se tiran los dardos importa) y si solo importa donde quedan clavados al final, entonces tienes 334 combinaciones.

La unidad completa que hace todo es esta, aunque adjunto proyecto en Delphi7 para los más gandules:


delphi
  1. unit UnitDardos;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, StdCtrls, ExtCtrls;
  8.  
  9. type
  10.   TFormDardos = class(TForm)
  11.     Memo1: TMemo;
  12.     Panel1: TPanel;
  13.     Button1: TButton;
  14.     Label1: TLabel;
  15.     EdDardos: TEdit;
  16.     Label2: TLabel;
  17.     EdPuntos: TEdit;
  18.     EdOrden: TCheckBox;
  19.     procedure Button1Click(Sender: TObject);
  20.   private
  21.     NumDardos: integer;
  22.     Suma: integer;
  23.     //La tirada "2x18" vale de puntos 36...
  24.     tirada: array[1..63] of string;
  25.     puntos: array [1..63] of integer;
  26.     //Aqui metere las combinaciones que encuentre...
  27.     combinaciones: array of string;
  28.     procedure DameTiradas(Num, Sum: integer; Inicio: integer = 1; Previas: string = '');
  29.   public
  30.     { Public declarations }
  31.   end;
  32.  
  33. var
  34.   FormDardos: TFormDardos;
  35.  
  36. implementation
  37.  
  38. {$R *.dfm}
  39.  
  40. procedure TFormDardos.Button1Click(Sender: TObject);
  41. var
  42.   p, i, j: integer;
  43.   t: string;
  44. begin
  45.   Memo1.Lines.Clear;
  46.   SetLength(Combinaciones, 0);
  47.   //Leo datos de pantalla
  48.   try
  49.     NumDardos:= StrToInt(EdDardos.Text);
  50.     Suma:= StrToInt(EdPuntos.Text);
  51.   except
  52.     ShowMessage('Escribe los números bien!');
  53.   end;
  54.   //Creo todos los posibles resultados de tirar 1 dardo solo:
  55.   p:= 0;
  56.   for i:= 1 to 20 do begin
  57.     //Numero simple "i"
  58.     inc(p);
  59.     puntos[p]:= i;
  60.     tirada[p]:= IntToStr(i);
  61.     //Numero doble "i"
  62.     inc(p);
  63.     puntos[p]:= i*2;
  64.     tirada[p]:= 'D'+IntToStr(i);
  65.     //Numero triple "i"
  66.     inc(p);
  67.     puntos[p]:= i*3;
  68.     tirada[p]:= 'T'+IntToStr(i);
  69.   end;
  70.   //Añado diana simple
  71.   inc(p);
  72.   puntos[p]:= 25;
  73.   tirada[p]:= 'Diana';
  74.   //Añado diana doble (mosca)
  75.   inc(p);
  76.   puntos[p]:= 50;
  77.   tirada[p]:= 'Mosca';
  78.   //Añado dardo fuera
  79.   inc(p);
  80.   puntos[p]:= 0;
  81.   tirada[p]:= 'fuera';
  82.   //
  83.   //Ordeno de mas a menos puntos las posibles tiradas de 1 dardo
  84.   for i:= 2 to high(puntos) do begin
  85.     for j:= i-1 downto 1 do begin
  86.       if Puntos[j]<Puntos[j+1] then begin
  87.         p:= Puntos[j];
  88.         Puntos[j]:= Puntos[j+1];
  89.         Puntos[j+1]:= p;
  90.         t:= tirada[j];
  91.         tirada[j]:= tirada[j+1];
  92.         tirada[j+1]:= t;
  93.       end else begin
  94.         break;
  95.       end;
  96.     end;
  97.   end;
  98.  
  99.   //Muestro posibles tiradas de 1 dardo (debug solo):
  100.   //for i:= Low(tirada) to High(tirada) do
  101.   //  Memo1.Lines.Add('Tirada '+IntToStr(i)+' = '+tirada[i]);
  102.  
  103.   // Uso una funcion recursiva: dame las combinaciones de N tiradas que sumen X
  104.   DameTiradas(NumDardos, Suma);
  105.  
  106.   for i:= Low(combinaciones) to High(Combinaciones) do
  107.     Memo1.Lines.Add('Combinación '+IntToStr(i)+' = '+Combinaciones[i]);
  108.  
  109. end;
  110.  
  111. procedure TFormDardos.DameTiradas(Num, Sum: integer; Inicio: integer = 1; Previas: string = '');
  112. var i: integer;
  113.  
  114.   //A las tiradas previas le sumo esta
  115.   function AnadeTirada(i: integer): string;
  116.   begin
  117.     result:= Previas;
  118.     if result<>'' then result:= result+', ';
  119.     result:= result + tirada[i];
  120.   end;
  121.  
  122. begin
  123.   //Si tiene que sumar "Sum", solo uso tiradas de Sum o menor valor como incio...
  124.   for i:= Inicio to High(tirada) do begin
  125.     //Si Num es 1, necesito que sume justo lo que me falta...
  126.     if (Num=1) then begin
  127.       if Puntos[i]=Sum then begin
  128.         //BINGO, nueva combinacion encontrada!
  129.         SetLength(Combinaciones, Length(Combinaciones)+1);
  130.         Combinaciones[High(Combinaciones)]:= AnadeTirada(i);
  131.       end else if (Puntos[i]<Sum) then begin
  132.         //Si suma de menos, al estar ordenado decreciente, desisto.
  133.         break;
  134.       end;
  135.     end else begin
  136.       //Num es mayor de 1, me vale con "no pasarme" <=
  137.       if (puntos[i]<=Sum) then begin
  138.         //Recursivamente, continuo...
  139.         if EdOrden.checked then begin
  140.           //Las anteriores no necesito volver a probarlas
  141.           DameTiradas(Num-1, Sum-puntos[i], i, AnadeTirada(i));
  142.         end else begin
  143.           //Orden importa, inicio busqueda de mas tiradas por la primera
  144.           DameTiradas(Num-1, Sum-puntos[i], 0, AnadeTirada(i));
  145.         end;
  146.       end;
  147.     end;
  148.   end;
  149. end;
  150.  
  151. end.

Archivos adjuntos


  • 0

#4 Rox77

Rox77

    Member

  • Miembros
  • PipPip
  • 30 mensajes

Escrito 23 junio 2012 - 03:59

Hola Sergio, muchas gracias primero por contestar y segundo por tomarte la molestia de pasarlo a Delphi (mejorado ;) ), yo lo unico que queria es que alguien que dominara C/C++ le diera un vistazo al código por si había alguna burrada escrita o algo mal.

Por cierto Sergio, ¿eres o has sido dardero?, porque eso de "mosca" al 50... :)

Probado tu programa, en realidad tienes razón a medias, es cierto que en el primer programa que publiqué estaba mal, me daba esas 1857 que no es verdad, pero en el segundo si esta bien y son 1863, el tuyo también está bien pero cuentas la primera como "Combinacion 0 = D13,fuera,fuera" :) y por eso salen 1862.

Lo que no entiendo bien es a lo que te refieres con lo de "sin importar el orden en que se tiraron los dardos" ¿ Que la tirada sea de mayor a menor ?  Y la funcion recursiva la encuentro muy sofisticada comparada con la que tengo yo en C++ (simple a más no poder) total para calcular una combinación con permutaciones y repeticion (vamos un todo vale).

Lo de añadir el número de dardos si está bien, yo en mi version 3 (he seguido toquetando el codigo de mi versión 2, le he cogido gustillo al programa...jeje) he hecho otra función para calcular cual es la puntuación que más veces se repite y es 60 puntos (no se porque pero creo que tiene cierto sentido matemático) con mas de 3000 y muchas combinaciones.

La siguiente parte que tengo en mente es pasar el programa a JavaScript (si soy capaz) para ver si puede ponerse en un gadchet de blogger en el blog de mi equipo de dardos y en el del club de pelo y que la gente pueda trastear con la tonteria.

¿Si te animas? ;)

De nuevo gracias Sergio. Un saludo.
  • 0

#5 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.092 mensajes
  • LocationMurcia, España

Escrito 25 junio 2012 - 01:20

Si, he sido muy muy dardero, pero no del 501, del de conseguir 3 de cada cosa más puntos, y asl menos por aquí a la diana "doble" se le llama "mosca", porque cuesta darle a la cobarde.

La diferencia entre un metodo y el otro (con/sin orden) es que si para ti es lo mismo una tirada de 12, 12, 0 que otra de 12, 0, 12 (el orden no importa) entonces solo tienes 300 y pico combinaciones, pero si el orden en que cada dardo se clava importa, entonces te subes a mil y pico.

Y lo de contar la primera jugada como cero vaya cagada mia... las prisas!

Respecto de hacerlo recursivo, para mi es mas intuitivo, y si quieres pasarte a N dardos, es aun más claro. Si además ordenas como yo hago las posibles tiradas por puntos, puedes "para de contar" cuando te pasas de 26 y no seguir con la lista, y eso ahorra bastantes "saltos recursivos". Maneras de pensar, supongo.
  • 0

#6 Rox77

Rox77

    Member

  • Miembros
  • PipPip
  • 30 mensajes

Escrito 25 junio 2012 - 01:23

Si, he sido muy muy dardero, pero no del 501, del de conseguir 3 de cada cosa más puntos, y asl menos por aquí a la diana "doble" se le llama "mosca", porque cuesta darle a la cobarde.


Supongo que te refieres a "Cricket", y por aqui tambien se le llama "mosca" o "bull" o "conguito"...jeje, por eso me dio la pista de que tenias que ser (o haber sido) dardero. Pues nada, a ver si algún dia coincidimos y nos jugamos unas partidillas ;)

La diferencia entre un metodo y el otro (con/sin orden) es que si para ti es lo mismo una tirada de 12, 12, 0 que otra de 12, 0, 12 (el orden no importa) entonces solo tienes 300 y pico combinaciones, pero si el orden en que cada dardo se clava importa, entonces te subes a mil y pico.


Vale, ahora si lo entiendo pero a mi me suena al reves de como lo habías expresado, al decir "el orden no importa" lo considero que "no importa como se haga la tirada HAY que tenerla en cuenta" a la hora de contabilizarla como una combinación posible, y tu interpretación es al contrario. Pero está claro ahora.

Y lo de contar la primera jugada como cero vaya cagada mia... las prisas!


Psssss, menuda tontería, si yo era por poner pegas , que soy muy "tiquismiquis" y cuando no me cuadra hasta que no encuentro porqué no suelo parar, (pregunta a Cadetill para más referencias...jajajaja)

Respecto de hacerlo recursivo, para mi es mas intuitivo, y si quieres pasarte a N dardos, es aun más claro. Si además ordenas como yo hago las posibles tiradas por puntos, puedes "para de contar" cuando te pasas de 26 y no seguir con la lista, y eso ahorra bastantes "saltos recursivos". Maneras de pensar, supongo.


Niveles de conocimiento supongo....a mi no me pidas más del IF THEN ELSE o el FOR DO que me pierdo...jajaja.

Lo dicho, gracias Sergio.
  • 0

#7 Rox77

Rox77

    Member

  • Miembros
  • PipPip
  • 30 mensajes

Escrito 11 julio 2012 - 08:26

La siguiente parte que tengo en mente es pasar el programa a JavaScript (si soy capaz) para ver si puede ponerse en un gadchet de blogger en el blog de mi equipo de dardos y en el del club de pelo y que la gente pueda trastear con la tonteria.

Como lo prometido es deuda y nadie se "animó" (bueno le concedemos una linea en los creditos a Cadetill, pero mu pequeñita) aquí os dejo el código en JavaScript, para uso y disfrute de la comunidad (sea cual sea el disfrute de esto :) ).


javascript
  1. <html>
  2.  
  3.  
  4. <head>
  5.  
  6. <SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript">
  7. <!--
  8. ppuntos = 63;
  9. lanzamiento = new Array(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,25,
  10.                     2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,50,
  11. 3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60);
  12. tlanzamiento = new Array("0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20", "25",
  13.     "D1","D2","D3","D4","D5","D6","D7","D8","D9","D10","D11","D12","D13","D14","D15","D16","D17","D18","D19","D20", "BULL",
  14.     "T1","T2","T3","T4","T5","T6","T7","T8","T9","T10","T11","T12","T13","T14","T15","T16","T17","T18","T19","T20" );
  15. combinaciones = 0;
  16. texto = "";
  17.  
  18. function combi(tirada, mostrar)
  19. {
  20. combinaciones = 0;
  21. texto = "Resultado: \n"  "----------------\n";
  22. for( i = 0; i < ppuntos;)
  23.   for( j = 0; j < ppuntos;)
  24.   for( k = 0; k < ppuntos;)
  25.     if (lanzamiento[i]  lanzamiento[j]  lanzamiento[k] == tirada)
  26.     { combinaciones  ;
  27.     if (mostrar == 1)
  28.     {
  29.       texto = texto  "[ "  tlanzamiento[i]  " "    tlanzamiento[j]  " "  tlanzamiento[k]  " ]"  "\n";
  30.       }
  31.     }
  32.   if (mostrar == 1)
  33.   {   
  34.   texto = texto  "----------------\n"  combinaciones  " combinaciones\n"  "para "  tirada  " puntos.\n";
  35.   }
  36.   document.form1.textarea1.value = texto; 
  37. }
  38.  
  39.  
  40. -->
  41. </script>
  42.  
  43. </head>
  44. <body>
  45. <p align="center"><font size="1" face="verdana" color="brown">
  46. El programa calcula el número de posibles combinaciones
  47. que podemos realizar en una tirada de 3 dardos para conseguir
  48. una puntuacion deseada. Sin contemplar el orden, ni repeticiones.<br>
  49. </font></p>
  50. <form name="form1" method="post" action="" align="center">
  51. <font size="1" face="verdana">Puntos:</font>
  52. <input type="text" size="4" name="puntos">
  53. <input type="button" name="btnCalcular" value="Calcular"
  54. onclick="combi(document.form1.puntos.value,1)">
  55. <br>
  56. <textarea name="textarea1" rows="10" cols="20">
  57. </textarea>
  58. </form>
  59. <p align="center"><font size="1" face="verdana" color="brown">Roberto Pulido (c) 2012</font></p>
  60.  
  61. </body>
  62. </html>

 

Saludos. ;)
  • 0




IP.Board spam blocked by CleanTalk.