Freccette incontra Codegolf


11

Penso che tutti abbiano familiarità con le freccette, alcune persone non capiscono i punteggi, quindi per quelle persone qui è un link utile su questo.

Il bordo

Un bersaglio può essere paragonato a una torta tagliata in 20 pezzi. Ogni pezzo è diviso in 4 sezioni.

  • un piccolo anello esterno chiamato doppio (punti x2)
  • un grande anello chiamato singolo (punti x1)
  • un altro piccolo anello chiamato triple (punti x3)
  • un altro grande anello chiamato singolo (punti x1)

Nel mezzo della tavola ci sono altri 2 anelli, uno verde e uno rosso (tavola classica)

  • Anello rosso, centro del tabellone chiamato bullseye o doppio toro ed è buono per 50 punti. Questo conta come un doppio e per questo è permesso fare il checkout con esso.
  • Anello verde, chiamato toro, singolo toro o semplicemente 25 e conta come singolo.

Sfida

Trova tutte le possibilità di pagamento con 3 freccette o meno.
L'utente può inserire un numero intero e dovrai verificare se è possibile ottenere il punteggio su 0 con 3 freccette (o meno).

Esempi

Esempio 1:

Input: 170  
Output: T20, T20, Bullseye

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

Esempio 3:

Input: 169
Output: No possible checkout!

Regole

  • Regola di dardo di base, devi terminare con un doppio (anello esterno del tabellone o bullseye)
  • Nessun uso di risorse esterne.
  • È consentita la codifica rigida di possibili checkout, ma ricorda che questo è codegolf, non otterrai un codice breve;)
  • Le celle da colpire verranno visualizzate nel formato C + N dove C = T per Triple, D per double e S per single.
    • bullseye può essere chiamato bullseye o DB, DBull o qualcosa di simile.

Possibili checkout

Per iniziare, il checkout più alto possibile è 170.
169.168.166.165.163.162.159 non sono possibili in 3 freccette.
Il checkout più basso possibile è 2.

Inoltre

Questo non è un requisito, aggiungi la possibilità di mostrare tutti i checkout possibili per tutti i punteggi. Fondamentalmente perché mi chiedo quante combinazioni sono possibili: P

Il vincitore sarà quello con il codice più breve.

Buona codifica.


1
La prima regola elencata è errata (e invalida il primo esempio) perché puoi anche finire su un toro. Sarebbe utile chiarire se ti aspetti un programma, una funzione o entrambi; e quanta flessibilità c'è nel formato di output.
Peter Taylor,

1
@PeterTaylor Lo renderò più chiaro, dal momento che l'anello verde e l'anello rosso nel mezzo sono chiamati Toro singolo e bullseye o doppio toro.
Teun Pronk,

1
+1 per una domanda eccellente. Questo è il tipo di problema del mondo reale che i computer sono bravi a risolvere. Puoi lanciare un 6 in S2 D1 D1, che manca nell'output di esempio (dovrebbe essere lì, a meno che non consideri S2 S2 D1 e D1 D1 D1 come uguali, ma sono chiaramente elencati come diversi.) Ci sono alcuni piccole ambiguità sul formato di output e sul conteggio dei risultati che affronterò nella mia risposta.
Level River St,

Risposte:


2

C ++ 248/228 230/214 caratteri

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. Hai salvato alcuni caratteri dichiarando tutte le variabili contemporaneamente ed eliminando le parentesi non necessarie. Si scopre che in C ++ tutta la logica e bit per bit e / o hanno una precedenza inferiore rispetto alle comparazioni.

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

Ho fatto una funzione piuttosto che un programma, come altri hanno fatto. Restituisce il numero totale di possibilità trovate. Può essere ridotto da 230 a 214 caratteri eliminando la funzione di totalizzazione.

Uscita campione, punteggio 6:

inserisci qui la descrizione dell'immagine

Conto diverse freccette prima e seconda come la stessa combinazione, come ha fatto l'OP (esempio:

T1 S1 D1 = S1 T1 D1) anche se questo costa 7 caratteri extra. Elencherò sempre per primo il punteggio più alto (ignorando il raddoppio e il triplo) poiché immagino che ciò sia più rilevante per il giocatore (che può cambiare la sua strategia se perde il primo dardo). Per lo stesso motivo, elenco le freccette in ordine secondo il secondo dardo. Considero il 3 ° dardo completamente diverso dagli altri due, quindi considero D1 D2 e ​​D2 D1 come casi diversi, mentre l'OP li ha elencati come uguali.

Con questo sistema di conteggio ottengo 42336 possibilità totali , lo stesso di mmumboss. Contando diverse prime e seconde freccette come combinazioni diverse, questo arriva a 83349.

