Dardos encontra Codegolf

11

Eu acho que todo mundo está familiarizado com dardos, algumas pessoas não entendem a pontuação, portanto, para essas pessoas aqui, há um link útil sobre isso.

O quadro

Um alvo de dardos pode ser comparado a um pedaço de torta em 20 pedaços. Cada peça é dividida em 4 seções.

  • um pequeno anel externo chamado duplo (pontos x2)
  • um grande anel chamado single (pontos x1)
  • outro pequeno anel chamado triplo (pontos x3)
  • outro grande anel chamado single (pontos x1)

No meio do tabuleiro existem mais 2 anéis, um verde e um vermelho (tabuleiro clássico)

  • Anel vermelho, centro do tabuleiro chamado bullseye ou double bull e vale 50 pontos. Este conta como um dobro e por isso é permitido fazer checkout com ele.
  • Anel verde, chamado touro, touro único ou simplesmente 25 e conta como um único.

Desafio

Encontre todas as possibilidades de pagamento com 3 dardos ou menos.
O usuário pode inserir um número inteiro e você terá que verificar se é possível obter a pontuação para 0 com 3 dardos (ou menos).

Exemplos

Exemplo 1:

Input: 170  
Output: T20, T20, Bullseye

Exemplo 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;

Exemplo 3:

Input: 169
Output: No possible checkout!

Regras

  • Regra básica de dardo, você deve terminar com um duplo (anel externo do tabuleiro ou alvo)
  • Não há uso de recursos externos.
  • É permitida a codificação rígida de possíveis check-out, mas lembre-se de que este é um codegolf; ele não abrevia seu código;)
  • As células a serem atingidas serão exibidas no formato C + N, onde C = T para Triple, D para double e S para single.
    • bullseye pode ser chamado bullseye ou DB, DBull ou algo semelhante.

Possíveis checkouts

Para começar, o checkout mais alto possível é 170.
169.168.166.165.163.162.159 não são possíveis em 3 dardos.
A compra mais baixa possível é 2.

além do que, além do mais

Isso não é um requisito, adicione a possibilidade de mostrar todos os check-outs possíveis para todas as pontuações. Basicamente, porque me pergunto quantas combinações são possíveis: P

O vencedor será aquele com o código mais curto.

Feliz codificação.

Teun Pronk
fonte
1
A primeira regra listada está incorreta (e invalida o primeiro exemplo) porque você também pode terminar em um touro. Seria útil esclarecer se você está esperando um programa, uma função ou ambas; e quanta flexibilidade existe no formato de saída.
Peter Taylor
1
@ PeterTaylor Vou deixar isso mais claro, já que o anel verde e o anel vermelho no meio são chamados de touro único e bullseye ou touro duplo.
Teun Pronk
1
+1 para uma excelente pergunta. Esse é o tipo de problema do mundo real que os computadores são bons em resolver. Você pode lançar um 6 em S2 D1 D1, que está ausente do exemplo de saída (ele deve estar lá, a menos que você considere S2 S2 D1 e D1 D1 D1 os mesmos, mas eles estão claramente listados como diferentes.) pequenas ambiguidades sobre o formato de saída e contagem de resultados que abordarei na minha resposta.
Level River St

Respostas:

2

Caracteres C ++ 248/228 230/214

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. Salvei alguns caracteres declarando todas as variáveis ​​de uma só vez e eliminando colchetes desnecessários. Acontece que em C ++ toda lógica e bit a bit e / ou têm precedência menor do que as comparações.

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;}

Eu fiz uma função em vez de programar, como outros fizeram. Retorna o número total de possibilidades encontradas. Pode ser reduzido de 230 para 214 caracteres, eliminando o recurso totalizador.

Resultado da amostra, pontuação 6:

insira a descrição da imagem aqui

Eu conto primeiro e segundo dardos diferentes como a mesma combinação, como o OP fez (exemplo:

T1 S1 D1 = S1 T1 D1) mesmo que isso custe 7 caracteres extras. Eu sempre listo a pontuação mais alta primeiro (ignorando dobrar e triplicar), pois acho que isso é mais relevante para o jogador (que pode mudar sua estratégia se errar com o primeiro dardo.) Pela mesma razão, listo os dardos em ordem, de acordo com o segundo dardo. Considero o terceiro dardo completamente diferente dos outros dois; portanto, considero D1 D2 e ​​D2 D1 como casos diferentes, enquanto o OP os lista como iguais.

Com esse sistema de contagem, eu tenho 42336 possibilidades totais , o mesmo que mmumboss. Contando primeiro e segundo dardos diferentes como combinações diferentes, isso aumenta para 83349.

