Segna un singolo dardo


22

introduzione

Scrivi un programma o una funzione che, date le coordinate di dove un dardo atterra su un bersaglio, restituisca il punteggio di quel dardo. Le coordinate del dardo sono fornite come due numeri interi, x,ymisurati dal centro del bersaglio, con precisione millimetrica.

Come segnare un dardo

Freccette è una partita giocata lanciando un dardo su una tavola circolare. Il bersaglio per le freccette è diviso in 20 "cunei" di pari dimensioni. Partendo dall'alto e procedendo in senso orario, le sezioni hanno valori di 20,1,18,4,13,6,10,15,2,17,3,19,7,16,8,11,14,9,12 , 5. Se il tuo dardo atterra nelle parti bianche o nere di uno qualsiasi dei cunei, ottieni il valore indicato all'esterno di quel cuneo.
ecco una foto di un bersaglio.


Tuttavia, se il tuo dardo atterra nell'anello esterno verde / rosso del bersaglio, ottieni il doppio dei punti indicati all'esterno del cuneo che colpisci. Allo stesso modo, colpendo l'anello verde / rosso interno (quello tra le due sezioni bianco / nero), ottieni il triplo del numero indicato all'esterno del cuneo. Se il tuo dardo colpisce il cerchio più interno (l'occhio di tori rosso) invece ottieni 50 punti e, infine, se il tuo dardo colpisce il cerchio più interno (l'anello verde attorno all'occhio di toro), ottieni 25 punti.

Le dimensioni degli anelli, misurate dal centro del bersaglio, sono le seguenti:

immagine non in scala


Bullseye (50): [0mm-6mm)
25:            [6mm-16mm)
Inner Single:  [16mm-99mm)
Triple:        [99mm-107mm)
Outer Single:  [107mm-162mm)
Double:        [162mm-170mm)
Miss (0):       170mm+

Nota 1: le immagini fornite sono solo a scopo illustrativo e non sono in scala.

Nota 2: le misure fornite sono approssimative e potrebbero non essere precise su un vero bersaglio.

Nota 3: tutte le misure fornite sono [inclusive-exclusive). Ai fini di questa sfida, non ci preoccuperemo delle freccette che colpiscono il filo e rimbalzano. Se il dardo atterra "sul filo" con una delle linee radiali, spetta al rispondente decidere se rompere la cravatta in senso orario o antiorario. La direzione di rottura del legame deve essere coerente e indicata.

Nota 4: Il bersaglio viene appeso in modo standard con la parte centrale della sezione 20 che si trova direttamente sopra il punto centrale e la sezione 3 direttamente sotto il punto centrale.

Ingresso

Due numeri interi che rappresentano le x,ycoordinate di dove è atterrato il dardo, misurato in millimetri, rispetto al centro del bersaglio.

Produzione

Un unico numero intero, per il numero di punti che verrebbero assegnati a un dardo atterrato alle coordinate indicate.

Campione

0,0     -> 50
2,101   -> 60
-163,-1 -> 22
6,18    ->  1
-6,18   ->  5
45,-169 ->  0
22, 22  ->  4 (if tie-broken clock-wise)
            18(if tie-broken counter-clockwise)
-150,0  ->  11
-150,-1 ->  11

punteggio

. Vince il minor numero di byte nel codice sorgente.

Scappatoie standard vietate .


1
@Shaggy Non vedo alcun motivo decente per farlo.
Jonathan Allan,

5
@Shaggy Puoi spiegare perché dovrebbe essere così? Personalmente mi piacerebbe che le mie freccette fossero sempre garantite per colpire il bersaglio per le freccette, ma per il bene della sfida, ho pensato che fosse meglio attenersi alla realtà piuttosto che alla fantasia.
mypetlion il

1
Casi di prova suggeriti: -150,-1e -150,0che dovrebbero dare 11e potrebbero essere un caso limite in alcune implementazioni, poiché questa è la transizione tra theta convergente in -pi e theta = + pi in coordinate polari. (La mia risposta iniziale non è riuscita sul secondo.)
Arnauld il

1
Dangit, x = y = 0 mi sta completamente incasinando !! Bella sfida
BradC,

1
Spero non ti dispiaccia, ho modificato in una versione migliore della seconda foto.
BradC,

Risposte:


19

JavaScript (ES7), 137 byte

Prende le coordinate nella sintassi del curry (x)(y). Utilizza il tie-break in senso antiorario.

x=>y=>(r=(x*x+y*y)**.5)<6?50:r<16?25:(r<99?1:r<107?3:r<162||r<170&&2)*parseInt('b8g7j3h2fa6d4i1k5c9eb'[Math.atan2(y,x)*3.1831+10.5|0],36)

Provalo online!

Come?

(x,y)(r,θ)

r=x2+y2
θ=arctan2(y,x)

r

θs

s=θ+π2π×20+12=θ×10π+10+12

340×34010/π

10π3.1831

11

11,8,16,7,19,3,17,2,15,10,6,13,4,18,1,20,5,12,9,14,11

11θπθ+π

Uscita grafica

Il seguente frammento di codice ES6 disegna il bersaglio usando la stessa logica del codice golf.


8

JavaScript (ES6) + SVG (HTML5), 53 + 523 51 + 519 507 = 576 570 558 byte

document.write`<svg width=345 height=345>`;i=b=Math.PI/10;s=Math.sin(a=-b/2);c=Math.cos(a);f=(r,f,n)=>document.write(`<path d=M172,172L${[172+r*s,172+r*c]}A${[r,r,0,0,1,172+r*t,172+r*d]}z fill=#${f} n=${n} />`);g=(q,r,m,n,i)=>f(q,i?474:`b32`,n*m)+f(r,i?`fff`:`000`,n);[3,17,2,15,10,6,13,4,18,1,20,5,12,9,14,11,8,16,7,19].map(n=>{t=s;d=c;s=Math.sin(a+=b);c=Math.cos(a);g(170,162,2,n,i=!i);g(107,99,3,n,i);});document.write`<circle cx=172 cy=172 r=16 fill=#474 n=25 /><circle cx=172 cy=172 r=6 fill=#b32 n=50`
<body onclick=alert(+event.target.getAttribute`n`)>

L'input avviene tramite clic del mouse, l'output tramite alert. Modifica: salvato 12 byte utilizzando colori leggermente più approssimativi come suggerito da @Arnauld.


Immagino che nessuno ti biasimerà se lo usi b33e 474per il rosso e il verde. :-)
Arnauld,

