Dardos se encuentra con Codegolf

11

Creo que todos están familiarizados con los dardos, algunas personas no entienden los puntajes, por lo que para esas personas aquí hay un enlace útil sobre eso.

El tablero

Un tablero de dardos se puede comparar con un pastel cortado en 20 piezas. Cada pieza está dividida en 4 secciones.

  • un pequeño anillo externo llamado doble (puntos x2)
  • un gran anillo llamado single (puntos x1)
  • otro pequeño anillo llamado triple (puntos x3)
  • otro gran anillo llamado single (puntos x1)

En el centro del tablero hay 2 anillos más, uno verde y rojo (tablero clásico)

  • Anillo rojo, centro del tablero llamado diana o doble toro y es bueno por 50 puntos. Este cuenta como un doble y por eso está permitido pagar con él.
  • Anillo verde, llamado toro, toro simple o simplemente 25 y cuenta como un solo.

Desafío

Encuentra todas las posibilidades de pago con 3 dardos o menos.
El usuario puede ingresar un número entero y deberá verificar si es posible obtener el puntaje a 0 con 3 dardos (o menos).

Ejemplos

Ejemplo 1:

Input: 170  
Output: T20, T20, Bullseye

Ejemplo 2

Input: 6  
Output: D3;  
        S3,S1,D1;  
        S2,D2;  
        S2,S2,D1;  
        D2,D1;  
        S4,D1;  
        D1,D1,D1;  
        S1,S1,D2;  
        T1,S1,D1;

Ejemplo 3

Input: 169
Output: No possible checkout!

Reglas

  • Regla básica de dardos, debes terminar con un doble (anillo exterior del tablero o diana)
  • Sin uso de recursos externos.
  • Se permite la codificación dura de posibles pagos, pero recuerde que esto es codegolf, no obtendrá su código corto;)
  • Las celdas para golpear se mostrarán en formato C + N donde C = T para Triple, D para doble y S para simple.
    • bullseye puede llamarse bullseye o DB, DBull o algo similar.

Posibles pagos

Para comenzar, el pago más alto posible es 170.
169,168,166,165,163,162,159 no son posibles en 3 dardos.
El pago más bajo posible es 2.

Adicionalmente

Esto no es un requisito, agregue la posibilidad de mostrar todos los pagos posibles para todos los puntajes. Básicamente porque me pregunto cuántas combinaciones son posibles: P

El ganador será el que tenga el código más corto.

Feliz codificación

Teun Pronk
fuente
1
La primera regla enumerada es incorrecta (e invalida el primer ejemplo) porque también puede terminar en un toro. Sería útil aclarar si está esperando un programa, una función o ambos; y cuánta flexibilidad hay en el formato de salida.
Peter Taylor
1
@PeterTaylor Dejaré esto más claro, ya que el anillo verde y el anillo rojo en el medio se llaman Toro simple y diana o doble toro.
Teun Pronk
1
+1 por excelente pregunta. Este es el tipo de problema del mundo real que las computadoras son buenas para resolver. Puede lanzar un 6 en S2 D1 D1, que falta en su salida de ejemplo (debe estar allí, a menos que considere que S2 S2 D1 y D1 D1 D1 son iguales, pero están claramente listados como diferentes). Hay algunos ambigüedades menores sobre el formato de salida y el recuento de resultados que abordaré en mi respuesta.
Level River St

Respuestas:

2

C ++ 248/228 230/214 caracteres

Rev 0:

int f(int s){char m[4]="SDT";int t=0;for(int b=2;b<77;b+=1+(b==62)*12)for(int a=2;a<77;a+=1+(a==62)*12){int c=s-a/3*(a%3+1)-b/3*(b%3+1);if(((c+38)/40==1)|(c==50)&&(c%2==0)&(a>=b)){printf("%c%d %c%d D%d\n",m[a%3],a/3,m[b%3],b/3,c/2);t++;}}return t;}

Rev 1. Guardado algunos caracteres declarando todas las variables a la vez y eliminando corchetes innecesarios. Resulta que en C ++ toda lógica y bit a bit y / o tienen menor prioridad que las comparaciones.