Eu não usei um loop for com conjuntos, como outros fizeram (sou bastante novo em C ++ e nem sei se é possível.) Em vez disso, abusei de uma condicional no incremento do loop para passar de 20 para 25 Eu uso a variável de um único loop para codificar todas as pontuações possíveis para um único dardo, assim: S1 D1 T1 S2 D2 T2 etc. com módulo e divisão para decodificar. Isso economiza a verbosidade de declarar mais para loops, embora torne as expressões mais complicadas.

O resultado disso é que um dardo não utilizado é mostrado como T0, mas acho claro o que se entende, especialmente porque (considerando diferentes primeiro e segundo dardos como a mesma combinação), pude agrupá-los no início da minha saída.

Versão não destruída aqui. Alguns outros recursos são o uso dos operadores & e && seletivamente com | de modo a dar a ordem de precedência que eu quero sem colchetes.

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
fonte
204 bytes
ceilingcat
4

MATLAB ( 299 249 241 caracteres)

Este é o meu primeiro golfe sério. Minha primeira tentativa (136 caracteres) fornece o resultado correto, mas não com a formatação correta. Dá todas as possibilidades de olhar para o número de pontos para cada dardo. Isso significa que 20 simples e 10 duplos têm uma entrada separada, no entanto, ambos são exibidos como 20. É claro que o último dardo é sempre um dobro.

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,:)

Na segunda tentativa, a formatação foi aprimorada, o que naturalmente aumentou o 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','')

Aprimorado de 299 para 249 caracteres, ao mesmo tempo em que melhora a formatação da saída. Para esta versão aprimorada, a saída para os casos de exemplo é:

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:

De acordo com minhas habilidades de cálculo, há um total de 42336 possibilidades para terminar o jogo de dardos.

mmumboss
fonte
O resultado deve mostrar qual célula atingir, portanto, no primeiro item, ela 60 60 50deve ser T20 T20 Bullseye. Vou deixar isso mais claro na pergunta. Muito bem, porém, quase lá :)
Teun Pronk
1
Sim, eu já mencionei isso. Esta é a primeira tentativa inacabada. ;)
mmumboss
oops pesaroso lol, eu era curioso sobre o código e resultam eu não ler a história acima xD
Teun Pronk
Isso deveria ser melhor. A única coisa que consigo pensar é que o touro ainda é exibido como 25. Mas espero que esteja tudo bem, pois, caso contrário, não há outra possibilidade senão codificar isso, o que simplesmente não é divertido.
mmumboss
Touro único, como 25 é de fato aceitável, é a única maneira que você pode jogar 25 com um dardo de qualquer forma
Teun Pronk
2

Ruby (260 caracteres)

"O último deve ser duplo" foi a peça que faltava - não conseguia entender por que 168 não deveria ter 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
fonte
1

Python 2.7 (270 caracteres)

Não tenho certeza se o python permitirá um one-liner, mas ele está em três.

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

Ou mais de 278 caracteres com uma mensagem apropriada 'No Checkout' (por exemplo, 290 aqui):

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

Aqui vamos nós:

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

Coisas com as quais não estou feliz:

for x in a for y in a for z in

Isso é superior a 10% do total. Existe uma maneira mais compacta sem ferramentas, etc?

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

Isso é usado para evitar duplicatas no caso de um acabamento com dois dardos (por exemplo, ['', 'S1', 'D1'] e ['S1', '', 'D1']). Considero que a ordem é importante (ei - o último dardo deve ser um duplo, portanto, claramente, a ordem é importante), mas o não lançamento é um caso especial.

psion5mx
fonte
1

05AB1E , 43 bytes

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

Muito lento. Saída como uma lista de listas ou uma lista vazia, se não for possível concluir. Meus touros são S25e D25; se isso não for permitido, posso alterá-lo.

Experimente online ou verifique alguns casos de teste de uma só vez .

Explicação:

Existem algumas etapas:

1) Crie uma lista de todos os dardos simples, duplos e triplos possíveis:

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) Obtenha todos os finalizadores possíveis (terminando com um duplo) de até 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) Mantenha apenas aqueles para os quais a pontuação total é igual ao número inteiro 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) Converta os dados na lista de resultados impressa (ou seja, [[20,3],[5,1],[1,2]]torna-se ["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
fonte
0

Kotlin , 254 bytes

Nota: o algoritmo é baseado na resposta C ++ do 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!")}

Experimente online!

JohnWells
fonte