@Arnauld Abbastanza giusto, anche se b33è bb3333così b22(aka bb3322) è più vicino al tuo originale be3628.
Neil,

7

Intel 8086/8087 assembly, 180 144 142 138 byte

Questo utilizza il coprocessore matematico 8087 per tutte le trit e l'aritmetica in virgola mobile. Tutti i calcoli vengono eseguiti in hardware con precisione in virgola mobile a 80 bit.

df06 b101 d8c8 df06 af01 d8c8 dec1 d9fa df1e b301 8b16 b301
33c0 81fa aa00 7c03 eb53 9083 fa06 7d05 b032 eb49 9083 fa10
7d05 b019 eb3f 90df 06b7 01df 06b5 01d9 f3df 06b1 01dd d2d9
ebde f9de c9de c1df 1eb3 01a1 b301 bb9c 01d7 83fa 6b7d 0a83
fa63 7c05 b303 eb09 9081 faa2 007c 04b3 02f6 e30b 0810 0713
0311 020f 0a06 0d04 1201 1405 0c09 0e0b 0a00

Scritto come MASM MACRO (sostanzialmente una funzione), prende X e Y come coordinate e restituisce il punteggio calcolato in AX. Il pareggio è rotto in senso orario.

MAX_BULL EQU 6
MAX_25   EQU 16
MIN_3X   EQU 99
MAX_3X   EQU 107
MIN_2X   EQU 162
MAX_2X   EQU 170

; cartesian coordinates to radius
; ST = sqrt( X^2 + Y^2 )
; input: X,Y (mem16,mem16)
; output: Radius (mem16)
FCRAD   MACRO X, Y, R
    FILD  Y         ; ST[] = Y
    FMUL  ST,ST     ; ST = y^2 
    FILD  X         ; ST[] = X
    FMUL  ST,ST     ; ST = x^2
    FADD            ; ST = ST + ST1
    FSQRT           ; ST = SQRT(ST)
    FISTP R         ; R = ROUND(ST)
        ENDM