int f(int s){char m[4]="SDT";int a,b,c,t=0;for(b=2;b<77;b+=1+(b==62)*12)for(a=2;a<77;a+=1+(a==62)*12){c=s-a/3*(a%3+1)-b/3*(b%3+1);if(c>1&c<41|c==50&&c%2==0&a>=b){printf("%c%d %c%d D%d\n",m[a%3],a/3,m[b%3],b/3,c/2);t++;}}return t;}

Hice una función en lugar de un programa, como lo han hecho otros. Devuelve el número total de posibilidades encontradas. Se puede reducir de 230 a 214 caracteres eliminando la función de totalización.

Salida de muestra, puntaje 6:

ingrese la descripción de la imagen aquí

Cuento diferentes dardos primero y segundo como la misma combinación, como lo ha hecho el OP (ejemplo:

T1 S1 D1 = S1 T1 D1) aunque esto cuesta 7 caracteres adicionales. Siempre enumero el puntaje más alto primero (haciendo caso omiso de duplicar y triplicar) ya que creo que esto es más relevante para el jugador (que puede cambiar su estrategia si falla con el primer dardo). Por la misma razón, enumero los dardos en orden de acuerdo con El segundo dardo. Considero que el tercer dardo es completamente diferente a los otros dos, por lo tanto, considero que D1 D2 y D2 D1 son casos diferentes, mientras que el OP los enumera como iguales.

Con este sistema de conteo obtengo 42336 posibilidades totales , lo mismo que mmumboss. Contando diferentes dardos primero y segundo como combinaciones diferentes, esto va hasta 83349.

No he usado un bucle for con conjuntos como lo han hecho otros (soy bastante nuevo en C ++ y ni siquiera sé si es posible). En cambio, abuso de un condicional en el incremento del bucle para saltar de 20 a 25 Utilizo la variable de un solo bucle para codificar todas las puntuaciones posibles para un solo dardo, así: S1 D1 T1 S2 D2 T2, etc. con módulo y división para decodificar. Esto ahorra la verbosidad de declarar más para bucles, aunque hace que las expresiones sean más complicadas.

El resultado de esto es que un dardo no utilizado se muestra como T0, pero creo que está claro lo que significa, especialmente porque (al considerar diferentes dardos primero y segundo como la misma combinación) he podido agruparlos todos al principio de mi salida

Versión sin golf aquí. Algunas otras características son el uso selectivo de los operadores & y && con | de manera tal de dar el orden de precedencia que quiero sin paréntesis.

int f(int s)
{
  char m[4] = "SDT";
  int a,b,c,t=0;
    for (b = 2; b < 77; b += 1 + (b == 62) * 12)
      for (a = 2; a < 77; a += 1 + (a == 62) * 12){
        c = s - a / 3 * (a % 3 + 1) - b / 3 * (b % 3 + 1);
        if (c>1 & c<41 | c == 50 && c % 2 == 0 & a >= b){
          printf("%c%d %c%d D%d\n", m[a % 3], a / 3, m[b % 3], b / 3, c / 2);
          t++;
        }
     }
   return t;
}
Level River St
fuente
204 bytes
ceilingcat
4

MATLAB ( 299 249 241 caracteres)

Este es mi primer juego de golf serio. Mi primer intento (136 caracteres) da el resultado correcto, pero no con el formato correcto. Da todas las posibilidades mirando el número de puntos para cada dardo. Esto significa que solo 20 y doble 10 tienen una entrada separada, sin embargo, ambos se muestran como 20. Por supuesto, el último dardo siempre es un doble.

function f(x);u=[1:20 25].';y=[u;2*u; 3*u(1:end-1)];v=combvec([combnk(y,2);[y y];[zeros(62,1) y];[0 0]].',y(22:42).').';v(sum(v,2)==x,:)

En el segundo intento, se mejora el formato, que por supuesto ha aumentado el número de caracteres:

function f(x);h=.1;u=h+[1:20,25].';y=[u;2*u;3*u(1:20)];v=combvec([combnk(y,2);[y,y];h*ones(62,1),y];[h,h]].',y(22:42).').';t='SDT';r=@fix;strrep(arrayfun(@(x)[t(int8((x-r(x))/h)),num2str(h*r(x)/(x-r(x)))],v(sum(r(v),2)==x,:),'un',0),'S0','')