Non ho usato un ciclo for con set come hanno fatto altri (sono abbastanza nuovo in C ++ e non so nemmeno se sia possibile.) Invece abuso di un condizionale nell'incremento del loop per passare da 20 a 25 Uso la variabile da un singolo loop per codificare tutti i punteggi possibili per un singolo dardo, in questo modo: S1 D1 T1 S2 D2 T2 ecc. Con modulo e divisione da decodificare. Ciò consente di risparmiare sulla verbosità di dichiarare di più per i loop, sebbene renda le espressioni più complicate.

Il risultato di ciò è che un dardo inutilizzato viene mostrato come T0, ma penso che sia chiaro cosa significhi, specialmente perché (considerando le diverse freccette primo e secondo come la stessa combinazione) sono stato in grado di raggrupparli tutti all'inizio della mia uscita.

Versione non golfata qui. Un paio di altre funzioni sono l'uso selettivo degli operatori & e && con | in modo da dare l'ordine di precedenza che desidero senza parentesi.

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


4

MATLAB ( 299 249 241 caratteri)

Questo è il mio primo golf serio. Il mio primo tentativo (136 caratteri) dà il risultato corretto, ma non con la formattazione corretta. Offre tutte le possibilità osservando il numero di punti per ogni dardo. Ciò significa che il singolo 20 e il doppio 10 hanno una voce separata, tuttavia, entrambi vengono visualizzati come 20. Ovviamente l'ultimo dardo è sempre un doppio.

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

Nel secondo tentativo la formattazione è migliorata, il che ha ovviamente aumentato il numero di caratteri:

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

Migliorato da 299 a 249 caratteri, mentre allo stesso tempo migliora anche la formattazione dell'output. Per questa versione migliorata, l'output per i casi di esempio è:

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

Ulteriori:

Secondo le mie capacità di calcolo, ci sono un totale di 42336 possibilità di terminare il gioco del dardo.


Il risultato dovrebbe mostrare quale cella colpire, quindi nel primo 60 60 50dovrebbe essere T20 T20 Bullseye. Lo chiarirò più chiaramente nella domanda. Va bene, quasi lì :)
Teun Pronk,

1
Sì, l'ho già sottolineato da solo. Questo è il primo tentativo incompiuto. ;)
mmumboss,

oops scusa lol, ero curioso di sapere il codice e il risultato non ho letto la storia sopra xD
Teun Pronk,

Questo dovrebbe essere migliore. L'unica cosa a cui riesco a pensare è che il toro è ancora visualizzato come 25. Ma spero che vada bene, poiché altrimenti non c'è altra possibilità che codificare questo, il che è semplicemente divertente.
mmumboss,

Il toro singolo come 25 è davvero accettabile, è l'unico modo in cui puoi lanciare 25 con 1 dardo comunque
Teun Pronk,

2

Ruby (260 caratteri)

"L'ultimo dovrebbe essere un doppio" era il pezzo mancante - non riuscivo a capire perché 168 non dovesse avere risultati ...:

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;

1

Python 2.7 (270 caratteri)

Non sono sicuro che Python consenta un one-liner, ma è in tre.

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 278+ caratteri con un messaggio "No Checkout" (ad esempio 290 qui):

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

Eccoci qui:

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

Cose di cui non sono contento:

for x in a for y in a for z in

Questo è oltre il 10% del totale. Esiste un modo più compatto senza itertools ecc?

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

Questo è usato per evitare duplicati nel caso di una finitura a due freccette (ad es. ['', 'S1', 'D1'] e ['S1', '', 'D1']). Ritengo che l'ordine abbia importanza (ehi, l'ultimo dardo deve essere un doppio, quindi l'ordine chiaramente conta), ma il non lancio è un caso speciale.


1

05AB1E , 43 byte

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

Abbastanza lento. Viene emesso come elenco di elenchi o elenco vuoto se non è possibile finire. I miei tori sono S25e D25; se ciò non è consentito, posso cambiarlo.

Provalo online o verifica alcuni casi di test contemporaneamente .

Spiegazione:

Ci sono un paio di passaggi:

1) Crea un elenco di tutte le possibili freccette singole, doppie e triple:

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) Ottieni tutti i finisher possibili (che terminano con un doppio) fino a 3 freccette:

Ð           # 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) Conservare solo quelli per i quali il punteggio totale è uguale all'intero di input:

ʒ   }       # 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) Converti i dati nella lista dei risultati piuttosto stampata (cioè [[20,3],[5,1],[1,2]]diventa ["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)

0

Kotlin , 254 byte

Nota: algorythm si basa sulla risposta C ++ di 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!")}

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.