; cartesian coordinates to sector #
; input: X,Y (mem16,mem16)
; output: Sector (mem16)
FCSEC   MACRO X, Y, S
    FILD  Y         ; ST[] = Y
    FILD  X         ; ST[] = X
    FPATAN          ; ST = atan2(Y,X)
    FILD  CTEN      ; ST[] = 10
    FST   ST(2)     ; ST(2) = 10
    FLDPI           ; ST[] = pi
    FDIV            ; ST = 10 / pi
    FMUL            ; ST = A * ST
    FADD            ; ST = ST + 10
    FISTP S         ; S = ROUND(ST)
        ENDM

; score the dart throw
; input: X / Y coordinates (mem16)
; output: Score (AX)
SCORE   MACRO X, Y
        LOCAL IS_BULL, IS_25, IS_3X, IS_2X, MUL_SCORE, DONE
    FCRAD X, Y, FDW         ; FDW = radius(X,Y)
    MOV  DX, FDW            ; DX = FDW = radius
    XOR  AX, AX             ; score is initially 0
    CMP  DX, MAX_2X         ; >= 170 (miss)
    JL   IS_BULL            ; if not, check for bullseye
    JMP  DONE
IS_BULL:
    CMP  DX, MAX_BULL       ; < 6 (inner bullseye)
    JGE  IS_25              ; if not, check for 25
    MOV  AL, 50             ; score is 50
    JMP  DONE
IS_25:
    CMP  DX, MAX_25         ; < 16 (outer bullseye)
    JGE  IS_3X              ; if not, check for triple
    MOV  AL, 25             ; score is 25
    JMP  DONE
IS_3X:
    FCSEC X, Y, FDW         ; FDW = sector(X,Y)
    MOV  AX, FDW            ; load sector # into AX
    MOV  BX, OFFSET SCR     ; load base score table
    XLAT                    ; put base score into AL
    CMP  DX, MAX_3X         ; < 107 (triple upper bounds)
    JGE  IS_2X              ; if not, check for double
    CMP  DX, MIN_3X         ; >= 99 (triple lower bounds)
    JL   IS_2X              ; if not, check for double
    MOV  BL, 3              ; this is triple score
    JMP  MUL_SCORE          ; go forth and multiply
IS_2X:
    CMP  DX, MIN_2X         ; >= 162 (double lower bounds) (> 170 already checked)
    JL   DONE               ; if not, single score
    MOV  BL, 2              ; this is double score
MUL_SCORE:
    MUL  BL                 ; multiply score either 2x or 3x
DONE:
    ENDM

; DATA (place in appropriate segment)
SCR     DB  11,8,16,7,19,3,17,2,15,10,6  ; score table
        DB  13,4,18,1,20,5,12,9,14,11
CTEN    DW  10      ; constant 10 to load into FPU
FDW     DW  ?       ; temp DW variable for CPU/FPU data transfer

Un programma di test di esempio per PC DOS. Scaricalo qui DARTTEST.COM .

INCLUDE DART.ASM            ; the above file
INCLUDE INDEC.ASM           ; generic I/O routines - input int
INCLUDE OUTDEC.ASM          ; generic I/O routines - output int

    FINIT                   ; reset 8087

    MOV  AH, 2              ; display "X" prompt
    MOV  DL, 'X'
    INT  21H
    CALL INDEC              ; read decimal for X into AX
    MOV  X, AX

    MOV  AH, 2              ; display "Y" prompt
    MOV  DL, 'Y'
    INT  21H
    CALL INDEC              ; read decimal for Y into AX
    MOV  Y, AX

    SCORE X, Y              ; AX = SCORE( X, Y )

    CALL OUTDEC             ; display score

X   DW  ?
Y   DW  ?

Produzione

Esempio di utilizzo del programma di test sopra riportato . Richiesto PC IBM reale con 8087, DOSBox o il tuo emulatore preferito.