Mejorado de 299 a 249 caracteres, al mismo tiempo que incluso mejora el formato de salida. Para esta versión mejorada, la salida para los casos de ejemplo es:

f (170):

'T20'    'T20'    'D25'

f (6):

'S1'    'S3'    'D1'
'S1'    'T1'    'D1'
'S2'    'D1'    'D1'
'S2'    'S2'    'D1'
'D1'    'D1'    'D1'
''      'S4'    'D1'
''      'D2'    'D1'
'S1'    'S1'    'D2'
''      'S2'    'D2'
''      'D1'    'D2'
''      ''      'D3'

f (169):

Empty cell array: 0-by-3

Adicional:

Según mis habilidades de cálculo, hay un total de 42336 posibilidades para finalizar el juego de dardos.

mmumboss
fuente
El resultado debería mostrar qué celda golpear, por lo que en el primero dice que 60 60 50debería ser T20 T20 Bullseye. Dejaré esto más claro en la pregunta. Bien hecho, casi allí :)
Teun Pronk
1
Sí, ya lo señalé yo mismo. Este es el primer intento inacabado. ;)
mmumboss
oops lo siento lol, tenía curiosidad sobre el código y el resultado No leí la historia anterior xD
Teun Pronk
Esto debería ser mejor. Lo único que se me ocurre es que el toro todavía se muestra como 25. Pero espero que esto esté bien, ya que de lo contrario no hay otra posibilidad que codificar esto, lo que simplemente no es divertido.
mmumboss
Solo un toro como 25 es realmente aceptable, es la única forma en que puedes lanzar 25 con 1 dardo de todos modos
Teun Pronk
2

Rubí (260 caracteres)

"El último debería ser un doble" fue la pieza que faltaba; no podía entender por qué 168 no debería tener resultados ...:

c=->n,d=3{d=d-1;r=[];n==0?[r]:(d>=0&&n>0?(o='0SDT';((1..20).map{|p|(1..3).map{|h|c.(n-p*h,d).map{|m|r<<["#{o[h]}#{p}"]+m}}};c.(n-50,d).map{|m|r<<['DB']+m};c.(n-25,d).map{|m|r<<[?B]+m})):1;r.select{|*i,j|j[?D]}.tap{|x|d!=2?1:puts(x.map{|i|"#{i.join(?,)};"})})}

c. (170)

T20,T20,DB;

c. (6)

S1,S1,D2;
S1,T1,D1;
S1,S3,D1;
D1,D1,D1;
D1,S2,D1;
D1,D2;
T1,S1,D1;
S2,D1,D1;
S2,S2,D1;
S2,D2;
D2,D1;
S3,S1,D1;
D3;
S4,D1;
Uri Agassi
fuente
1

Python 2.7 (270 caracteres)

No estoy seguro de que Python permita una línea, pero él está en tres.

def f(n):
 a={'%s%s'%('0SDT'[i],n):n*i for n in range(1,21)+[25] for i in [1,2,3] if n*i<75};a['']=0
 for r in [' '.join(h[:3]) for h in [(x,y,z,a[x]+a[y]+a[z]) for x in a for y in a for z in {k:a[k] for k in a if 'D' in k}] if h[3]==n and len(h[0])<=len(h[1])]:print r

O más de 278 caracteres con un mensaje apropiado de 'No pago' (por ejemplo, 290 aquí):

def f(n):
 a={'%s%s'%('0SDT'[i],n):n*i for n in range(1,21)+[25] for i in [1,2,3] if n*i<75};a['']=0;
 for r in [' '.join(h[:3]) for h in [(x,y,z,a[x]+a[y]+a[z]) for x in a for y in a for z in {k:a[k] for k in a if 'D' in k}] if h[3]==n and len(h[0])<=len(h[1])] or ['No Checkout']:print r

Aquí vamos:

f (170)

T20 T20 D25

f (6)

S3 S1 D1
S2 S2 D1
S2 D1 D1
S1 S3 D1
S1 S1 D2
S1 T1 D1
 S2 D2
 S4 D1
  D3
 D2 D1
 D1 D2
T1 S1 D1
D1 S2 D1
D1 D1 D1

f (169)

No Checkout

Cosas con las que no estoy contento:

for x in a for y in a for z in