A>DARTTEST.COM
X: 0
Y: 0
50
A>DARTTEST.COM
X: 2
Y: 101
60
A>DARTTEST.COM
X: -163
Y: -1
22
A>DARTTEST.COM
X: 6
Y: 18
1
A>DARTTEST.COM
X: -6
Y: 18
5
A>DARTTEST.COM
X: 45
Y: -169
0
A>DARTTEST.COM
X: 22
Y: 22
4
A>DARTTEST.COM
X: -150
Y: 0
11
A>DARTTEST.COM
X: -150
Y: 0
11
A>DARTTEST.COM
X: -150
Y: -1
11
A>DARTTEST.COM
X: -7
Y: -6
25
A>DARTTEST.COM
X: -90
Y: 138
24

* Modifiche:

  • -36 byte rimuovendo l'istruzione di arrotondamento del tronco e la costante 10.5. Cravatta ora rotta in senso orario.
  • -2 byte rimuovendo FRNDINT non più necessario
  • -4 byte, FMUL usa la stessa sorgente / destinazione

6

Gelatina , 56 byte

æA/Æ°_9:18ị“!@umÞẓẓS’Œ?¤
ḅıA<“©Ñckɱȥ‘TṂị“2ı¢¤¢£¡‘¹×>3$?Ç

Un collegamento monadico che accetta la coppia come un elenco [x,y]che fornisce il punteggio.
Utilizza il pareggio in senso orario.

Provalo online! Oppure vedi la suite di test

NB una versione diadica ha anche 56 byte

Come?

æA/Æ°_9:18ị“!@umÞẓẓS’Œ?¤ - Link 1, segment score: pair [x, y]
  /                      - reduce by:
æA                       -   arc tangent
   Æ°                    - convert from radians to degrees
     _9                  - subtract 9 (align 0 with boundary between 1 & 20)
       :18               - integer divide by 18 (yields a segment index from 0 to 19)
                       ¤ - nilad followed by link(s) as a nilad:
           “!@umÞẓẓS’    -   base 250 number = 2091180117530057584
                     Œ?  -   shortest permutation of natural numbers [1..N] which
                         -   would reside at that index in a list of all permutations of
                         -   those same numbers ordered lexicographically.
                         -   = [18,4,13,6,10,15,2,17,3,19,7,16,8,11,14,9,12,5,20,1]
          ị              - index into (yields the score associated with the segment)

ḅıA<“©Ñckɱȥ‘TṂị“2ı¢¤¢£¡‘¹×>3$?Ç - Main Link: segment score: pair [x, y]
 ı                              - √(-1)
ḅ                               - convert from base = x+iy
  A                             - absolute value = √(x²+y²)
    “©Ñckɱȥ‘                    - code-page index list = [6,16,99,107,162,170]
                                - (i.e. the radial boundaries)
            T                   - list of truthy indexes
             Ṃ                  - minimal value (0 if empty)
               “2ı¢¤¢£¡‘        - code-page index list = [50,25,1,3,1,2,0]
              ị                 - index into
                                - (i.e. get an override score (>3) OR a multiplier (<=3))
                              Ç - call last Link (1) as a monad (get the segment score)
                             ?  - if...
                            $   - ...condition: last two links as a monad:
                          >     -      (override OR multiplier) greater than?
                           3    -      three
                        ¹       - ...then: identity (keep override as is)
                         ×      - ...else: multiply (by multiplier)

4

TI-Basic (TI-84 Plus CE), 147 146 byte

Prompt X,Y
abs(X+iY→R
int(E-12+11.5+10π-1R▸Pθ(X,Y→θ
{11,8,16,7,19,3,17,2,15,10,6,13,4,18,1,20,5,12,9,14,11
25((R<6)+(R<16))+Ans(θ)(R≥16 and R<170)(1+(R≥162)+2(R≥99 and R<107

Richiede X e Y su righe separate.

Tie-break in senso antiorario.

TI-Basic è un linguaggio tokenizzato ; tutti i token utilizzati qui sono un byte.

Spiegazione:

Prompt X,Y
# 5 bytes, Prompt for X and Y
abs(X+iY→R
# 8 bytes, store distance from origin in R
int(E-12+11.5+10π-1R▸Pθ(X,Y→θ
# 22 bytes, store index in list of point values by polar angle in θ
{11,8,16,7,19,3,17,2,15,10,6,13,4,18,1,20,5,12,9,14,11
# 55 bytes, list of point values
25((R<6)+(R<16))+Ans(θ)(R≥16 and R<170)(1+(R≥162)+2(R≥99 and R<107
# 57 56 bytes, calculate the score

Utilizza il fatto che i confronti booleani di TI-Basic restituiscono 0 o 1 aggiungendoli e moltiplicandoli per i valori dei punti.


3

T-SQL, 392 374 366 byte

UPDATE t SET x=1WHERE x=0
SELECT TOP 1IIF(r<16,f,b*f)
FROM(SELECT r=SQRT(x*x+y*y),w=FLOOR(10*ATN2(y,x)/PI()+.5)FROM t)p,
(VALUES(10,11),(9,14),(8,9),(7,12),(6,5),(5,20),(4,1),(3,18),(2,4),(1,13),(0,6),
   (-1,10),(-2,15),(-3,2),(-4,17),(-5,3),(-6,19),(-7,7),(-8,16),(-9,8),(-10,11))s(a,b),
(VALUES(6,50),(16,25),(99,1),(107,3),(162,1),(170,2),(999,0))d(e,f)
WHERE a=w AND r<e

Le interruzioni di riga sono leggibili. L'iniziale UPDATEsi occupa del x=y=0problema che altrimenti genererebbe un errore ATN2(), ma non cambia il punteggio.

L'input viene preso tramite la tabella t preesistente , secondo le nostre linee guida IO . A causa dell'utilizzo TOP 1, questa tabella dovrebbe contenere solo una singola riga.

Fondamentalmente mi unisco a 3 tavoli:

  • Tabella p : x e y dalla tabella di input t vengono convertiti in r polari e un valore "a cuneo" w che rappresenta un numero compreso tra -11 e 11 positivo, per il cuneo di punteggio in cui è caduto il dardo. "Tie breaker" è antiorario. (Ho provato ROUND(), che era leggermente più corto, ma ha dato un pareggio incoerente.)
  • Tabella s : questa è una tabella di ricerca per convertire un valore di "cuneo" a in un punteggio b .
  • Tabella d : questa è una tabella di ricerca che restituisce il calcolo del punteggio in base alla distanza dal centro. e è la distanza e si unisce a r , e restituisce solo una singola riga in base a TOP 1. Il valore f è un punteggio fisso (per un occhio di bue) o un moltiplicatore per il punteggio a cuneo.

EDIT : abbandonato il ORDER BY, sembra funzionare correttamente senza di esso, almeno su SQL 2017. Ho anche lasciato cadere la AND y=0condizione di aggiornamento; Ho testato tutti i yvalori interi , cambiando x=0per x=1non cambiare mai il punteggio.

EDIT 2 : Rimossa la colonna g dalla tabella d , sostituita con IIF()un'istruzione che restituisce fdirettamente (per un occhio di bue), o f*b, salvato 8 byte. Inoltre rimosso lo spazio dopo TOP 1.


2

Haskell , 198 byte

p=pure
a#b=(!!(sum[1|k<-a,k<=b]))
a!b=([6,16,99,107,162,170]#(sqrt$a*a+b*b))[p 50,p 25,id,(*3),id,(*2),p 0]$([pi/20,3*pi/20..6]#(pi+atan2 b a))[11,8,16,7,19,3,17,2,15,10,6,13,4,18,1,20,5,12,9,14,11]

La cravatta si rompe in senso antiorario. (#)è una funzione di ricerca. L'angolo polare viene utilizzato per indicizzare dall'elenco di numeri, iniziando dal atan2punto di taglio a 11. La distanza viene utilizzata per indicizzare dall'elenco di funzioni [const 50, const 25, id, (*3), id, (*2), const 0]e alla fine questa funzione viene applicata al numero ottenuto in precedenza.

Provalo online!


1

Perl 5 -MMath::Trig':pi' -MMath::Trig':radial' -apl , 166 byte

($d,$a)=cartesian_to_cylindrical@F;$_=(1+($d>161||$d<6)+($d<107&&$d>98)*2)*($d<170)*($d<16?25:("6 134 181 205 129 14118 167 193 172 1510"=~/../g)[($a/pi*10+41/2)%20])

Provalo online!

Prende lo spazio delle due coordinate separato su STDIN. La rottura del legame è in senso antiorario.

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.