Esto es más del 10% del total. ¿Existe una forma más compacta sin itertools, etc.?

and len(h[0])<=len(h[1])

Esto se utiliza para evitar duplicados en el caso de un acabado de dos dardos (por ejemplo, ['', 'S1', 'D1'] y ['S1', '', 'D1']). Considero que el orden es importante (oye, el último dardo tiene que ser doble, así que claramente el orden es importante), pero el no lanzamiento es un caso especial.

psion5mx
fuente
1

05AB1E , 43 bytes

20L25ª3Lâ¨Ðʒθ<}Uã«XâXìε˜2ô}ʒPOQ}εε`…TSDsèì

Bastante lento. Se muestra como una lista de listas o una lista vacía si no es posible finalizar. Mis toros son S25y D25; Si esto no está permitido, puedo cambiarlo.

Pruébelo en línea o verifique algunos casos de prueba a la vez .

Explicación:

Hay un par de pasos:

1) Cree una lista de todos los posibles dardos simples, dobles y triples:

20L         # Create a list in the range [1,20]
   25ª      # Append 25 to this list
      3L    # Create a list in the range [1,3]
        â   # Create all possible pairs of these two lists
         ¨  # Remove the last pair (which is the Triple Bull)
            # Now we have a list of all possible darts:
            #  [[1,1],[1,2],[1,3],[2,1],...,[20,3],[25,1],[25,2]]

2) Obtenga todos los finalizadores posibles (que terminan con un doble) de hasta 3 dardos:

Ð           # Triplicate this list
 ʒ  }       # Filter the top copy by:
  θ         #  Where the last value
   <        #  Decremented by 1 is truthy (==1), so all doubles
     U      # Pop this filtered list of doubles, and store it in variable `X`
 ã          # Create all possible pairs of the list of darts with itself
  «         # Merge it with the list of darts
            # We now have a list containing all possible variations for 1 or 2 darts
 Xâ         # Then create all possible pairs of these with the doubles from variable `X`
   Xì       # And prepend the doubles themselves as well
            # Now we have all possible variations of 1 double; 1 dart + 1 double;
            # or 2 darts + 1 double
     ε   }  # Map each to:
      ˜     #  Deep-flatten the list
       2ô   #  And split it into parts of size 2
            #  (this is to convert for example a 2 darts + 1 double from
            #   [[[20,3],[5,1]],[1,2]] to [[20,3],[5,1],[1,2]])
            # Now we have a list of all possible finishers of up to 3 darts

3) Solo mantenga aquellos para los cuales la puntuación total es igual al entero de entrada:

ʒ   }       # Filter this list by:
 P          #  Get the product of each inner-most lists
            #   i.e. [[20,3],[5,1],[1,2]] → [60,5,2]
  O         #  Take the sum of those
            #   i.e. [60,5,2] → 67
   Q        #  Check if this value is equal to the (implicit) input-integer
            # Now we only have the finishers left with a total value equal to the input

4) Convierta los datos a la lista de resultados impresa (es decir, se [[20,3],[5,1],[1,2]]convierte en ["T20","S5","D2"]):

ε           # Map each of the remaining finishers of up to 3 darts to:
 ε          #  Map each inner list to:
  `         #   Push both values separately to the stack ([20,3] → 20 and 3)
   TSD     #   Push string "TSD"
       s    #   Swap to get the integer for single/double/triple at the top of the stack
        è   #   Use it to index into the string
            #   NOTE: 05AB1E has 0-based indexing with automatic wraparound,
            #   so the triple 3 will wrap around to index 0 for character "T"
         ì  #   Prepend this character in front of the dart-value
            # (after which the result is output implicitly as result)
Kevin Cruijssen
fuente
0

Kotlin , 254 bytes

Nota: el algoritmo se basa en la respuesta C ++ de Level River St.

{s:Int->val m="SDT"
var c=0
val r=(2..62).toList()+listOf(75,76)
for(t in r)for(o in r){val l=s-o/3*(o%3+1)-t/3*(t%3+1)
if((l>1&&l<41||l==50)&&l%2==0&&o>=t){println("${m[o%3]}${o/3},${m[t%3]}${t/3},D${l/2}")
c++}}
if(c<1)println("No possible checkout!")}

Pruébalo en línea!

JohnWells
fuente